3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8 * Copyright (C) Jean François Micouleau 1998-2000.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
34 #define PRINTER_HANDLE_IS_PRINTER 0
35 #define PRINTER_HANDLE_IS_PRINTSERVER 1
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer{
46 BOOL document_started;
48 int jobid; /* jobid in printing backend */
49 POLICY_HND printer_hnd;
53 fstring printerservername;
62 SPOOL_NOTIFY_OPTION *option;
63 POLICY_HND client_hnd;
64 uint32 client_connected;
72 typedef struct _counter_printer_0 {
80 static ubi_dlList Printer_list;
81 static ubi_dlList counter_list;
83 static struct cli_state cli;
84 static uint32 smb_connections=0;
86 #define OPEN_HANDLE(pnum) ((pnum!=NULL) && (pnum->open!=False) && (IVAL(pnum->printer_hnd.data,16)==(uint32)sys_getpid()))
87 #define OUR_HANDLE(pnum) ((pnum==NULL)?"NULL":(IVAL(pnum->data,16)==sys_getpid()?"OURS":"OTHER"))
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
94 return PRINTER_STATUS_PAUSED;
103 static int nt_printq_status(int v)
107 return PRINTER_STATUS_PAUSED;
116 /****************************************************************************
117 initialise printer handle states...
118 ****************************************************************************/
119 void init_printer_hnd(void)
121 ubi_dlInitList(&Printer_list);
122 ubi_dlInitList(&counter_list);
125 /****************************************************************************
126 create a unique printer handle
127 ****************************************************************************/
128 static void create_printer_hnd(POLICY_HND *hnd)
130 static uint32 prt_hnd_low = 0;
131 static uint32 prt_hnd_high = 0;
133 if (hnd == NULL) return;
135 /* i severely doubt that prt_hnd_high will ever be non-zero... */
137 if (prt_hnd_low == 0) prt_hnd_high++;
139 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
140 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
141 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
142 SIVAL(hnd->data, 12, time(NULL)); /* something random */
143 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
146 /****************************************************************************
147 find printer index by handle
148 ****************************************************************************/
149 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
151 Printer_entry *find_printer;
153 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
155 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
157 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
158 DEBUG(4,("Found printer handle \n"));
159 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
164 DEBUG(3,("Whoops, Printer handle not found: "));
165 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
169 /****************************************************************************
171 ****************************************************************************/
172 static void clear_handle(POLICY_HND *hnd)
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
180 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
184 /* weird if the test succeds !!! */
185 if (smb_connections==0) {
186 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
190 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
195 if(!spoolss_disconnect_from_client(&cli))
198 message_deregister(MSG_PRINTER_NOTIFY);
206 /****************************************************************************
207 close printer index by handle
208 ****************************************************************************/
209 static BOOL close_printer_handle(POLICY_HND *hnd)
211 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
213 if (!OPEN_HANDLE(Printer)) {
214 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
218 if (Printer->notify.client_connected==True)
219 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
220 return ERROR_INVALID_HANDLE;
223 Printer->notify.flags=0;
224 Printer->notify.options=0;
225 Printer->notify.localmachine[0]='\0';
226 Printer->notify.printerlocal=0;
227 safe_free(Printer->notify.option);
228 Printer->notify.option=NULL;
229 Printer->notify.client_connected=False;
233 ubi_dlRemThis(&Printer_list, Printer);
240 /****************************************************************************
241 delete a printer given a handle
242 ****************************************************************************/
243 static BOOL delete_printer_handle(POLICY_HND *hnd)
245 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
247 if (!OPEN_HANDLE(Printer)) {
248 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
252 if (del_a_printer(Printer->dev.handlename) != 0) {
253 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
257 if (*lp_deleteprinter_cmd()) {
259 pid_t local_pid = sys_getpid();
260 char *cmd = lp_deleteprinter_cmd();
267 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
268 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
272 /* Printer->dev.handlename equals portname equals sharename */
273 slprintf(command, sizeof(command), "%s \"%s\"", cmd,
274 Printer->dev.handlename);
275 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
278 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
279 ret = smbrun(command, tmp_file, False);
284 DEBUGADD(10,("returned [%d]\n", ret));
285 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
288 /* Send SIGHUP to process group... is there a better way? */
291 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
292 lp_remove_service( i );
302 /****************************************************************************
303 return the snum of a printer corresponding to an handle
304 ****************************************************************************/
305 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
307 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
309 if (!OPEN_HANDLE(Printer)) {
310 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
314 switch (Printer->printer_type) {
315 case PRINTER_HANDLE_IS_PRINTER:
316 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
317 *number = print_queue_snum(Printer->dev.handlename);
318 return (*number != -1);
319 case PRINTER_HANDLE_IS_PRINTSERVER:
328 /****************************************************************************
329 set printer handle type.
330 ****************************************************************************/
331 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
333 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
335 if (!OPEN_HANDLE(Printer)) {
336 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
340 DEBUG(4,("Setting printer access=%x\n", access_required));
341 Printer->access = access_required;
345 /****************************************************************************
346 Set printer handle type.
347 Check if it's \\server or \\server\printer
348 ****************************************************************************/
350 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
352 DEBUG(3,("Setting printer type=%s\n", handlename));
354 if ( strlen(handlename) < 3 ) {
355 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
359 /* it's a print server */
360 if (!strchr(handlename+2, '\\')) {
361 DEBUGADD(4,("Printer is a print server\n"));
362 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
367 DEBUGADD(4,("Printer is a printer\n"));
368 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
375 /****************************************************************************
376 Set printer handle name.
377 ****************************************************************************/
379 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
381 NT_PRINTER_INFO_LEVEL *printer = NULL;
383 int n_services=lp_numservices();
387 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
389 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
390 ZERO_STRUCT(Printer->dev.printerservername);
391 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
395 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
398 aprinter=strchr(handlename+2, '\\');
401 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
404 * store the Samba share name in it
405 * in back we have the long printer name
406 * need to iterate all the snum and do a
407 * get_a_printer each time to find the printer
408 * faster to do it here than later.
411 for (snum=0;snum<n_services && found==False;snum++) {
413 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
416 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
418 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
421 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
422 printer->info_2->printername, aprinter ));
424 if ( strlen(printer->info_2->printername) != strlen(aprinter) ) {
425 free_a_printer(&printer, 2);
429 if ( strncasecmp(printer->info_2->printername, aprinter, strlen(aprinter))) {
430 free_a_printer(&printer, 2);
438 * if we haven't found a printer with the given handlename
439 * then it can be a share name as you can open both \\server\printer and
444 * we still check if the printer description file exists as NT won't be happy
445 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
449 DEBUGADD(5,("Printer not found, checking for share now\n"));
451 for (snum=0;snum<n_services && found==False;snum++) {
453 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
456 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
458 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
461 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
462 printer->info_2->printername, aprinter ));
464 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
465 free_a_printer(&printer, 2);
469 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
470 free_a_printer(&printer, 2);
479 DEBUGADD(4,("Printer not found\n"));
484 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
485 printer->info_2->printername, lp_servicename(snum),snum));
487 ZERO_STRUCT(Printer->dev.handlename);
488 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
490 free_a_printer(&printer, 2);
495 /****************************************************************************
496 find first available printer slot. creates a printer handle for you.
497 ****************************************************************************/
499 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
501 Printer_entry *new_printer;
503 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
505 create_printer_hnd(hnd);
507 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
510 ZERO_STRUCTP(new_printer);
512 new_printer->open = True;
513 new_printer->notify.option=NULL;
515 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
517 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
519 if (!set_printer_hnd_printertype(new_printer, name)) {
520 close_printer_handle(hnd);
524 if (!set_printer_hnd_name(new_printer, name)) {
525 close_printer_handle(hnd);
532 /********************************************************************
533 Return True is the handle is a print server.
534 ********************************************************************/
535 static BOOL handle_is_printserver(const POLICY_HND *handle)
537 Printer_entry *Printer=find_printer_index_by_hnd(handle);
539 if (!OPEN_HANDLE(Printer))
542 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
548 /****************************************************************************
549 allocate more memory for a BUFFER.
550 ****************************************************************************/
551 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
559 /* damn, I'm doing the reverse operation of prs_grow() :) */
560 if (buffer_size < prs_data_size(ps))
563 extra_space = buffer_size - prs_data_size(ps);
566 * save the offset and move to the end of the buffer
567 * prs_grow() checks the extra_space against the offset
569 old_offset=prs_offset(ps);
570 prs_set_offset(ps, prs_data_size(ps));
572 if (!prs_grow(ps, extra_space))
575 prs_set_offset(ps, old_offset);
577 buffer->string_at_end=prs_data_size(ps);
582 /***************************************************************************
583 receive the notify message
584 ****************************************************************************/
585 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
589 Printer_entry *find_printer;
591 memcpy(printer, buf, len);
593 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
595 /* Iterate the printer list. */
596 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
599 * if the entry is the given printer or if it's a printerserver
600 * we send the message
603 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
604 if (strcmp(find_printer->dev.handlename, printer))
607 if (find_printer->notify.client_connected==True)
608 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
613 /***************************************************************************
615 ****************************************************************************/
616 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
620 Printer_entry *Printer=find_printer_index_by_hnd(handle);
622 if (!OPEN_HANDLE(Printer)) {
623 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
627 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
628 fstrcpy(printer, Printer->dev.handlename);
630 fstrcpy(printer, "");
632 /*srv_spoolss_receive_message(printer);*/
633 message_send_all(MSG_PRINTER_NOTIFY, printer, strlen(printer));
638 /********************************************************************
639 * spoolss_open_printer
641 * called from the spoolss dispatcher
642 ********************************************************************/
643 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername,
644 const PRINTER_DEFAULT *printer_default,
645 uint32 user_switch, SPOOL_USER_CTR user_ctr,
650 if (printername == NULL)
651 return ERROR_INVALID_PRINTER_NAME;
653 /* some sanity check because you can open a printer or a print server */
654 /* aka: \\server\printer or \\server */
655 unistr2_to_ascii(name, printername, sizeof(name)-1);
657 DEBUGADD(3,("checking name: %s\n",name));
659 if (!open_printer_hnd(handle, name))
660 return ERROR_INVALID_PRINTER_NAME;
663 if (printer_default->datatype_ptr != NULL)
665 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
666 set_printer_hnd_datatype(handle, datatype);
669 set_printer_hnd_datatype(handle, "");
672 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
673 close_printer_handle(handle);
674 return ERROR_ACCESS_DENIED;
677 /* Disallow MS AddPrinterWizard if access rights are insufficient OR
678 if parameter disables it. The client tries an OpenPrinterEx with
679 SERVER_ALL_ACCESS(0xf0003), which we force to fail. It then tries
680 OpenPrinterEx with SERVER_READ(0x20002) which we allow. This lets
681 it see any printers there, but does not show the MSAPW */
682 if (handle_is_printserver(handle) &&
683 printer_default->access_required != (SERVER_READ) &&
684 !lp_ms_add_printer_wizard() ) {
685 return ERROR_ACCESS_DENIED;
688 return NT_STATUS_NO_PROBLEMO;
691 /****************************************************************************
692 ****************************************************************************/
693 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
694 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
698 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
707 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
708 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
712 printer->info_3=NULL;
713 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
716 printer->info_6=NULL;
717 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
726 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
728 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
729 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
731 nt_devmode->specversion=devmode->specversion;
732 nt_devmode->driverversion=devmode->driverversion;
733 nt_devmode->size=devmode->size;
734 nt_devmode->driverextra=devmode->driverextra;
735 nt_devmode->fields=devmode->fields;
736 nt_devmode->orientation=devmode->orientation;
737 nt_devmode->papersize=devmode->papersize;
738 nt_devmode->paperlength=devmode->paperlength;
739 nt_devmode->paperwidth=devmode->paperwidth;
740 nt_devmode->scale=devmode->scale;
741 nt_devmode->copies=devmode->copies;
742 nt_devmode->defaultsource=devmode->defaultsource;
743 nt_devmode->printquality=devmode->printquality;
744 nt_devmode->color=devmode->color;
745 nt_devmode->duplex=devmode->duplex;
746 nt_devmode->yresolution=devmode->yresolution;
747 nt_devmode->ttoption=devmode->ttoption;
748 nt_devmode->collate=devmode->collate;
750 nt_devmode->logpixels=devmode->logpixels;
751 nt_devmode->bitsperpel=devmode->bitsperpel;
752 nt_devmode->pelswidth=devmode->pelswidth;
753 nt_devmode->pelsheight=devmode->pelsheight;
754 nt_devmode->displayflags=devmode->displayflags;
755 nt_devmode->displayfrequency=devmode->displayfrequency;
756 nt_devmode->icmmethod=devmode->icmmethod;
757 nt_devmode->icmintent=devmode->icmintent;
758 nt_devmode->mediatype=devmode->mediatype;
759 nt_devmode->dithertype=devmode->dithertype;
760 nt_devmode->reserved1=devmode->reserved1;
761 nt_devmode->reserved2=devmode->reserved2;
762 nt_devmode->panningwidth=devmode->panningwidth;
763 nt_devmode->panningheight=devmode->panningheight;
765 if (nt_devmode->driverextra != 0) {
766 /* if we had a previous private delete it and make a new one */
767 safe_free(nt_devmode->private);
768 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
770 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
776 /********************************************************************
777 * api_spoolss_closeprinter
778 ********************************************************************/
779 uint32 _spoolss_closeprinter(POLICY_HND *handle)
781 Printer_entry *Printer=find_printer_index_by_hnd(handle);
783 if (Printer && Printer->document_started)
784 _spoolss_enddocprinter(handle); /* print job was not closed */
786 if (!close_printer_handle(handle))
787 return ERROR_INVALID_HANDLE;
789 return NT_STATUS_NO_PROBLEMO;
792 /********************************************************************
793 * api_spoolss_deleteprinter
794 ********************************************************************/
795 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
797 Printer_entry *Printer=find_printer_index_by_hnd(handle);
799 if (Printer && Printer->document_started)
800 _spoolss_enddocprinter(handle); /* print job was not closed */
802 if (!delete_printer_handle(handle))
803 return ERROR_INVALID_HANDLE;
805 srv_spoolss_sendnotify(handle);
807 return NT_STATUS_NO_PROBLEMO;
810 /********************************************************************
811 GetPrinterData on a printer server Handle.
812 ********************************************************************/
813 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
817 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
819 if (!strcmp(value, "BeepEnabled")) {
821 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
823 SIVAL(*data, 0, 0x01);
828 if (!strcmp(value, "EventLog")) {
830 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
832 SIVAL(*data, 0, 0x1B);
837 if (!strcmp(value, "NetPopup")) {
839 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
841 SIVAL(*data, 0, 0x01);
846 if (!strcmp(value, "MajorVersion")) {
848 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
850 SIVAL(*data, 0, 0x02);
855 if (!strcmp(value, "DefaultSpoolDirectory")) {
856 pstring string="You are using a Samba server";
858 *needed = 2*(strlen(string)+1);
859 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
861 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
863 /* it's done by hand ready to go on the wire */
864 for (i=0; i<strlen(string); i++) {
865 (*data)[2*i]=string[i];
871 if (!strcmp(value, "Architecture")) {
872 pstring string="Windows NT x86";
874 *needed = 2*(strlen(string)+1);
875 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
877 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
878 for (i=0; i<strlen(string); i++) {
879 (*data)[2*i]=string[i];
888 /********************************************************************
889 GetPrinterData on a printer Handle.
890 ********************************************************************/
891 static BOOL getprinterdata_printer(POLICY_HND *handle,
892 fstring value, uint32 *type,
893 uint8 **data, uint32 *needed, uint32 in_size )
895 NT_PRINTER_INFO_LEVEL *printer = NULL;
899 Printer_entry *Printer = find_printer_index_by_hnd(handle);
901 DEBUG(5,("getprinterdata_printer\n"));
903 if (!OPEN_HANDLE(Printer)) {
904 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
908 if(!get_printer_snum(handle, &snum))
911 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
914 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
915 free_a_printer(&printer, 2);
919 free_a_printer(&printer, 2);
921 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
924 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
928 memset(*data, 0, in_size *sizeof(uint8));
929 /* copy the min(in_size, len) */
930 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
937 DEBUG(5,("getprinterdata_printer:copy done\n"));
944 /********************************************************************
945 * spoolss_getprinterdata
946 ********************************************************************/
947 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
956 Printer_entry *Printer = find_printer_index_by_hnd(handle);
959 * Reminder: when it's a string, the length is in BYTES
960 * even if UNICODE is negociated.
967 /* in case of problem, return some default values */
971 DEBUG(4,("_spoolss_getprinterdata\n"));
973 if (!OPEN_HANDLE(Printer)) {
974 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
975 return ERROR_NOT_ENOUGH_MEMORY;
976 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
977 return ERROR_INVALID_HANDLE;
980 unistr2_to_ascii(value, valuename, sizeof(value)-1);
982 if (handle_is_printserver(handle))
983 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
985 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
988 DEBUG(5, ("value not found, allocating %d\n", *out_size));
989 /* reply this param doesn't exist */
991 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
992 return ERROR_NOT_ENOUGH_MEMORY;
993 memset(*data, '\0', *out_size*sizeof(uint8));
998 return ERROR_INVALID_PARAMETER;
1001 if (*needed > *out_size)
1002 return ERROR_MORE_DATA;
1004 return NT_STATUS_NO_PROBLEMO;
1007 /***************************************************************************
1008 connect to the client
1009 ****************************************************************************/
1010 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1015 * If it's the first connection, contact the client
1016 * and connect to the IPC$ share anonumously
1018 if (smb_connections==0) {
1019 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1021 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1027 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1033 /********************************************************************
1035 * ReplyFindFirstPrinterChangeNotifyEx
1037 * jfmxxxx: before replying OK: status=0
1038 * should do a rpc call to the workstation asking ReplyOpenPrinter
1039 * have to code it, later.
1041 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1042 * called from api_spoolss_rffpcnex
1043 ********************************************************************/
1044 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1045 const UNISTR2 *localmachine, uint32 printerlocal,
1046 SPOOL_NOTIFY_OPTION *option)
1048 /* store the notify value in the printer struct */
1050 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1052 if (!OPEN_HANDLE(Printer)) {
1053 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1054 return ERROR_INVALID_HANDLE;
1057 Printer->notify.flags=flags;
1058 Printer->notify.options=options;
1059 Printer->notify.printerlocal=printerlocal;
1060 Printer->notify.option=option;
1061 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1063 /* connect to the client machine and send a ReplyOpenPrinter */
1064 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1065 Printer->notify.printerlocal, 1,
1066 &Printer->notify.client_hnd))
1067 Printer->notify.client_connected=True;
1069 return NT_STATUS_NO_PROBLEMO;
1072 /*******************************************************************
1073 * fill a notify_info_data with the servername
1074 ********************************************************************/
1075 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1076 NT_PRINTER_INFO_LEVEL *printer)
1080 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1082 data->notify_data.data.length= (uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1083 temp_name, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1086 /*******************************************************************
1087 * fill a notify_info_data with the servicename
1088 * jfmxxxx: it's incorrect should be long_printername
1089 ********************************************************************/
1090 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1091 NT_PRINTER_INFO_LEVEL *printer)
1094 data->notify_data.data.length=strlen(lp_servicename(snum));
1095 dos_PutUniCode(data->notify_data.data.string, lp_servicename(snum), sizeof(data->notify_data.data.string), True);
1097 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1098 printer->info_2->printername, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1101 /*******************************************************************
1102 * fill a notify_info_data with the servicename
1103 ********************************************************************/
1104 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1106 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1107 lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
1110 /*******************************************************************
1111 * fill a notify_info_data with the port name
1112 ********************************************************************/
1113 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1115 /* even if it's strange, that's consistant in all the code */
1117 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1118 lp_servicename(snum), sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1121 /*******************************************************************
1122 * fill a notify_info_data with the printername
1123 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1124 * but it doesn't exist, have to see what to do
1125 ********************************************************************/
1126 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1128 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1129 printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1132 /*******************************************************************
1133 * fill a notify_info_data with the comment
1134 ********************************************************************/
1135 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1137 if (*printer->info_2->comment == '\0')
1138 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1139 lp_comment(snum), sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1141 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1142 printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1145 /*******************************************************************
1146 * fill a notify_info_data with the comment
1147 * jfm:xxxx incorrect, have to create a new smb.conf option
1148 * location = "Room 1, floor 2, building 3"
1149 ********************************************************************/
1150 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1152 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1153 printer->info_2->location, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1156 /*******************************************************************
1157 * fill a notify_info_data with the device mode
1158 * jfm:xxxx don't to it for know but that's a real problem !!!
1159 ********************************************************************/
1160 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1164 /*******************************************************************
1165 * fill a notify_info_data with the separator file name
1166 * jfm:xxxx just return no file could add an option to smb.conf
1167 * separator file = "separator.txt"
1168 ********************************************************************/
1169 static void spoolss_notify_sepfile(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 printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True) - sizeof(uint16))/sizeof(uint16));
1175 /*******************************************************************
1176 * fill a notify_info_data with the print processor
1177 * jfm:xxxx return always winprint to indicate we don't do anything to it
1178 ********************************************************************/
1179 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1181 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1182 printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1185 /*******************************************************************
1186 * fill a notify_info_data with the print processor options
1187 * jfm:xxxx send an empty string
1188 ********************************************************************/
1189 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1191 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1192 printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1195 /*******************************************************************
1196 * fill a notify_info_data with the data type
1197 * jfm:xxxx always send RAW as data type
1198 ********************************************************************/
1199 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1201 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1202 printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1205 /*******************************************************************
1206 * fill a notify_info_data with the security descriptor
1207 * jfm:xxxx send an null pointer to say no security desc
1208 * have to implement security before !
1209 ********************************************************************/
1210 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1212 data->notify_data.data.length=0;
1213 data->notify_data.data.string[0]=0x00;
1216 /*******************************************************************
1217 * fill a notify_info_data with the attributes
1218 * jfm:xxxx a samba printer is always shared
1219 ********************************************************************/
1220 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1222 data->notify_data.value[0] = PRINTER_ATTRIBUTE_SHARED \
1223 | PRINTER_ATTRIBUTE_LOCAL \
1224 | PRINTER_ATTRIBUTE_RAW_ONLY ;
1227 /*******************************************************************
1228 * fill a notify_info_data with the priority
1229 ********************************************************************/
1230 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1232 data->notify_data.value[0] = printer->info_2->priority;
1235 /*******************************************************************
1236 * fill a notify_info_data with the default priority
1237 ********************************************************************/
1238 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1240 data->notify_data.value[0] = printer->info_2->default_priority;
1243 /*******************************************************************
1244 * fill a notify_info_data with the start time
1245 ********************************************************************/
1246 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1248 data->notify_data.value[0] = printer->info_2->starttime;
1251 /*******************************************************************
1252 * fill a notify_info_data with the until time
1253 ********************************************************************/
1254 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1256 data->notify_data.value[0] = printer->info_2->untiltime;
1259 /*******************************************************************
1260 * fill a notify_info_data with the status
1261 ********************************************************************/
1262 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1265 print_queue_struct *q=NULL;
1266 print_status_struct status;
1268 memset(&status, 0, sizeof(status));
1269 count = print_queue_status(snum, &q, &status);
1270 data->notify_data.value[0]=(uint32) status.status;
1274 /*******************************************************************
1275 * fill a notify_info_data with the number of jobs queued
1276 ********************************************************************/
1277 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1279 print_queue_struct *q=NULL;
1280 print_status_struct status;
1282 memset(&status, 0, sizeof(status));
1283 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1287 /*******************************************************************
1288 * fill a notify_info_data with the average ppm
1289 ********************************************************************/
1290 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1292 /* always respond 8 pages per minutes */
1293 /* a little hard ! */
1294 data->notify_data.value[0] = printer->info_2->averageppm;
1297 /*******************************************************************
1298 * fill a notify_info_data with
1299 ********************************************************************/
1300 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1302 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1303 queue->user, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1306 /*******************************************************************
1307 * fill a notify_info_data with
1308 ********************************************************************/
1309 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1311 data->notify_data.value[0]=nt_printj_status(queue->status);
1314 /*******************************************************************
1315 * fill a notify_info_data with
1316 ********************************************************************/
1317 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1319 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1320 queue->file, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1323 /*******************************************************************
1324 * fill a notify_info_data with
1325 ********************************************************************/
1326 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1328 char *p = "unknown";
1329 switch (queue->status) {
1343 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1344 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1347 /*******************************************************************
1348 * fill a notify_info_data with
1349 ********************************************************************/
1350 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1352 data->notify_data.value[0]=0x0;
1355 /*******************************************************************
1356 * fill a notify_info_data with
1357 ********************************************************************/
1358 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1360 data->notify_data.value[0]=queue->size;
1363 /*******************************************************************
1364 * fill a notify_info_data with
1365 ********************************************************************/
1366 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1368 data->notify_data.value[0]=queue->job;
1373 struct s_notify_info_data_table
1379 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1380 print_queue_struct *queue,
1381 NT_PRINTER_INFO_LEVEL *printer);
1384 struct s_notify_info_data_table notify_info_data_table[] =
1386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, NULL },
1429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1436 { END, END, "", END, NULL }
1439 /*******************************************************************
1440 return the size of info_data structure
1441 ********************************************************************/
1442 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1446 while (notify_info_data_table[i].type != END)
1448 if ( (notify_info_data_table[i].type == type ) &&
1449 (notify_info_data_table[i].field == field ) )
1451 return (notify_info_data_table[i].size);
1459 /*******************************************************************
1460 return the type of notify_info_data
1461 ********************************************************************/
1462 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1466 while (notify_info_data_table[i].type != END)
1468 if ( (notify_info_data_table[i].type == type ) &&
1469 (notify_info_data_table[i].field == field ) )
1471 if (notify_info_data_table[i].size == POINTER)
1486 /****************************************************************************
1487 ****************************************************************************/
1488 static int search_notify(uint16 type, uint16 field, int *value)
1493 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1495 if ( (notify_info_data_table[j].type == type ) &&
1496 (notify_info_data_table[j].field == field ) )
1501 if ( found && (notify_info_data_table[j].fn != NULL) )
1507 /****************************************************************************
1508 ****************************************************************************/
1509 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1511 info_data->type = type;
1512 info_data->field = field;
1513 info_data->reserved = 0;
1515 info_data->size = size_of_notify_info_data(type, field);
1516 info_data->enc_type = type_of_notify_info_data(type, field);
1520 /*******************************************************************
1522 * fill a notify_info struct with info asked
1524 ********************************************************************/
1525 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1531 SPOOL_NOTIFY_INFO_DATA *current_data;
1532 NT_PRINTER_INFO_LEVEL *printer = NULL;
1533 print_queue_struct *queue=NULL;
1535 DEBUG(4,("construct_notify_printer_info\n"));
1537 type=option_type->type;
1539 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1540 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1541 option_type->count, lp_servicename(snum)));
1543 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1546 for(field_num=0; field_num<option_type->count; field_num++) {
1547 field = option_type->fields[field_num];
1548 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1550 if (!search_notify(type, field, &j) )
1553 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1556 current_data=&info->data[info->count];
1558 construct_info_data(current_data, type, field, id);
1559 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1564 free_a_printer(&printer, 2);
1568 /*******************************************************************
1570 * fill a notify_info struct with info asked
1572 ********************************************************************/
1573 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1579 SPOOL_NOTIFY_INFO_DATA *current_data;
1580 NT_PRINTER_INFO_LEVEL *printer = NULL;
1582 DEBUG(4,("construct_notify_jobs_info\n"));
1584 type = option_type->type;
1586 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1587 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1588 option_type->count));
1590 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1593 for(field_num=0; field_num<option_type->count; field_num++) {
1594 field = option_type->fields[field_num];
1596 if (!search_notify(type, field, &j) )
1599 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1603 current_data=&(info->data[info->count]);
1605 construct_info_data(current_data, type, field, id);
1606 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1610 free_a_printer(&printer, 2);
1615 * JFM: The enumeration is not that simple, it's even non obvious.
1617 * let's take an example: I want to monitor the PRINTER SERVER for
1618 * the printer's name and the number of jobs currently queued.
1619 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1620 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1622 * I have 3 printers on the back of my server.
1624 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1627 * 1 printer 1 name 1
1628 * 2 printer 1 cjob 1
1629 * 3 printer 2 name 2
1630 * 4 printer 2 cjob 2
1631 * 5 printer 3 name 3
1632 * 6 printer 3 name 3
1634 * that's the print server case, the printer case is even worse.
1639 /*******************************************************************
1641 * enumerate all printers on the printserver
1642 * fill a notify_info struct with info asked
1644 ********************************************************************/
1645 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1648 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1649 int n_services=lp_numservices();
1652 SPOOL_NOTIFY_OPTION *option;
1653 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1655 DEBUG(4,("printserver_notify_info\n"));
1657 option=Printer->notify.option;
1663 for (i=0; i<option->count; i++) {
1664 option_type=&(option->ctr.type[i]);
1666 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1669 for (snum=0; snum<n_services; snum++)
1670 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1671 if (construct_notify_printer_info(info, snum, option_type, id))
1676 * Debugging information, don't delete.
1679 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1680 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1681 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1683 for (i=0; i<info->count; i++) {
1684 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1685 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1686 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1690 return NT_STATUS_NO_PROBLEMO;
1693 /*******************************************************************
1695 * fill a notify_info struct with info asked
1697 ********************************************************************/
1698 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1701 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1704 SPOOL_NOTIFY_OPTION *option;
1705 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1707 print_queue_struct *queue=NULL;
1708 print_status_struct status;
1710 DEBUG(4,("printer_notify_info\n"));
1712 option=Printer->notify.option;
1718 get_printer_snum(hnd, &snum);
1720 for (i=0; i<option->count; i++) {
1721 option_type=&option->ctr.type[i];
1723 switch ( option_type->type ) {
1724 case PRINTER_NOTIFY_TYPE:
1725 if(construct_notify_printer_info(info, snum, option_type, id))
1729 case JOB_NOTIFY_TYPE:
1730 memset(&status, 0, sizeof(status));
1731 count = print_queue_status(snum, &queue, &status);
1732 for (j=0; j<count; j++)
1733 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1740 * Debugging information, don't delete.
1743 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1744 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1745 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1747 for (i=0; i<info->count; i++) {
1748 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1749 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1750 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1753 return NT_STATUS_NO_PROBLEMO;
1756 /********************************************************************
1758 ********************************************************************/
1759 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1760 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1762 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1764 if (!OPEN_HANDLE(Printer)) {
1765 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1766 return ERROR_INVALID_HANDLE;
1769 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1771 /* jfm: the change value isn't used right now.
1772 * we will honour it when
1773 * a) we'll be able to send notification to the client
1774 * b) we'll have a way to communicate between the spoolss process.
1776 * same thing for option->flags
1777 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1778 * I don't have a global notification system, I'm sending back all the
1779 * informations even when _NOTHING_ has changed.
1782 /* just discard the SPOOL_NOTIFY_OPTION */
1784 safe_free(option->ctr.type);
1786 switch (Printer->printer_type) {
1787 case PRINTER_HANDLE_IS_PRINTSERVER:
1788 return printserver_notify_info(handle, info);
1790 case PRINTER_HANDLE_IS_PRINTER:
1791 return printer_notify_info(handle, info);
1795 return ERROR_INVALID_HANDLE;
1798 /********************************************************************
1799 * construct_printer_info_0
1800 * fill a printer_info_1 struct
1801 ********************************************************************/
1802 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, fstring servername)
1806 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1807 counter_printer_0 *session_counter;
1808 uint32 global_counter;
1810 time_t setup_time = time(NULL);
1812 print_queue_struct *queue=NULL;
1813 print_status_struct status;
1815 memset(&status, 0, sizeof(status));
1817 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1820 count = print_queue_status(snum, &queue, &status);
1822 /* check if we already have a counter for this printer */
1823 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1825 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1826 if (session_counter->snum == snum)
1830 /* it's the first time, add it to the list */
1831 if (session_counter==NULL) {
1832 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1833 free_a_printer(&ntprinter, 2);
1836 ZERO_STRUCTP(session_counter);
1837 session_counter->snum=snum;
1838 session_counter->counter=0;
1839 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1843 session_counter->counter++;
1846 * the global_counter should be stored in a TDB as it's common to all the clients
1847 * and should be zeroed on samba startup
1849 global_counter=session_counter->counter;
1851 /* the description and the name are of the form \\server\share */
1852 slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter->info_2->printername);
1854 init_unistr(&printer->printername, chaine);
1856 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername);
1857 init_unistr(&printer->servername, chaine);
1859 printer->cjobs = count;
1860 printer->total_jobs = 0;
1861 printer->total_bytes = 0;
1863 t=gmtime(&setup_time);
1864 ntprinter->info_2->setuptime = (uint32)setup_time; /* FIXME !! */
1866 printer->year = t->tm_year+1900;
1867 printer->month = t->tm_mon+1;
1868 printer->dayofweek = t->tm_wday;
1869 printer->day = t->tm_mday;
1870 printer->hour = t->tm_hour;
1871 printer->minute = t->tm_min;
1872 printer->second = t->tm_sec;
1873 printer->milliseconds = 0;
1875 printer->global_counter = global_counter;
1876 printer->total_pages = 0;
1877 printer->major_version = 0x0004; /* NT 4 */
1878 printer->build_version = 0x0565; /* build 1381 */
1879 printer->unknown7 = 0x1;
1880 printer->unknown8 = 0x0;
1881 printer->unknown9 = 0x0;
1882 printer->session_counter = session_counter->counter;
1883 printer->unknown11 = 0x0;
1884 printer->printer_errors = 0x0; /* number of print failure */
1885 printer->unknown13 = 0x0;
1886 printer->unknown14 = 0x1;
1887 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1888 printer->unknown16 = 0x0;
1889 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1890 printer->unknown18 = 0x0;
1891 printer->status = nt_printq_status(status.status);
1892 printer->unknown20 = 0x0;
1893 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1894 printer->unknown22 = 0x0;
1895 printer->unknown23 = 0x6; /* 6 ???*/
1896 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1897 printer->unknown25 = 0;
1898 printer->unknown26 = 0;
1899 printer->unknown27 = 0;
1900 printer->unknown28 = 0;
1901 printer->unknown29 = 0;
1904 free_a_printer(&ntprinter,2);
1908 /********************************************************************
1909 * construct_printer_info_1
1910 * fill a printer_info_1 struct
1911 ********************************************************************/
1912 static BOOL construct_printer_info_1(fstring server, uint32 flags, PRINTER_INFO_1 *printer, int snum)
1916 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1918 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1921 printer->flags=flags;
1923 if (*ntprinter->info_2->comment == '\0') {
1924 init_unistr(&printer->comment, lp_comment(snum));
1925 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1926 ntprinter->info_2->drivername, lp_comment(snum));
1929 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1930 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1931 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1934 snprintf(chaine2,sizeof(chaine)-1,"%s%s", server, ntprinter->info_2->printername);
1936 init_unistr(&printer->description, chaine);
1937 init_unistr(&printer->name, chaine2);
1939 free_a_printer(&ntprinter,2);
1944 /****************************************************************************
1945 Free a DEVMODE struct.
1946 ****************************************************************************/
1948 static void free_dev_mode(DEVICEMODE *dev)
1954 safe_free(dev->private);
1959 /****************************************************************************
1960 Create a DEVMODE struct. Returns malloced memory.
1961 ****************************************************************************/
1963 static DEVICEMODE *construct_dev_mode(int snum, char *servername)
1967 NT_PRINTER_INFO_LEVEL *printer = NULL;
1968 NT_DEVICEMODE *ntdevmode = NULL;
1969 DEVICEMODE *devmode = NULL;
1971 DEBUG(7,("construct_dev_mode\n"));
1973 DEBUGADD(8,("getting printer characteristics\n"));
1975 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
1976 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
1980 ZERO_STRUCTP(devmode);
1982 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1985 if (printer->info_2->devmode)
1986 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
1988 if (ntdevmode == NULL)
1991 DEBUGADD(8,("loading DEVICEMODE\n"));
1993 snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, printer->info_2->printername);
1994 init_unistr(&devmode->devicename, adevice);
1996 snprintf(aform, sizeof(aform), ntdevmode->formname);
1997 init_unistr(&devmode->formname, aform);
1999 devmode->specversion = ntdevmode->specversion;
2000 devmode->driverversion = ntdevmode->driverversion;
2001 devmode->size = ntdevmode->size;
2002 devmode->driverextra = ntdevmode->driverextra;
2003 devmode->fields = ntdevmode->fields;
2005 devmode->orientation = ntdevmode->orientation;
2006 devmode->papersize = ntdevmode->papersize;
2007 devmode->paperlength = ntdevmode->paperlength;
2008 devmode->paperwidth = ntdevmode->paperwidth;
2009 devmode->scale = ntdevmode->scale;
2010 devmode->copies = ntdevmode->copies;
2011 devmode->defaultsource = ntdevmode->defaultsource;
2012 devmode->printquality = ntdevmode->printquality;
2013 devmode->color = ntdevmode->color;
2014 devmode->duplex = ntdevmode->duplex;
2015 devmode->yresolution = ntdevmode->yresolution;
2016 devmode->ttoption = ntdevmode->ttoption;
2017 devmode->collate = ntdevmode->collate;
2018 devmode->icmmethod = ntdevmode->icmmethod;
2019 devmode->icmintent = ntdevmode->icmintent;
2020 devmode->mediatype = ntdevmode->mediatype;
2021 devmode->dithertype = ntdevmode->dithertype;
2023 if (ntdevmode->private != NULL) {
2024 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2028 free_nt_devicemode(&ntdevmode);
2029 free_a_printer(&printer,2);
2036 free_nt_devicemode(&ntdevmode);
2038 free_a_printer(&printer,2);
2039 free_dev_mode(devmode);
2044 /********************************************************************
2045 * construct_printer_info_2
2046 * fill a printer_info_2 struct
2047 ********************************************************************/
2049 static BOOL construct_printer_info_2(fstring servername, PRINTER_INFO_2 *printer, int snum)
2055 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2057 print_queue_struct *queue=NULL;
2058 print_status_struct status;
2059 memset(&status, 0, sizeof(status));
2061 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2064 memset(&status, 0, sizeof(status));
2065 count = print_queue_status(snum, &queue, &status);
2067 snprintf(chaine, sizeof(chaine)-1, "%s", servername);
2069 if (strlen(servername)!=0)
2074 snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter->info_2->printername);
2076 init_unistr(&printer->servername, chaine); /* servername*/
2077 init_unistr(&printer->printername, chaine2); /* printername*/
2078 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2079 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2080 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2082 if (*ntprinter->info_2->comment == '\0')
2083 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2085 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2087 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2088 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2089 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2090 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2091 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2093 printer->attributes = ntprinter->info_2->attributes;
2095 printer->priority = ntprinter->info_2->priority; /* priority */
2096 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2097 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2098 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2099 printer->status = nt_printq_status(status.status); /* status */
2100 printer->cjobs = count; /* jobs */
2101 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2103 if((printer->devmode = construct_dev_mode(snum, servername)) == NULL) {
2104 DEBUG(8, ("Returning NULL Devicemode!\n"));
2107 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2108 /* steal the printer info sec_desc structure. [badly done]. */
2109 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2110 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2111 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2112 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2115 printer->secdesc = NULL;
2118 free_a_printer(&ntprinter, 2);
2123 /********************************************************************
2124 * construct_printer_info_3
2125 * fill a printer_info_3 struct
2126 ********************************************************************/
2127 static BOOL construct_printer_info_3(fstring servername,
2128 PRINTER_INFO_3 **pp_printer, int snum)
2130 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2131 PRINTER_INFO_3 *printer = NULL;
2133 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2137 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2138 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2142 ZERO_STRUCTP(printer);
2144 printer->flags = 4; /* These are the components of the SD we are returning. */
2145 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2146 /* steal the printer info sec_desc structure. [badly done]. */
2147 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2151 * Set the flags for the components we are returning.
2154 if (printer->secdesc->owner_sid)
2155 printer->flags |= OWNER_SECURITY_INFORMATION;
2157 if (printer->secdesc->grp_sid)
2158 printer->flags |= GROUP_SECURITY_INFORMATION;
2160 if (printer->secdesc->dacl)
2161 printer->flags |= DACL_SECURITY_INFORMATION;
2163 if (printer->secdesc->sacl)
2164 printer->flags |= SACL_SECURITY_INFORMATION;
2167 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2168 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2169 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2172 free_a_printer(&ntprinter, 2);
2174 *pp_printer = printer;
2178 /********************************************************************
2179 Spoolss_enumprinters.
2180 ********************************************************************/
2181 static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2185 int n_services=lp_numservices();
2186 PRINTER_INFO_1 *printers=NULL;
2187 PRINTER_INFO_1 current_prt;
2189 DEBUG(4,("enum_all_printers_info_1\n"));
2191 for (snum=0; snum<n_services; snum++) {
2192 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2193 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2195 if (construct_printer_info_1(server, flags, ¤t_prt, snum)) {
2196 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2198 return ERROR_NOT_ENOUGH_MEMORY;
2200 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2201 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2207 /* check the required size. */
2208 for (i=0; i<*returned; i++)
2209 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2211 if (!alloc_buffer_size(buffer, *needed))
2212 return ERROR_INSUFFICIENT_BUFFER;
2214 /* fill the buffer with the structures */
2215 for (i=0; i<*returned; i++)
2216 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2219 safe_free(printers);
2221 if (*needed > offered) {
2223 return ERROR_INSUFFICIENT_BUFFER;
2226 return NT_STATUS_NO_PROBLEMO;
2229 /********************************************************************
2230 enum_all_printers_info_1_local.
2231 *********************************************************************/
2232 static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2235 DEBUG(4,("enum_all_printers_info_1_local\n"));
2237 fstrcpy(temp, "\\\\");
2238 fstrcat(temp, global_myname);
2240 if (!strcmp(name, temp)) {
2241 fstrcat(temp, "\\");
2242 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2245 return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2248 /********************************************************************
2249 enum_all_printers_info_1_name.
2250 *********************************************************************/
2251 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2254 DEBUG(4,("enum_all_printers_info_1_name\n"));
2256 fstrcpy(temp, "\\\\");
2257 fstrcat(temp, global_myname);
2259 if (!strcmp(name, temp)) {
2260 fstrcat(temp, "\\");
2261 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2264 return ERROR_INVALID_NAME;
2267 /********************************************************************
2268 enum_all_printers_info_1_remote.
2269 *********************************************************************/
2270 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2272 PRINTER_INFO_1 *printer;
2273 fstring printername;
2276 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2278 /* JFM: currently it's more a place holder than anything else.
2279 * In the spooler world there is a notion of server registration.
2280 * the print servers are registring (sp ?) on the PDC (in the same domain)
2282 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2285 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2286 return ERROR_NOT_ENOUGH_MEMORY;
2290 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2291 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2292 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2294 init_unistr(&printer->description, desc);
2295 init_unistr(&printer->name, printername);
2296 init_unistr(&printer->comment, comment);
2297 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2299 /* check the required size. */
2300 *needed += spoolss_size_printer_info_1(printer);
2302 if (!alloc_buffer_size(buffer, *needed)) {
2304 return ERROR_INSUFFICIENT_BUFFER;
2307 /* fill the buffer with the structures */
2308 new_smb_io_printer_info_1("", buffer, printer, 0);
2313 if (*needed > offered) {
2315 return ERROR_INSUFFICIENT_BUFFER;
2318 return NT_STATUS_NO_PROBLEMO;
2321 /********************************************************************
2322 enum_all_printers_info_1_network.
2323 *********************************************************************/
2324 static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2327 DEBUG(4,("enum_all_printers_info_1_network\n"));
2329 fstrcpy(temp, "\\\\");
2330 fstrcat(temp, global_myname);
2331 fstrcat(temp, "\\");
2332 return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2335 /********************************************************************
2336 * api_spoolss_enumprinters
2338 * called from api_spoolss_enumprinters (see this to understand)
2339 ********************************************************************/
2340 static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2344 int n_services=lp_numservices();
2345 PRINTER_INFO_2 *printers=NULL;
2346 PRINTER_INFO_2 current_prt;
2348 for (snum=0; snum<n_services; snum++) {
2349 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2350 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2352 if (construct_printer_info_2(servername, ¤t_prt, snum)) {
2353 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2354 return ERROR_NOT_ENOUGH_MEMORY;
2355 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2356 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2362 /* check the required size. */
2363 for (i=0; i<*returned; i++)
2364 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2366 if (!alloc_buffer_size(buffer, *needed)) {
2367 for (i=0; i<*returned; i++) {
2368 free_devmode(printers[i].devmode);
2369 free_sec_desc(&printers[i].secdesc);
2371 safe_free(printers);
2372 return ERROR_INSUFFICIENT_BUFFER;
2375 /* fill the buffer with the structures */
2376 for (i=0; i<*returned; i++)
2377 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2380 for (i=0; i<*returned; i++) {
2381 free_devmode(printers[i].devmode);
2382 free_sec_desc(&printers[i].secdesc);
2384 safe_free(printers);
2386 if (*needed > offered) {
2388 return ERROR_INSUFFICIENT_BUFFER;
2391 return NT_STATUS_NO_PROBLEMO;
2394 /********************************************************************
2395 * handle enumeration of printers at level 1
2396 ********************************************************************/
2397 static uint32 enumprinters_level1( uint32 flags, fstring name,
2398 NEW_BUFFER *buffer, uint32 offered,
2399 uint32 *needed, uint32 *returned)
2401 /* Not all the flags are equals */
2403 if (flags & PRINTER_ENUM_LOCAL)
2404 return enum_all_printers_info_1_local(name, buffer, offered, needed, returned);
2406 if (flags & PRINTER_ENUM_NAME)
2407 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2409 if (flags & PRINTER_ENUM_REMOTE)
2410 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2412 if (flags & PRINTER_ENUM_NETWORK)
2413 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
2415 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2418 /********************************************************************
2419 * handle enumeration of printers at level 2
2420 ********************************************************************/
2421 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2422 NEW_BUFFER *buffer, uint32 offered,
2423 uint32 *needed, uint32 *returned)
2427 fstrcpy(temp, "\\\\");
2428 fstrcat(temp, global_myname);
2430 if (flags & PRINTER_ENUM_LOCAL) {
2431 if (!strcmp(servername, temp))
2432 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2434 return enum_all_printers_info_2("", buffer, offered, needed, returned);
2437 if (flags & PRINTER_ENUM_NAME) {
2438 if (!strcmp(servername, temp))
2439 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2441 return ERROR_INVALID_NAME;
2444 if (flags & PRINTER_ENUM_REMOTE)
2445 return ERROR_INVALID_LEVEL;
2447 return NT_STATUS_NO_PROBLEMO;
2450 /********************************************************************
2451 * handle enumeration of printers at level 5
2452 ********************************************************************/
2453 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2454 NEW_BUFFER *buffer, uint32 offered,
2455 uint32 *needed, uint32 *returned)
2457 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2458 return NT_STATUS_NO_PROBLEMO;
2461 /********************************************************************
2462 * api_spoolss_enumprinters
2464 * called from api_spoolss_enumprinters (see this to understand)
2465 ********************************************************************/
2466 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2467 NEW_BUFFER *buffer, uint32 offered,
2468 uint32 *needed, uint32 *returned)
2472 DEBUG(4,("_spoolss_enumprinters\n"));
2479 * flags==PRINTER_ENUM_NAME
2480 * if name=="" then enumerates all printers
2481 * if name!="" then enumerate the printer
2482 * flags==PRINTER_ENUM_REMOTE
2483 * name is NULL, enumerate printers
2484 * Level 2: name!="" enumerates printers, name can't be NULL
2485 * Level 3: doesn't exist
2486 * Level 4: does a local registry lookup
2487 * Level 5: same as Level 2
2490 unistr2_to_ascii(name, servername, sizeof(name)-1);
2495 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2498 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2501 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2506 return ERROR_INVALID_LEVEL;
2511 /****************************************************************************
2512 ****************************************************************************/
2513 static uint32 getprinter_level_0(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2515 PRINTER_INFO_0 *printer=NULL;
2517 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2518 return ERROR_NOT_ENOUGH_MEMORY;
2520 construct_printer_info_0(printer, snum, servername);
2522 /* check the required size. */
2523 *needed += spoolss_size_printer_info_0(printer);
2525 if (!alloc_buffer_size(buffer, *needed)) {
2527 return ERROR_INSUFFICIENT_BUFFER;
2530 /* fill the buffer with the structures */
2531 new_smb_io_printer_info_0("", buffer, printer, 0);
2536 if (*needed > offered) {
2537 return ERROR_INSUFFICIENT_BUFFER;
2540 return NT_STATUS_NO_PROBLEMO;
2543 /****************************************************************************
2544 ****************************************************************************/
2545 static uint32 getprinter_level_1(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2547 PRINTER_INFO_1 *printer=NULL;
2549 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2550 return ERROR_NOT_ENOUGH_MEMORY;
2552 construct_printer_info_1(servername, PRINTER_ENUM_ICON8, printer, snum);
2554 /* check the required size. */
2555 *needed += spoolss_size_printer_info_1(printer);
2557 if (!alloc_buffer_size(buffer, *needed)) {
2559 return ERROR_INSUFFICIENT_BUFFER;
2562 /* fill the buffer with the structures */
2563 new_smb_io_printer_info_1("", buffer, printer, 0);
2568 if (*needed > offered) {
2569 return ERROR_INSUFFICIENT_BUFFER;
2572 return NT_STATUS_NO_PROBLEMO;
2575 /****************************************************************************
2576 ****************************************************************************/
2577 static uint32 getprinter_level_2(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2579 PRINTER_INFO_2 *printer=NULL;
2582 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2583 return ERROR_NOT_ENOUGH_MEMORY;
2585 fstrcpy(temp, "\\\\");
2586 fstrcat(temp, servername);
2587 construct_printer_info_2(temp, printer, snum);
2589 /* check the required size. */
2590 *needed += spoolss_size_printer_info_2(printer);
2592 if (!alloc_buffer_size(buffer, *needed)) {
2593 free_printer_info_2(printer);
2594 return ERROR_INSUFFICIENT_BUFFER;
2597 /* fill the buffer with the structures */
2598 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2599 free_printer_info_2(printer);
2600 return ERROR_NOT_ENOUGH_MEMORY;
2604 free_printer_info_2(printer);
2606 if (*needed > offered) {
2607 return ERROR_INSUFFICIENT_BUFFER;
2610 return NT_STATUS_NO_PROBLEMO;
2613 /****************************************************************************
2614 ****************************************************************************/
2615 static uint32 getprinter_level_3(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2617 PRINTER_INFO_3 *printer=NULL;
2620 fstrcpy(temp, "\\\\");
2621 fstrcat(temp, servername);
2622 if (!construct_printer_info_3(temp, &printer, snum))
2623 return ERROR_NOT_ENOUGH_MEMORY;
2625 /* check the required size. */
2626 *needed += spoolss_size_printer_info_3(printer);
2628 if (!alloc_buffer_size(buffer, *needed)) {
2629 free_printer_info_3(printer);
2630 return ERROR_INSUFFICIENT_BUFFER;
2633 /* fill the buffer with the structures */
2634 new_smb_io_printer_info_3("", buffer, printer, 0);
2637 free_printer_info_3(printer);
2639 if (*needed > offered) {
2640 return ERROR_INSUFFICIENT_BUFFER;
2643 return NT_STATUS_NO_PROBLEMO;
2646 /****************************************************************************
2647 ****************************************************************************/
2648 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2649 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2656 pstrcpy(servername, global_myname);
2658 if (!get_printer_snum(handle, &snum))
2659 return ERROR_INVALID_HANDLE;
2663 return getprinter_level_0(servername, snum, buffer, offered, needed);
2665 return getprinter_level_1(servername,snum, buffer, offered, needed);
2667 return getprinter_level_2(servername,snum, buffer, offered, needed);
2669 return getprinter_level_3(servername,snum, buffer, offered, needed);
2671 return ERROR_INVALID_LEVEL;
2676 /********************************************************************
2677 * fill a DRIVER_INFO_1 struct
2678 ********************************************************************/
2679 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2681 init_unistr( &info->name, driver.info_3->name);
2684 /********************************************************************
2685 * construct_printer_driver_info_1
2686 ********************************************************************/
2687 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2689 NT_PRINTER_INFO_LEVEL *printer = NULL;
2690 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2692 ZERO_STRUCT(driver);
2694 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2695 return ERROR_INVALID_PRINTER_NAME;
2697 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2698 return ERROR_UNKNOWN_PRINTER_DRIVER;
2700 fill_printer_driver_info_1(info, driver, servername, architecture);
2702 free_a_printer(&printer,2);
2704 return NT_STATUS_NO_PROBLEMO;
2707 /********************************************************************
2708 * construct_printer_driver_info_2
2709 * fill a printer_info_2 struct
2710 ********************************************************************/
2711 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2713 pstring temp_driverpath;
2714 pstring temp_datafile;
2715 pstring temp_configfile;
2717 info->version=driver.info_3->cversion;
2719 init_unistr( &info->name, driver.info_3->name );
2720 init_unistr( &info->architecture, driver.info_3->environment );
2722 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2723 init_unistr( &info->driverpath, temp_driverpath );
2725 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2726 init_unistr( &info->datafile, temp_datafile );
2728 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2729 init_unistr( &info->configfile, temp_configfile );
2732 /********************************************************************
2733 * construct_printer_driver_info_2
2734 * fill a printer_info_2 struct
2735 ********************************************************************/
2736 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2738 NT_PRINTER_INFO_LEVEL *printer = NULL;
2739 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2741 ZERO_STRUCT(printer);
2742 ZERO_STRUCT(driver);
2744 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2745 return ERROR_INVALID_PRINTER_NAME;
2747 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2748 return ERROR_UNKNOWN_PRINTER_DRIVER;
2750 fill_printer_driver_info_2(info, driver, servername);
2752 free_a_printer(&printer,2);
2754 return NT_STATUS_NO_PROBLEMO;
2757 /********************************************************************
2758 * copy a strings array and convert to UNICODE
2760 * convert an array of ascii string to a UNICODE string
2761 ********************************************************************/
2762 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2769 DEBUG(6,("init_unistr_array\n"));
2773 if (char_array == NULL)
2777 if (!v) v = ""; /* hack to handle null lists */
2779 if (strlen(v) == 0) break;
2780 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2781 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2782 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2783 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2786 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2791 (*uni_array)[j]=0x0000;
2794 DEBUGADD(6,("last one:done\n"));
2797 /********************************************************************
2798 * construct_printer_info_3
2799 * fill a printer_info_3 struct
2800 ********************************************************************/
2801 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2803 pstring temp_driverpath;
2804 pstring temp_datafile;
2805 pstring temp_configfile;
2806 pstring temp_helpfile;
2810 info->version=driver.info_3->cversion;
2812 init_unistr( &info->name, driver.info_3->name );
2813 init_unistr( &info->architecture, driver.info_3->environment );
2815 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2816 init_unistr( &info->driverpath, temp_driverpath );
2818 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2819 init_unistr( &info->datafile, temp_datafile );
2821 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2822 init_unistr( &info->configfile, temp_configfile );
2824 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2825 init_unistr( &info->helpfile, temp_helpfile );
2827 init_unistr( &info->monitorname, driver.info_3->monitorname );
2828 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2830 info->dependentfiles=NULL;
2831 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2834 /********************************************************************
2835 * construct_printer_info_3
2836 * fill a printer_info_3 struct
2837 ********************************************************************/
2838 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2840 NT_PRINTER_INFO_LEVEL *printer = NULL;
2841 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2843 ZERO_STRUCT(driver);
2845 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2846 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2848 return ERROR_INVALID_PRINTER_NAME;
2850 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2851 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2853 free_a_printer(&printer,2);
2854 return ERROR_UNKNOWN_PRINTER_DRIVER;
2857 fill_printer_driver_info_3(info, driver, servername);
2859 free_a_printer(&printer,2);
2861 return NT_STATUS_NO_PROBLEMO;
2864 /********************************************************************
2865 * construct_printer_info_6
2866 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2867 ********************************************************************/
2869 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2871 pstring temp_driverpath;
2872 pstring temp_datafile;
2873 pstring temp_configfile;
2874 pstring temp_helpfile;
2878 memset(&nullstr, '\0', sizeof(fstring));
2880 info->version=driver.info_3->cversion;
2882 init_unistr( &info->name, driver.info_3->name );
2883 init_unistr( &info->architecture, driver.info_3->environment );
2885 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2886 init_unistr( &info->driverpath, temp_driverpath );
2888 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2889 init_unistr( &info->datafile, temp_datafile );
2891 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2892 init_unistr( &info->configfile, temp_configfile );
2894 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2895 init_unistr( &info->helpfile, temp_helpfile );
2897 init_unistr( &info->monitorname, driver.info_3->monitorname );
2898 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2900 info->dependentfiles=NULL;
2901 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2903 info->previousdrivernames=NULL;
2904 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2906 info->driver_date.low=0;
2907 info->driver_date.high=0;
2910 info->driver_version_low=0;
2911 info->driver_version_high=0;
2913 init_unistr( &info->mfgname, "");
2914 init_unistr( &info->oem_url, "");
2915 init_unistr( &info->hardware_id, "");
2916 init_unistr( &info->provider, "");
2919 /********************************************************************
2920 * construct_printer_info_6
2921 * fill a printer_info_6 struct
2922 ********************************************************************/
2923 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2925 NT_PRINTER_INFO_LEVEL *printer = NULL;
2926 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2928 ZERO_STRUCT(driver);
2930 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2931 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2933 return ERROR_INVALID_PRINTER_NAME;
2935 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2936 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2938 free_a_printer(&printer,2);
2939 return ERROR_UNKNOWN_PRINTER_DRIVER;
2942 fill_printer_driver_info_6(info, driver, servername);
2944 free_a_printer(&printer,2);
2946 return NT_STATUS_NO_PROBLEMO;
2949 /****************************************************************************
2950 ****************************************************************************/
2952 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2954 safe_free(info->dependentfiles);
2957 /****************************************************************************
2958 ****************************************************************************/
2960 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2962 safe_free(info->dependentfiles);
2966 /****************************************************************************
2967 ****************************************************************************/
2968 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2970 DRIVER_INFO_1 *info=NULL;
2973 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2974 return ERROR_NOT_ENOUGH_MEMORY;
2976 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2977 if (status != NT_STATUS_NO_PROBLEMO) {
2982 /* check the required size. */
2983 *needed += spoolss_size_printer_driver_info_1(info);
2985 if (!alloc_buffer_size(buffer, *needed)) {
2987 return ERROR_INSUFFICIENT_BUFFER;
2990 /* fill the buffer with the structures */
2991 new_smb_io_printer_driver_info_1("", buffer, info, 0);
2996 if (*needed > offered)
2997 return ERROR_INSUFFICIENT_BUFFER;
2999 return NT_STATUS_NO_PROBLEMO;
3002 /****************************************************************************
3003 ****************************************************************************/
3004 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3006 DRIVER_INFO_2 *info=NULL;
3009 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3010 return ERROR_NOT_ENOUGH_MEMORY;
3012 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3013 if (status != NT_STATUS_NO_PROBLEMO) {
3018 /* check the required size. */
3019 *needed += spoolss_size_printer_driver_info_2(info);
3021 if (!alloc_buffer_size(buffer, *needed)) {
3023 return ERROR_INSUFFICIENT_BUFFER;
3026 /* fill the buffer with the structures */
3027 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3032 if (*needed > offered)
3033 return ERROR_INSUFFICIENT_BUFFER;
3035 return NT_STATUS_NO_PROBLEMO;
3038 /****************************************************************************
3039 ****************************************************************************/
3040 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3047 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3048 if (status != NT_STATUS_NO_PROBLEMO) {
3052 /* check the required size. */
3053 *needed += spoolss_size_printer_driver_info_3(&info);
3055 if (!alloc_buffer_size(buffer, *needed)) {
3056 free_printer_driver_info_3(&info);
3057 return ERROR_INSUFFICIENT_BUFFER;
3060 /* fill the buffer with the structures */
3061 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3063 free_printer_driver_info_3(&info);
3065 if (*needed > offered)
3066 return ERROR_INSUFFICIENT_BUFFER;
3068 return NT_STATUS_NO_PROBLEMO;
3071 /****************************************************************************
3072 ****************************************************************************/
3073 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3080 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3081 if (status != NT_STATUS_NO_PROBLEMO) {
3085 /* check the required size. */
3086 *needed += spoolss_size_printer_driver_info_6(&info);
3088 if (!alloc_buffer_size(buffer, *needed)) {
3089 free_printer_driver_info_3(&info);
3090 return ERROR_INSUFFICIENT_BUFFER;
3093 /* fill the buffer with the structures */
3094 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3096 free_printer_driver_info_6(&info);
3098 if (*needed > offered)
3099 return ERROR_INSUFFICIENT_BUFFER;
3101 return NT_STATUS_NO_PROBLEMO;
3104 /****************************************************************************
3105 ****************************************************************************/
3106 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3107 uint32 clientmajorversion, uint32 clientminorversion,
3108 NEW_BUFFER *buffer, uint32 offered,
3109 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3112 fstring architecture;
3115 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3118 *servermajorversion=0;
3119 *serverminorversion=0;
3121 pstrcpy(servername, global_myname);
3122 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3124 if (!get_printer_snum(handle, &snum))
3125 return ERROR_INVALID_HANDLE;
3129 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3132 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3135 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3138 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3141 return ERROR_INVALID_LEVEL;
3146 /****************************************************************************
3147 ****************************************************************************/
3148 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3150 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3152 if (OPEN_HANDLE(Printer)) {
3153 Printer->page_started=True;
3157 DEBUG(3,("Error in startpageprinter printer handle\n"));
3158 return ERROR_INVALID_HANDLE;
3161 /****************************************************************************
3162 ****************************************************************************/
3163 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3165 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3167 if (!OPEN_HANDLE(Printer)) {
3168 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3169 return ERROR_INVALID_HANDLE;
3172 Printer->page_started=False;
3174 return NT_STATUS_NO_PROBLEMO;
3177 /****************************************************************************
3178 Return a user struct for a pipe user.
3179 ****************************************************************************/
3181 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3183 if (p->ntlmssp_auth_validated) {
3184 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3186 extern struct current_user current_user;
3187 memcpy(user, ¤t_user, sizeof(struct current_user));
3193 /********************************************************************
3194 * api_spoolss_getprinter
3195 * called from the spoolss dispatcher
3197 ********************************************************************/
3198 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3199 pipes_struct *p, DOC_INFO *docinfo,
3202 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3206 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3207 struct current_user user;
3209 if (!OPEN_HANDLE(Printer)) {
3210 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3211 return ERROR_INVALID_HANDLE;
3214 get_current_user(&user, p);
3217 * a nice thing with NT is it doesn't listen to what you tell it.
3218 * when asked to send _only_ RAW datas, it tries to send datas
3221 * So I add checks like in NT Server ...
3223 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3224 * there's a bug in NT client-side code, so we'll fix it in the
3225 * server-side code. *nnnnnggggh!*
3228 if (info_1->p_datatype != 0) {
3229 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3230 if (strcmp(datatype, "RAW") != 0) {
3232 return ERROR_INVALID_DATATYPE;
3236 /* get the share number of the printer */
3237 if (!get_printer_snum(handle, &snum)) {
3238 return ERROR_INVALID_HANDLE;
3241 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3243 Printer->jobid = print_job_start(&user, snum, jobname);
3245 /* An error occured in print_job_start() so return an appropriate
3248 if (Printer->jobid == -1) {
3249 return map_nt_error_from_unix(errno);
3252 Printer->document_started=True;
3253 (*jobid) = Printer->jobid;
3255 srv_spoolss_sendnotify(handle);
3259 /********************************************************************
3260 * api_spoolss_getprinter
3261 * called from the spoolss dispatcher
3263 ********************************************************************/
3264 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3266 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3268 if (!OPEN_HANDLE(Printer)) {
3269 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3270 return ERROR_INVALID_HANDLE;
3273 Printer->document_started=False;
3274 print_job_end(Printer->jobid);
3275 /* error codes unhandled so far ... */
3277 srv_spoolss_sendnotify(handle);
3282 /****************************************************************************
3283 ****************************************************************************/
3284 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3287 uint32 *buffer_written)
3289 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3291 if (!OPEN_HANDLE(Printer)) {
3292 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3293 return ERROR_INVALID_HANDLE;
3296 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3302 /********************************************************************
3303 * api_spoolss_getprinter
3304 * called from the spoolss dispatcher
3306 ********************************************************************/
3307 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3310 struct current_user user;
3313 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3315 get_current_user(&user, p);
3317 if (!OPEN_HANDLE(Printer)) {
3318 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3319 return ERROR_INVALID_HANDLE;
3322 if (!get_printer_snum(handle, &snum) )
3323 return ERROR_INVALID_HANDLE;
3326 case PRINTER_CONTROL_PAUSE:
3327 if (print_queue_pause(&user, snum, &errcode)) {
3328 srv_spoolss_sendnotify(handle);
3332 case PRINTER_CONTROL_RESUME:
3333 case PRINTER_CONTROL_UNPAUSE:
3334 if (print_queue_resume(&user, snum, &errcode)) {
3335 srv_spoolss_sendnotify(handle);
3339 case PRINTER_CONTROL_PURGE:
3340 if (print_queue_purge(&user, snum, &errcode)) {
3341 srv_spoolss_sendnotify(handle);
3348 return (uint32)errcode;
3350 return ERROR_INVALID_FUNCTION;
3353 /********************************************************************
3354 * api_spoolss_abortprinter
3355 ********************************************************************/
3357 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3359 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3362 /********************************************************************
3363 * called by spoolss_api_setprinter
3364 * when updating a printer description
3365 ********************************************************************/
3366 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3367 const SPOOL_PRINTER_INFO_LEVEL *info,
3368 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3370 struct current_user user;
3374 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3376 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3377 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3378 return ERROR_INVALID_HANDLE;
3381 /* Work out which user is performing the operation */
3382 get_current_user(&user, p);
3384 /* Check the user has permissions to change the security
3385 descriptor. By experimentation with two NT machines, the user
3386 requires Full Access to the printer to change security
3388 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3389 result = ERROR_ACCESS_DENIED;
3393 result = nt_printing_setsec(Printer->dev.handlename, secdesc_ctr);
3399 /********************************************************************
3400 Do Samba sanity checks on a printer info struct.
3401 ********************************************************************/
3403 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3406 * Ensure that this printer is shared under the correct name
3407 * as this is what Samba insists upon.
3410 if (!(info->attributes & PRINTER_ATTRIBUTE_SHARED)) {
3411 DEBUG(10,("check_printer_ok: SHARED check failed (%x).\n", (unsigned int)info->attributes ));
3415 if (!(info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY)) {
3416 /* NT forgets to set the raw attribute but sends the correct type. */
3417 if (strequal(info->datatype, "RAW"))
3418 info->attributes |= PRINTER_ATTRIBUTE_RAW_ONLY;
3420 DEBUG(10,("check_printer_ok: RAW check failed (%x).\n", (unsigned int)info->attributes ));
3425 if (!strequal(info->sharename, lp_servicename(snum))) {
3426 DEBUG(10,("check_printer_ok: NAME check failed (%s) (%s).\n", info->sharename, lp_servicename(snum)));
3433 /****************************************************************************
3434 ****************************************************************************/
3435 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3437 pid_t local_pid = sys_getpid();
3438 char *cmd = lp_addprinter_cmd();
3443 pstring driverlocation;
3447 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3448 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3452 /* build driver path... only 9X architecture is needed for legacy reasons */
3453 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3455 /* change \ to \\ for the shell */
3456 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3458 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3459 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3460 cmd, printer->info_2->printername, printer->info_2->sharename,
3461 printer->info_2->portname, printer->info_2->drivername,
3462 printer->info_2->location, driverlocation);
3465 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3466 ret = smbrun(command, tmp_file, False);
3467 DEBUGADD(10,("returned [%d]\n", ret));
3475 qlines = file_lines_load(tmp_file, &numlines);
3476 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3477 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3481 /* Set the portname to what the script says the portname should be. */
3482 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3483 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3485 /* Send SIGHUP to process group... is there a better way? */
3490 file_lines_free(qlines);
3494 /********************************************************************
3495 * called by spoolss_api_setprinter
3496 * when updating a printer description
3497 ********************************************************************/
3499 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3500 const SPOOL_PRINTER_INFO_LEVEL *info,
3501 DEVICEMODE *devmode)
3504 NT_PRINTER_INFO_LEVEL *printer = NULL;
3505 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3508 DEBUG(8,("update_printer\n"));
3510 result = NT_STATUS_NO_PROBLEMO;
3512 /* Check calling user has permission to update printer description */
3515 DEBUG(0,("Send a mail to samba@samba.org\n"));
3516 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3517 result = ERROR_INVALID_LEVEL;
3521 if (!OPEN_HANDLE(Printer)) {
3522 result = ERROR_INVALID_HANDLE;
3526 if (!get_printer_snum(handle, &snum)) {
3527 result = ERROR_INVALID_HANDLE;
3531 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3532 DEBUG(3, ("printer property change denied by security "
3534 result = ERROR_ACCESS_DENIED;
3538 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0) {
3539 result = ERROR_INVALID_HANDLE;
3543 DEBUGADD(8,("Converting info_2 struct\n"));
3546 * convert_printer_info converts the incoming
3547 * info from the client and overwrites the info
3548 * just read from the tdb in the pointer 'printer'.
3551 convert_printer_info(info, printer, level);
3553 if (info->info_2->devmode_ptr != 0) {
3554 /* we have a valid devmode
3555 convert it and link it*/
3558 * Ensure printer->info_2->devmode is a valid pointer
3559 * as we will be overwriting it in convert_devicemode().
3562 if (printer->info_2->devmode == NULL)
3563 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3565 DEBUGADD(8,("Converting the devicemode struct\n"));
3566 convert_devicemode(devmode, printer->info_2->devmode);
3569 if (printer->info_2->devmode != NULL)
3570 free_nt_devicemode(&printer->info_2->devmode);
3571 printer->info_2->devmode=NULL;
3575 * Do sanity check on the requested changes for Samba.
3578 if (!check_printer_ok(printer->info_2, snum)) {
3579 result = ERROR_INVALID_PARAMETER;
3583 if (*lp_addprinter_cmd() )
3584 if ( !add_printer_hook(printer) ) {
3585 result = ERROR_ACCESS_DENIED;
3589 if (add_a_printer(*printer, 2)!=0) {
3590 /* I don't really know what to return here !!! */
3591 result = ERROR_ACCESS_DENIED;
3596 free_a_printer(&printer, 2);
3598 srv_spoolss_sendnotify(handle);
3603 /****************************************************************************
3604 ****************************************************************************/
3605 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3606 const SPOOL_PRINTER_INFO_LEVEL *info,
3607 DEVMODE_CTR devmode_ctr,
3608 SEC_DESC_BUF *secdesc_ctr,
3609 uint32 command, pipes_struct *p)
3611 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3613 if (!OPEN_HANDLE(Printer)) {
3614 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3615 return ERROR_INVALID_HANDLE;
3618 /* check the level */
3621 return control_printer(handle, command, p);
3624 return update_printer(handle, level, info, devmode_ctr.devmode);
3627 return update_printer_sec(handle, level, info, p,
3631 return ERROR_INVALID_LEVEL;
3636 /****************************************************************************
3637 ****************************************************************************/
3638 uint32 _spoolss_fcpn(POLICY_HND *handle)
3640 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3642 if (!OPEN_HANDLE(Printer)) {
3643 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3644 return ERROR_INVALID_HANDLE;
3647 if (Printer->notify.client_connected==True)
3648 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3649 return ERROR_INVALID_HANDLE;
3651 Printer->notify.flags=0;
3652 Printer->notify.options=0;
3653 Printer->notify.localmachine[0]='\0';
3654 Printer->notify.printerlocal=0;
3655 if (Printer->notify.option)
3656 safe_free(Printer->notify.option->ctr.type);
3657 safe_free(Printer->notify.option);
3658 Printer->notify.option=NULL;
3659 Printer->notify.client_connected=False;
3661 return NT_STATUS_NO_PROBLEMO;
3664 /****************************************************************************
3665 ****************************************************************************/
3666 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3667 NEW_BUFFER *buffer, uint32 offered,
3671 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3672 returns for AddJob. AddJob
3673 must fail on non-local
3677 /****************************************************************************
3678 ****************************************************************************/
3679 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3680 int position, int snum)
3685 time_t unixdate = time(NULL);
3687 t=gmtime(&unixdate);
3688 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3690 job_info->jobid=queue->job;
3691 init_unistr(&job_info->printername, lp_servicename(snum));
3692 init_unistr(&job_info->machinename, temp_name);
3693 init_unistr(&job_info->username, queue->user);
3694 init_unistr(&job_info->document, queue->file);
3695 init_unistr(&job_info->datatype, "RAW");
3696 init_unistr(&job_info->text_status, "");
3697 job_info->status=nt_printj_status(queue->status);
3698 job_info->priority=queue->priority;
3699 job_info->position=position;
3700 job_info->totalpages=0;
3701 job_info->pagesprinted=0;
3703 make_systemtime(&job_info->submitted, t);
3706 /****************************************************************************
3707 ****************************************************************************/
3708 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3709 int position, int snum)
3712 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3716 time_t unixdate = time(NULL);
3718 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3721 t=gmtime(&unixdate);
3722 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3724 job_info->jobid=queue->job;
3726 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3728 init_unistr(&job_info->printername, chaine);
3730 init_unistr(&job_info->machinename, temp_name);
3731 init_unistr(&job_info->username, queue->user);
3732 init_unistr(&job_info->document, queue->file);
3733 init_unistr(&job_info->notifyname, queue->user);
3734 init_unistr(&job_info->datatype, "RAW");
3735 init_unistr(&job_info->printprocessor, "winprint");
3736 init_unistr(&job_info->parameters, "");
3737 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3738 init_unistr(&job_info->text_status, "");
3740 /* and here the security descriptor */
3742 job_info->status=nt_printj_status(queue->status);
3743 job_info->priority=queue->priority;
3744 job_info->position=position;
3745 job_info->starttime=0;
3746 job_info->untiltime=0;
3747 job_info->totalpages=0;
3748 job_info->size=queue->size;
3749 make_systemtime(&(job_info->submitted), t);
3750 job_info->timeelapsed=0;
3751 job_info->pagesprinted=0;
3753 if((job_info->devmode = construct_dev_mode(snum, global_myname)) == NULL) {
3754 free_a_printer(&ntprinter, 2);
3758 free_a_printer(&ntprinter, 2);
3762 /****************************************************************************
3763 Enumjobs at level 1.
3764 ****************************************************************************/
3765 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3766 NEW_BUFFER *buffer, uint32 offered,
3767 uint32 *needed, uint32 *returned)
3772 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3776 return ERROR_NOT_ENOUGH_MEMORY;
3779 for (i=0; i<*returned; i++)
3780 fill_job_info_1(&info[i], &queue[i], i, snum);
3784 /* check the required size. */
3785 for (i=0; i<*returned; i++)
3786 (*needed) += spoolss_size_job_info_1(&info[i]);
3788 if (!alloc_buffer_size(buffer, *needed)) {
3790 return ERROR_INSUFFICIENT_BUFFER;
3793 /* fill the buffer with the structures */
3794 for (i=0; i<*returned; i++)
3795 new_smb_io_job_info_1("", buffer, &info[i], 0);
3800 if (*needed > offered) {
3802 return ERROR_INSUFFICIENT_BUFFER;
3805 return NT_STATUS_NO_PROBLEMO;
3808 /****************************************************************************
3809 Enumjobs at level 2.
3810 ****************************************************************************/
3811 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
3812 NEW_BUFFER *buffer, uint32 offered,
3813 uint32 *needed, uint32 *returned)
3818 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
3822 return ERROR_NOT_ENOUGH_MEMORY;
3825 for (i=0; i<*returned; i++)
3826 fill_job_info_2(&(info[i]), &queue[i], i, snum);
3830 /* check the required size. */
3831 for (i=0; i<*returned; i++)
3832 (*needed) += spoolss_size_job_info_2(&info[i]);
3834 if (!alloc_buffer_size(buffer, *needed)) {
3836 return ERROR_INSUFFICIENT_BUFFER;
3839 /* fill the buffer with the structures */
3840 for (i=0; i<*returned; i++)
3841 new_smb_io_job_info_2("", buffer, &info[i], 0);
3846 if (*needed > offered) {
3848 return ERROR_INSUFFICIENT_BUFFER;
3851 return NT_STATUS_NO_PROBLEMO;
3854 /****************************************************************************
3856 ****************************************************************************/
3857 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
3858 NEW_BUFFER *buffer, uint32 offered,
3859 uint32 *needed, uint32 *returned)
3862 print_queue_struct *queue=NULL;
3863 print_status_struct prt_status;
3865 DEBUG(4,("_spoolss_enumjobs\n"));
3867 ZERO_STRUCT(prt_status);
3872 if (!get_printer_snum(handle, &snum))
3873 return ERROR_INVALID_HANDLE;
3875 *returned = print_queue_status(snum, &queue, &prt_status);
3876 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
3878 if (*returned == 0) {
3880 return NT_STATUS_NO_PROBLEMO;
3885 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
3888 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
3893 return ERROR_INVALID_LEVEL;
3899 /****************************************************************************
3900 ****************************************************************************/
3901 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
3906 /****************************************************************************
3907 ****************************************************************************/
3908 uint32 _spoolss_setjob( POLICY_HND *handle,
3916 struct current_user user;
3918 print_status_struct prt_status;
3920 memset(&prt_status, 0, sizeof(prt_status));
3922 if (!get_printer_snum(handle, &snum)) {
3923 return ERROR_INVALID_HANDLE;
3926 if (!print_job_exists(jobid)) {
3927 return ERROR_INVALID_PRINTER_NAME;
3930 get_current_user(&user, p);
3933 case JOB_CONTROL_CANCEL:
3934 case JOB_CONTROL_DELETE:
3935 if (print_job_delete(&user, jobid)) {
3936 srv_spoolss_sendnotify(handle);
3940 case JOB_CONTROL_PAUSE:
3941 if (print_job_pause(&user, jobid)) {
3942 srv_spoolss_sendnotify(handle);
3946 case JOB_CONTROL_RESUME:
3947 if (print_job_resume(&user, jobid)) {
3948 srv_spoolss_sendnotify(handle);
3953 return ERROR_INVALID_LEVEL;
3956 return ERROR_INVALID_HANDLE;
3959 /****************************************************************************
3960 Enumerates all printer drivers at level 1.
3961 ****************************************************************************/
3962 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3967 fstring *list = NULL;
3969 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3970 DRIVER_INFO_1 *driver_info_1=NULL;
3974 #define MAX_VERSION 4
3976 for (version=0; version<MAX_VERSION; version++) {
3978 ndrivers=get_ntdrivers(&list, architecture, version);
3979 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
3982 return ERROR_NOT_ENOUGH_MEMORY;
3985 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
3987 return ERROR_NOT_ENOUGH_MEMORY;
3991 for (i=0; i<ndrivers; i++) {
3993 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3994 ZERO_STRUCT(driver);
3995 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
3999 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4000 free_a_printer_driver(driver, 3);
4003 *returned+=ndrivers;
4007 /* check the required size. */
4008 for (i=0; i<*returned; i++) {
4009 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4010 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4013 if (!alloc_buffer_size(buffer, *needed)) {
4014 safe_free(driver_info_1);
4015 return ERROR_INSUFFICIENT_BUFFER;
4018 /* fill the buffer with the form structures */
4019 for (i=0; i<*returned; i++) {
4020 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4021 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4024 safe_free(driver_info_1);
4026 if (*needed > offered) {
4028 return ERROR_INSUFFICIENT_BUFFER;
4031 return NT_STATUS_NO_PROBLEMO;
4034 /****************************************************************************
4035 Enumerates all printer drivers at level 2.
4036 ****************************************************************************/
4037 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4042 fstring *list = NULL;
4044 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4045 DRIVER_INFO_2 *driver_info_2=NULL;
4049 #define MAX_VERSION 4
4051 for (version=0; version<MAX_VERSION; version++) {
4053 ndrivers=get_ntdrivers(&list, architecture, version);
4054 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4057 return ERROR_NOT_ENOUGH_MEMORY;
4060 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4062 return ERROR_NOT_ENOUGH_MEMORY;
4066 for (i=0; i<ndrivers; i++) {
4069 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4070 ZERO_STRUCT(driver);
4071 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4075 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4076 free_a_printer_driver(driver, 3);
4079 *returned+=ndrivers;
4083 /* check the required size. */
4084 for (i=0; i<*returned; i++) {
4085 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4086 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4089 if (!alloc_buffer_size(buffer, *needed)) {
4090 safe_free(driver_info_2);
4091 return ERROR_INSUFFICIENT_BUFFER;
4094 /* fill the buffer with the form structures */
4095 for (i=0; i<*returned; i++) {
4096 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4097 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4100 safe_free(driver_info_2);
4102 if (*needed > offered) {
4104 return ERROR_INSUFFICIENT_BUFFER;
4107 return NT_STATUS_NO_PROBLEMO;
4110 /****************************************************************************
4111 Enumerates all printer drivers at level 3.
4112 ****************************************************************************/
4113 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4118 fstring *list = NULL;
4120 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4121 DRIVER_INFO_3 *driver_info_3=NULL;
4125 #define MAX_VERSION 4
4127 for (version=0; version<MAX_VERSION; version++) {
4129 ndrivers=get_ntdrivers(&list, architecture, version);
4130 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4133 return ERROR_NOT_ENOUGH_MEMORY;
4136 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4138 return ERROR_NOT_ENOUGH_MEMORY;
4142 for (i=0; i<ndrivers; i++) {
4145 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4146 ZERO_STRUCT(driver);
4147 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4151 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4152 free_a_printer_driver(driver, 3);
4155 *returned+=ndrivers;
4159 /* check the required size. */
4160 for (i=0; i<*returned; i++) {
4161 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4162 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4165 if (!alloc_buffer_size(buffer, *needed)) {
4166 safe_free(driver_info_3);
4167 return ERROR_INSUFFICIENT_BUFFER;
4170 /* fill the buffer with the driver structures */
4171 for (i=0; i<*returned; i++) {
4172 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4173 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4176 for (i=0; i<*returned; i++)
4177 safe_free(driver_info_3[i].dependentfiles);
4179 safe_free(driver_info_3);
4181 if (*needed > offered) {
4183 return ERROR_INSUFFICIENT_BUFFER;
4186 return NT_STATUS_NO_PROBLEMO;
4189 /****************************************************************************
4190 Enumerates all printer drivers.
4191 ****************************************************************************/
4192 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4193 NEW_BUFFER *buffer, uint32 offered,
4194 uint32 *needed, uint32 *returned)
4196 fstring *list = NULL;
4198 fstring architecture;
4200 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4201 fstrcpy(servername, global_myname);
4205 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4209 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4212 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4215 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4220 return ERROR_INVALID_LEVEL;
4225 /****************************************************************************
4226 ****************************************************************************/
4227 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4229 form->flag=list->flag;
4230 init_unistr(&form->name, list->name);
4231 form->width=list->width;
4232 form->length=list->length;
4233 form->left=list->left;
4234 form->top=list->top;
4235 form->right=list->right;
4236 form->bottom=list->bottom;
4239 /****************************************************************************
4240 ****************************************************************************/
4241 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4242 NEW_BUFFER *buffer, uint32 offered,
4243 uint32 *needed, uint32 *numofforms)
4245 nt_forms_struct *list=NULL;
4250 DEBUG(4,("_new_spoolss_enumforms\n"));
4251 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4252 DEBUGADD(5,("Info level [%d]\n", level));
4254 *numofforms = get_ntforms(&list);
4255 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4257 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4261 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4263 return ERROR_NOT_ENOUGH_MEMORY;
4266 /* construct the list of form structures */
4267 for (i=0; i<*numofforms; i++) {
4268 DEBUGADD(6,("Filling form number [%d]\n",i));
4269 fill_form_1(&forms_1[i], &list[i]);
4274 /* check the required size. */
4275 for (i=0; i<*numofforms; i++) {
4276 DEBUGADD(6,("adding form [%d]'s size\n",i));
4277 buffer_size += spoolss_size_form_1(&forms_1[i]);
4280 *needed=buffer_size;
4282 if (!alloc_buffer_size(buffer, buffer_size)){
4284 return ERROR_INSUFFICIENT_BUFFER;
4287 /* fill the buffer with the form structures */
4288 for (i=0; i<*numofforms; i++) {
4289 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4290 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4295 if (*needed > offered) {
4297 return ERROR_INSUFFICIENT_BUFFER;
4300 return NT_STATUS_NO_PROBLEMO;
4304 return ERROR_INVALID_LEVEL;
4309 /****************************************************************************
4310 ****************************************************************************/
4311 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4313 nt_forms_struct *list=NULL;
4319 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4321 DEBUG(4,("_spoolss_getform\n"));
4322 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4323 DEBUGADD(5,("Info level [%d]\n", level));
4325 numofforms = get_ntforms(&list);
4326 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4328 if (numofforms == 0)
4329 return ERROR_NO_MORE_ITEMS;
4334 /* Check if the requested name is in the list of form structures */
4335 for (i=0; i<numofforms; i++) {
4337 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4339 if (strequal(form_name, list[i].name)) {
4340 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4341 fill_form_1(&form_1, &list[i]);
4348 /* check the required size. */
4350 *needed=spoolss_size_form_1(&form_1);
4352 if (!alloc_buffer_size(buffer, buffer_size)){
4353 return ERROR_INSUFFICIENT_BUFFER;
4356 if (*needed > offered) {
4357 return ERROR_INSUFFICIENT_BUFFER;
4360 /* fill the buffer with the form structures */
4361 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4362 new_smb_io_form_1("", buffer, &form_1, 0);
4364 return NT_STATUS_NO_PROBLEMO;
4368 return ERROR_INVALID_LEVEL;
4372 /****************************************************************************
4373 ****************************************************************************/
4374 static void fill_port_1(PORT_INFO_1 *port, char *name)
4376 init_unistr(&port->port_name, name);
4379 /****************************************************************************
4380 ****************************************************************************/
4381 static void fill_port_2(PORT_INFO_2 *port, char *name)
4383 init_unistr(&port->port_name, name);
4384 init_unistr(&port->monitor_name, "Local Monitor");
4385 init_unistr(&port->description, "Local Port");
4386 #define PORT_TYPE_WRITE 1
4387 port->port_type=PORT_TYPE_WRITE;
4391 /****************************************************************************
4393 ****************************************************************************/
4394 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4396 PORT_INFO_1 *ports=NULL;
4399 if (*lp_enumports_cmd()) {
4400 pid_t local_pid = sys_getpid();
4401 char *cmd = lp_enumports_cmd();
4409 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4410 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4414 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4415 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4418 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4419 ret = smbrun(command, tmp_file, False);
4420 DEBUG(10,("Returned [%d]\n", ret));
4423 /* Is this the best error to return here? */
4424 return ERROR_ACCESS_DENIED;
4428 qlines = file_lines_load(tmp_file, &numlines);
4429 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4430 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4434 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4435 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4436 file_lines_free(qlines);
4437 return ERROR_NOT_ENOUGH_MEMORY;
4440 for (i=0; i<numlines; i++) {
4441 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4442 fill_port_1(&ports[i], qlines[i]);
4445 file_lines_free(qlines);
4448 *returned = numlines;
4451 *returned = 1; /* Sole Samba port returned. */
4453 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4454 return ERROR_NOT_ENOUGH_MEMORY;
4456 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4458 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4461 /* check the required size. */
4462 for (i=0; i<*returned; i++) {
4463 DEBUGADD(6,("adding port [%d]'s size\n", i));
4464 *needed += spoolss_size_port_info_1(&ports[i]);
4467 if (!alloc_buffer_size(buffer, *needed)) {
4469 return ERROR_INSUFFICIENT_BUFFER;
4472 /* fill the buffer with the ports structures */
4473 for (i=0; i<*returned; i++) {
4474 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4475 new_smb_io_port_1("", buffer, &ports[i], 0);
4480 if (*needed > offered) {
4482 return ERROR_INSUFFICIENT_BUFFER;
4485 return NT_STATUS_NO_PROBLEMO;
4488 /****************************************************************************
4490 ****************************************************************************/
4492 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4494 PORT_INFO_2 *ports=NULL;
4497 if (*lp_enumports_cmd()) {
4498 pid_t local_pid = sys_getpid();
4499 char *cmd = lp_enumports_cmd();
4507 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4508 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4512 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4513 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4516 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4517 ret = smbrun(command, tmp_file, False);
4518 DEBUGADD(10,("returned [%d]\n", ret));
4521 /* Is this the best error to return here? */
4522 return ERROR_ACCESS_DENIED;
4526 qlines = file_lines_load(tmp_file, &numlines);
4527 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4528 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4532 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4533 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4534 file_lines_free(qlines);
4535 return ERROR_NOT_ENOUGH_MEMORY;
4538 for (i=0; i<numlines; i++) {
4539 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4540 fill_port_2(&(ports[i]), qlines[i]);
4543 file_lines_free(qlines);
4546 *returned = numlines;
4552 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4553 return ERROR_NOT_ENOUGH_MEMORY;
4555 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4557 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4560 /* check the required size. */
4561 for (i=0; i<*returned; i++) {
4562 DEBUGADD(6,("adding port [%d]'s size\n", i));
4563 *needed += spoolss_size_port_info_2(&ports[i]);
4566 if (!alloc_buffer_size(buffer, *needed)) {
4568 return ERROR_INSUFFICIENT_BUFFER;
4571 /* fill the buffer with the ports structures */
4572 for (i=0; i<*returned; i++) {
4573 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4574 new_smb_io_port_2("", buffer, &ports[i], 0);
4579 if (*needed > offered) {
4581 return ERROR_INSUFFICIENT_BUFFER;
4584 return NT_STATUS_NO_PROBLEMO;
4587 /****************************************************************************
4589 ****************************************************************************/
4590 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4591 NEW_BUFFER *buffer, uint32 offered,
4592 uint32 *needed, uint32 *returned)
4594 DEBUG(4,("_spoolss_enumports\n"));
4601 return enumports_level_1(buffer, offered, needed, returned);
4604 return enumports_level_2(buffer, offered, needed, returned);
4607 return ERROR_INVALID_LEVEL;
4612 /****************************************************************************
4613 ****************************************************************************/
4614 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4615 const SPOOL_PRINTER_INFO_LEVEL *info,
4616 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4617 uint32 user_switch, const SPOOL_USER_CTR *user,
4620 NT_PRINTER_INFO_LEVEL *printer = NULL;
4624 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4625 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4626 return ERROR_NOT_ENOUGH_MEMORY;
4629 ZERO_STRUCTP(printer);
4631 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4632 convert_printer_info(info, printer, 2);
4634 if (*lp_addprinter_cmd() )
4635 if ( !add_printer_hook(printer) ) {
4636 free_a_printer(&printer,2);
4637 return ERROR_ACCESS_DENIED;
4640 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4641 printer->info_2->sharename);
4643 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4644 free_a_printer(&printer,2);
4645 return ERROR_ACCESS_DENIED;
4648 /* you must be a printer admin to add a new printer */
4649 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4650 free_a_printer(&printer,2);
4651 return ERROR_ACCESS_DENIED;
4655 * Do sanity check on the requested changes for Samba.
4658 if (!check_printer_ok(printer->info_2, snum)) {
4659 free_a_printer(&printer,2);
4660 return ERROR_INVALID_PARAMETER;
4663 /* write the ASCII on disk */
4664 if (add_a_printer(*printer, 2) != 0) {
4665 free_a_printer(&printer,2);
4666 return ERROR_ACCESS_DENIED;
4669 if (!open_printer_hnd(handle, name)) {
4670 /* Handle open failed - remove addition. */
4671 del_a_printer(printer->info_2->sharename);
4672 free_a_printer(&printer,2);
4673 return ERROR_ACCESS_DENIED;
4676 free_a_printer(&printer,2);
4678 srv_spoolss_sendnotify(handle);
4680 return NT_STATUS_NO_PROBLEMO;
4683 /****************************************************************************
4684 ****************************************************************************/
4685 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4686 const SPOOL_PRINTER_INFO_LEVEL *info,
4687 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4688 uint32 user_switch, const SPOOL_USER_CTR *user,
4693 /* we don't handle yet */
4694 /* but I know what to do ... */
4695 return ERROR_INVALID_LEVEL;
4698 return spoolss_addprinterex_level_2(uni_srv_name, info,
4699 unk0, unk1, unk2, unk3,
4700 user_switch, user, handle);
4703 return ERROR_INVALID_LEVEL;
4708 /****************************************************************************
4709 ****************************************************************************/
4710 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4711 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4713 uint32 err = NT_STATUS_NO_PROBLEMO;
4714 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4715 struct current_user user;
4717 ZERO_STRUCT(driver);
4719 get_current_user(&user, p);
4721 convert_printer_driver_info(info, &driver, level);
4723 DEBUG(5,("Cleaning driver's information\n"));
4724 clean_up_driver_struct(driver, level);
4726 DEBUG(5,("Moving driver to final destination\n"));
4727 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4729 err = ERROR_ACCESS_DENIED;
4733 if (add_a_printer_driver(driver, level)!=0) {
4734 err = ERROR_ACCESS_DENIED;
4739 free_a_printer_driver(driver, level);
4743 /****************************************************************************
4744 ****************************************************************************/
4745 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4747 init_unistr(&info->name, name);
4750 /****************************************************************************
4751 ****************************************************************************/
4752 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4756 pstring short_archi;
4757 DRIVER_DIRECTORY_1 *info=NULL;
4759 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4761 if (get_short_archi(short_archi, long_archi)==FALSE)
4762 return ERROR_INVALID_ENVIRONMENT;
4764 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4765 return ERROR_NOT_ENOUGH_MEMORY;
4767 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4769 DEBUG(4,("printer driver directory: [%s]\n", path));
4771 fill_driverdir_1(info, path);
4773 *needed += spoolss_size_driverdir_info_1(info);
4775 if (!alloc_buffer_size(buffer, *needed)) {
4777 return ERROR_INSUFFICIENT_BUFFER;
4780 new_smb_io_driverdir_1("", buffer, info, 0);
4784 if (*needed > offered)
4785 return ERROR_INSUFFICIENT_BUFFER;
4787 return NT_STATUS_NO_PROBLEMO;
4790 /****************************************************************************
4791 ****************************************************************************/
4792 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4793 NEW_BUFFER *buffer, uint32 offered,
4796 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4802 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4805 return ERROR_INVALID_LEVEL;
4810 /****************************************************************************
4811 ****************************************************************************/
4812 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4813 uint32 in_value_len, uint32 in_data_len,
4814 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4816 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
4818 NT_PRINTER_INFO_LEVEL *printer = NULL;
4823 uint32 biggest_valuesize;
4824 uint32 biggest_datasize;
4826 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4831 ZERO_STRUCT(printer);
4833 *out_max_value_len=0;
4839 *out_max_data_len=0;
4843 DEBUG(5,("spoolss_enumprinterdata\n"));
4845 if (!OPEN_HANDLE(Printer)) {
4846 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4847 return ERROR_INVALID_HANDLE;
4850 if (!get_printer_snum(handle, &snum))
4851 return ERROR_INVALID_HANDLE;
4853 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
4854 return ERROR_INVALID_HANDLE;
4857 * The NT machine wants to know the biggest size of value and data
4859 * cf: MSDN EnumPrinterData remark section
4861 if ( (in_value_len==0) && (in_data_len==0) ) {
4862 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
4866 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
4867 * if this parameter size doesn't exist.
4868 * Ok - my opinion here is that the client is not asking for the greatest
4869 * possible size of all the parameters, but is asking specifically for the size needed
4870 * for this specific parameter. In that case we can remove the loop below and
4871 * simplify this lookup code considerably. JF - comments welcome. JRA.
4874 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4876 free_a_printer(&printer, 2);
4877 return ERROR_NO_MORE_ITEMS;
4885 biggest_valuesize=0;
4888 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
4889 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
4890 if (data_len > biggest_datasize) biggest_datasize=data_len;
4892 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
4900 * I think this is correct, it doesn't break APW and
4901 * allows Gerald's Win32 test programs to work correctly,
4902 * but may need altering.... JRA.
4905 if (param_index == 0) {
4906 /* No parameters found. */
4907 free_a_printer(&printer, 2);
4908 return ERROR_NO_MORE_ITEMS;
4911 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
4912 *out_value_len=2*(1+biggest_valuesize);
4913 *out_data_len=biggest_datasize;
4915 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
4917 free_a_printer(&printer, 2);
4918 return NT_STATUS_NO_PROBLEMO;
4922 * the value len is wrong in NT sp3
4923 * that's the number of bytes not the number of unicode chars
4926 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4928 free_a_printer(&printer, 2);
4929 return ERROR_NO_MORE_ITEMS;
4932 free_a_printer(&printer, 2);
4936 * - counted in bytes in the request
4937 * - counted in UNICODE chars in the max reply
4938 * - counted in bytes in the real size
4940 * take a pause *before* coding not *during* coding
4943 *out_max_value_len=(in_value_len/sizeof(uint16));
4944 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
4946 return ERROR_NOT_ENOUGH_MEMORY;
4949 ZERO_STRUCTP(*out_value);
4950 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
4954 /* the data is counted in bytes */
4955 *out_max_data_len=in_data_len;
4956 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
4958 return ERROR_NOT_ENOUGH_MEMORY;
4961 ZERO_STRUCTP(*data_out);
4962 memcpy(*data_out, data, (size_t)data_len);
4963 *out_data_len=data_len;
4967 return NT_STATUS_NO_PROBLEMO;
4970 /****************************************************************************
4971 ****************************************************************************/
4972 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
4973 const UNISTR2 *value,
4978 uint32 numeric_data)
4980 NT_PRINTER_INFO_LEVEL *printer = NULL;
4981 NT_PRINTER_PARAM *param = NULL;
4983 uint32 status = 0x0;
4984 Printer_entry *Printer=find_printer_index_by_hnd(handle);
4986 DEBUG(5,("spoolss_setprinterdata\n"));
4989 if (!OPEN_HANDLE(Printer)) {
4990 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4991 return ERROR_INVALID_HANDLE;
4994 if (!get_printer_snum(handle, &snum))
4995 return ERROR_INVALID_HANDLE;
4997 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4998 DEBUG(3, ("security descriptor change denied by existing "
4999 "security descriptor\n"));
5000 return ERROR_ACCESS_DENIED;
5003 status = get_a_printer(&printer, 2, lp_servicename(snum));
5005 return ERROR_INVALID_NAME;
5007 convert_specific_param(¶m, value , type, data, real_len);
5008 unlink_specific_param_if_exist(printer->info_2, param);
5010 if (!add_a_specific_param(printer->info_2, param))
5011 status = ERROR_INVALID_PARAMETER;
5013 status = add_a_printer(*printer, 2);
5015 free_a_printer(&printer, 2);
5019 /****************************************************************************
5020 ****************************************************************************/
5021 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5023 NT_PRINTER_INFO_LEVEL *printer = NULL;
5024 NT_PRINTER_PARAM param;
5026 uint32 status = 0x0;
5027 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5029 DEBUG(5,("spoolss_deleteprinterdata\n"));
5031 if (!OPEN_HANDLE(Printer)) {
5032 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5033 return ERROR_INVALID_HANDLE;
5036 if (!get_printer_snum(handle, &snum))
5037 return ERROR_INVALID_HANDLE;
5039 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5040 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5041 "security descriptor\n"));
5042 return ERROR_ACCESS_DENIED;
5045 status = get_a_printer(&printer, 2, lp_servicename(snum));
5047 return ERROR_INVALID_NAME;
5049 ZERO_STRUCTP(¶m);
5050 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5052 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5053 status = ERROR_INVALID_PARAMETER;
5055 status = add_a_printer(*printer, 2);
5057 free_a_printer(&printer, 2);
5061 /****************************************************************************
5062 ****************************************************************************/
5063 uint32 _spoolss_addform( POLICY_HND *handle,
5068 nt_forms_struct *list=NULL;
5069 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5071 DEBUG(5,("spoolss_addform\n"));
5073 if (!OPEN_HANDLE(Printer)) {
5074 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5075 return ERROR_INVALID_HANDLE;
5078 count=get_ntforms(&list);
5079 if(!add_a_form(&list, form, &count))
5080 return ERROR_NOT_ENOUGH_MEMORY;
5081 write_ntforms(&list, count);
5088 /****************************************************************************
5089 ****************************************************************************/
5090 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5094 nt_forms_struct *list=NULL;
5095 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5097 DEBUG(5,("spoolss_deleteform\n"));
5099 if (!OPEN_HANDLE(Printer)) {
5100 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5101 return ERROR_INVALID_HANDLE;
5104 count = get_ntforms(&list);
5105 if(!delete_a_form(&list, form_name, &count, &ret))
5106 return ERROR_INVALID_PARAMETER;
5113 /****************************************************************************
5114 ****************************************************************************/
5115 uint32 _spoolss_setform( POLICY_HND *handle,
5116 const UNISTR2 *uni_name,
5121 nt_forms_struct *list=NULL;
5122 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5124 DEBUG(5,("spoolss_setform\n"));
5126 if (!OPEN_HANDLE(Printer)) {
5127 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5128 return ERROR_INVALID_HANDLE;
5130 count=get_ntforms(&list);
5131 update_a_form(&list, form, count);
5132 write_ntforms(&list, count);
5139 /****************************************************************************
5140 enumprintprocessors level 1.
5141 ****************************************************************************/
5142 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5144 PRINTPROCESSOR_1 *info_1=NULL;
5146 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5147 return ERROR_NOT_ENOUGH_MEMORY;
5151 init_unistr(&info_1->name, "winprint");
5153 *needed += spoolss_size_printprocessor_info_1(info_1);
5155 if (!alloc_buffer_size(buffer, *needed))
5156 return ERROR_INSUFFICIENT_BUFFER;
5158 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5162 if (*needed > offered) {
5164 return ERROR_INSUFFICIENT_BUFFER;
5167 return NT_STATUS_NO_PROBLEMO;
5170 /****************************************************************************
5171 ****************************************************************************/
5172 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5173 NEW_BUFFER *buffer, uint32 offered,
5174 uint32 *needed, uint32 *returned)
5176 DEBUG(5,("spoolss_enumprintprocessors\n"));
5179 * Enumerate the print processors ...
5181 * Just reply with "winprint", to keep NT happy
5182 * and I can use my nice printer checker.
5190 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5193 return ERROR_INVALID_LEVEL;
5198 /****************************************************************************
5199 enumprintprocdatatypes level 1.
5200 ****************************************************************************/
5201 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5203 PRINTPROCDATATYPE_1 *info_1=NULL;
5205 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5206 return ERROR_NOT_ENOUGH_MEMORY;
5210 init_unistr(&info_1->name, "RAW");
5212 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5214 if (!alloc_buffer_size(buffer, *needed))
5215 return ERROR_INSUFFICIENT_BUFFER;
5217 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5221 if (*needed > offered) {
5223 return ERROR_INSUFFICIENT_BUFFER;
5226 return NT_STATUS_NO_PROBLEMO;
5229 /****************************************************************************
5230 ****************************************************************************/
5231 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5232 NEW_BUFFER *buffer, uint32 offered,
5233 uint32 *needed, uint32 *returned)
5235 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5242 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5245 return ERROR_INVALID_LEVEL;
5250 /****************************************************************************
5251 enumprintmonitors level 1.
5252 ****************************************************************************/
5253 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5255 PRINTMONITOR_1 *info_1=NULL;
5257 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5258 return ERROR_NOT_ENOUGH_MEMORY;
5262 init_unistr(&info_1->name, "Local Port");
5264 *needed += spoolss_size_printmonitor_info_1(info_1);
5266 if (!alloc_buffer_size(buffer, *needed))
5267 return ERROR_INSUFFICIENT_BUFFER;
5269 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5273 if (*needed > offered) {
5275 return ERROR_INSUFFICIENT_BUFFER;
5278 return NT_STATUS_NO_PROBLEMO;
5281 /****************************************************************************
5282 enumprintmonitors level 2.
5283 ****************************************************************************/
5284 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5286 PRINTMONITOR_2 *info_2=NULL;
5288 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5289 return ERROR_NOT_ENOUGH_MEMORY;
5293 init_unistr(&info_2->name, "Local Port");
5294 init_unistr(&info_2->environment, "Windows NT X86");
5295 init_unistr(&info_2->dll_name, "localmon.dll");
5297 *needed += spoolss_size_printmonitor_info_2(info_2);
5299 if (!alloc_buffer_size(buffer, *needed))
5300 return ERROR_INSUFFICIENT_BUFFER;
5302 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5306 if (*needed > offered) {
5308 return ERROR_INSUFFICIENT_BUFFER;
5311 return NT_STATUS_NO_PROBLEMO;
5314 /****************************************************************************
5315 ****************************************************************************/
5316 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5317 NEW_BUFFER *buffer, uint32 offered,
5318 uint32 *needed, uint32 *returned)
5320 DEBUG(5,("spoolss_enumprintmonitors\n"));
5323 * Enumerate the print monitors ...
5325 * Just reply with "Local Port", to keep NT happy
5326 * and I can use my nice printer checker.
5334 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5337 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5340 return ERROR_INVALID_LEVEL;
5345 /****************************************************************************
5346 ****************************************************************************/
5347 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5351 JOB_INFO_1 *info_1=NULL;
5353 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5355 if (info_1 == NULL) {
5357 return ERROR_NOT_ENOUGH_MEMORY;
5360 for (i=0; i<count && found==False; i++) {
5361 if (queue[i].job==(int)jobid)
5368 /* I shoud reply something else ... I can't find the good one */
5369 return NT_STATUS_NO_PROBLEMO;
5372 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5376 *needed += spoolss_size_job_info_1(info_1);
5378 if (!alloc_buffer_size(buffer, *needed)) {
5380 return ERROR_INSUFFICIENT_BUFFER;
5383 new_smb_io_job_info_1("", buffer, info_1, 0);
5387 if (*needed > offered)
5388 return ERROR_INSUFFICIENT_BUFFER;
5390 return NT_STATUS_NO_PROBLEMO;
5394 /****************************************************************************
5395 ****************************************************************************/
5396 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5401 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5403 ZERO_STRUCTP(info_2);
5405 if (info_2 == NULL) {
5407 return ERROR_NOT_ENOUGH_MEMORY;
5410 for (i=0; i<count && found==False; i++) {
5411 if (queue[i].job==(int)jobid)
5418 /* I shoud reply something else ... I can't find the good one */
5419 return NT_STATUS_NO_PROBLEMO;
5422 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5426 *needed += spoolss_size_job_info_2(info_2);
5428 if (!alloc_buffer_size(buffer, *needed)) {
5430 return ERROR_INSUFFICIENT_BUFFER;
5433 new_smb_io_job_info_2("", buffer, info_2, 0);
5435 free_dev_mode(info_2->devmode);
5438 if (*needed > offered)
5439 return ERROR_INSUFFICIENT_BUFFER;
5441 return NT_STATUS_NO_PROBLEMO;
5444 /****************************************************************************
5445 ****************************************************************************/
5446 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5447 NEW_BUFFER *buffer, uint32 offered,
5452 print_queue_struct *queue=NULL;
5453 print_status_struct prt_status;
5455 DEBUG(5,("spoolss_getjob\n"));
5457 memset(&prt_status, 0, sizeof(prt_status));
5461 if (!get_printer_snum(handle, &snum))
5462 return ERROR_INVALID_HANDLE;
5464 count = print_queue_status(snum, &queue, &prt_status);
5466 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5467 count, prt_status.status, prt_status.message));
5471 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5474 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5478 return ERROR_INVALID_LEVEL;