3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8 * Copyright (C) Jean François Micouleau 1998-2000.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
34 #define PRINTER_HANDLE_IS_PRINTER 0
35 #define PRINTER_HANDLE_IS_PRINTSERVER 1
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer{
46 BOOL document_started;
48 int jobid; /* jobid in printing backend */
49 POLICY_HND printer_hnd;
53 fstring printerservername;
62 SPOOL_NOTIFY_OPTION *option;
63 POLICY_HND client_hnd;
64 uint32 client_connected;
72 typedef struct _counter_printer_0 {
80 static ubi_dlList Printer_list;
81 static ubi_dlList counter_list;
83 static struct cli_state cli;
84 static uint32 smb_connections=0;
86 #define OPEN_HANDLE(pnum) ((pnum!=NULL) && (pnum->open!=False) && (IVAL(pnum->printer_hnd.data,16)==(uint32)sys_getpid()))
87 #define OUR_HANDLE(pnum) ((pnum==NULL)?"NULL":(IVAL(pnum->data,16)==sys_getpid()?"OURS":"OTHER"))
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
94 return PRINTER_STATUS_PAUSED;
103 static int nt_printq_status(int v)
107 return PRINTER_STATUS_PAUSED;
116 /****************************************************************************
117 initialise printer handle states...
118 ****************************************************************************/
119 void init_printer_hnd(void)
121 ubi_dlInitList(&Printer_list);
122 ubi_dlInitList(&counter_list);
125 /****************************************************************************
126 create a unique printer handle
127 ****************************************************************************/
128 static void create_printer_hnd(POLICY_HND *hnd)
130 static uint32 prt_hnd_low = 0;
131 static uint32 prt_hnd_high = 0;
133 if (hnd == NULL) return;
135 /* i severely doubt that prt_hnd_high will ever be non-zero... */
137 if (prt_hnd_low == 0) prt_hnd_high++;
139 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
140 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
141 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
142 SIVAL(hnd->data, 12, time(NULL)); /* something random */
143 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
146 /****************************************************************************
147 find printer index by handle
148 ****************************************************************************/
149 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
151 Printer_entry *find_printer;
153 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
155 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
157 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
158 DEBUG(4,("Found printer handle \n"));
159 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
164 DEBUG(3,("Whoops, Printer handle not found: "));
165 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
169 /****************************************************************************
171 ****************************************************************************/
172 static void clear_handle(POLICY_HND *hnd)
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
180 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
184 /* weird if the test succeds !!! */
185 if (smb_connections==0) {
186 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
190 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
195 if(!spoolss_disconnect_from_client(&cli))
198 message_deregister(MSG_PRINTER_NOTIFY);
206 /****************************************************************************
207 close printer index by handle
208 ****************************************************************************/
209 static BOOL close_printer_handle(POLICY_HND *hnd)
211 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
213 if (!OPEN_HANDLE(Printer)) {
214 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
218 if (Printer->notify.client_connected==True)
219 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
220 return ERROR_INVALID_HANDLE;
223 Printer->notify.flags=0;
224 Printer->notify.options=0;
225 Printer->notify.localmachine[0]='\0';
226 Printer->notify.printerlocal=0;
227 safe_free(Printer->notify.option);
228 Printer->notify.option=NULL;
229 Printer->notify.client_connected=False;
233 ubi_dlRemThis(&Printer_list, Printer);
240 /****************************************************************************
241 delete a printer given a handle
242 ****************************************************************************/
243 static BOOL delete_printer_handle(POLICY_HND *hnd)
245 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
247 if (!OPEN_HANDLE(Printer)) {
248 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
252 if (del_a_printer(Printer->dev.handlename) != 0) {
253 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
257 if (*lp_deleteprinter_cmd()) {
259 pid_t local_pid = sys_getpid();
260 char *cmd = lp_deleteprinter_cmd();
267 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
268 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
272 /* Printer->dev.handlename equals portname equals sharename */
273 slprintf(command, sizeof(command), "%s \"%s\"", cmd,
274 Printer->dev.handlename);
275 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
278 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
279 ret = smbrun(command, tmp_file, False);
284 DEBUGADD(10,("returned [%d]\n", ret));
285 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
288 /* Send SIGHUP to process group... is there a better way? */
291 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
292 lp_remove_service( i );
302 /****************************************************************************
303 return the snum of a printer corresponding to an handle
304 ****************************************************************************/
305 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
307 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
309 if (!OPEN_HANDLE(Printer)) {
310 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
314 switch (Printer->printer_type) {
315 case PRINTER_HANDLE_IS_PRINTER:
316 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
317 *number = print_queue_snum(Printer->dev.handlename);
318 return (*number != -1);
319 case PRINTER_HANDLE_IS_PRINTSERVER:
326 /****************************************************************************
327 set printer handle type.
328 ****************************************************************************/
329 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
331 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
333 if (!OPEN_HANDLE(Printer)) {
334 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
338 DEBUG(4,("Setting printer access=%x\n", access_required));
339 Printer->access = access_required;
343 /****************************************************************************
344 Set printer handle type.
345 Check if it's \\server or \\server\printer
346 ****************************************************************************/
348 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
350 DEBUG(3,("Setting printer type=%s\n", handlename));
352 if ( strlen(handlename) < 3 ) {
353 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
357 /* it's a print server */
358 if (!strchr(handlename+2, '\\')) {
359 DEBUGADD(4,("Printer is a print server\n"));
360 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
364 DEBUGADD(4,("Printer is a printer\n"));
365 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
371 /****************************************************************************
372 Set printer handle name.
373 ****************************************************************************/
375 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
377 NT_PRINTER_INFO_LEVEL *printer = NULL;
379 int n_services=lp_numservices();
383 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
385 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
386 ZERO_STRUCT(Printer->dev.printerservername);
387 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
391 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
394 aprinter=strchr(handlename+2, '\\');
397 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
400 * store the Samba share name in it
401 * in back we have the long printer name
402 * need to iterate all the snum and do a
403 * get_a_printer each time to find the printer
404 * faster to do it here than later.
407 for (snum=0;snum<n_services && found==False;snum++) {
409 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
412 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
414 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
417 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
418 printer->info_2->printername, aprinter ));
420 if ( strlen(printer->info_2->printername) != strlen(aprinter) ) {
421 free_a_printer(&printer, 2);
425 if ( strncasecmp(printer->info_2->printername, aprinter, strlen(aprinter))) {
426 free_a_printer(&printer, 2);
434 * if we haven't found a printer with the given handlename
435 * then it can be a share name as you can open both \\server\printer and
440 * we still check if the printer description file exists as NT won't be happy
441 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
445 DEBUGADD(5,("Printer not found, checking for share now\n"));
447 for (snum=0;snum<n_services && found==False;snum++) {
449 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
452 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
454 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
457 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
458 printer->info_2->printername, aprinter ));
460 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
461 free_a_printer(&printer, 2);
465 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
466 free_a_printer(&printer, 2);
475 DEBUGADD(4,("Printer not found\n"));
480 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
481 printer->info_2->printername, lp_servicename(snum),snum));
483 ZERO_STRUCT(Printer->dev.handlename);
484 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
486 free_a_printer(&printer, 2);
491 /****************************************************************************
492 find first available printer slot. creates a printer handle for you.
493 ****************************************************************************/
495 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
497 Printer_entry *new_printer;
499 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
501 create_printer_hnd(hnd);
503 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
506 ZERO_STRUCTP(new_printer);
508 new_printer->open = True;
509 new_printer->notify.option=NULL;
511 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
513 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
515 if (!set_printer_hnd_printertype(new_printer, name)) {
516 close_printer_handle(hnd);
520 if (!set_printer_hnd_name(new_printer, name)) {
521 close_printer_handle(hnd);
528 /********************************************************************
529 Return True is the handle is a print server.
530 ********************************************************************/
531 static BOOL handle_is_printserver(const POLICY_HND *handle)
533 Printer_entry *Printer=find_printer_index_by_hnd(handle);
535 if (!OPEN_HANDLE(Printer))
538 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
544 /****************************************************************************
545 allocate more memory for a BUFFER.
546 ****************************************************************************/
547 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
555 /* damn, I'm doing the reverse operation of prs_grow() :) */
556 if (buffer_size < prs_data_size(ps))
559 extra_space = buffer_size - prs_data_size(ps);
562 * save the offset and move to the end of the buffer
563 * prs_grow() checks the extra_space against the offset
565 old_offset=prs_offset(ps);
566 prs_set_offset(ps, prs_data_size(ps));
568 if (!prs_grow(ps, extra_space))
571 prs_set_offset(ps, old_offset);
573 buffer->string_at_end=prs_data_size(ps);
578 /***************************************************************************
579 receive the notify message
580 ****************************************************************************/
581 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
585 Printer_entry *find_printer;
588 fstrcpy(printer,buf);
591 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
595 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
597 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
599 /* Iterate the printer list. */
600 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
603 * if the entry is the given printer or if it's a printerserver
604 * we send the message
607 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
608 if (strcmp(find_printer->dev.handlename, printer))
611 if (find_printer->notify.client_connected==True)
612 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
617 /***************************************************************************
619 ****************************************************************************/
620 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
624 Printer_entry *Printer=find_printer_index_by_hnd(handle);
626 if (!OPEN_HANDLE(Printer)) {
627 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
631 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
632 fstrcpy(printer, Printer->dev.handlename);
634 fstrcpy(printer, "");
636 /*srv_spoolss_receive_message(printer);*/
637 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
639 message_send_all(MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1); /* Null terminate... */
644 /********************************************************************
645 * spoolss_open_printer
647 * called from the spoolss dispatcher
648 ********************************************************************/
649 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername,
650 const PRINTER_DEFAULT *printer_default,
651 uint32 user_switch, SPOOL_USER_CTR user_ctr,
656 if (printername == NULL)
657 return ERROR_INVALID_PRINTER_NAME;
659 /* some sanity check because you can open a printer or a print server */
660 /* aka: \\server\printer or \\server */
661 unistr2_to_ascii(name, printername, sizeof(name)-1);
663 DEBUGADD(3,("checking name: %s\n",name));
665 if (!open_printer_hnd(handle, name))
666 return ERROR_INVALID_PRINTER_NAME;
669 if (printer_default->datatype_ptr != NULL)
671 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
672 set_printer_hnd_datatype(handle, datatype);
675 set_printer_hnd_datatype(handle, "");
678 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
679 close_printer_handle(handle);
680 return ERROR_ACCESS_DENIED;
683 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
684 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
685 Then both Win2k and WinNT clients try an OpenPrinterEx with
686 SERVER_ALL_ACCESS, which we force to fail. Then they try
687 OpenPrinterEx with SERVER_READ which we allow. This lets the
688 client view printer folder, but does not show the MSAPW.
690 Note: this test needs code to check access rights here too. Jeremy
691 could you look at this? */
693 if (handle_is_printserver(handle) &&
694 !lp_ms_add_printer_wizard()) {
695 if (printer_default->access_required == 0)
696 return NT_STATUS_NO_PROBLEMO;
697 else if (printer_default->access_required != (SERVER_READ))
698 return ERROR_ACCESS_DENIED;
701 return NT_STATUS_NO_PROBLEMO;
704 /****************************************************************************
705 ****************************************************************************/
706 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
707 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
711 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
720 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
721 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
725 printer->info_3=NULL;
726 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
729 printer->info_6=NULL;
730 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
739 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
741 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
742 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
744 nt_devmode->specversion=devmode->specversion;
745 nt_devmode->driverversion=devmode->driverversion;
746 nt_devmode->size=devmode->size;
747 nt_devmode->driverextra=devmode->driverextra;
748 nt_devmode->fields=devmode->fields;
749 nt_devmode->orientation=devmode->orientation;
750 nt_devmode->papersize=devmode->papersize;
751 nt_devmode->paperlength=devmode->paperlength;
752 nt_devmode->paperwidth=devmode->paperwidth;
753 nt_devmode->scale=devmode->scale;
754 nt_devmode->copies=devmode->copies;
755 nt_devmode->defaultsource=devmode->defaultsource;
756 nt_devmode->printquality=devmode->printquality;
757 nt_devmode->color=devmode->color;
758 nt_devmode->duplex=devmode->duplex;
759 nt_devmode->yresolution=devmode->yresolution;
760 nt_devmode->ttoption=devmode->ttoption;
761 nt_devmode->collate=devmode->collate;
763 nt_devmode->logpixels=devmode->logpixels;
764 nt_devmode->bitsperpel=devmode->bitsperpel;
765 nt_devmode->pelswidth=devmode->pelswidth;
766 nt_devmode->pelsheight=devmode->pelsheight;
767 nt_devmode->displayflags=devmode->displayflags;
768 nt_devmode->displayfrequency=devmode->displayfrequency;
769 nt_devmode->icmmethod=devmode->icmmethod;
770 nt_devmode->icmintent=devmode->icmintent;
771 nt_devmode->mediatype=devmode->mediatype;
772 nt_devmode->dithertype=devmode->dithertype;
773 nt_devmode->reserved1=devmode->reserved1;
774 nt_devmode->reserved2=devmode->reserved2;
775 nt_devmode->panningwidth=devmode->panningwidth;
776 nt_devmode->panningheight=devmode->panningheight;
778 if (nt_devmode->driverextra != 0) {
779 /* if we had a previous private delete it and make a new one */
780 safe_free(nt_devmode->private);
781 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
783 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
789 /********************************************************************
790 * api_spoolss_closeprinter
791 ********************************************************************/
792 uint32 _spoolss_closeprinter(POLICY_HND *handle)
794 Printer_entry *Printer=find_printer_index_by_hnd(handle);
796 if (Printer && Printer->document_started)
797 _spoolss_enddocprinter(handle); /* print job was not closed */
799 if (!close_printer_handle(handle))
800 return ERROR_INVALID_HANDLE;
802 return NT_STATUS_NO_PROBLEMO;
805 /********************************************************************
806 * api_spoolss_deleteprinter
807 ********************************************************************/
808 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
810 Printer_entry *Printer=find_printer_index_by_hnd(handle);
812 if (Printer && Printer->document_started)
813 _spoolss_enddocprinter(handle); /* print job was not closed */
815 if (!delete_printer_handle(handle))
816 return ERROR_INVALID_HANDLE;
818 srv_spoolss_sendnotify(handle);
820 return NT_STATUS_NO_PROBLEMO;
823 /********************************************************************
824 GetPrinterData on a printer server Handle.
825 ********************************************************************/
826 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
830 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
832 if (!strcmp(value, "BeepEnabled")) {
834 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
836 SIVAL(*data, 0, 0x01);
841 if (!strcmp(value, "EventLog")) {
843 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
845 SIVAL(*data, 0, 0x1B);
850 if (!strcmp(value, "NetPopup")) {
852 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
854 SIVAL(*data, 0, 0x01);
859 if (!strcmp(value, "MajorVersion")) {
861 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
863 SIVAL(*data, 0, 0x02);
868 if (!strcmp(value, "DefaultSpoolDirectory")) {
869 pstring string="You are using a Samba server";
871 *needed = 2*(strlen(string)+1);
872 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
874 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
876 /* it's done by hand ready to go on the wire */
877 for (i=0; i<strlen(string); i++) {
878 (*data)[2*i]=string[i];
884 if (!strcmp(value, "Architecture")) {
885 pstring string="Windows NT x86";
887 *needed = 2*(strlen(string)+1);
888 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
890 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
891 for (i=0; i<strlen(string); i++) {
892 (*data)[2*i]=string[i];
901 /********************************************************************
902 GetPrinterData on a printer Handle.
903 ********************************************************************/
904 static BOOL getprinterdata_printer(POLICY_HND *handle,
905 fstring value, uint32 *type,
906 uint8 **data, uint32 *needed, uint32 in_size )
908 NT_PRINTER_INFO_LEVEL *printer = NULL;
912 Printer_entry *Printer = find_printer_index_by_hnd(handle);
914 DEBUG(5,("getprinterdata_printer\n"));
916 if (!OPEN_HANDLE(Printer)) {
917 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
921 if(!get_printer_snum(handle, &snum))
924 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
927 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
928 free_a_printer(&printer, 2);
932 free_a_printer(&printer, 2);
934 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
937 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
941 memset(*data, 0, in_size *sizeof(uint8));
942 /* copy the min(in_size, len) */
943 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
950 DEBUG(5,("getprinterdata_printer:copy done\n"));
957 /********************************************************************
958 * spoolss_getprinterdata
959 ********************************************************************/
960 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
969 Printer_entry *Printer = find_printer_index_by_hnd(handle);
972 * Reminder: when it's a string, the length is in BYTES
973 * even if UNICODE is negociated.
980 /* in case of problem, return some default values */
984 DEBUG(4,("_spoolss_getprinterdata\n"));
986 if (!OPEN_HANDLE(Printer)) {
987 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
988 return ERROR_NOT_ENOUGH_MEMORY;
989 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
990 return ERROR_INVALID_HANDLE;
993 unistr2_to_ascii(value, valuename, sizeof(value)-1);
995 if (handle_is_printserver(handle))
996 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
998 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
1001 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1002 /* reply this param doesn't exist */
1004 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1005 return ERROR_NOT_ENOUGH_MEMORY;
1006 memset(*data, '\0', *out_size*sizeof(uint8));
1011 return ERROR_INVALID_PARAMETER;
1014 if (*needed > *out_size)
1015 return ERROR_MORE_DATA;
1017 return NT_STATUS_NO_PROBLEMO;
1020 /***************************************************************************
1021 connect to the client
1022 ****************************************************************************/
1023 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1028 * If it's the first connection, contact the client
1029 * and connect to the IPC$ share anonumously
1031 if (smb_connections==0) {
1032 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1034 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1040 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1046 /********************************************************************
1048 * ReplyFindFirstPrinterChangeNotifyEx
1050 * jfmxxxx: before replying OK: status=0
1051 * should do a rpc call to the workstation asking ReplyOpenPrinter
1052 * have to code it, later.
1054 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1055 * called from api_spoolss_rffpcnex
1056 ********************************************************************/
1057 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1058 const UNISTR2 *localmachine, uint32 printerlocal,
1059 SPOOL_NOTIFY_OPTION *option)
1061 /* store the notify value in the printer struct */
1063 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1065 if (!OPEN_HANDLE(Printer)) {
1066 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1067 return ERROR_INVALID_HANDLE;
1070 Printer->notify.flags=flags;
1071 Printer->notify.options=options;
1072 Printer->notify.printerlocal=printerlocal;
1073 Printer->notify.option=option;
1074 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1076 /* connect to the client machine and send a ReplyOpenPrinter */
1077 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1078 Printer->notify.printerlocal, 1,
1079 &Printer->notify.client_hnd))
1080 Printer->notify.client_connected=True;
1082 return NT_STATUS_NO_PROBLEMO;
1085 /*******************************************************************
1086 * fill a notify_info_data with the servername
1087 ********************************************************************/
1088 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1089 NT_PRINTER_INFO_LEVEL *printer)
1093 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1095 data->notify_data.data.length= (uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1096 temp_name, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1099 /*******************************************************************
1100 * fill a notify_info_data with the servicename
1101 * jfmxxxx: it's incorrect should be long_printername
1102 ********************************************************************/
1103 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1104 NT_PRINTER_INFO_LEVEL *printer)
1107 data->notify_data.data.length=strlen(lp_servicename(snum));
1108 dos_PutUniCode(data->notify_data.data.string, lp_servicename(snum), sizeof(data->notify_data.data.string), True);
1110 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1111 printer->info_2->printername, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1114 /*******************************************************************
1115 * fill a notify_info_data with the servicename
1116 ********************************************************************/
1117 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1119 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1120 lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
1123 /*******************************************************************
1124 * fill a notify_info_data with the port name
1125 ********************************************************************/
1126 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1128 /* even if it's strange, that's consistant in all the code */
1130 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1131 lp_servicename(snum), sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1134 /*******************************************************************
1135 * fill a notify_info_data with the printername
1136 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1137 * but it doesn't exist, have to see what to do
1138 ********************************************************************/
1139 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1141 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1142 printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1145 /*******************************************************************
1146 * fill a notify_info_data with the comment
1147 ********************************************************************/
1148 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1150 if (*printer->info_2->comment == '\0')
1151 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1152 lp_comment(snum), sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1154 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1155 printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1158 /*******************************************************************
1159 * fill a notify_info_data with the comment
1160 * jfm:xxxx incorrect, have to create a new smb.conf option
1161 * location = "Room 1, floor 2, building 3"
1162 ********************************************************************/
1163 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1165 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1166 printer->info_2->location, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1169 /*******************************************************************
1170 * fill a notify_info_data with the device mode
1171 * jfm:xxxx don't to it for know but that's a real problem !!!
1172 ********************************************************************/
1173 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1177 /*******************************************************************
1178 * fill a notify_info_data with the separator file name
1179 * jfm:xxxx just return no file could add an option to smb.conf
1180 * separator file = "separator.txt"
1181 ********************************************************************/
1182 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1184 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1185 printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True) - sizeof(uint16))/sizeof(uint16));
1188 /*******************************************************************
1189 * fill a notify_info_data with the print processor
1190 * jfm:xxxx return always winprint to indicate we don't do anything to it
1191 ********************************************************************/
1192 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1194 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1195 printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1198 /*******************************************************************
1199 * fill a notify_info_data with the print processor options
1200 * jfm:xxxx send an empty string
1201 ********************************************************************/
1202 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1204 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1205 printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1208 /*******************************************************************
1209 * fill a notify_info_data with the data type
1210 * jfm:xxxx always send RAW as data type
1211 ********************************************************************/
1212 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1214 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1215 printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1218 /*******************************************************************
1219 * fill a notify_info_data with the security descriptor
1220 * jfm:xxxx send an null pointer to say no security desc
1221 * have to implement security before !
1222 ********************************************************************/
1223 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1225 data->notify_data.data.length=0;
1226 data->notify_data.data.string[0]=0x00;
1229 /*******************************************************************
1230 * fill a notify_info_data with the attributes
1231 * jfm:xxxx a samba printer is always shared
1232 ********************************************************************/
1233 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1235 data->notify_data.value[0] = PRINTER_ATTRIBUTE_SHARED \
1236 | PRINTER_ATTRIBUTE_LOCAL \
1237 | PRINTER_ATTRIBUTE_RAW_ONLY ;
1240 /*******************************************************************
1241 * fill a notify_info_data with the priority
1242 ********************************************************************/
1243 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1245 data->notify_data.value[0] = printer->info_2->priority;
1248 /*******************************************************************
1249 * fill a notify_info_data with the default priority
1250 ********************************************************************/
1251 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1253 data->notify_data.value[0] = printer->info_2->default_priority;
1256 /*******************************************************************
1257 * fill a notify_info_data with the start time
1258 ********************************************************************/
1259 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1261 data->notify_data.value[0] = printer->info_2->starttime;
1264 /*******************************************************************
1265 * fill a notify_info_data with the until time
1266 ********************************************************************/
1267 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1269 data->notify_data.value[0] = printer->info_2->untiltime;
1272 /*******************************************************************
1273 * fill a notify_info_data with the status
1274 ********************************************************************/
1275 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1278 print_queue_struct *q=NULL;
1279 print_status_struct status;
1281 memset(&status, 0, sizeof(status));
1282 count = print_queue_status(snum, &q, &status);
1283 data->notify_data.value[0]=(uint32) status.status;
1287 /*******************************************************************
1288 * fill a notify_info_data with the number of jobs queued
1289 ********************************************************************/
1290 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1292 print_queue_struct *q=NULL;
1293 print_status_struct status;
1295 memset(&status, 0, sizeof(status));
1296 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1300 /*******************************************************************
1301 * fill a notify_info_data with the average ppm
1302 ********************************************************************/
1303 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1305 /* always respond 8 pages per minutes */
1306 /* a little hard ! */
1307 data->notify_data.value[0] = printer->info_2->averageppm;
1310 /*******************************************************************
1311 * fill a notify_info_data with
1312 ********************************************************************/
1313 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1315 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1316 queue->user, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1319 /*******************************************************************
1320 * fill a notify_info_data with
1321 ********************************************************************/
1322 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1324 data->notify_data.value[0]=nt_printj_status(queue->status);
1327 /*******************************************************************
1328 * fill a notify_info_data with
1329 ********************************************************************/
1330 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1332 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1333 queue->file, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1336 /*******************************************************************
1337 * fill a notify_info_data with
1338 ********************************************************************/
1339 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1341 char *p = "unknown";
1342 switch (queue->status) {
1356 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1357 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1360 /*******************************************************************
1361 * fill a notify_info_data with
1362 ********************************************************************/
1363 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1365 data->notify_data.value[0]=0x0;
1368 /*******************************************************************
1369 * fill a notify_info_data with
1370 ********************************************************************/
1371 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1373 data->notify_data.value[0]=queue->size;
1376 /*******************************************************************
1377 * fill a notify_info_data with
1378 ********************************************************************/
1379 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1381 data->notify_data.value[0]=queue->job;
1386 struct s_notify_info_data_table
1392 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1393 print_queue_struct *queue,
1394 NT_PRINTER_INFO_LEVEL *printer);
1397 struct s_notify_info_data_table notify_info_data_table[] =
1399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, NULL },
1442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1449 { END, END, "", END, NULL }
1452 /*******************************************************************
1453 return the size of info_data structure
1454 ********************************************************************/
1455 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1459 while (notify_info_data_table[i].type != END)
1461 if ( (notify_info_data_table[i].type == type ) &&
1462 (notify_info_data_table[i].field == field ) )
1464 return (notify_info_data_table[i].size);
1471 /*******************************************************************
1472 return the type of notify_info_data
1473 ********************************************************************/
1474 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1478 while (notify_info_data_table[i].type != END)
1480 if ( (notify_info_data_table[i].type == type ) &&
1481 (notify_info_data_table[i].field == field ) )
1483 if (notify_info_data_table[i].size == POINTER)
1497 /****************************************************************************
1498 ****************************************************************************/
1499 static int search_notify(uint16 type, uint16 field, int *value)
1504 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1506 if ( (notify_info_data_table[j].type == type ) &&
1507 (notify_info_data_table[j].field == field ) )
1512 if ( found && (notify_info_data_table[j].fn != NULL) )
1518 /****************************************************************************
1519 ****************************************************************************/
1520 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1522 info_data->type = type;
1523 info_data->field = field;
1524 info_data->reserved = 0;
1526 info_data->size = size_of_notify_info_data(type, field);
1527 info_data->enc_type = type_of_notify_info_data(type, field);
1531 /*******************************************************************
1533 * fill a notify_info struct with info asked
1535 ********************************************************************/
1536 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1542 SPOOL_NOTIFY_INFO_DATA *current_data;
1543 NT_PRINTER_INFO_LEVEL *printer = NULL;
1544 print_queue_struct *queue=NULL;
1546 DEBUG(4,("construct_notify_printer_info\n"));
1548 type=option_type->type;
1550 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1551 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1552 option_type->count, lp_servicename(snum)));
1554 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1557 for(field_num=0; field_num<option_type->count; field_num++) {
1558 field = option_type->fields[field_num];
1559 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1561 if (!search_notify(type, field, &j) )
1564 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1567 current_data=&info->data[info->count];
1569 construct_info_data(current_data, type, field, id);
1570 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1575 free_a_printer(&printer, 2);
1579 /*******************************************************************
1581 * fill a notify_info struct with info asked
1583 ********************************************************************/
1584 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1590 SPOOL_NOTIFY_INFO_DATA *current_data;
1591 NT_PRINTER_INFO_LEVEL *printer = NULL;
1593 DEBUG(4,("construct_notify_jobs_info\n"));
1595 type = option_type->type;
1597 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1598 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1599 option_type->count));
1601 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1604 for(field_num=0; field_num<option_type->count; field_num++) {
1605 field = option_type->fields[field_num];
1607 if (!search_notify(type, field, &j) )
1610 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1614 current_data=&(info->data[info->count]);
1616 construct_info_data(current_data, type, field, id);
1617 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1621 free_a_printer(&printer, 2);
1626 * JFM: The enumeration is not that simple, it's even non obvious.
1628 * let's take an example: I want to monitor the PRINTER SERVER for
1629 * the printer's name and the number of jobs currently queued.
1630 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1631 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1633 * I have 3 printers on the back of my server.
1635 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1638 * 1 printer 1 name 1
1639 * 2 printer 1 cjob 1
1640 * 3 printer 2 name 2
1641 * 4 printer 2 cjob 2
1642 * 5 printer 3 name 3
1643 * 6 printer 3 name 3
1645 * that's the print server case, the printer case is even worse.
1650 /*******************************************************************
1652 * enumerate all printers on the printserver
1653 * fill a notify_info struct with info asked
1655 ********************************************************************/
1656 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1659 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1660 int n_services=lp_numservices();
1663 SPOOL_NOTIFY_OPTION *option;
1664 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1666 DEBUG(4,("printserver_notify_info\n"));
1668 option=Printer->notify.option;
1674 for (i=0; i<option->count; i++) {
1675 option_type=&(option->ctr.type[i]);
1677 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1680 for (snum=0; snum<n_services; snum++)
1681 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1682 if (construct_notify_printer_info(info, snum, option_type, id))
1687 * Debugging information, don't delete.
1690 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1691 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1692 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1694 for (i=0; i<info->count; i++) {
1695 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1696 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1697 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1701 return NT_STATUS_NO_PROBLEMO;
1704 /*******************************************************************
1706 * fill a notify_info struct with info asked
1708 ********************************************************************/
1709 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1712 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1715 SPOOL_NOTIFY_OPTION *option;
1716 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1718 print_queue_struct *queue=NULL;
1719 print_status_struct status;
1721 DEBUG(4,("printer_notify_info\n"));
1723 option=Printer->notify.option;
1729 get_printer_snum(hnd, &snum);
1731 for (i=0; i<option->count; i++) {
1732 option_type=&option->ctr.type[i];
1734 switch ( option_type->type ) {
1735 case PRINTER_NOTIFY_TYPE:
1736 if(construct_notify_printer_info(info, snum, option_type, id))
1740 case JOB_NOTIFY_TYPE:
1741 memset(&status, 0, sizeof(status));
1742 count = print_queue_status(snum, &queue, &status);
1743 for (j=0; j<count; j++)
1744 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1751 * Debugging information, don't delete.
1754 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1755 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1756 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1758 for (i=0; i<info->count; i++) {
1759 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1760 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1761 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1764 return NT_STATUS_NO_PROBLEMO;
1767 /********************************************************************
1769 ********************************************************************/
1770 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1771 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1773 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1775 if (!OPEN_HANDLE(Printer)) {
1776 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1777 return ERROR_INVALID_HANDLE;
1780 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1782 /* jfm: the change value isn't used right now.
1783 * we will honour it when
1784 * a) we'll be able to send notification to the client
1785 * b) we'll have a way to communicate between the spoolss process.
1787 * same thing for option->flags
1788 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1789 * I don't have a global notification system, I'm sending back all the
1790 * informations even when _NOTHING_ has changed.
1793 /* just discard the SPOOL_NOTIFY_OPTION */
1795 safe_free(option->ctr.type);
1797 switch (Printer->printer_type) {
1798 case PRINTER_HANDLE_IS_PRINTSERVER:
1799 return printserver_notify_info(handle, info);
1800 case PRINTER_HANDLE_IS_PRINTER:
1801 return printer_notify_info(handle, info);
1804 return ERROR_INVALID_HANDLE;
1807 /********************************************************************
1808 * construct_printer_info_0
1809 * fill a printer_info_1 struct
1810 ********************************************************************/
1811 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, fstring servername)
1815 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1816 counter_printer_0 *session_counter;
1817 uint32 global_counter;
1819 time_t setup_time = time(NULL);
1821 print_queue_struct *queue=NULL;
1822 print_status_struct status;
1824 memset(&status, 0, sizeof(status));
1826 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1829 count = print_queue_status(snum, &queue, &status);
1831 /* check if we already have a counter for this printer */
1832 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1834 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1835 if (session_counter->snum == snum)
1839 /* it's the first time, add it to the list */
1840 if (session_counter==NULL) {
1841 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1842 free_a_printer(&ntprinter, 2);
1845 ZERO_STRUCTP(session_counter);
1846 session_counter->snum=snum;
1847 session_counter->counter=0;
1848 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1852 session_counter->counter++;
1855 * the global_counter should be stored in a TDB as it's common to all the clients
1856 * and should be zeroed on samba startup
1858 global_counter=session_counter->counter;
1860 /* the description and the name are of the form \\server\share */
1861 slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter->info_2->printername);
1863 init_unistr(&printer->printername, chaine);
1865 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername);
1866 init_unistr(&printer->servername, chaine);
1868 printer->cjobs = count;
1869 printer->total_jobs = 0;
1870 printer->total_bytes = 0;
1872 t=gmtime(&setup_time);
1873 ntprinter->info_2->setuptime = (uint32)setup_time; /* FIXME !! */
1875 printer->year = t->tm_year+1900;
1876 printer->month = t->tm_mon+1;
1877 printer->dayofweek = t->tm_wday;
1878 printer->day = t->tm_mday;
1879 printer->hour = t->tm_hour;
1880 printer->minute = t->tm_min;
1881 printer->second = t->tm_sec;
1882 printer->milliseconds = 0;
1884 printer->global_counter = global_counter;
1885 printer->total_pages = 0;
1886 printer->major_version = 0x0004; /* NT 4 */
1887 printer->build_version = 0x0565; /* build 1381 */
1888 printer->unknown7 = 0x1;
1889 printer->unknown8 = 0x0;
1890 printer->unknown9 = 0x0;
1891 printer->session_counter = session_counter->counter;
1892 printer->unknown11 = 0x0;
1893 printer->printer_errors = 0x0; /* number of print failure */
1894 printer->unknown13 = 0x0;
1895 printer->unknown14 = 0x1;
1896 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1897 printer->unknown16 = 0x0;
1898 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1899 printer->unknown18 = 0x0;
1900 printer->status = nt_printq_status(status.status);
1901 printer->unknown20 = 0x0;
1902 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1903 printer->unknown22 = 0x0;
1904 printer->unknown23 = 0x6; /* 6 ???*/
1905 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1906 printer->unknown25 = 0;
1907 printer->unknown26 = 0;
1908 printer->unknown27 = 0;
1909 printer->unknown28 = 0;
1910 printer->unknown29 = 0;
1913 free_a_printer(&ntprinter,2);
1917 /********************************************************************
1918 * construct_printer_info_1
1919 * fill a printer_info_1 struct
1920 ********************************************************************/
1921 static BOOL construct_printer_info_1(fstring server, uint32 flags, PRINTER_INFO_1 *printer, int snum)
1925 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1927 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1930 printer->flags=flags;
1932 if (*ntprinter->info_2->comment == '\0') {
1933 init_unistr(&printer->comment, lp_comment(snum));
1934 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1935 ntprinter->info_2->drivername, lp_comment(snum));
1938 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1939 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1940 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1943 snprintf(chaine2,sizeof(chaine)-1,"%s%s", server, ntprinter->info_2->printername);
1945 init_unistr(&printer->description, chaine);
1946 init_unistr(&printer->name, chaine2);
1948 free_a_printer(&ntprinter,2);
1953 /****************************************************************************
1954 Free a DEVMODE struct.
1955 ****************************************************************************/
1957 static void free_dev_mode(DEVICEMODE *dev)
1963 safe_free(dev->private);
1968 /****************************************************************************
1969 Create a DEVMODE struct. Returns malloced memory.
1970 ****************************************************************************/
1972 static DEVICEMODE *construct_dev_mode(int snum, char *servername)
1976 NT_PRINTER_INFO_LEVEL *printer = NULL;
1977 NT_DEVICEMODE *ntdevmode = NULL;
1978 DEVICEMODE *devmode = NULL;
1980 DEBUG(7,("construct_dev_mode\n"));
1982 DEBUGADD(8,("getting printer characteristics\n"));
1984 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
1985 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
1989 ZERO_STRUCTP(devmode);
1991 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1994 if (printer->info_2->devmode)
1995 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
1997 if (ntdevmode == NULL)
2000 DEBUGADD(8,("loading DEVICEMODE\n"));
2002 snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, printer->info_2->printername);
2003 init_unistr(&devmode->devicename, adevice);
2005 snprintf(aform, sizeof(aform), ntdevmode->formname);
2006 init_unistr(&devmode->formname, aform);
2008 devmode->specversion = ntdevmode->specversion;
2009 devmode->driverversion = ntdevmode->driverversion;
2010 devmode->size = ntdevmode->size;
2011 devmode->driverextra = ntdevmode->driverextra;
2012 devmode->fields = ntdevmode->fields;
2014 devmode->orientation = ntdevmode->orientation;
2015 devmode->papersize = ntdevmode->papersize;
2016 devmode->paperlength = ntdevmode->paperlength;
2017 devmode->paperwidth = ntdevmode->paperwidth;
2018 devmode->scale = ntdevmode->scale;
2019 devmode->copies = ntdevmode->copies;
2020 devmode->defaultsource = ntdevmode->defaultsource;
2021 devmode->printquality = ntdevmode->printquality;
2022 devmode->color = ntdevmode->color;
2023 devmode->duplex = ntdevmode->duplex;
2024 devmode->yresolution = ntdevmode->yresolution;
2025 devmode->ttoption = ntdevmode->ttoption;
2026 devmode->collate = ntdevmode->collate;
2027 devmode->icmmethod = ntdevmode->icmmethod;
2028 devmode->icmintent = ntdevmode->icmintent;
2029 devmode->mediatype = ntdevmode->mediatype;
2030 devmode->dithertype = ntdevmode->dithertype;
2032 if (ntdevmode->private != NULL) {
2033 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2037 free_nt_devicemode(&ntdevmode);
2038 free_a_printer(&printer,2);
2045 free_nt_devicemode(&ntdevmode);
2047 free_a_printer(&printer,2);
2048 free_dev_mode(devmode);
2053 /********************************************************************
2054 * construct_printer_info_2
2055 * fill a printer_info_2 struct
2056 ********************************************************************/
2058 static BOOL construct_printer_info_2(fstring servername, PRINTER_INFO_2 *printer, int snum)
2064 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2066 print_queue_struct *queue=NULL;
2067 print_status_struct status;
2068 memset(&status, 0, sizeof(status));
2070 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2073 memset(&status, 0, sizeof(status));
2074 count = print_queue_status(snum, &queue, &status);
2076 snprintf(chaine, sizeof(chaine)-1, "%s", servername);
2078 if (strlen(servername)!=0)
2083 if (!strchr(ntprinter->info_2->printername, '\\')) {
2084 snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter->info_2->printername);
2086 pstrcpy(chaine2, ntprinter->info_2->printername);
2089 init_unistr(&printer->servername, chaine); /* servername*/
2090 init_unistr(&printer->printername, chaine2); /* printername*/
2091 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2092 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2093 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2095 if (*ntprinter->info_2->comment == '\0')
2096 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2098 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2100 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2101 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2102 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2103 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2104 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2106 printer->attributes = ntprinter->info_2->attributes;
2108 printer->priority = ntprinter->info_2->priority; /* priority */
2109 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2110 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2111 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2112 printer->status = nt_printq_status(status.status); /* status */
2113 printer->cjobs = count; /* jobs */
2114 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2116 if((printer->devmode = construct_dev_mode(snum, servername)) == NULL) {
2117 DEBUG(8, ("Returning NULL Devicemode!\n"));
2120 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2121 /* steal the printer info sec_desc structure. [badly done]. */
2122 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2123 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2124 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2125 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2128 printer->secdesc = NULL;
2131 free_a_printer(&ntprinter, 2);
2136 /********************************************************************
2137 * construct_printer_info_3
2138 * fill a printer_info_3 struct
2139 ********************************************************************/
2140 static BOOL construct_printer_info_3(fstring servername,
2141 PRINTER_INFO_3 **pp_printer, int snum)
2143 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2144 PRINTER_INFO_3 *printer = NULL;
2146 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2150 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2151 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2155 ZERO_STRUCTP(printer);
2157 printer->flags = 4; /* These are the components of the SD we are returning. */
2158 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2159 /* steal the printer info sec_desc structure. [badly done]. */
2160 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2164 * Set the flags for the components we are returning.
2167 if (printer->secdesc->owner_sid)
2168 printer->flags |= OWNER_SECURITY_INFORMATION;
2170 if (printer->secdesc->grp_sid)
2171 printer->flags |= GROUP_SECURITY_INFORMATION;
2173 if (printer->secdesc->dacl)
2174 printer->flags |= DACL_SECURITY_INFORMATION;
2176 if (printer->secdesc->sacl)
2177 printer->flags |= SACL_SECURITY_INFORMATION;
2180 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2181 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2182 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2185 free_a_printer(&ntprinter, 2);
2187 *pp_printer = printer;
2191 /********************************************************************
2192 Spoolss_enumprinters.
2193 ********************************************************************/
2194 static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2198 int n_services=lp_numservices();
2199 PRINTER_INFO_1 *printers=NULL;
2200 PRINTER_INFO_1 current_prt;
2202 DEBUG(4,("enum_all_printers_info_1\n"));
2204 for (snum=0; snum<n_services; snum++) {
2205 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2206 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2208 if (construct_printer_info_1(server, flags, ¤t_prt, snum)) {
2209 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2211 return ERROR_NOT_ENOUGH_MEMORY;
2213 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2214 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2220 /* check the required size. */
2221 for (i=0; i<*returned; i++)
2222 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2224 if (!alloc_buffer_size(buffer, *needed))
2225 return ERROR_INSUFFICIENT_BUFFER;
2227 /* fill the buffer with the structures */
2228 for (i=0; i<*returned; i++)
2229 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2232 safe_free(printers);
2234 if (*needed > offered) {
2236 return ERROR_INSUFFICIENT_BUFFER;
2239 return NT_STATUS_NO_PROBLEMO;
2242 /********************************************************************
2243 enum_all_printers_info_1_local.
2244 *********************************************************************/
2245 static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2248 DEBUG(4,("enum_all_printers_info_1_local\n"));
2250 fstrcpy(temp, "\\\\");
2251 fstrcat(temp, global_myname);
2253 if (!strcmp(name, temp)) {
2254 fstrcat(temp, "\\");
2255 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2258 return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2261 /********************************************************************
2262 enum_all_printers_info_1_name.
2263 *********************************************************************/
2264 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2267 DEBUG(4,("enum_all_printers_info_1_name\n"));
2269 fstrcpy(temp, "\\\\");
2270 fstrcat(temp, global_myname);
2272 if (!strcmp(name, temp)) {
2273 fstrcat(temp, "\\");
2274 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2277 return ERROR_INVALID_NAME;
2280 /********************************************************************
2281 enum_all_printers_info_1_remote.
2282 *********************************************************************/
2283 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2285 PRINTER_INFO_1 *printer;
2286 fstring printername;
2289 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2291 /* JFM: currently it's more a place holder than anything else.
2292 * In the spooler world there is a notion of server registration.
2293 * the print servers are registring (sp ?) on the PDC (in the same domain)
2295 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2298 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2299 return ERROR_NOT_ENOUGH_MEMORY;
2303 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2304 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2305 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2307 init_unistr(&printer->description, desc);
2308 init_unistr(&printer->name, printername);
2309 init_unistr(&printer->comment, comment);
2310 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2312 /* check the required size. */
2313 *needed += spoolss_size_printer_info_1(printer);
2315 if (!alloc_buffer_size(buffer, *needed)) {
2317 return ERROR_INSUFFICIENT_BUFFER;
2320 /* fill the buffer with the structures */
2321 new_smb_io_printer_info_1("", buffer, printer, 0);
2326 if (*needed > offered) {
2328 return ERROR_INSUFFICIENT_BUFFER;
2331 return NT_STATUS_NO_PROBLEMO;
2334 /********************************************************************
2335 enum_all_printers_info_1_network.
2336 *********************************************************************/
2337 static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2340 DEBUG(4,("enum_all_printers_info_1_network\n"));
2342 fstrcpy(temp, "\\\\");
2343 fstrcat(temp, global_myname);
2344 fstrcat(temp, "\\");
2345 return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2348 /********************************************************************
2349 * api_spoolss_enumprinters
2351 * called from api_spoolss_enumprinters (see this to understand)
2352 ********************************************************************/
2353 static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2357 int n_services=lp_numservices();
2358 PRINTER_INFO_2 *printers=NULL;
2359 PRINTER_INFO_2 current_prt;
2361 for (snum=0; snum<n_services; snum++) {
2362 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2363 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2365 if (construct_printer_info_2(servername, ¤t_prt, snum)) {
2366 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2367 return ERROR_NOT_ENOUGH_MEMORY;
2368 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2369 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2375 /* check the required size. */
2376 for (i=0; i<*returned; i++)
2377 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2379 if (!alloc_buffer_size(buffer, *needed)) {
2380 for (i=0; i<*returned; i++) {
2381 free_devmode(printers[i].devmode);
2382 free_sec_desc(&printers[i].secdesc);
2384 safe_free(printers);
2385 return ERROR_INSUFFICIENT_BUFFER;
2388 /* fill the buffer with the structures */
2389 for (i=0; i<*returned; i++)
2390 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2393 for (i=0; i<*returned; i++) {
2394 free_devmode(printers[i].devmode);
2395 free_sec_desc(&printers[i].secdesc);
2397 safe_free(printers);
2399 if (*needed > offered) {
2401 return ERROR_INSUFFICIENT_BUFFER;
2404 return NT_STATUS_NO_PROBLEMO;
2407 /********************************************************************
2408 * handle enumeration of printers at level 1
2409 ********************************************************************/
2410 static uint32 enumprinters_level1( uint32 flags, fstring name,
2411 NEW_BUFFER *buffer, uint32 offered,
2412 uint32 *needed, uint32 *returned)
2414 /* Not all the flags are equals */
2416 if (flags & PRINTER_ENUM_LOCAL)
2417 return enum_all_printers_info_1_local(name, buffer, offered, needed, returned);
2419 if (flags & PRINTER_ENUM_NAME)
2420 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2422 if (flags & PRINTER_ENUM_REMOTE)
2423 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2425 if (flags & PRINTER_ENUM_NETWORK)
2426 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
2428 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2431 /********************************************************************
2432 * handle enumeration of printers at level 2
2433 ********************************************************************/
2434 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2435 NEW_BUFFER *buffer, uint32 offered,
2436 uint32 *needed, uint32 *returned)
2440 fstrcpy(temp, "\\\\");
2441 fstrcat(temp, global_myname);
2443 if (flags & PRINTER_ENUM_LOCAL) {
2444 if (!strcmp(servername, temp))
2445 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2447 return enum_all_printers_info_2("", buffer, offered, needed, returned);
2450 if (flags & PRINTER_ENUM_NAME) {
2451 if (!strcmp(servername, temp))
2452 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2454 return ERROR_INVALID_NAME;
2457 if (flags & PRINTER_ENUM_REMOTE)
2458 return ERROR_INVALID_LEVEL;
2460 return NT_STATUS_NO_PROBLEMO;
2463 /********************************************************************
2464 * handle enumeration of printers at level 5
2465 ********************************************************************/
2466 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2467 NEW_BUFFER *buffer, uint32 offered,
2468 uint32 *needed, uint32 *returned)
2470 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2471 return NT_STATUS_NO_PROBLEMO;
2474 /********************************************************************
2475 * api_spoolss_enumprinters
2477 * called from api_spoolss_enumprinters (see this to understand)
2478 ********************************************************************/
2479 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2480 NEW_BUFFER *buffer, uint32 offered,
2481 uint32 *needed, uint32 *returned)
2485 DEBUG(4,("_spoolss_enumprinters\n"));
2492 * flags==PRINTER_ENUM_NAME
2493 * if name=="" then enumerates all printers
2494 * if name!="" then enumerate the printer
2495 * flags==PRINTER_ENUM_REMOTE
2496 * name is NULL, enumerate printers
2497 * Level 2: name!="" enumerates printers, name can't be NULL
2498 * Level 3: doesn't exist
2499 * Level 4: does a local registry lookup
2500 * Level 5: same as Level 2
2503 unistr2_to_ascii(name, servername, sizeof(name)-1);
2508 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2510 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2512 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2516 return ERROR_INVALID_LEVEL;
2520 /****************************************************************************
2521 ****************************************************************************/
2522 static uint32 getprinter_level_0(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2524 PRINTER_INFO_0 *printer=NULL;
2526 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2527 return ERROR_NOT_ENOUGH_MEMORY;
2529 construct_printer_info_0(printer, snum, servername);
2531 /* check the required size. */
2532 *needed += spoolss_size_printer_info_0(printer);
2534 if (!alloc_buffer_size(buffer, *needed)) {
2536 return ERROR_INSUFFICIENT_BUFFER;
2539 /* fill the buffer with the structures */
2540 new_smb_io_printer_info_0("", buffer, printer, 0);
2545 if (*needed > offered) {
2546 return ERROR_INSUFFICIENT_BUFFER;
2549 return NT_STATUS_NO_PROBLEMO;
2552 /****************************************************************************
2553 ****************************************************************************/
2554 static uint32 getprinter_level_1(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2556 PRINTER_INFO_1 *printer=NULL;
2558 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2559 return ERROR_NOT_ENOUGH_MEMORY;
2561 construct_printer_info_1(servername, PRINTER_ENUM_ICON8, printer, snum);
2563 /* check the required size. */
2564 *needed += spoolss_size_printer_info_1(printer);
2566 if (!alloc_buffer_size(buffer, *needed)) {
2568 return ERROR_INSUFFICIENT_BUFFER;
2571 /* fill the buffer with the structures */
2572 new_smb_io_printer_info_1("", buffer, printer, 0);
2577 if (*needed > offered) {
2578 return ERROR_INSUFFICIENT_BUFFER;
2581 return NT_STATUS_NO_PROBLEMO;
2584 /****************************************************************************
2585 ****************************************************************************/
2586 static uint32 getprinter_level_2(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2588 PRINTER_INFO_2 *printer=NULL;
2591 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2592 return ERROR_NOT_ENOUGH_MEMORY;
2594 fstrcpy(temp, "\\\\");
2595 fstrcat(temp, servername);
2596 construct_printer_info_2(temp, printer, snum);
2598 /* check the required size. */
2599 *needed += spoolss_size_printer_info_2(printer);
2601 if (!alloc_buffer_size(buffer, *needed)) {
2602 free_printer_info_2(printer);
2603 return ERROR_INSUFFICIENT_BUFFER;
2606 /* fill the buffer with the structures */
2607 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2608 free_printer_info_2(printer);
2609 return ERROR_NOT_ENOUGH_MEMORY;
2613 free_printer_info_2(printer);
2615 if (*needed > offered) {
2616 return ERROR_INSUFFICIENT_BUFFER;
2619 return NT_STATUS_NO_PROBLEMO;
2622 /****************************************************************************
2623 ****************************************************************************/
2624 static uint32 getprinter_level_3(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2626 PRINTER_INFO_3 *printer=NULL;
2629 fstrcpy(temp, "\\\\");
2630 fstrcat(temp, servername);
2631 if (!construct_printer_info_3(temp, &printer, snum))
2632 return ERROR_NOT_ENOUGH_MEMORY;
2634 /* check the required size. */
2635 *needed += spoolss_size_printer_info_3(printer);
2637 if (!alloc_buffer_size(buffer, *needed)) {
2638 free_printer_info_3(printer);
2639 return ERROR_INSUFFICIENT_BUFFER;
2642 /* fill the buffer with the structures */
2643 new_smb_io_printer_info_3("", buffer, printer, 0);
2646 free_printer_info_3(printer);
2648 if (*needed > offered) {
2649 return ERROR_INSUFFICIENT_BUFFER;
2652 return NT_STATUS_NO_PROBLEMO;
2655 /****************************************************************************
2656 ****************************************************************************/
2657 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2658 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2665 pstrcpy(servername, global_myname);
2667 if (!get_printer_snum(handle, &snum))
2668 return ERROR_INVALID_HANDLE;
2672 return getprinter_level_0(servername, snum, buffer, offered, needed);
2674 return getprinter_level_1(servername,snum, buffer, offered, needed);
2676 return getprinter_level_2(servername,snum, buffer, offered, needed);
2678 return getprinter_level_3(servername,snum, buffer, offered, needed);
2680 return ERROR_INVALID_LEVEL;
2684 /********************************************************************
2685 * fill a DRIVER_INFO_1 struct
2686 ********************************************************************/
2687 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2689 init_unistr( &info->name, driver.info_3->name);
2692 /********************************************************************
2693 * construct_printer_driver_info_1
2694 ********************************************************************/
2695 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2697 NT_PRINTER_INFO_LEVEL *printer = NULL;
2698 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2700 ZERO_STRUCT(driver);
2702 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2703 return ERROR_INVALID_PRINTER_NAME;
2705 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2706 return ERROR_UNKNOWN_PRINTER_DRIVER;
2708 fill_printer_driver_info_1(info, driver, servername, architecture);
2710 free_a_printer(&printer,2);
2712 return NT_STATUS_NO_PROBLEMO;
2715 /********************************************************************
2716 * construct_printer_driver_info_2
2717 * fill a printer_info_2 struct
2718 ********************************************************************/
2719 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2721 pstring temp_driverpath;
2722 pstring temp_datafile;
2723 pstring temp_configfile;
2725 info->version=driver.info_3->cversion;
2727 init_unistr( &info->name, driver.info_3->name );
2728 init_unistr( &info->architecture, driver.info_3->environment );
2730 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2731 init_unistr( &info->driverpath, temp_driverpath );
2733 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2734 init_unistr( &info->datafile, temp_datafile );
2736 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2737 init_unistr( &info->configfile, temp_configfile );
2740 /********************************************************************
2741 * construct_printer_driver_info_2
2742 * fill a printer_info_2 struct
2743 ********************************************************************/
2744 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2746 NT_PRINTER_INFO_LEVEL *printer = NULL;
2747 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2749 ZERO_STRUCT(printer);
2750 ZERO_STRUCT(driver);
2752 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2753 return ERROR_INVALID_PRINTER_NAME;
2755 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2756 return ERROR_UNKNOWN_PRINTER_DRIVER;
2758 fill_printer_driver_info_2(info, driver, servername);
2760 free_a_printer(&printer,2);
2762 return NT_STATUS_NO_PROBLEMO;
2765 /********************************************************************
2766 * copy a strings array and convert to UNICODE
2768 * convert an array of ascii string to a UNICODE string
2769 ********************************************************************/
2770 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2777 DEBUG(6,("init_unistr_array\n"));
2781 if (char_array == NULL)
2785 if (!v) v = ""; /* hack to handle null lists */
2787 if (strlen(v) == 0) break;
2788 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2789 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2790 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2791 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2794 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2799 (*uni_array)[j]=0x0000;
2802 DEBUGADD(6,("last one:done\n"));
2805 /********************************************************************
2806 * construct_printer_info_3
2807 * fill a printer_info_3 struct
2808 ********************************************************************/
2809 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2811 pstring temp_driverpath;
2812 pstring temp_datafile;
2813 pstring temp_configfile;
2814 pstring temp_helpfile;
2818 info->version=driver.info_3->cversion;
2820 init_unistr( &info->name, driver.info_3->name );
2821 init_unistr( &info->architecture, driver.info_3->environment );
2823 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2824 init_unistr( &info->driverpath, temp_driverpath );
2826 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2827 init_unistr( &info->datafile, temp_datafile );
2829 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2830 init_unistr( &info->configfile, temp_configfile );
2832 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2833 init_unistr( &info->helpfile, temp_helpfile );
2835 init_unistr( &info->monitorname, driver.info_3->monitorname );
2836 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2838 info->dependentfiles=NULL;
2839 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2842 /********************************************************************
2843 * construct_printer_info_3
2844 * fill a printer_info_3 struct
2845 ********************************************************************/
2846 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2848 NT_PRINTER_INFO_LEVEL *printer = NULL;
2849 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2851 ZERO_STRUCT(driver);
2853 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2854 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2856 return ERROR_INVALID_PRINTER_NAME;
2858 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2859 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2861 free_a_printer(&printer,2);
2862 return ERROR_UNKNOWN_PRINTER_DRIVER;
2865 fill_printer_driver_info_3(info, driver, servername);
2867 free_a_printer(&printer,2);
2869 return NT_STATUS_NO_PROBLEMO;
2872 /********************************************************************
2873 * construct_printer_info_6
2874 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2875 ********************************************************************/
2877 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2879 pstring temp_driverpath;
2880 pstring temp_datafile;
2881 pstring temp_configfile;
2882 pstring temp_helpfile;
2886 memset(&nullstr, '\0', sizeof(fstring));
2888 info->version=driver.info_3->cversion;
2890 init_unistr( &info->name, driver.info_3->name );
2891 init_unistr( &info->architecture, driver.info_3->environment );
2893 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2894 init_unistr( &info->driverpath, temp_driverpath );
2896 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2897 init_unistr( &info->datafile, temp_datafile );
2899 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2900 init_unistr( &info->configfile, temp_configfile );
2902 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2903 init_unistr( &info->helpfile, temp_helpfile );
2905 init_unistr( &info->monitorname, driver.info_3->monitorname );
2906 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2908 info->dependentfiles=NULL;
2909 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2911 info->previousdrivernames=NULL;
2912 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2914 info->driver_date.low=0;
2915 info->driver_date.high=0;
2918 info->driver_version_low=0;
2919 info->driver_version_high=0;
2921 init_unistr( &info->mfgname, "");
2922 init_unistr( &info->oem_url, "");
2923 init_unistr( &info->hardware_id, "");
2924 init_unistr( &info->provider, "");
2927 /********************************************************************
2928 * construct_printer_info_6
2929 * fill a printer_info_6 struct
2930 ********************************************************************/
2931 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2933 NT_PRINTER_INFO_LEVEL *printer = NULL;
2934 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2936 ZERO_STRUCT(driver);
2938 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2939 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2941 return ERROR_INVALID_PRINTER_NAME;
2943 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2944 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2946 free_a_printer(&printer,2);
2947 return ERROR_UNKNOWN_PRINTER_DRIVER;
2950 fill_printer_driver_info_6(info, driver, servername);
2952 free_a_printer(&printer,2);
2954 return NT_STATUS_NO_PROBLEMO;
2957 /****************************************************************************
2958 ****************************************************************************/
2960 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2962 safe_free(info->dependentfiles);
2965 /****************************************************************************
2966 ****************************************************************************/
2968 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2970 safe_free(info->dependentfiles);
2974 /****************************************************************************
2975 ****************************************************************************/
2976 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2978 DRIVER_INFO_1 *info=NULL;
2981 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2982 return ERROR_NOT_ENOUGH_MEMORY;
2984 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2985 if (status != NT_STATUS_NO_PROBLEMO) {
2990 /* check the required size. */
2991 *needed += spoolss_size_printer_driver_info_1(info);
2993 if (!alloc_buffer_size(buffer, *needed)) {
2995 return ERROR_INSUFFICIENT_BUFFER;
2998 /* fill the buffer with the structures */
2999 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3004 if (*needed > offered)
3005 return ERROR_INSUFFICIENT_BUFFER;
3007 return NT_STATUS_NO_PROBLEMO;
3010 /****************************************************************************
3011 ****************************************************************************/
3012 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3014 DRIVER_INFO_2 *info=NULL;
3017 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3018 return ERROR_NOT_ENOUGH_MEMORY;
3020 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3021 if (status != NT_STATUS_NO_PROBLEMO) {
3026 /* check the required size. */
3027 *needed += spoolss_size_printer_driver_info_2(info);
3029 if (!alloc_buffer_size(buffer, *needed)) {
3031 return ERROR_INSUFFICIENT_BUFFER;
3034 /* fill the buffer with the structures */
3035 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3040 if (*needed > offered)
3041 return ERROR_INSUFFICIENT_BUFFER;
3043 return NT_STATUS_NO_PROBLEMO;
3046 /****************************************************************************
3047 ****************************************************************************/
3048 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3055 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3056 if (status != NT_STATUS_NO_PROBLEMO) {
3060 /* check the required size. */
3061 *needed += spoolss_size_printer_driver_info_3(&info);
3063 if (!alloc_buffer_size(buffer, *needed)) {
3064 free_printer_driver_info_3(&info);
3065 return ERROR_INSUFFICIENT_BUFFER;
3068 /* fill the buffer with the structures */
3069 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3071 free_printer_driver_info_3(&info);
3073 if (*needed > offered)
3074 return ERROR_INSUFFICIENT_BUFFER;
3076 return NT_STATUS_NO_PROBLEMO;
3079 /****************************************************************************
3080 ****************************************************************************/
3081 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3088 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3089 if (status != NT_STATUS_NO_PROBLEMO) {
3093 /* check the required size. */
3094 *needed += spoolss_size_printer_driver_info_6(&info);
3096 if (!alloc_buffer_size(buffer, *needed)) {
3097 free_printer_driver_info_6(&info);
3098 return ERROR_INSUFFICIENT_BUFFER;
3101 /* fill the buffer with the structures */
3102 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3104 free_printer_driver_info_6(&info);
3106 if (*needed > offered)
3107 return ERROR_INSUFFICIENT_BUFFER;
3109 return NT_STATUS_NO_PROBLEMO;
3112 /****************************************************************************
3113 ****************************************************************************/
3114 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3115 uint32 clientmajorversion, uint32 clientminorversion,
3116 NEW_BUFFER *buffer, uint32 offered,
3117 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3120 fstring architecture;
3123 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3126 *servermajorversion=0;
3127 *serverminorversion=0;
3129 pstrcpy(servername, global_myname);
3130 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3132 if (!get_printer_snum(handle, &snum))
3133 return ERROR_INVALID_HANDLE;
3137 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3139 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3141 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3143 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3145 return ERROR_INVALID_LEVEL;
3149 /****************************************************************************
3150 ****************************************************************************/
3151 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3153 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3155 if (OPEN_HANDLE(Printer)) {
3156 Printer->page_started=True;
3160 DEBUG(3,("Error in startpageprinter printer handle\n"));
3161 return ERROR_INVALID_HANDLE;
3164 /****************************************************************************
3165 ****************************************************************************/
3166 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3168 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3170 if (!OPEN_HANDLE(Printer)) {
3171 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3172 return ERROR_INVALID_HANDLE;
3175 Printer->page_started=False;
3177 return NT_STATUS_NO_PROBLEMO;
3180 /****************************************************************************
3181 Return a user struct for a pipe user.
3182 ****************************************************************************/
3184 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3186 if (p->ntlmssp_auth_validated) {
3187 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3189 extern struct current_user current_user;
3190 memcpy(user, ¤t_user, sizeof(struct current_user));
3196 /********************************************************************
3197 * api_spoolss_getprinter
3198 * called from the spoolss dispatcher
3200 ********************************************************************/
3201 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3202 pipes_struct *p, DOC_INFO *docinfo,
3205 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3209 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3210 struct current_user user;
3212 if (!OPEN_HANDLE(Printer)) {
3213 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3214 return ERROR_INVALID_HANDLE;
3217 get_current_user(&user, p);
3220 * a nice thing with NT is it doesn't listen to what you tell it.
3221 * when asked to send _only_ RAW datas, it tries to send datas
3224 * So I add checks like in NT Server ...
3226 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3227 * there's a bug in NT client-side code, so we'll fix it in the
3228 * server-side code. *nnnnnggggh!*
3231 if (info_1->p_datatype != 0) {
3232 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3233 if (strcmp(datatype, "RAW") != 0) {
3235 return ERROR_INVALID_DATATYPE;
3239 /* get the share number of the printer */
3240 if (!get_printer_snum(handle, &snum)) {
3241 return ERROR_INVALID_HANDLE;
3244 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3246 Printer->jobid = print_job_start(&user, snum, jobname);
3248 /* An error occured in print_job_start() so return an appropriate
3251 if (Printer->jobid == -1) {
3252 return map_nt_error_from_unix(errno);
3255 Printer->document_started=True;
3256 (*jobid) = Printer->jobid;
3258 srv_spoolss_sendnotify(handle);
3262 /********************************************************************
3263 * api_spoolss_getprinter
3264 * called from the spoolss dispatcher
3266 ********************************************************************/
3267 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3269 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3271 if (!OPEN_HANDLE(Printer)) {
3272 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3273 return ERROR_INVALID_HANDLE;
3276 Printer->document_started=False;
3277 print_job_end(Printer->jobid);
3278 /* error codes unhandled so far ... */
3280 srv_spoolss_sendnotify(handle);
3285 /****************************************************************************
3286 ****************************************************************************/
3287 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3290 uint32 *buffer_written)
3292 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3294 if (!OPEN_HANDLE(Printer)) {
3295 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3296 return ERROR_INVALID_HANDLE;
3299 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3305 /********************************************************************
3306 * api_spoolss_getprinter
3307 * called from the spoolss dispatcher
3309 ********************************************************************/
3310 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3313 struct current_user user;
3316 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3318 get_current_user(&user, p);
3320 if (!OPEN_HANDLE(Printer)) {
3321 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3322 return ERROR_INVALID_HANDLE;
3325 if (!get_printer_snum(handle, &snum) )
3326 return ERROR_INVALID_HANDLE;
3329 case PRINTER_CONTROL_PAUSE:
3330 if (print_queue_pause(&user, snum, &errcode)) {
3331 srv_spoolss_sendnotify(handle);
3335 case PRINTER_CONTROL_RESUME:
3336 case PRINTER_CONTROL_UNPAUSE:
3337 if (print_queue_resume(&user, snum, &errcode)) {
3338 srv_spoolss_sendnotify(handle);
3342 case PRINTER_CONTROL_PURGE:
3343 if (print_queue_purge(&user, snum, &errcode)) {
3344 srv_spoolss_sendnotify(handle);
3351 return (uint32)errcode;
3353 return ERROR_INVALID_FUNCTION;
3356 /********************************************************************
3357 * api_spoolss_abortprinter
3358 ********************************************************************/
3360 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3362 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3365 /********************************************************************
3366 * called by spoolss_api_setprinter
3367 * when updating a printer description
3368 ********************************************************************/
3369 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3370 const SPOOL_PRINTER_INFO_LEVEL *info,
3371 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3373 struct current_user user;
3377 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3379 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3380 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3381 return ERROR_INVALID_HANDLE;
3384 /* Work out which user is performing the operation */
3385 get_current_user(&user, p);
3387 /* Check the user has permissions to change the security
3388 descriptor. By experimentation with two NT machines, the user
3389 requires Full Access to the printer to change security
3391 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3392 result = ERROR_ACCESS_DENIED;
3396 result = nt_printing_setsec(Printer->dev.handlename, secdesc_ctr);
3402 /********************************************************************
3403 Do Samba sanity checks on a printer info struct.
3404 ********************************************************************/
3406 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3409 * Ensure that this printer is shared under the correct name
3410 * as this is what Samba insists upon.
3413 if (!(info->attributes & (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_NETWORK))) {
3414 DEBUG(10,("check_printer_ok: SHARED/NETWORK check failed (%x).\n",
3415 (unsigned int)info->attributes ));
3419 if (!(info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY)) {
3420 /* NT forgets to set the raw attribute but sends the correct type. */
3421 if (strequal(info->datatype, "RAW"))
3422 info->attributes |= PRINTER_ATTRIBUTE_RAW_ONLY;
3424 DEBUG(10,("check_printer_ok: RAW check failed (%x).\n", (unsigned int)info->attributes ));
3430 * Sometimes the NT client doesn't set the sharename, but
3431 * includes the sharename in the printername. This could
3432 * cause SETPRINTER to fail which causes problems with the
3433 * client getting confused between local/remote printers...
3436 if (*info->sharename == '\0') {
3437 char *p = strrchr(info->printername, '\\');
3439 fstrcpy(info->sharename, p+1);
3442 if (!strequal(info->sharename, lp_servicename(snum))) {
3443 DEBUG(10,("check_printer_ok: NAME check failed (%s) (%s).\n",
3444 info->sharename, lp_servicename(snum)));
3451 /****************************************************************************
3452 ****************************************************************************/
3453 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3455 pid_t local_pid = sys_getpid();
3456 char *cmd = lp_addprinter_cmd();
3461 pstring driverlocation;
3465 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3466 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3470 /* build driver path... only 9X architecture is needed for legacy reasons */
3471 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3473 /* change \ to \\ for the shell */
3474 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3476 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3477 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3478 cmd, printer->info_2->printername, printer->info_2->sharename,
3479 printer->info_2->portname, printer->info_2->drivername,
3480 printer->info_2->location, driverlocation);
3483 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3484 ret = smbrun(command, tmp_file, False);
3485 DEBUGADD(10,("returned [%d]\n", ret));
3493 qlines = file_lines_load(tmp_file, &numlines);
3494 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3495 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3499 /* Set the portname to what the script says the portname should be. */
3500 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3501 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3503 /* Send SIGHUP to process group... is there a better way? */
3508 file_lines_free(qlines);
3512 /********************************************************************
3513 * called by spoolss_api_setprinter
3514 * when updating a printer description
3515 ********************************************************************/
3517 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3518 const SPOOL_PRINTER_INFO_LEVEL *info,
3519 DEVICEMODE *devmode)
3522 NT_PRINTER_INFO_LEVEL *printer = NULL;
3523 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3526 DEBUG(8,("update_printer\n"));
3528 result = NT_STATUS_NO_PROBLEMO;
3530 /* Check calling user has permission to update printer description */
3533 DEBUG(0,("Send a mail to samba@samba.org\n"));
3534 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3535 result = ERROR_INVALID_LEVEL;
3539 if (!OPEN_HANDLE(Printer)) {
3540 result = ERROR_INVALID_HANDLE;
3544 if (!get_printer_snum(handle, &snum)) {
3545 result = ERROR_INVALID_HANDLE;
3549 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3550 DEBUG(3, ("printer property change denied by security "
3552 result = ERROR_ACCESS_DENIED;
3556 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0) {
3557 result = ERROR_INVALID_HANDLE;
3561 DEBUGADD(8,("Converting info_2 struct\n"));
3564 * convert_printer_info converts the incoming
3565 * info from the client and overwrites the info
3566 * just read from the tdb in the pointer 'printer'.
3569 convert_printer_info(info, printer, level);
3571 if (info->info_2->devmode_ptr != 0) {
3572 /* we have a valid devmode
3573 convert it and link it*/
3576 * Ensure printer->info_2->devmode is a valid pointer
3577 * as we will be overwriting it in convert_devicemode().
3580 if (printer->info_2->devmode == NULL)
3581 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3583 DEBUGADD(8,("Converting the devicemode struct\n"));
3584 convert_devicemode(devmode, printer->info_2->devmode);
3587 if (printer->info_2->devmode != NULL)
3588 free_nt_devicemode(&printer->info_2->devmode);
3589 printer->info_2->devmode=NULL;
3593 * Do sanity check on the requested changes for Samba.
3596 if (!check_printer_ok(printer->info_2, snum)) {
3597 result = ERROR_INVALID_PARAMETER;
3601 if (*lp_addprinter_cmd() )
3602 if ( !add_printer_hook(printer) ) {
3603 result = ERROR_ACCESS_DENIED;
3607 if (add_a_printer(*printer, 2)!=0) {
3608 /* I don't really know what to return here !!! */
3609 result = ERROR_ACCESS_DENIED;
3614 free_a_printer(&printer, 2);
3616 srv_spoolss_sendnotify(handle);
3621 /****************************************************************************
3622 ****************************************************************************/
3623 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3624 const SPOOL_PRINTER_INFO_LEVEL *info,
3625 DEVMODE_CTR devmode_ctr,
3626 SEC_DESC_BUF *secdesc_ctr,
3627 uint32 command, pipes_struct *p)
3629 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3631 if (!OPEN_HANDLE(Printer)) {
3632 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3633 return ERROR_INVALID_HANDLE;
3636 /* check the level */
3639 return control_printer(handle, command, p);
3641 return update_printer(handle, level, info, devmode_ctr.devmode);
3643 return update_printer_sec(handle, level, info, p,
3646 return ERROR_INVALID_LEVEL;
3650 /****************************************************************************
3651 ****************************************************************************/
3652 uint32 _spoolss_fcpn(POLICY_HND *handle)
3654 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3656 if (!OPEN_HANDLE(Printer)) {
3657 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3658 return ERROR_INVALID_HANDLE;
3661 if (Printer->notify.client_connected==True)
3662 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3663 return ERROR_INVALID_HANDLE;
3665 Printer->notify.flags=0;
3666 Printer->notify.options=0;
3667 Printer->notify.localmachine[0]='\0';
3668 Printer->notify.printerlocal=0;
3669 if (Printer->notify.option)
3670 safe_free(Printer->notify.option->ctr.type);
3671 safe_free(Printer->notify.option);
3672 Printer->notify.option=NULL;
3673 Printer->notify.client_connected=False;
3675 return NT_STATUS_NO_PROBLEMO;
3678 /****************************************************************************
3679 ****************************************************************************/
3680 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3681 NEW_BUFFER *buffer, uint32 offered,
3685 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3686 returns for AddJob. AddJob
3687 must fail on non-local
3691 /****************************************************************************
3692 ****************************************************************************/
3693 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3694 int position, int snum)
3699 time_t unixdate = time(NULL);
3701 t=gmtime(&unixdate);
3702 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3704 job_info->jobid=queue->job;
3705 init_unistr(&job_info->printername, lp_servicename(snum));
3706 init_unistr(&job_info->machinename, temp_name);
3707 init_unistr(&job_info->username, queue->user);
3708 init_unistr(&job_info->document, queue->file);
3709 init_unistr(&job_info->datatype, "RAW");
3710 init_unistr(&job_info->text_status, "");
3711 job_info->status=nt_printj_status(queue->status);
3712 job_info->priority=queue->priority;
3713 job_info->position=position;
3714 job_info->totalpages=0;
3715 job_info->pagesprinted=0;
3717 make_systemtime(&job_info->submitted, t);
3720 /****************************************************************************
3721 ****************************************************************************/
3722 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3723 int position, int snum)
3726 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3730 time_t unixdate = time(NULL);
3732 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3735 t=gmtime(&unixdate);
3736 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3738 job_info->jobid=queue->job;
3740 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3742 init_unistr(&job_info->printername, chaine);
3744 init_unistr(&job_info->machinename, temp_name);
3745 init_unistr(&job_info->username, queue->user);
3746 init_unistr(&job_info->document, queue->file);
3747 init_unistr(&job_info->notifyname, queue->user);
3748 init_unistr(&job_info->datatype, "RAW");
3749 init_unistr(&job_info->printprocessor, "winprint");
3750 init_unistr(&job_info->parameters, "");
3751 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3752 init_unistr(&job_info->text_status, "");
3754 /* and here the security descriptor */
3756 job_info->status=nt_printj_status(queue->status);
3757 job_info->priority=queue->priority;
3758 job_info->position=position;
3759 job_info->starttime=0;
3760 job_info->untiltime=0;
3761 job_info->totalpages=0;
3762 job_info->size=queue->size;
3763 make_systemtime(&(job_info->submitted), t);
3764 job_info->timeelapsed=0;
3765 job_info->pagesprinted=0;
3767 if((job_info->devmode = construct_dev_mode(snum, global_myname)) == NULL) {
3768 free_a_printer(&ntprinter, 2);
3772 free_a_printer(&ntprinter, 2);
3776 /****************************************************************************
3777 Enumjobs at level 1.
3778 ****************************************************************************/
3779 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3780 NEW_BUFFER *buffer, uint32 offered,
3781 uint32 *needed, uint32 *returned)
3786 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3790 return ERROR_NOT_ENOUGH_MEMORY;
3793 for (i=0; i<*returned; i++)
3794 fill_job_info_1(&info[i], &queue[i], i, snum);
3798 /* check the required size. */
3799 for (i=0; i<*returned; i++)
3800 (*needed) += spoolss_size_job_info_1(&info[i]);
3802 if (!alloc_buffer_size(buffer, *needed)) {
3804 return ERROR_INSUFFICIENT_BUFFER;
3807 /* fill the buffer with the structures */
3808 for (i=0; i<*returned; i++)
3809 new_smb_io_job_info_1("", buffer, &info[i], 0);
3814 if (*needed > offered) {
3816 return ERROR_INSUFFICIENT_BUFFER;
3819 return NT_STATUS_NO_PROBLEMO;
3822 /****************************************************************************
3823 Enumjobs at level 2.
3824 ****************************************************************************/
3825 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
3826 NEW_BUFFER *buffer, uint32 offered,
3827 uint32 *needed, uint32 *returned)
3832 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
3836 return ERROR_NOT_ENOUGH_MEMORY;
3839 for (i=0; i<*returned; i++)
3840 fill_job_info_2(&(info[i]), &queue[i], i, snum);
3844 /* check the required size. */
3845 for (i=0; i<*returned; i++)
3846 (*needed) += spoolss_size_job_info_2(&info[i]);
3848 if (!alloc_buffer_size(buffer, *needed)) {
3850 return ERROR_INSUFFICIENT_BUFFER;
3853 /* fill the buffer with the structures */
3854 for (i=0; i<*returned; i++)
3855 new_smb_io_job_info_2("", buffer, &info[i], 0);
3860 if (*needed > offered) {
3862 return ERROR_INSUFFICIENT_BUFFER;
3865 return NT_STATUS_NO_PROBLEMO;
3868 /****************************************************************************
3870 ****************************************************************************/
3871 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
3872 NEW_BUFFER *buffer, uint32 offered,
3873 uint32 *needed, uint32 *returned)
3876 print_queue_struct *queue=NULL;
3877 print_status_struct prt_status;
3879 DEBUG(4,("_spoolss_enumjobs\n"));
3881 ZERO_STRUCT(prt_status);
3886 if (!get_printer_snum(handle, &snum))
3887 return ERROR_INVALID_HANDLE;
3889 *returned = print_queue_status(snum, &queue, &prt_status);
3890 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
3892 if (*returned == 0) {
3894 return NT_STATUS_NO_PROBLEMO;
3899 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
3901 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
3905 return ERROR_INVALID_LEVEL;
3910 /****************************************************************************
3911 ****************************************************************************/
3912 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
3917 /****************************************************************************
3918 ****************************************************************************/
3919 uint32 _spoolss_setjob( POLICY_HND *handle,
3927 struct current_user user;
3929 print_status_struct prt_status;
3931 memset(&prt_status, 0, sizeof(prt_status));
3933 if (!get_printer_snum(handle, &snum)) {
3934 return ERROR_INVALID_HANDLE;
3937 if (!print_job_exists(jobid)) {
3938 return ERROR_INVALID_PRINTER_NAME;
3941 get_current_user(&user, p);
3944 case JOB_CONTROL_CANCEL:
3945 case JOB_CONTROL_DELETE:
3946 if (print_job_delete(&user, jobid)) {
3947 srv_spoolss_sendnotify(handle);
3951 case JOB_CONTROL_PAUSE:
3952 if (print_job_pause(&user, jobid)) {
3953 srv_spoolss_sendnotify(handle);
3957 case JOB_CONTROL_RESUME:
3958 if (print_job_resume(&user, jobid)) {
3959 srv_spoolss_sendnotify(handle);
3964 return ERROR_INVALID_LEVEL;
3967 return ERROR_INVALID_HANDLE;
3970 /****************************************************************************
3971 Enumerates all printer drivers at level 1.
3972 ****************************************************************************/
3973 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3978 fstring *list = NULL;
3980 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3981 DRIVER_INFO_1 *driver_info_1=NULL;
3985 #define MAX_VERSION 4
3987 for (version=0; version<MAX_VERSION; version++) {
3989 ndrivers=get_ntdrivers(&list, architecture, version);
3990 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
3993 return ERROR_NOT_ENOUGH_MEMORY;
3996 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
3998 return ERROR_NOT_ENOUGH_MEMORY;
4002 for (i=0; i<ndrivers; i++) {
4004 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4005 ZERO_STRUCT(driver);
4006 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4010 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4011 free_a_printer_driver(driver, 3);
4014 *returned+=ndrivers;
4018 /* check the required size. */
4019 for (i=0; i<*returned; i++) {
4020 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4021 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4024 if (!alloc_buffer_size(buffer, *needed)) {
4025 safe_free(driver_info_1);
4026 return ERROR_INSUFFICIENT_BUFFER;
4029 /* fill the buffer with the form structures */
4030 for (i=0; i<*returned; i++) {
4031 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4032 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4035 safe_free(driver_info_1);
4037 if (*needed > offered) {
4039 return ERROR_INSUFFICIENT_BUFFER;
4042 return NT_STATUS_NO_PROBLEMO;
4045 /****************************************************************************
4046 Enumerates all printer drivers at level 2.
4047 ****************************************************************************/
4048 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4053 fstring *list = NULL;
4055 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4056 DRIVER_INFO_2 *driver_info_2=NULL;
4060 #define MAX_VERSION 4
4062 for (version=0; version<MAX_VERSION; version++) {
4064 ndrivers=get_ntdrivers(&list, architecture, version);
4065 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4068 return ERROR_NOT_ENOUGH_MEMORY;
4071 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4073 return ERROR_NOT_ENOUGH_MEMORY;
4077 for (i=0; i<ndrivers; i++) {
4080 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4081 ZERO_STRUCT(driver);
4082 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4086 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4087 free_a_printer_driver(driver, 3);
4090 *returned+=ndrivers;
4094 /* check the required size. */
4095 for (i=0; i<*returned; i++) {
4096 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4097 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4100 if (!alloc_buffer_size(buffer, *needed)) {
4101 safe_free(driver_info_2);
4102 return ERROR_INSUFFICIENT_BUFFER;
4105 /* fill the buffer with the form structures */
4106 for (i=0; i<*returned; i++) {
4107 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4108 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4111 safe_free(driver_info_2);
4113 if (*needed > offered) {
4115 return ERROR_INSUFFICIENT_BUFFER;
4118 return NT_STATUS_NO_PROBLEMO;
4121 /****************************************************************************
4122 Enumerates all printer drivers at level 3.
4123 ****************************************************************************/
4124 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4129 fstring *list = NULL;
4131 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4132 DRIVER_INFO_3 *driver_info_3=NULL;
4136 #define MAX_VERSION 4
4138 for (version=0; version<MAX_VERSION; version++) {
4140 ndrivers=get_ntdrivers(&list, architecture, version);
4141 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4144 return ERROR_NOT_ENOUGH_MEMORY;
4147 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4149 return ERROR_NOT_ENOUGH_MEMORY;
4153 for (i=0; i<ndrivers; i++) {
4156 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4157 ZERO_STRUCT(driver);
4158 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4162 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4163 free_a_printer_driver(driver, 3);
4166 *returned+=ndrivers;
4170 /* check the required size. */
4171 for (i=0; i<*returned; i++) {
4172 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4173 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4176 if (!alloc_buffer_size(buffer, *needed)) {
4177 safe_free(driver_info_3);
4178 return ERROR_INSUFFICIENT_BUFFER;
4181 /* fill the buffer with the driver structures */
4182 for (i=0; i<*returned; i++) {
4183 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4184 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4187 for (i=0; i<*returned; i++)
4188 safe_free(driver_info_3[i].dependentfiles);
4190 safe_free(driver_info_3);
4192 if (*needed > offered) {
4194 return ERROR_INSUFFICIENT_BUFFER;
4197 return NT_STATUS_NO_PROBLEMO;
4200 /****************************************************************************
4201 Enumerates all printer drivers.
4202 ****************************************************************************/
4203 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4204 NEW_BUFFER *buffer, uint32 offered,
4205 uint32 *needed, uint32 *returned)
4207 fstring *list = NULL;
4209 fstring architecture;
4211 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4212 fstrcpy(servername, global_myname);
4216 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4220 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4222 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4224 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4228 return ERROR_INVALID_LEVEL;
4232 /****************************************************************************
4233 ****************************************************************************/
4234 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4236 form->flag=list->flag;
4237 init_unistr(&form->name, list->name);
4238 form->width=list->width;
4239 form->length=list->length;
4240 form->left=list->left;
4241 form->top=list->top;
4242 form->right=list->right;
4243 form->bottom=list->bottom;
4246 /****************************************************************************
4247 ****************************************************************************/
4248 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4249 NEW_BUFFER *buffer, uint32 offered,
4250 uint32 *needed, uint32 *numofforms)
4252 nt_forms_struct *list=NULL;
4257 DEBUG(4,("_new_spoolss_enumforms\n"));
4258 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4259 DEBUGADD(5,("Info level [%d]\n", level));
4261 *numofforms = get_ntforms(&list);
4262 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4264 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4268 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4270 return ERROR_NOT_ENOUGH_MEMORY;
4273 /* construct the list of form structures */
4274 for (i=0; i<*numofforms; i++) {
4275 DEBUGADD(6,("Filling form number [%d]\n",i));
4276 fill_form_1(&forms_1[i], &list[i]);
4281 /* check the required size. */
4282 for (i=0; i<*numofforms; i++) {
4283 DEBUGADD(6,("adding form [%d]'s size\n",i));
4284 buffer_size += spoolss_size_form_1(&forms_1[i]);
4287 *needed=buffer_size;
4289 if (!alloc_buffer_size(buffer, buffer_size)){
4291 return ERROR_INSUFFICIENT_BUFFER;
4294 /* fill the buffer with the form structures */
4295 for (i=0; i<*numofforms; i++) {
4296 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4297 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4302 if (*needed > offered) {
4304 return ERROR_INSUFFICIENT_BUFFER;
4307 return NT_STATUS_NO_PROBLEMO;
4311 return ERROR_INVALID_LEVEL;
4316 /****************************************************************************
4317 ****************************************************************************/
4318 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4320 nt_forms_struct *list=NULL;
4326 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4328 DEBUG(4,("_spoolss_getform\n"));
4329 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4330 DEBUGADD(5,("Info level [%d]\n", level));
4332 numofforms = get_ntforms(&list);
4333 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4335 if (numofforms == 0)
4336 return ERROR_NO_MORE_ITEMS;
4341 /* Check if the requested name is in the list of form structures */
4342 for (i=0; i<numofforms; i++) {
4344 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4346 if (strequal(form_name, list[i].name)) {
4347 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4348 fill_form_1(&form_1, &list[i]);
4355 /* check the required size. */
4357 *needed=spoolss_size_form_1(&form_1);
4359 if (!alloc_buffer_size(buffer, buffer_size)){
4360 return ERROR_INSUFFICIENT_BUFFER;
4363 if (*needed > offered) {
4364 return ERROR_INSUFFICIENT_BUFFER;
4367 /* fill the buffer with the form structures */
4368 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4369 new_smb_io_form_1("", buffer, &form_1, 0);
4371 return NT_STATUS_NO_PROBLEMO;
4375 return ERROR_INVALID_LEVEL;
4379 /****************************************************************************
4380 ****************************************************************************/
4381 static void fill_port_1(PORT_INFO_1 *port, char *name)
4383 init_unistr(&port->port_name, name);
4386 /****************************************************************************
4387 ****************************************************************************/
4388 static void fill_port_2(PORT_INFO_2 *port, char *name)
4390 init_unistr(&port->port_name, name);
4391 init_unistr(&port->monitor_name, "Local Monitor");
4392 init_unistr(&port->description, "Local Port");
4393 #define PORT_TYPE_WRITE 1
4394 port->port_type=PORT_TYPE_WRITE;
4398 /****************************************************************************
4400 ****************************************************************************/
4401 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4403 PORT_INFO_1 *ports=NULL;
4406 if (*lp_enumports_cmd()) {
4407 pid_t local_pid = sys_getpid();
4408 char *cmd = lp_enumports_cmd();
4416 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4417 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4421 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4422 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4425 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4426 ret = smbrun(command, tmp_file, False);
4427 DEBUG(10,("Returned [%d]\n", ret));
4430 /* Is this the best error to return here? */
4431 return ERROR_ACCESS_DENIED;
4435 qlines = file_lines_load(tmp_file, &numlines);
4436 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4437 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4441 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4442 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4443 file_lines_free(qlines);
4444 return ERROR_NOT_ENOUGH_MEMORY;
4447 for (i=0; i<numlines; i++) {
4448 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4449 fill_port_1(&ports[i], qlines[i]);
4452 file_lines_free(qlines);
4455 *returned = numlines;
4458 *returned = 1; /* Sole Samba port returned. */
4460 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4461 return ERROR_NOT_ENOUGH_MEMORY;
4463 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4465 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4468 /* check the required size. */
4469 for (i=0; i<*returned; i++) {
4470 DEBUGADD(6,("adding port [%d]'s size\n", i));
4471 *needed += spoolss_size_port_info_1(&ports[i]);
4474 if (!alloc_buffer_size(buffer, *needed)) {
4476 return ERROR_INSUFFICIENT_BUFFER;
4479 /* fill the buffer with the ports structures */
4480 for (i=0; i<*returned; i++) {
4481 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4482 new_smb_io_port_1("", buffer, &ports[i], 0);
4487 if (*needed > offered) {
4489 return ERROR_INSUFFICIENT_BUFFER;
4492 return NT_STATUS_NO_PROBLEMO;
4495 /****************************************************************************
4497 ****************************************************************************/
4499 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4501 PORT_INFO_2 *ports=NULL;
4504 if (*lp_enumports_cmd()) {
4505 pid_t local_pid = sys_getpid();
4506 char *cmd = lp_enumports_cmd();
4514 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4515 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4519 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4520 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4523 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4524 ret = smbrun(command, tmp_file, False);
4525 DEBUGADD(10,("returned [%d]\n", ret));
4528 /* Is this the best error to return here? */
4529 return ERROR_ACCESS_DENIED;
4533 qlines = file_lines_load(tmp_file, &numlines);
4534 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4535 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4539 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4540 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4541 file_lines_free(qlines);
4542 return ERROR_NOT_ENOUGH_MEMORY;
4545 for (i=0; i<numlines; i++) {
4546 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4547 fill_port_2(&(ports[i]), qlines[i]);
4550 file_lines_free(qlines);
4553 *returned = numlines;
4559 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4560 return ERROR_NOT_ENOUGH_MEMORY;
4562 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4564 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4567 /* check the required size. */
4568 for (i=0; i<*returned; i++) {
4569 DEBUGADD(6,("adding port [%d]'s size\n", i));
4570 *needed += spoolss_size_port_info_2(&ports[i]);
4573 if (!alloc_buffer_size(buffer, *needed)) {
4575 return ERROR_INSUFFICIENT_BUFFER;
4578 /* fill the buffer with the ports structures */
4579 for (i=0; i<*returned; i++) {
4580 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4581 new_smb_io_port_2("", buffer, &ports[i], 0);
4586 if (*needed > offered) {
4588 return ERROR_INSUFFICIENT_BUFFER;
4591 return NT_STATUS_NO_PROBLEMO;
4594 /****************************************************************************
4596 ****************************************************************************/
4597 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4598 NEW_BUFFER *buffer, uint32 offered,
4599 uint32 *needed, uint32 *returned)
4601 DEBUG(4,("_spoolss_enumports\n"));
4608 return enumports_level_1(buffer, offered, needed, returned);
4610 return enumports_level_2(buffer, offered, needed, returned);
4612 return ERROR_INVALID_LEVEL;
4616 /****************************************************************************
4617 ****************************************************************************/
4618 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4619 const SPOOL_PRINTER_INFO_LEVEL *info,
4620 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4621 uint32 user_switch, const SPOOL_USER_CTR *user,
4624 NT_PRINTER_INFO_LEVEL *printer = NULL;
4628 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4629 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4630 return ERROR_NOT_ENOUGH_MEMORY;
4633 ZERO_STRUCTP(printer);
4635 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4636 convert_printer_info(info, printer, 2);
4638 if (*lp_addprinter_cmd() )
4639 if ( !add_printer_hook(printer) ) {
4640 free_a_printer(&printer,2);
4641 return ERROR_ACCESS_DENIED;
4644 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4645 printer->info_2->sharename);
4647 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4648 free_a_printer(&printer,2);
4649 return ERROR_ACCESS_DENIED;
4652 /* you must be a printer admin to add a new printer */
4653 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4654 free_a_printer(&printer,2);
4655 return ERROR_ACCESS_DENIED;
4659 * Do sanity check on the requested changes for Samba.
4662 if (!check_printer_ok(printer->info_2, snum)) {
4663 free_a_printer(&printer,2);
4664 return ERROR_INVALID_PARAMETER;
4667 /* write the ASCII on disk */
4668 if (add_a_printer(*printer, 2) != 0) {
4669 free_a_printer(&printer,2);
4670 return ERROR_ACCESS_DENIED;
4673 if (!open_printer_hnd(handle, name)) {
4674 /* Handle open failed - remove addition. */
4675 del_a_printer(printer->info_2->sharename);
4676 free_a_printer(&printer,2);
4677 return ERROR_ACCESS_DENIED;
4680 free_a_printer(&printer,2);
4682 srv_spoolss_sendnotify(handle);
4684 return NT_STATUS_NO_PROBLEMO;
4687 /****************************************************************************
4688 ****************************************************************************/
4689 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4690 const SPOOL_PRINTER_INFO_LEVEL *info,
4691 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4692 uint32 user_switch, const SPOOL_USER_CTR *user,
4697 /* we don't handle yet */
4698 /* but I know what to do ... */
4699 return ERROR_INVALID_LEVEL;
4701 return spoolss_addprinterex_level_2(uni_srv_name, info,
4702 unk0, unk1, unk2, unk3,
4703 user_switch, user, handle);
4705 return ERROR_INVALID_LEVEL;
4709 /****************************************************************************
4710 ****************************************************************************/
4711 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4712 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4714 uint32 err = NT_STATUS_NO_PROBLEMO;
4715 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4716 struct current_user user;
4718 ZERO_STRUCT(driver);
4720 get_current_user(&user, p);
4722 convert_printer_driver_info(info, &driver, level);
4724 DEBUG(5,("Cleaning driver's information\n"));
4725 clean_up_driver_struct(driver, level);
4727 DEBUG(5,("Moving driver to final destination\n"));
4728 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4730 err = ERROR_ACCESS_DENIED;
4734 if (add_a_printer_driver(driver, level)!=0) {
4735 err = ERROR_ACCESS_DENIED;
4740 free_a_printer_driver(driver, level);
4744 /****************************************************************************
4745 ****************************************************************************/
4746 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4748 init_unistr(&info->name, name);
4751 /****************************************************************************
4752 ****************************************************************************/
4753 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4757 pstring short_archi;
4758 DRIVER_DIRECTORY_1 *info=NULL;
4760 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4762 if (get_short_archi(short_archi, long_archi)==FALSE)
4763 return ERROR_INVALID_ENVIRONMENT;
4765 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4766 return ERROR_NOT_ENOUGH_MEMORY;
4768 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4770 DEBUG(4,("printer driver directory: [%s]\n", path));
4772 fill_driverdir_1(info, path);
4774 *needed += spoolss_size_driverdir_info_1(info);
4776 if (!alloc_buffer_size(buffer, *needed)) {
4778 return ERROR_INSUFFICIENT_BUFFER;
4781 new_smb_io_driverdir_1("", buffer, info, 0);
4785 if (*needed > offered)
4786 return ERROR_INSUFFICIENT_BUFFER;
4788 return NT_STATUS_NO_PROBLEMO;
4791 /****************************************************************************
4792 ****************************************************************************/
4793 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4794 NEW_BUFFER *buffer, uint32 offered,
4797 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4803 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4805 return ERROR_INVALID_LEVEL;
4809 /****************************************************************************
4810 ****************************************************************************/
4811 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4812 uint32 in_value_len, uint32 in_data_len,
4813 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4815 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
4817 NT_PRINTER_INFO_LEVEL *printer = NULL;
4822 uint32 biggest_valuesize;
4823 uint32 biggest_datasize;
4825 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4830 ZERO_STRUCT(printer);
4832 *out_max_value_len=0;
4838 *out_max_data_len=0;
4842 DEBUG(5,("spoolss_enumprinterdata\n"));
4844 if (!OPEN_HANDLE(Printer)) {
4845 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4846 return ERROR_INVALID_HANDLE;
4849 if (!get_printer_snum(handle, &snum))
4850 return ERROR_INVALID_HANDLE;
4852 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
4853 return ERROR_INVALID_HANDLE;
4856 * The NT machine wants to know the biggest size of value and data
4858 * cf: MSDN EnumPrinterData remark section
4860 if ( (in_value_len==0) && (in_data_len==0) ) {
4861 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
4865 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
4866 * if this parameter size doesn't exist.
4867 * Ok - my opinion here is that the client is not asking for the greatest
4868 * possible size of all the parameters, but is asking specifically for the size needed
4869 * for this specific parameter. In that case we can remove the loop below and
4870 * simplify this lookup code considerably. JF - comments welcome. JRA.
4873 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4875 free_a_printer(&printer, 2);
4876 return ERROR_NO_MORE_ITEMS;
4884 biggest_valuesize=0;
4887 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
4888 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
4889 if (data_len > biggest_datasize) biggest_datasize=data_len;
4891 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
4899 * I think this is correct, it doesn't break APW and
4900 * allows Gerald's Win32 test programs to work correctly,
4901 * but may need altering.... JRA.
4904 if (param_index == 0) {
4905 /* No parameters found. */
4906 free_a_printer(&printer, 2);
4907 return ERROR_NO_MORE_ITEMS;
4910 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
4911 *out_value_len=2*(1+biggest_valuesize);
4912 *out_data_len=biggest_datasize;
4914 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
4916 free_a_printer(&printer, 2);
4917 return NT_STATUS_NO_PROBLEMO;
4921 * the value len is wrong in NT sp3
4922 * that's the number of bytes not the number of unicode chars
4925 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4927 free_a_printer(&printer, 2);
4928 return ERROR_NO_MORE_ITEMS;
4931 free_a_printer(&printer, 2);
4935 * - counted in bytes in the request
4936 * - counted in UNICODE chars in the max reply
4937 * - counted in bytes in the real size
4939 * take a pause *before* coding not *during* coding
4942 *out_max_value_len=(in_value_len/sizeof(uint16));
4943 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
4945 return ERROR_NOT_ENOUGH_MEMORY;
4948 ZERO_STRUCTP(*out_value);
4949 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
4953 /* the data is counted in bytes */
4954 *out_max_data_len=in_data_len;
4955 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
4957 return ERROR_NOT_ENOUGH_MEMORY;
4960 ZERO_STRUCTP(*data_out);
4961 memcpy(*data_out, data, (size_t)data_len);
4962 *out_data_len=data_len;
4966 return NT_STATUS_NO_PROBLEMO;
4969 /****************************************************************************
4970 ****************************************************************************/
4971 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
4972 const UNISTR2 *value,
4977 uint32 numeric_data)
4979 NT_PRINTER_INFO_LEVEL *printer = NULL;
4980 NT_PRINTER_PARAM *param = NULL;
4982 uint32 status = 0x0;
4983 Printer_entry *Printer=find_printer_index_by_hnd(handle);
4985 DEBUG(5,("spoolss_setprinterdata\n"));
4988 if (!OPEN_HANDLE(Printer)) {
4989 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4990 return ERROR_INVALID_HANDLE;
4993 if (!get_printer_snum(handle, &snum))
4994 return ERROR_INVALID_HANDLE;
4996 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4997 DEBUG(3, ("security descriptor change denied by existing "
4998 "security descriptor\n"));
4999 return ERROR_ACCESS_DENIED;
5002 status = get_a_printer(&printer, 2, lp_servicename(snum));
5004 return ERROR_INVALID_NAME;
5006 convert_specific_param(¶m, value , type, data, real_len);
5007 unlink_specific_param_if_exist(printer->info_2, param);
5009 if (!add_a_specific_param(printer->info_2, param))
5010 status = ERROR_INVALID_PARAMETER;
5012 status = add_a_printer(*printer, 2);
5014 free_a_printer(&printer, 2);
5018 /****************************************************************************
5019 ****************************************************************************/
5020 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5022 NT_PRINTER_INFO_LEVEL *printer = NULL;
5023 NT_PRINTER_PARAM param;
5025 uint32 status = 0x0;
5026 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5028 DEBUG(5,("spoolss_deleteprinterdata\n"));
5030 if (!OPEN_HANDLE(Printer)) {
5031 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5032 return ERROR_INVALID_HANDLE;
5035 if (!get_printer_snum(handle, &snum))
5036 return ERROR_INVALID_HANDLE;
5038 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5039 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5040 "security descriptor\n"));
5041 return ERROR_ACCESS_DENIED;
5044 status = get_a_printer(&printer, 2, lp_servicename(snum));
5046 return ERROR_INVALID_NAME;
5048 ZERO_STRUCTP(¶m);
5049 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5051 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5052 status = ERROR_INVALID_PARAMETER;
5054 status = add_a_printer(*printer, 2);
5056 free_a_printer(&printer, 2);
5060 /****************************************************************************
5061 ****************************************************************************/
5062 uint32 _spoolss_addform( POLICY_HND *handle,
5067 nt_forms_struct *list=NULL;
5068 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5070 DEBUG(5,("spoolss_addform\n"));
5072 if (!OPEN_HANDLE(Printer)) {
5073 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5074 return ERROR_INVALID_HANDLE;
5077 count=get_ntforms(&list);
5078 if(!add_a_form(&list, form, &count))
5079 return ERROR_NOT_ENOUGH_MEMORY;
5080 write_ntforms(&list, count);
5087 /****************************************************************************
5088 ****************************************************************************/
5089 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5093 nt_forms_struct *list=NULL;
5094 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5096 DEBUG(5,("spoolss_deleteform\n"));
5098 if (!OPEN_HANDLE(Printer)) {
5099 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5100 return ERROR_INVALID_HANDLE;
5103 count = get_ntforms(&list);
5104 if(!delete_a_form(&list, form_name, &count, &ret))
5105 return ERROR_INVALID_PARAMETER;
5112 /****************************************************************************
5113 ****************************************************************************/
5114 uint32 _spoolss_setform( POLICY_HND *handle,
5115 const UNISTR2 *uni_name,
5120 nt_forms_struct *list=NULL;
5121 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5123 DEBUG(5,("spoolss_setform\n"));
5125 if (!OPEN_HANDLE(Printer)) {
5126 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5127 return ERROR_INVALID_HANDLE;
5129 count=get_ntforms(&list);
5130 update_a_form(&list, form, count);
5131 write_ntforms(&list, count);
5138 /****************************************************************************
5139 enumprintprocessors level 1.
5140 ****************************************************************************/
5141 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5143 PRINTPROCESSOR_1 *info_1=NULL;
5145 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5146 return ERROR_NOT_ENOUGH_MEMORY;
5150 init_unistr(&info_1->name, "winprint");
5152 *needed += spoolss_size_printprocessor_info_1(info_1);
5154 if (!alloc_buffer_size(buffer, *needed))
5155 return ERROR_INSUFFICIENT_BUFFER;
5157 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5161 if (*needed > offered) {
5163 return ERROR_INSUFFICIENT_BUFFER;
5166 return NT_STATUS_NO_PROBLEMO;
5169 /****************************************************************************
5170 ****************************************************************************/
5171 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5172 NEW_BUFFER *buffer, uint32 offered,
5173 uint32 *needed, uint32 *returned)
5175 DEBUG(5,("spoolss_enumprintprocessors\n"));
5178 * Enumerate the print processors ...
5180 * Just reply with "winprint", to keep NT happy
5181 * and I can use my nice printer checker.
5189 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5191 return ERROR_INVALID_LEVEL;
5195 /****************************************************************************
5196 enumprintprocdatatypes level 1.
5197 ****************************************************************************/
5198 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5200 PRINTPROCDATATYPE_1 *info_1=NULL;
5202 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5203 return ERROR_NOT_ENOUGH_MEMORY;
5207 init_unistr(&info_1->name, "RAW");
5209 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5211 if (!alloc_buffer_size(buffer, *needed))
5212 return ERROR_INSUFFICIENT_BUFFER;
5214 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5218 if (*needed > offered) {
5220 return ERROR_INSUFFICIENT_BUFFER;
5223 return NT_STATUS_NO_PROBLEMO;
5226 /****************************************************************************
5227 ****************************************************************************/
5228 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5229 NEW_BUFFER *buffer, uint32 offered,
5230 uint32 *needed, uint32 *returned)
5232 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5239 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5241 return ERROR_INVALID_LEVEL;
5245 /****************************************************************************
5246 enumprintmonitors level 1.
5247 ****************************************************************************/
5248 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5250 PRINTMONITOR_1 *info_1=NULL;
5252 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5253 return ERROR_NOT_ENOUGH_MEMORY;
5257 init_unistr(&info_1->name, "Local Port");
5259 *needed += spoolss_size_printmonitor_info_1(info_1);
5261 if (!alloc_buffer_size(buffer, *needed))
5262 return ERROR_INSUFFICIENT_BUFFER;
5264 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5268 if (*needed > offered) {
5270 return ERROR_INSUFFICIENT_BUFFER;
5273 return NT_STATUS_NO_PROBLEMO;
5276 /****************************************************************************
5277 enumprintmonitors level 2.
5278 ****************************************************************************/
5279 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5281 PRINTMONITOR_2 *info_2=NULL;
5283 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5284 return ERROR_NOT_ENOUGH_MEMORY;
5288 init_unistr(&info_2->name, "Local Port");
5289 init_unistr(&info_2->environment, "Windows NT X86");
5290 init_unistr(&info_2->dll_name, "localmon.dll");
5292 *needed += spoolss_size_printmonitor_info_2(info_2);
5294 if (!alloc_buffer_size(buffer, *needed))
5295 return ERROR_INSUFFICIENT_BUFFER;
5297 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5301 if (*needed > offered) {
5303 return ERROR_INSUFFICIENT_BUFFER;
5306 return NT_STATUS_NO_PROBLEMO;
5309 /****************************************************************************
5310 ****************************************************************************/
5311 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5312 NEW_BUFFER *buffer, uint32 offered,
5313 uint32 *needed, uint32 *returned)
5315 DEBUG(5,("spoolss_enumprintmonitors\n"));
5318 * Enumerate the print monitors ...
5320 * Just reply with "Local Port", to keep NT happy
5321 * and I can use my nice printer checker.
5329 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5331 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5333 return ERROR_INVALID_LEVEL;
5337 /****************************************************************************
5338 ****************************************************************************/
5339 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5343 JOB_INFO_1 *info_1=NULL;
5345 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5347 if (info_1 == NULL) {
5349 return ERROR_NOT_ENOUGH_MEMORY;
5352 for (i=0; i<count && found==False; i++) {
5353 if (queue[i].job==(int)jobid)
5360 /* I shoud reply something else ... I can't find the good one */
5361 return NT_STATUS_NO_PROBLEMO;
5364 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5368 *needed += spoolss_size_job_info_1(info_1);
5370 if (!alloc_buffer_size(buffer, *needed)) {
5372 return ERROR_INSUFFICIENT_BUFFER;
5375 new_smb_io_job_info_1("", buffer, info_1, 0);
5379 if (*needed > offered)
5380 return ERROR_INSUFFICIENT_BUFFER;
5382 return NT_STATUS_NO_PROBLEMO;
5386 /****************************************************************************
5387 ****************************************************************************/
5388 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5393 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5395 ZERO_STRUCTP(info_2);
5397 if (info_2 == NULL) {
5399 return ERROR_NOT_ENOUGH_MEMORY;
5402 for (i=0; i<count && found==False; i++) {
5403 if (queue[i].job==(int)jobid)
5410 /* I shoud reply something else ... I can't find the good one */
5411 return NT_STATUS_NO_PROBLEMO;
5414 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5418 *needed += spoolss_size_job_info_2(info_2);
5420 if (!alloc_buffer_size(buffer, *needed)) {
5422 return ERROR_INSUFFICIENT_BUFFER;
5425 new_smb_io_job_info_2("", buffer, info_2, 0);
5427 free_dev_mode(info_2->devmode);
5430 if (*needed > offered)
5431 return ERROR_INSUFFICIENT_BUFFER;
5433 return NT_STATUS_NO_PROBLEMO;
5436 /****************************************************************************
5437 ****************************************************************************/
5438 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5439 NEW_BUFFER *buffer, uint32 offered,
5444 print_queue_struct *queue=NULL;
5445 print_status_struct prt_status;
5447 DEBUG(5,("spoolss_getjob\n"));
5449 memset(&prt_status, 0, sizeof(prt_status));
5453 if (!get_printer_snum(handle, &snum))
5454 return ERROR_INVALID_HANDLE;
5456 count = print_queue_status(snum, &queue, &prt_status);
5458 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5459 count, prt_status.status, prt_status.message));
5463 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5465 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5468 return ERROR_INVALID_LEVEL;