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)
1106 /* the notify name should not contain the \\server\ part */
1107 char *p = strrchr(printer->info_2->printername, '\\');
1109 p = printer->info_2->printername;
1114 data->notify_data.data.length=strlen(lp_servicename(snum));
1115 dos_PutUniCode(data->notify_data.data.string, lp_servicename(snum), sizeof(data->notify_data.data.string), True);
1117 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1118 p, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1121 /*******************************************************************
1122 * fill a notify_info_data with the servicename
1123 ********************************************************************/
1124 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1126 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1127 lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
1130 /*******************************************************************
1131 * fill a notify_info_data with the port name
1132 ********************************************************************/
1133 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1135 /* even if it's strange, that's consistant in all the code */
1137 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1138 lp_servicename(snum), sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1141 /*******************************************************************
1142 * fill a notify_info_data with the printername
1143 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1144 * but it doesn't exist, have to see what to do
1145 ********************************************************************/
1146 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1148 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1149 printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1152 /*******************************************************************
1153 * fill a notify_info_data with the comment
1154 ********************************************************************/
1155 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1157 if (*printer->info_2->comment == '\0')
1158 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1159 lp_comment(snum), sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1161 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1162 printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1165 /*******************************************************************
1166 * fill a notify_info_data with the comment
1167 * jfm:xxxx incorrect, have to create a new smb.conf option
1168 * location = "Room 1, floor 2, building 3"
1169 ********************************************************************/
1170 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1172 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1173 printer->info_2->location, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1176 /*******************************************************************
1177 * fill a notify_info_data with the device mode
1178 * jfm:xxxx don't to it for know but that's a real problem !!!
1179 ********************************************************************/
1180 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1184 /*******************************************************************
1185 * fill a notify_info_data with the separator file name
1186 * jfm:xxxx just return no file could add an option to smb.conf
1187 * separator file = "separator.txt"
1188 ********************************************************************/
1189 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1191 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1192 printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True) - sizeof(uint16))/sizeof(uint16));
1195 /*******************************************************************
1196 * fill a notify_info_data with the print processor
1197 * jfm:xxxx return always winprint to indicate we don't do anything to it
1198 ********************************************************************/
1199 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1201 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1202 printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1205 /*******************************************************************
1206 * fill a notify_info_data with the print processor options
1207 * jfm:xxxx send an empty string
1208 ********************************************************************/
1209 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1211 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1212 printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1215 /*******************************************************************
1216 * fill a notify_info_data with the data type
1217 * jfm:xxxx always send RAW as data type
1218 ********************************************************************/
1219 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1221 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1222 printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1225 /*******************************************************************
1226 * fill a notify_info_data with the security descriptor
1227 * jfm:xxxx send an null pointer to say no security desc
1228 * have to implement security before !
1229 ********************************************************************/
1230 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1232 data->notify_data.data.length=0;
1233 data->notify_data.data.string[0]=0x00;
1236 /*******************************************************************
1237 * fill a notify_info_data with the attributes
1238 * jfm:xxxx a samba printer is always shared
1239 ********************************************************************/
1240 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1242 data->notify_data.value[0] = PRINTER_ATTRIBUTE_SHARED \
1243 | PRINTER_ATTRIBUTE_LOCAL \
1244 | PRINTER_ATTRIBUTE_RAW_ONLY ;
1247 /*******************************************************************
1248 * fill a notify_info_data with the priority
1249 ********************************************************************/
1250 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1252 data->notify_data.value[0] = printer->info_2->priority;
1255 /*******************************************************************
1256 * fill a notify_info_data with the default priority
1257 ********************************************************************/
1258 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1260 data->notify_data.value[0] = printer->info_2->default_priority;
1263 /*******************************************************************
1264 * fill a notify_info_data with the start time
1265 ********************************************************************/
1266 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1268 data->notify_data.value[0] = printer->info_2->starttime;
1271 /*******************************************************************
1272 * fill a notify_info_data with the until time
1273 ********************************************************************/
1274 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1276 data->notify_data.value[0] = printer->info_2->untiltime;
1279 /*******************************************************************
1280 * fill a notify_info_data with the status
1281 ********************************************************************/
1282 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1285 print_queue_struct *q=NULL;
1286 print_status_struct status;
1288 memset(&status, 0, sizeof(status));
1289 count = print_queue_status(snum, &q, &status);
1290 data->notify_data.value[0]=(uint32) status.status;
1294 /*******************************************************************
1295 * fill a notify_info_data with the number of jobs queued
1296 ********************************************************************/
1297 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1299 print_queue_struct *q=NULL;
1300 print_status_struct status;
1302 memset(&status, 0, sizeof(status));
1303 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1307 /*******************************************************************
1308 * fill a notify_info_data with the average ppm
1309 ********************************************************************/
1310 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1312 /* always respond 8 pages per minutes */
1313 /* a little hard ! */
1314 data->notify_data.value[0] = printer->info_2->averageppm;
1317 /*******************************************************************
1318 * fill a notify_info_data with username
1319 ********************************************************************/
1320 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1322 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1323 queue->user, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1326 /*******************************************************************
1327 * fill a notify_info_data with job status
1328 ********************************************************************/
1329 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1331 data->notify_data.value[0]=nt_printj_status(queue->status);
1334 /*******************************************************************
1335 * fill a notify_info_data with job name
1336 ********************************************************************/
1337 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1339 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1340 queue->file, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1343 /*******************************************************************
1344 * fill a notify_info_data with job status
1345 ********************************************************************/
1346 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1348 char *p = "unknown";
1350 switch (queue->status) {
1355 p = ""; /* NT provides the paused string */
1364 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1365 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1368 /*******************************************************************
1369 * fill a notify_info_data with job time
1370 ********************************************************************/
1371 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1373 data->notify_data.value[0]=0x0;
1376 /*******************************************************************
1377 * fill a notify_info_data with job size
1378 ********************************************************************/
1379 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1381 data->notify_data.value[0]=queue->size;
1384 /*******************************************************************
1385 * fill a notify_info_data with job position
1386 ********************************************************************/
1387 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1389 data->notify_data.value[0]=queue->job;
1392 /*******************************************************************
1393 * fill a notify_info_data with submitted time
1394 ********************************************************************/
1395 static void spoolss_notify_submitted_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1399 t=gmtime(&queue->time);
1401 data->notify_data.data.length = sizeof(SYSTEMTIME);
1402 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1407 struct s_notify_info_data_table
1413 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1414 print_queue_struct *queue,
1415 NT_PRINTER_INFO_LEVEL *printer);
1418 struct s_notify_info_data_table notify_info_data_table[] =
1420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1470 { END, END, "", END, NULL }
1473 /*******************************************************************
1474 return the size of info_data structure
1475 ********************************************************************/
1476 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1480 while (notify_info_data_table[i].type != END)
1482 if ( (notify_info_data_table[i].type == type ) &&
1483 (notify_info_data_table[i].field == field ) )
1485 return (notify_info_data_table[i].size);
1492 /*******************************************************************
1493 return the type of notify_info_data
1494 ********************************************************************/
1495 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1499 while (notify_info_data_table[i].type != END)
1501 if ( (notify_info_data_table[i].type == type ) &&
1502 (notify_info_data_table[i].field == field ) )
1504 if (notify_info_data_table[i].size == POINTER)
1518 /****************************************************************************
1519 ****************************************************************************/
1520 static int search_notify(uint16 type, uint16 field, int *value)
1525 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1527 if ( (notify_info_data_table[j].type == type ) &&
1528 (notify_info_data_table[j].field == field ) )
1533 if ( found && (notify_info_data_table[j].fn != NULL) )
1539 /****************************************************************************
1540 ****************************************************************************/
1541 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1543 info_data->type = type;
1544 info_data->field = field;
1545 info_data->reserved = 0;
1547 info_data->size = size_of_notify_info_data(type, field);
1548 info_data->enc_type = type_of_notify_info_data(type, field);
1552 /*******************************************************************
1554 * fill a notify_info struct with info asked
1556 ********************************************************************/
1557 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1563 SPOOL_NOTIFY_INFO_DATA *current_data;
1564 NT_PRINTER_INFO_LEVEL *printer = NULL;
1565 print_queue_struct *queue=NULL;
1567 DEBUG(4,("construct_notify_printer_info\n"));
1569 type=option_type->type;
1571 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1572 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1573 option_type->count, lp_servicename(snum)));
1575 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1578 for(field_num=0; field_num<option_type->count; field_num++) {
1579 field = option_type->fields[field_num];
1580 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1582 if (!search_notify(type, field, &j) )
1585 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1588 current_data=&info->data[info->count];
1590 construct_info_data(current_data, type, field, id);
1592 DEBUG(10,("construct_notify_printer_info: calling %s\n",
1593 notify_info_data_table[j].name ));
1595 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1600 free_a_printer(&printer, 2);
1604 /*******************************************************************
1606 * fill a notify_info struct with info asked
1608 ********************************************************************/
1609 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1615 SPOOL_NOTIFY_INFO_DATA *current_data;
1616 NT_PRINTER_INFO_LEVEL *printer = NULL;
1618 DEBUG(4,("construct_notify_jobs_info\n"));
1620 type = option_type->type;
1622 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1623 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1624 option_type->count));
1626 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1629 for(field_num=0; field_num<option_type->count; field_num++) {
1630 field = option_type->fields[field_num];
1632 if (!search_notify(type, field, &j) )
1635 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1639 current_data=&(info->data[info->count]);
1641 construct_info_data(current_data, type, field, id);
1642 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1646 free_a_printer(&printer, 2);
1651 * JFM: The enumeration is not that simple, it's even non obvious.
1653 * let's take an example: I want to monitor the PRINTER SERVER for
1654 * the printer's name and the number of jobs currently queued.
1655 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1656 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1658 * I have 3 printers on the back of my server.
1660 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1663 * 1 printer 1 name 1
1664 * 2 printer 1 cjob 1
1665 * 3 printer 2 name 2
1666 * 4 printer 2 cjob 2
1667 * 5 printer 3 name 3
1668 * 6 printer 3 name 3
1670 * that's the print server case, the printer case is even worse.
1675 /*******************************************************************
1677 * enumerate all printers on the printserver
1678 * fill a notify_info struct with info asked
1680 ********************************************************************/
1681 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1684 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1685 int n_services=lp_numservices();
1688 SPOOL_NOTIFY_OPTION *option;
1689 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1691 DEBUG(4,("printserver_notify_info\n"));
1693 option=Printer->notify.option;
1699 for (i=0; i<option->count; i++) {
1700 option_type=&(option->ctr.type[i]);
1702 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1705 for (snum=0; snum<n_services; snum++)
1706 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1707 if (construct_notify_printer_info(info, snum, option_type, id))
1712 * Debugging information, don't delete.
1715 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1716 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1717 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1719 for (i=0; i<info->count; i++) {
1720 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1721 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1722 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1726 return NT_STATUS_NO_PROBLEMO;
1729 /*******************************************************************
1731 * fill a notify_info struct with info asked
1733 ********************************************************************/
1734 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1737 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1740 SPOOL_NOTIFY_OPTION *option;
1741 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1743 print_queue_struct *queue=NULL;
1744 print_status_struct status;
1746 DEBUG(4,("printer_notify_info\n"));
1748 option=Printer->notify.option;
1754 get_printer_snum(hnd, &snum);
1756 for (i=0; i<option->count; i++) {
1757 option_type=&option->ctr.type[i];
1759 switch ( option_type->type ) {
1760 case PRINTER_NOTIFY_TYPE:
1761 if(construct_notify_printer_info(info, snum, option_type, id))
1765 case JOB_NOTIFY_TYPE:
1766 memset(&status, 0, sizeof(status));
1767 count = print_queue_status(snum, &queue, &status);
1768 for (j=0; j<count; j++)
1769 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1776 * Debugging information, don't delete.
1779 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1780 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1781 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1783 for (i=0; i<info->count; i++) {
1784 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1785 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1786 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1789 return NT_STATUS_NO_PROBLEMO;
1792 /********************************************************************
1794 ********************************************************************/
1795 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1796 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1798 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1800 if (!OPEN_HANDLE(Printer)) {
1801 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1802 return ERROR_INVALID_HANDLE;
1805 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1807 /* jfm: the change value isn't used right now.
1808 * we will honour it when
1809 * a) we'll be able to send notification to the client
1810 * b) we'll have a way to communicate between the spoolss process.
1812 * same thing for option->flags
1813 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1814 * I don't have a global notification system, I'm sending back all the
1815 * informations even when _NOTHING_ has changed.
1818 /* just discard the SPOOL_NOTIFY_OPTION */
1820 safe_free(option->ctr.type);
1822 switch (Printer->printer_type) {
1823 case PRINTER_HANDLE_IS_PRINTSERVER:
1824 return printserver_notify_info(handle, info);
1825 case PRINTER_HANDLE_IS_PRINTER:
1826 return printer_notify_info(handle, info);
1829 return ERROR_INVALID_HANDLE;
1832 /********************************************************************
1833 * construct_printer_info_0
1834 * fill a printer_info_0 struct
1835 ********************************************************************/
1836 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
1840 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1841 counter_printer_0 *session_counter;
1842 uint32 global_counter;
1846 print_queue_struct *queue=NULL;
1847 print_status_struct status;
1849 memset(&status, 0, sizeof(status));
1851 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1854 count = print_queue_status(snum, &queue, &status);
1856 /* check if we already have a counter for this printer */
1857 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1859 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1860 if (session_counter->snum == snum)
1864 /* it's the first time, add it to the list */
1865 if (session_counter==NULL) {
1866 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1867 free_a_printer(&ntprinter, 2);
1870 ZERO_STRUCTP(session_counter);
1871 session_counter->snum=snum;
1872 session_counter->counter=0;
1873 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1877 session_counter->counter++;
1880 * the global_counter should be stored in a TDB as it's common to all the clients
1881 * and should be zeroed on samba startup
1883 global_counter=session_counter->counter;
1885 pstrcpy(chaine,ntprinter->info_2->printername);
1887 init_unistr(&printer->printername, chaine);
1889 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
1890 init_unistr(&printer->servername, chaine);
1892 printer->cjobs = count;
1893 printer->total_jobs = 0;
1894 printer->total_bytes = 0;
1896 setuptime = (time_t)ntprinter->info_2->setuptime;
1897 t=gmtime(&setuptime);
1899 printer->year = t->tm_year+1900;
1900 printer->month = t->tm_mon+1;
1901 printer->dayofweek = t->tm_wday;
1902 printer->day = t->tm_mday;
1903 printer->hour = t->tm_hour;
1904 printer->minute = t->tm_min;
1905 printer->second = t->tm_sec;
1906 printer->milliseconds = 0;
1908 printer->global_counter = global_counter;
1909 printer->total_pages = 0;
1910 printer->major_version = 0x0004; /* NT 4 */
1911 printer->build_version = 0x0565; /* build 1381 */
1912 printer->unknown7 = 0x1;
1913 printer->unknown8 = 0x0;
1914 printer->unknown9 = 0x0;
1915 printer->session_counter = session_counter->counter;
1916 printer->unknown11 = 0x0;
1917 printer->printer_errors = 0x0; /* number of print failure */
1918 printer->unknown13 = 0x0;
1919 printer->unknown14 = 0x1;
1920 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1921 printer->unknown16 = 0x0;
1922 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1923 printer->unknown18 = 0x0;
1924 printer->status = nt_printq_status(status.status);
1925 printer->unknown20 = 0x0;
1926 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1927 printer->unknown22 = 0x0;
1928 printer->unknown23 = 0x6; /* 6 ???*/
1929 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1930 printer->unknown25 = 0;
1931 printer->unknown26 = 0;
1932 printer->unknown27 = 0;
1933 printer->unknown28 = 0;
1934 printer->unknown29 = 0;
1937 free_a_printer(&ntprinter,2);
1941 /********************************************************************
1942 * construct_printer_info_1
1943 * fill a printer_info_1 struct
1944 ********************************************************************/
1945 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
1949 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1951 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1954 printer->flags=flags;
1956 if (*ntprinter->info_2->comment == '\0') {
1957 init_unistr(&printer->comment, lp_comment(snum));
1958 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
1959 ntprinter->info_2->drivername, lp_comment(snum));
1962 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1963 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
1964 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1967 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
1969 init_unistr(&printer->description, chaine);
1970 init_unistr(&printer->name, chaine2);
1972 free_a_printer(&ntprinter,2);
1977 /****************************************************************************
1978 Free a DEVMODE struct.
1979 ****************************************************************************/
1981 static void free_dev_mode(DEVICEMODE *dev)
1987 safe_free(dev->private);
1992 /****************************************************************************
1993 Create a DEVMODE struct. Returns malloced memory.
1994 ****************************************************************************/
1996 static DEVICEMODE *construct_dev_mode(int snum)
2000 NT_PRINTER_INFO_LEVEL *printer = NULL;
2001 NT_DEVICEMODE *ntdevmode = NULL;
2002 DEVICEMODE *devmode = NULL;
2004 DEBUG(7,("construct_dev_mode\n"));
2006 DEBUGADD(8,("getting printer characteristics\n"));
2008 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2009 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2013 ZERO_STRUCTP(devmode);
2015 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2018 if (printer->info_2->devmode)
2019 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2021 if (ntdevmode == NULL)
2024 DEBUGADD(8,("loading DEVICEMODE\n"));
2026 safe_strcpy(adevice, printer->info_2->printername, sizeof(adevice));
2027 init_unistr(&devmode->devicename, adevice);
2029 snprintf(aform, sizeof(aform), ntdevmode->formname);
2030 init_unistr(&devmode->formname, aform);
2032 devmode->specversion = ntdevmode->specversion;
2033 devmode->driverversion = ntdevmode->driverversion;
2034 devmode->size = ntdevmode->size;
2035 devmode->driverextra = ntdevmode->driverextra;
2036 devmode->fields = ntdevmode->fields;
2038 devmode->orientation = ntdevmode->orientation;
2039 devmode->papersize = ntdevmode->papersize;
2040 devmode->paperlength = ntdevmode->paperlength;
2041 devmode->paperwidth = ntdevmode->paperwidth;
2042 devmode->scale = ntdevmode->scale;
2043 devmode->copies = ntdevmode->copies;
2044 devmode->defaultsource = ntdevmode->defaultsource;
2045 devmode->printquality = ntdevmode->printquality;
2046 devmode->color = ntdevmode->color;
2047 devmode->duplex = ntdevmode->duplex;
2048 devmode->yresolution = ntdevmode->yresolution;
2049 devmode->ttoption = ntdevmode->ttoption;
2050 devmode->collate = ntdevmode->collate;
2051 devmode->icmmethod = ntdevmode->icmmethod;
2052 devmode->icmintent = ntdevmode->icmintent;
2053 devmode->mediatype = ntdevmode->mediatype;
2054 devmode->dithertype = ntdevmode->dithertype;
2056 if (ntdevmode->private != NULL) {
2057 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2061 free_nt_devicemode(&ntdevmode);
2062 free_a_printer(&printer,2);
2069 free_nt_devicemode(&ntdevmode);
2071 free_a_printer(&printer,2);
2072 free_dev_mode(devmode);
2077 /********************************************************************
2078 * construct_printer_info_2
2079 * fill a printer_info_2 struct
2080 ********************************************************************/
2082 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2085 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2087 print_queue_struct *queue=NULL;
2088 print_status_struct status;
2089 memset(&status, 0, sizeof(status));
2091 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2094 memset(&status, 0, sizeof(status));
2095 count = print_queue_status(snum, &queue, &status);
2097 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2098 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2099 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2100 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2101 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2103 if (*ntprinter->info_2->comment == '\0')
2104 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2106 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2108 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2109 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2110 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2111 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2112 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2114 printer->attributes = ntprinter->info_2->attributes;
2116 printer->priority = ntprinter->info_2->priority; /* priority */
2117 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2118 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2119 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2120 printer->status = nt_printq_status(status.status); /* status */
2121 printer->cjobs = count; /* jobs */
2122 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2124 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2125 DEBUG(8, ("Returning NULL Devicemode!\n"));
2128 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2129 /* steal the printer info sec_desc structure. [badly done]. */
2130 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2131 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2132 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2133 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2136 printer->secdesc = NULL;
2139 free_a_printer(&ntprinter, 2);
2144 /********************************************************************
2145 * construct_printer_info_3
2146 * fill a printer_info_3 struct
2147 ********************************************************************/
2148 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2150 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2151 PRINTER_INFO_3 *printer = NULL;
2153 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2157 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2158 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2162 ZERO_STRUCTP(printer);
2164 printer->flags = 4; /* These are the components of the SD we are returning. */
2165 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2166 /* steal the printer info sec_desc structure. [badly done]. */
2167 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2171 * Set the flags for the components we are returning.
2174 if (printer->secdesc->owner_sid)
2175 printer->flags |= OWNER_SECURITY_INFORMATION;
2177 if (printer->secdesc->grp_sid)
2178 printer->flags |= GROUP_SECURITY_INFORMATION;
2180 if (printer->secdesc->dacl)
2181 printer->flags |= DACL_SECURITY_INFORMATION;
2183 if (printer->secdesc->sacl)
2184 printer->flags |= SACL_SECURITY_INFORMATION;
2187 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2188 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2189 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2192 free_a_printer(&ntprinter, 2);
2194 *pp_printer = printer;
2198 /********************************************************************
2199 Spoolss_enumprinters.
2200 ********************************************************************/
2201 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2205 int n_services=lp_numservices();
2206 PRINTER_INFO_1 *printers=NULL;
2207 PRINTER_INFO_1 current_prt;
2209 DEBUG(4,("enum_all_printers_info_1\n"));
2211 for (snum=0; snum<n_services; snum++) {
2212 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2213 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2215 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2216 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2218 return ERROR_NOT_ENOUGH_MEMORY;
2220 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2221 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2227 /* check the required size. */
2228 for (i=0; i<*returned; i++)
2229 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2231 if (!alloc_buffer_size(buffer, *needed))
2232 return ERROR_INSUFFICIENT_BUFFER;
2234 /* fill the buffer with the structures */
2235 for (i=0; i<*returned; i++)
2236 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2239 safe_free(printers);
2241 if (*needed > offered) {
2243 return ERROR_INSUFFICIENT_BUFFER;
2246 return NT_STATUS_NO_PROBLEMO;
2249 /********************************************************************
2250 enum_all_printers_info_1_local.
2251 *********************************************************************/
2252 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2254 DEBUG(4,("enum_all_printers_info_1_local\n"));
2256 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2259 /********************************************************************
2260 enum_all_printers_info_1_name.
2261 *********************************************************************/
2262 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2265 DEBUG(4,("enum_all_printers_info_1_name\n"));
2267 fstrcpy(temp, "\\\\");
2268 fstrcat(temp, global_myname);
2270 if (strequal(name, temp)) {
2271 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2274 return ERROR_INVALID_NAME;
2277 /********************************************************************
2278 enum_all_printers_info_1_remote.
2279 *********************************************************************/
2280 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2282 PRINTER_INFO_1 *printer;
2283 fstring printername;
2286 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2288 /* JFM: currently it's more a place holder than anything else.
2289 * In the spooler world there is a notion of server registration.
2290 * the print servers are registring (sp ?) on the PDC (in the same domain)
2292 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2295 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2296 return ERROR_NOT_ENOUGH_MEMORY;
2300 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2301 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2302 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2304 init_unistr(&printer->description, desc);
2305 init_unistr(&printer->name, printername);
2306 init_unistr(&printer->comment, comment);
2307 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2309 /* check the required size. */
2310 *needed += spoolss_size_printer_info_1(printer);
2312 if (!alloc_buffer_size(buffer, *needed)) {
2314 return ERROR_INSUFFICIENT_BUFFER;
2317 /* fill the buffer with the structures */
2318 new_smb_io_printer_info_1("", buffer, printer, 0);
2323 if (*needed > offered) {
2325 return ERROR_INSUFFICIENT_BUFFER;
2328 return NT_STATUS_NO_PROBLEMO;
2331 /********************************************************************
2332 enum_all_printers_info_1_network.
2333 *********************************************************************/
2334 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2336 DEBUG(4,("enum_all_printers_info_1_network\n"));
2338 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2341 /********************************************************************
2342 * api_spoolss_enumprinters
2344 * called from api_spoolss_enumprinters (see this to understand)
2345 ********************************************************************/
2346 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2350 int n_services=lp_numservices();
2351 PRINTER_INFO_2 *printers=NULL;
2352 PRINTER_INFO_2 current_prt;
2354 for (snum=0; snum<n_services; snum++) {
2355 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2356 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2358 if (construct_printer_info_2(¤t_prt, snum)) {
2359 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2360 return ERROR_NOT_ENOUGH_MEMORY;
2361 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2362 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2368 /* check the required size. */
2369 for (i=0; i<*returned; i++)
2370 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2372 if (!alloc_buffer_size(buffer, *needed)) {
2373 for (i=0; i<*returned; i++) {
2374 free_devmode(printers[i].devmode);
2375 free_sec_desc(&printers[i].secdesc);
2377 safe_free(printers);
2378 return ERROR_INSUFFICIENT_BUFFER;
2381 /* fill the buffer with the structures */
2382 for (i=0; i<*returned; i++)
2383 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2386 for (i=0; i<*returned; i++) {
2387 free_devmode(printers[i].devmode);
2388 free_sec_desc(&printers[i].secdesc);
2390 safe_free(printers);
2392 if (*needed > offered) {
2394 return ERROR_INSUFFICIENT_BUFFER;
2397 return NT_STATUS_NO_PROBLEMO;
2400 /********************************************************************
2401 * handle enumeration of printers at level 1
2402 ********************************************************************/
2403 static uint32 enumprinters_level1( uint32 flags, fstring name,
2404 NEW_BUFFER *buffer, uint32 offered,
2405 uint32 *needed, uint32 *returned)
2407 /* Not all the flags are equals */
2409 if (flags & PRINTER_ENUM_LOCAL)
2410 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2412 if (flags & PRINTER_ENUM_NAME)
2413 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2415 if (flags & PRINTER_ENUM_REMOTE)
2416 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2418 if (flags & PRINTER_ENUM_NETWORK)
2419 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2421 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2424 /********************************************************************
2425 * handle enumeration of printers at level 2
2426 ********************************************************************/
2427 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2428 NEW_BUFFER *buffer, uint32 offered,
2429 uint32 *needed, uint32 *returned)
2433 fstrcpy(temp, "\\\\");
2434 fstrcat(temp, global_myname);
2436 if (flags & PRINTER_ENUM_LOCAL) {
2437 if (strequal(servername, temp))
2438 return enum_all_printers_info_2(buffer, offered, needed, returned);
2440 return enum_all_printers_info_2(buffer, offered, needed, returned);
2443 if (flags & PRINTER_ENUM_NAME) {
2444 if (strequal(servername, temp))
2445 return enum_all_printers_info_2(buffer, offered, needed, returned);
2447 return ERROR_INVALID_NAME;
2450 if (flags & PRINTER_ENUM_REMOTE)
2451 return ERROR_INVALID_LEVEL;
2453 return NT_STATUS_NO_PROBLEMO;
2456 /********************************************************************
2457 * handle enumeration of printers at level 5
2458 ********************************************************************/
2459 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2460 NEW_BUFFER *buffer, uint32 offered,
2461 uint32 *needed, uint32 *returned)
2463 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2464 return NT_STATUS_NO_PROBLEMO;
2467 /********************************************************************
2468 * api_spoolss_enumprinters
2470 * called from api_spoolss_enumprinters (see this to understand)
2471 ********************************************************************/
2472 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2473 NEW_BUFFER *buffer, uint32 offered,
2474 uint32 *needed, uint32 *returned)
2478 DEBUG(4,("_spoolss_enumprinters\n"));
2485 * flags==PRINTER_ENUM_NAME
2486 * if name=="" then enumerates all printers
2487 * if name!="" then enumerate the printer
2488 * flags==PRINTER_ENUM_REMOTE
2489 * name is NULL, enumerate printers
2490 * Level 2: name!="" enumerates printers, name can't be NULL
2491 * Level 3: doesn't exist
2492 * Level 4: does a local registry lookup
2493 * Level 5: same as Level 2
2496 unistr2_to_ascii(name, servername, sizeof(name)-1);
2501 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2503 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2505 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2509 return ERROR_INVALID_LEVEL;
2513 /****************************************************************************
2514 ****************************************************************************/
2515 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2517 PRINTER_INFO_0 *printer=NULL;
2519 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2520 return ERROR_NOT_ENOUGH_MEMORY;
2522 construct_printer_info_0(printer, snum);
2524 /* check the required size. */
2525 *needed += spoolss_size_printer_info_0(printer);
2527 if (!alloc_buffer_size(buffer, *needed)) {
2529 return ERROR_INSUFFICIENT_BUFFER;
2532 /* fill the buffer with the structures */
2533 new_smb_io_printer_info_0("", buffer, printer, 0);
2538 if (*needed > offered) {
2539 return ERROR_INSUFFICIENT_BUFFER;
2542 return NT_STATUS_NO_PROBLEMO;
2545 /****************************************************************************
2546 ****************************************************************************/
2547 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2549 PRINTER_INFO_1 *printer=NULL;
2551 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2552 return ERROR_NOT_ENOUGH_MEMORY;
2554 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2556 /* check the required size. */
2557 *needed += spoolss_size_printer_info_1(printer);
2559 if (!alloc_buffer_size(buffer, *needed)) {
2561 return ERROR_INSUFFICIENT_BUFFER;
2564 /* fill the buffer with the structures */
2565 new_smb_io_printer_info_1("", buffer, printer, 0);
2570 if (*needed > offered) {
2571 return ERROR_INSUFFICIENT_BUFFER;
2574 return NT_STATUS_NO_PROBLEMO;
2577 /****************************************************************************
2578 ****************************************************************************/
2579 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2581 PRINTER_INFO_2 *printer=NULL;
2583 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2584 return ERROR_NOT_ENOUGH_MEMORY;
2586 construct_printer_info_2(printer, snum);
2588 /* check the required size. */
2589 *needed += spoolss_size_printer_info_2(printer);
2591 if (!alloc_buffer_size(buffer, *needed)) {
2592 free_printer_info_2(printer);
2593 return ERROR_INSUFFICIENT_BUFFER;
2596 /* fill the buffer with the structures */
2597 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2598 free_printer_info_2(printer);
2599 return ERROR_NOT_ENOUGH_MEMORY;
2603 free_printer_info_2(printer);
2605 if (*needed > offered) {
2606 return ERROR_INSUFFICIENT_BUFFER;
2609 return NT_STATUS_NO_PROBLEMO;
2612 /****************************************************************************
2613 ****************************************************************************/
2614 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2616 PRINTER_INFO_3 *printer=NULL;
2619 if (!construct_printer_info_3(&printer, snum))
2620 return ERROR_NOT_ENOUGH_MEMORY;
2622 /* check the required size. */
2623 *needed += spoolss_size_printer_info_3(printer);
2625 if (!alloc_buffer_size(buffer, *needed)) {
2626 free_printer_info_3(printer);
2627 return ERROR_INSUFFICIENT_BUFFER;
2630 /* fill the buffer with the structures */
2631 new_smb_io_printer_info_3("", buffer, printer, 0);
2634 free_printer_info_3(printer);
2636 if (*needed > offered) {
2637 return ERROR_INSUFFICIENT_BUFFER;
2640 return NT_STATUS_NO_PROBLEMO;
2643 /****************************************************************************
2644 ****************************************************************************/
2645 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2646 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2652 if (!get_printer_snum(handle, &snum))
2653 return ERROR_INVALID_HANDLE;
2657 return getprinter_level_0(snum, buffer, offered, needed);
2659 return getprinter_level_1(snum, buffer, offered, needed);
2661 return getprinter_level_2(snum, buffer, offered, needed);
2663 return getprinter_level_3(snum, buffer, offered, needed);
2665 return ERROR_INVALID_LEVEL;
2669 /********************************************************************
2670 * fill a DRIVER_INFO_1 struct
2671 ********************************************************************/
2672 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2674 init_unistr( &info->name, driver.info_3->name);
2677 /********************************************************************
2678 * construct_printer_driver_info_1
2679 ********************************************************************/
2680 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2682 NT_PRINTER_INFO_LEVEL *printer = NULL;
2683 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2685 ZERO_STRUCT(driver);
2687 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2688 return ERROR_INVALID_PRINTER_NAME;
2690 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2691 return ERROR_UNKNOWN_PRINTER_DRIVER;
2693 fill_printer_driver_info_1(info, driver, servername, architecture);
2695 free_a_printer(&printer,2);
2697 return NT_STATUS_NO_PROBLEMO;
2700 /********************************************************************
2701 * construct_printer_driver_info_2
2702 * fill a printer_info_2 struct
2703 ********************************************************************/
2704 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2706 pstring temp_driverpath;
2707 pstring temp_datafile;
2708 pstring temp_configfile;
2710 info->version=driver.info_3->cversion;
2712 init_unistr( &info->name, driver.info_3->name );
2713 init_unistr( &info->architecture, driver.info_3->environment );
2715 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2716 init_unistr( &info->driverpath, temp_driverpath );
2718 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2719 init_unistr( &info->datafile, temp_datafile );
2721 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2722 init_unistr( &info->configfile, temp_configfile );
2725 /********************************************************************
2726 * construct_printer_driver_info_2
2727 * fill a printer_info_2 struct
2728 ********************************************************************/
2729 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2731 NT_PRINTER_INFO_LEVEL *printer = NULL;
2732 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2734 ZERO_STRUCT(printer);
2735 ZERO_STRUCT(driver);
2737 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2738 return ERROR_INVALID_PRINTER_NAME;
2740 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2741 return ERROR_UNKNOWN_PRINTER_DRIVER;
2743 fill_printer_driver_info_2(info, driver, servername);
2745 free_a_printer(&printer,2);
2747 return NT_STATUS_NO_PROBLEMO;
2750 /********************************************************************
2751 * copy a strings array and convert to UNICODE
2753 * convert an array of ascii string to a UNICODE string
2754 ********************************************************************/
2755 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2762 DEBUG(6,("init_unistr_array\n"));
2766 if (char_array == NULL)
2770 if (!v) v = ""; /* hack to handle null lists */
2772 if (strlen(v) == 0) break;
2773 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2774 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2775 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2776 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2779 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2784 (*uni_array)[j]=0x0000;
2787 DEBUGADD(6,("last one:done\n"));
2790 /********************************************************************
2791 * construct_printer_info_3
2792 * fill a printer_info_3 struct
2793 ********************************************************************/
2794 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2796 pstring temp_driverpath;
2797 pstring temp_datafile;
2798 pstring temp_configfile;
2799 pstring temp_helpfile;
2803 info->version=driver.info_3->cversion;
2805 init_unistr( &info->name, driver.info_3->name );
2806 init_unistr( &info->architecture, driver.info_3->environment );
2808 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2809 init_unistr( &info->driverpath, temp_driverpath );
2811 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2812 init_unistr( &info->datafile, temp_datafile );
2814 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2815 init_unistr( &info->configfile, temp_configfile );
2817 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2818 init_unistr( &info->helpfile, temp_helpfile );
2820 init_unistr( &info->monitorname, driver.info_3->monitorname );
2821 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2823 info->dependentfiles=NULL;
2824 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2827 /********************************************************************
2828 * construct_printer_info_3
2829 * fill a printer_info_3 struct
2830 ********************************************************************/
2831 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2833 NT_PRINTER_INFO_LEVEL *printer = NULL;
2834 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2836 ZERO_STRUCT(driver);
2838 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2839 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2841 return ERROR_INVALID_PRINTER_NAME;
2843 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2844 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2846 free_a_printer(&printer,2);
2847 return ERROR_UNKNOWN_PRINTER_DRIVER;
2850 fill_printer_driver_info_3(info, driver, servername);
2852 free_a_printer(&printer,2);
2854 return NT_STATUS_NO_PROBLEMO;
2857 /********************************************************************
2858 * construct_printer_info_6
2859 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2860 ********************************************************************/
2862 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2864 pstring temp_driverpath;
2865 pstring temp_datafile;
2866 pstring temp_configfile;
2867 pstring temp_helpfile;
2871 memset(&nullstr, '\0', sizeof(fstring));
2873 info->version=driver.info_3->cversion;
2875 init_unistr( &info->name, driver.info_3->name );
2876 init_unistr( &info->architecture, driver.info_3->environment );
2878 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2879 init_unistr( &info->driverpath, temp_driverpath );
2881 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2882 init_unistr( &info->datafile, temp_datafile );
2884 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2885 init_unistr( &info->configfile, temp_configfile );
2887 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2888 init_unistr( &info->helpfile, temp_helpfile );
2890 init_unistr( &info->monitorname, driver.info_3->monitorname );
2891 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2893 info->dependentfiles=NULL;
2894 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2896 info->previousdrivernames=NULL;
2897 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2899 info->driver_date.low=0;
2900 info->driver_date.high=0;
2903 info->driver_version_low=0;
2904 info->driver_version_high=0;
2906 init_unistr( &info->mfgname, "");
2907 init_unistr( &info->oem_url, "");
2908 init_unistr( &info->hardware_id, "");
2909 init_unistr( &info->provider, "");
2912 /********************************************************************
2913 * construct_printer_info_6
2914 * fill a printer_info_6 struct
2915 ********************************************************************/
2916 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2918 NT_PRINTER_INFO_LEVEL *printer = NULL;
2919 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2921 ZERO_STRUCT(driver);
2923 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2924 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2926 return ERROR_INVALID_PRINTER_NAME;
2928 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2929 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2932 * Is this a W2k client ?
2936 free_a_printer(&printer,2);
2937 return ERROR_UNKNOWN_PRINTER_DRIVER;
2940 /* Yes - try again with a WinNT driver. */
2942 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2943 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2945 free_a_printer(&printer,2);
2946 return ERROR_UNKNOWN_PRINTER_DRIVER;
2950 fill_printer_driver_info_6(info, driver, servername);
2952 free_a_printer(&printer,2);
2954 return NT_STATUS_NO_PROBLEMO;
2957 /****************************************************************************
2958 ****************************************************************************/
2960 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2962 safe_free(info->dependentfiles);
2965 /****************************************************************************
2966 ****************************************************************************/
2968 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2970 safe_free(info->dependentfiles);
2974 /****************************************************************************
2975 ****************************************************************************/
2976 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2978 DRIVER_INFO_1 *info=NULL;
2981 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2982 return ERROR_NOT_ENOUGH_MEMORY;
2984 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2985 if (status != NT_STATUS_NO_PROBLEMO) {
2990 /* check the required size. */
2991 *needed += spoolss_size_printer_driver_info_1(info);
2993 if (!alloc_buffer_size(buffer, *needed)) {
2995 return ERROR_INSUFFICIENT_BUFFER;
2998 /* fill the buffer with the structures */
2999 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3004 if (*needed > offered)
3005 return ERROR_INSUFFICIENT_BUFFER;
3007 return NT_STATUS_NO_PROBLEMO;
3010 /****************************************************************************
3011 ****************************************************************************/
3012 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3014 DRIVER_INFO_2 *info=NULL;
3017 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3018 return ERROR_NOT_ENOUGH_MEMORY;
3020 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3021 if (status != NT_STATUS_NO_PROBLEMO) {
3026 /* check the required size. */
3027 *needed += spoolss_size_printer_driver_info_2(info);
3029 if (!alloc_buffer_size(buffer, *needed)) {
3031 return ERROR_INSUFFICIENT_BUFFER;
3034 /* fill the buffer with the structures */
3035 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3040 if (*needed > offered)
3041 return ERROR_INSUFFICIENT_BUFFER;
3043 return NT_STATUS_NO_PROBLEMO;
3046 /****************************************************************************
3047 ****************************************************************************/
3048 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3055 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3056 if (status != NT_STATUS_NO_PROBLEMO) {
3060 /* check the required size. */
3061 *needed += spoolss_size_printer_driver_info_3(&info);
3063 if (!alloc_buffer_size(buffer, *needed)) {
3064 free_printer_driver_info_3(&info);
3065 return ERROR_INSUFFICIENT_BUFFER;
3068 /* fill the buffer with the structures */
3069 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3071 free_printer_driver_info_3(&info);
3073 if (*needed > offered)
3074 return ERROR_INSUFFICIENT_BUFFER;
3076 return NT_STATUS_NO_PROBLEMO;
3079 /****************************************************************************
3080 ****************************************************************************/
3081 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3088 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3089 if (status != NT_STATUS_NO_PROBLEMO) {
3093 /* check the required size. */
3094 *needed += spoolss_size_printer_driver_info_6(&info);
3096 if (!alloc_buffer_size(buffer, *needed)) {
3097 free_printer_driver_info_6(&info);
3098 return ERROR_INSUFFICIENT_BUFFER;
3101 /* fill the buffer with the structures */
3102 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3104 free_printer_driver_info_6(&info);
3106 if (*needed > offered)
3107 return ERROR_INSUFFICIENT_BUFFER;
3109 return NT_STATUS_NO_PROBLEMO;
3112 /****************************************************************************
3113 ****************************************************************************/
3114 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3115 uint32 clientmajorversion, uint32 clientminorversion,
3116 NEW_BUFFER *buffer, uint32 offered,
3117 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3120 fstring architecture;
3123 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3126 *servermajorversion=0;
3127 *serverminorversion=0;
3129 pstrcpy(servername, global_myname);
3130 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3132 if (!get_printer_snum(handle, &snum))
3133 return ERROR_INVALID_HANDLE;
3137 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3139 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3141 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3143 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3145 return ERROR_INVALID_LEVEL;
3149 /****************************************************************************
3150 ****************************************************************************/
3151 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3153 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3155 if (OPEN_HANDLE(Printer)) {
3156 Printer->page_started=True;
3160 DEBUG(3,("Error in startpageprinter printer handle\n"));
3161 return ERROR_INVALID_HANDLE;
3164 /****************************************************************************
3165 ****************************************************************************/
3166 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3168 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3170 if (!OPEN_HANDLE(Printer)) {
3171 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3172 return ERROR_INVALID_HANDLE;
3175 Printer->page_started=False;
3177 return NT_STATUS_NO_PROBLEMO;
3180 /****************************************************************************
3181 Return a user struct for a pipe user.
3182 ****************************************************************************/
3184 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3186 if (p->ntlmssp_auth_validated) {
3187 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3189 extern struct current_user current_user;
3190 memcpy(user, ¤t_user, sizeof(struct current_user));
3196 /********************************************************************
3197 * api_spoolss_getprinter
3198 * called from the spoolss dispatcher
3200 ********************************************************************/
3201 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3202 pipes_struct *p, DOC_INFO *docinfo,
3205 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3209 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3210 struct current_user user;
3212 if (!OPEN_HANDLE(Printer)) {
3213 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3214 return ERROR_INVALID_HANDLE;
3217 get_current_user(&user, p);
3220 * a nice thing with NT is it doesn't listen to what you tell it.
3221 * when asked to send _only_ RAW datas, it tries to send datas
3224 * So I add checks like in NT Server ...
3226 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3227 * there's a bug in NT client-side code, so we'll fix it in the
3228 * server-side code. *nnnnnggggh!*
3231 if (info_1->p_datatype != 0) {
3232 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3233 if (strcmp(datatype, "RAW") != 0) {
3235 return ERROR_INVALID_DATATYPE;
3239 /* get the share number of the printer */
3240 if (!get_printer_snum(handle, &snum)) {
3241 return ERROR_INVALID_HANDLE;
3244 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3246 Printer->jobid = print_job_start(&user, snum, jobname);
3248 /* An error occured in print_job_start() so return an appropriate
3251 if (Printer->jobid == -1) {
3252 return map_nt_error_from_unix(errno);
3255 Printer->document_started=True;
3256 (*jobid) = Printer->jobid;
3258 srv_spoolss_sendnotify(handle);
3262 /********************************************************************
3263 * api_spoolss_getprinter
3264 * called from the spoolss dispatcher
3266 ********************************************************************/
3267 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3269 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3271 if (!OPEN_HANDLE(Printer)) {
3272 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3273 return ERROR_INVALID_HANDLE;
3276 Printer->document_started=False;
3277 print_job_end(Printer->jobid);
3278 /* error codes unhandled so far ... */
3280 srv_spoolss_sendnotify(handle);
3285 /****************************************************************************
3286 ****************************************************************************/
3287 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3290 uint32 *buffer_written)
3292 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3294 if (!OPEN_HANDLE(Printer)) {
3295 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3296 return ERROR_INVALID_HANDLE;
3299 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3305 /********************************************************************
3306 * api_spoolss_getprinter
3307 * called from the spoolss dispatcher
3309 ********************************************************************/
3310 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3313 struct current_user user;
3314 int snum, errcode = ERROR_INVALID_FUNCTION;
3315 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3317 get_current_user(&user, p);
3319 if (!OPEN_HANDLE(Printer)) {
3320 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3321 return ERROR_INVALID_HANDLE;
3324 if (!get_printer_snum(handle, &snum))
3325 return ERROR_INVALID_HANDLE;
3328 case PRINTER_CONTROL_PAUSE:
3329 if (print_queue_pause(&user, snum, &errcode)) {
3333 case PRINTER_CONTROL_RESUME:
3334 case PRINTER_CONTROL_UNPAUSE:
3335 if (print_queue_resume(&user, snum, &errcode)) {
3339 case PRINTER_CONTROL_PURGE:
3340 if (print_queue_purge(&user, snum, &errcode)) {
3345 return ERROR_INVALID_LEVEL;
3351 /********************************************************************
3352 * api_spoolss_abortprinter
3353 ********************************************************************/
3355 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3357 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3360 /********************************************************************
3361 * called by spoolss_api_setprinter
3362 * when updating a printer description
3363 ********************************************************************/
3364 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3365 const SPOOL_PRINTER_INFO_LEVEL *info,
3366 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3368 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3369 struct current_user user;
3373 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3375 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3376 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3377 OUR_HANDLE(handle)));
3379 result = ERROR_INVALID_HANDLE;
3383 /* NT seems to like setting the security descriptor even though
3384 nothing may have actually changed. This causes annoying
3385 dialog boxes when the user doesn't have permission to change
3386 the security descriptor. */
3388 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3390 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3392 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3393 result = NT_STATUS_NO_PROBLEMO;
3397 /* Work out which user is performing the operation */
3399 get_current_user(&user, p);
3401 /* Check the user has permissions to change the security
3402 descriptor. By experimentation with two NT machines, the user
3403 requires Full Access to the printer to change security
3406 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3407 result = ERROR_ACCESS_DENIED;
3411 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3414 free_sec_desc_buf(&new_secdesc_ctr);
3415 free_sec_desc_buf(&old_secdesc_ctr);
3420 /********************************************************************
3421 Do Samba sanity checks on a printer info struct.
3422 this has changed purpose: it now "canonicalises" printer
3423 info from a client rather than just checking it is correct
3424 ********************************************************************/
3426 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3428 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3429 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3431 /* we force some elements to "correct" values */
3432 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3433 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3434 global_myname, lp_servicename(snum));
3435 fstrcpy(info->sharename, lp_servicename(snum));
3436 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3437 | PRINTER_ATTRIBUTE_LOCAL \
3438 | PRINTER_ATTRIBUTE_RAW_ONLY \
3439 | PRINTER_ATTRIBUTE_QUEUED ;
3444 /****************************************************************************
3445 ****************************************************************************/
3446 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3448 pid_t local_pid = sys_getpid();
3449 char *cmd = lp_addprinter_cmd();
3454 pstring driverlocation;
3458 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3459 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3463 /* build driver path... only 9X architecture is needed for legacy reasons */
3464 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3466 /* change \ to \\ for the shell */
3467 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3469 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3470 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3471 cmd, printer->info_2->printername, printer->info_2->sharename,
3472 printer->info_2->portname, printer->info_2->drivername,
3473 printer->info_2->location, driverlocation);
3476 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3477 ret = smbrun(command, tmp_file, False);
3478 DEBUGADD(10,("returned [%d]\n", ret));
3486 qlines = file_lines_load(tmp_file, &numlines);
3487 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3488 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3492 /* Set the portname to what the script says the portname should be. */
3493 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3494 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3496 /* Send SIGHUP to process group... is there a better way? */
3501 file_lines_free(qlines);
3505 /* Return true if two devicemodes are equal */
3507 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3509 if (!strequal(d1->devicename, d2->devicename) ||
3510 !strequal(d1->formname, d2->formname)) {
3514 if (d1->specversion != d2->specversion ||
3515 d1->driverversion != d2->driverversion ||
3516 d1->size != d2->size ||
3517 d1->driverextra != d2->driverextra ||
3518 d1->orientation != d2->orientation ||
3519 d1->papersize != d2->papersize ||
3520 d1->paperlength != d2->paperlength ||
3521 d1->paperwidth != d2->paperwidth ||
3522 d1->scale != d2->scale ||
3523 d1->copies != d2->copies ||
3524 d1->defaultsource != d2->defaultsource ||
3525 d1->printquality != d2->printquality ||
3526 d1->color != d2->color ||
3527 d1->duplex != d2->duplex ||
3528 d1->yresolution != d2->yresolution ||
3529 d1->ttoption != d2->ttoption ||
3530 d1->collate != d2->collate ||
3531 d1->logpixels != d2->logpixels) {
3535 if (d1->fields != d2->fields ||
3536 d1->bitsperpel != d2->bitsperpel ||
3537 d1->pelswidth != d2->pelswidth ||
3538 d1->pelsheight != d2->pelsheight ||
3539 d1->displayflags != d2->displayflags ||
3540 d1->displayfrequency != d2->displayfrequency ||
3541 d1->icmmethod != d2->icmmethod ||
3542 d1->icmintent != d2->icmintent ||
3543 d1->mediatype != d2->mediatype ||
3544 d1->dithertype != d2->dithertype ||
3545 d1->reserved1 != d2->reserved1 ||
3546 d1->reserved2 != d2->reserved2 ||
3547 d1->panningwidth != d2->panningwidth ||
3548 d1->panningheight != d2->panningheight) {
3552 /* Not sure what to do about these fields */
3560 /* Return true if two NT_PRINTER_PARAM structures are equal */
3562 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3563 NT_PRINTER_PARAM *p2)
3565 if (!p1 && !p2) return True;
3567 if ((!p1 && p2) || (p1 && !p2)) return False;
3569 /* Compare lists of printer parameters */
3573 NT_PRINTER_PARAM *q = p1;
3575 /* Find the parameter in the second structure */
3579 if (strequal(p1->value, q->value) &&
3580 p1->type == q->type &&
3581 p1->data_len == q->data_len &&
3582 memcmp(p1->data, q->data, p1->data_len) == 0) {
3601 /********************************************************************
3602 * Called by update_printer when trying to work out whether to
3603 * actually update printer info.
3604 ********************************************************************/
3606 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3607 NT_PRINTER_INFO_LEVEL *p2)
3609 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3611 /* Trivial conditions */
3613 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3617 if ((!p1 && p2) || (p1 && !p2) ||
3618 (!p1->info_2 && p2->info_2) ||
3619 (p1->info_2 && !p2->info_2)) {
3623 /* Compare two nt_printer_info_level structures. Don't compare
3624 status or cjobs as they seem to have something to do with the
3630 if (pi1->attributes != pi2->attributes ||
3631 pi1->priority != pi2->priority ||
3632 pi1->default_priority != pi2->default_priority ||
3633 pi1->starttime != pi2->starttime ||
3634 pi1->untiltime != pi2->untiltime ||
3635 pi1->averageppm != pi2->averageppm) {
3639 /* Yuck - don't check the printername or servername as the
3640 add_a_printer() code plays games with them. You can't
3641 change the printername or the sharename through this interface
3644 if (!strequal(pi1->sharename, pi2->sharename) ||
3645 !strequal(pi1->portname, pi2->portname) ||
3646 !strequal(pi1->drivername, pi2->drivername) ||
3647 !strequal(pi1->comment, pi2->comment) ||
3648 !strequal(pi1->location, pi2->location)) {
3652 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3656 if (!strequal(pi1->sepfile, pi2->sepfile) ||
3657 !strequal(pi1->printprocessor, pi2->printprocessor) ||
3658 !strequal(pi1->datatype, pi2->datatype) ||
3659 !strequal(pi1->parameters, pi2->parameters)) {
3663 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3667 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3671 if (pi1->changeid != pi2->changeid ||
3672 pi1->c_setprinter != pi2->c_setprinter ||
3673 pi1->setuptime != pi2->setuptime) {
3680 /********************************************************************
3681 * called by spoolss_api_setprinter
3682 * when updating a printer description
3683 ********************************************************************/
3685 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3686 const SPOOL_PRINTER_INFO_LEVEL *info,
3687 DEVICEMODE *devmode)
3690 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3691 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3694 DEBUG(8,("update_printer\n"));
3696 result = NT_STATUS_NO_PROBLEMO;
3699 DEBUG(0,("Send a mail to samba@samba.org\n"));
3700 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3701 result = ERROR_INVALID_LEVEL;
3705 if (!OPEN_HANDLE(Printer)) {
3706 result = ERROR_INVALID_HANDLE;
3710 if (!get_printer_snum(handle, &snum)) {
3711 result = ERROR_INVALID_HANDLE;
3715 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3716 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3717 result = ERROR_INVALID_HANDLE;
3721 DEBUGADD(8,("Converting info_2 struct\n"));
3724 * convert_printer_info converts the incoming
3725 * info from the client and overwrites the info
3726 * just read from the tdb in the pointer 'printer'.
3729 convert_printer_info(info, printer, level);
3731 if (info->info_2->devmode_ptr != 0) {
3732 /* we have a valid devmode
3733 convert it and link it*/
3736 * Ensure printer->info_2->devmode is a valid pointer
3737 * as we will be overwriting it in convert_devicemode().
3740 if (printer->info_2->devmode == NULL)
3741 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3743 DEBUGADD(8,("Converting the devicemode struct\n"));
3744 convert_devicemode(devmode, printer->info_2->devmode);
3747 if (printer->info_2->devmode != NULL)
3748 free_nt_devicemode(&printer->info_2->devmode);
3749 printer->info_2->devmode=NULL;
3752 /* Do sanity check on the requested changes for Samba */
3754 if (!check_printer_ok(printer->info_2, snum)) {
3755 result = ERROR_INVALID_PARAMETER;
3759 /* NT likes to call this function even though nothing has actually
3760 changed. Check this so the user doesn't end up with an
3761 annoying permission denied dialog box. */
3763 if (nt_printer_info_level_equal(printer, old_printer)) {
3764 DEBUG(3, ("printer info has not changed\n"));
3765 result = NT_STATUS_NO_PROBLEMO;
3769 /* Check calling user has permission to update printer description */
3771 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3772 DEBUG(3, ("printer property change denied by security "
3774 result = ERROR_ACCESS_DENIED;
3778 /* Call addprinter hook */
3780 if (*lp_addprinter_cmd() )
3781 if ( !add_printer_hook(printer) ) {
3782 result = ERROR_ACCESS_DENIED;
3786 /* Update printer info */
3788 if (add_a_printer(*printer, 2)!=0) {
3789 /* I don't really know what to return here !!! */
3790 result = ERROR_ACCESS_DENIED;
3795 free_a_printer(&printer, 2);
3796 free_a_printer(&old_printer, 2);
3798 srv_spoolss_sendnotify(handle);
3803 /****************************************************************************
3804 ****************************************************************************/
3805 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3806 const SPOOL_PRINTER_INFO_LEVEL *info,
3807 DEVMODE_CTR devmode_ctr,
3808 SEC_DESC_BUF *secdesc_ctr,
3809 uint32 command, pipes_struct *p)
3811 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3813 if (!OPEN_HANDLE(Printer)) {
3814 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3815 return ERROR_INVALID_HANDLE;
3818 /* check the level */
3821 return control_printer(handle, command, p);
3823 return update_printer(handle, level, info, devmode_ctr.devmode);
3825 return update_printer_sec(handle, level, info, p,
3828 return ERROR_INVALID_LEVEL;
3832 /****************************************************************************
3833 ****************************************************************************/
3834 uint32 _spoolss_fcpn(POLICY_HND *handle)
3836 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3838 if (!OPEN_HANDLE(Printer)) {
3839 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3840 return ERROR_INVALID_HANDLE;
3843 if (Printer->notify.client_connected==True)
3844 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3845 return ERROR_INVALID_HANDLE;
3847 Printer->notify.flags=0;
3848 Printer->notify.options=0;
3849 Printer->notify.localmachine[0]='\0';
3850 Printer->notify.printerlocal=0;
3851 if (Printer->notify.option)
3852 safe_free(Printer->notify.option->ctr.type);
3853 safe_free(Printer->notify.option);
3854 Printer->notify.option=NULL;
3855 Printer->notify.client_connected=False;
3857 return NT_STATUS_NO_PROBLEMO;
3860 /****************************************************************************
3861 ****************************************************************************/
3862 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3863 NEW_BUFFER *buffer, uint32 offered,
3867 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3868 returns for AddJob. AddJob
3869 must fail on non-local
3873 /****************************************************************************
3874 ****************************************************************************/
3875 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3876 int position, int snum)
3882 t=gmtime(&queue->time);
3883 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3885 job_info->jobid=queue->job;
3886 init_unistr(&job_info->printername, lp_servicename(snum));
3887 init_unistr(&job_info->machinename, temp_name);
3888 init_unistr(&job_info->username, queue->user);
3889 init_unistr(&job_info->document, queue->file);
3890 init_unistr(&job_info->datatype, "RAW");
3891 init_unistr(&job_info->text_status, "");
3892 job_info->status=nt_printj_status(queue->status);
3893 job_info->priority=queue->priority;
3894 job_info->position=position;
3895 job_info->totalpages=0;
3896 job_info->pagesprinted=0;
3898 make_systemtime(&job_info->submitted, t);
3901 /****************************************************************************
3902 ****************************************************************************/
3903 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3904 int position, int snum)
3907 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3911 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3914 t=gmtime(&queue->time);
3915 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3917 job_info->jobid=queue->job;
3919 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3921 init_unistr(&job_info->printername, chaine);
3923 init_unistr(&job_info->machinename, temp_name);
3924 init_unistr(&job_info->username, queue->user);
3925 init_unistr(&job_info->document, queue->file);
3926 init_unistr(&job_info->notifyname, queue->user);
3927 init_unistr(&job_info->datatype, "RAW");
3928 init_unistr(&job_info->printprocessor, "winprint");
3929 init_unistr(&job_info->parameters, "");
3930 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3931 init_unistr(&job_info->text_status, "");
3933 /* and here the security descriptor */
3935 job_info->status=nt_printj_status(queue->status);
3936 job_info->priority=queue->priority;
3937 job_info->position=position;
3938 job_info->starttime=0;
3939 job_info->untiltime=0;
3940 job_info->totalpages=0;
3941 job_info->size=queue->size;
3942 make_systemtime(&(job_info->submitted), t);
3943 job_info->timeelapsed=0;
3944 job_info->pagesprinted=0;
3946 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
3947 free_a_printer(&ntprinter, 2);
3951 free_a_printer(&ntprinter, 2);
3955 /****************************************************************************
3956 Enumjobs at level 1.
3957 ****************************************************************************/
3958 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3959 NEW_BUFFER *buffer, uint32 offered,
3960 uint32 *needed, uint32 *returned)
3965 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3969 return ERROR_NOT_ENOUGH_MEMORY;
3972 for (i=0; i<*returned; i++)
3973 fill_job_info_1(&info[i], &queue[i], i, snum);
3977 /* check the required size. */
3978 for (i=0; i<*returned; i++)
3979 (*needed) += spoolss_size_job_info_1(&info[i]);
3981 if (!alloc_buffer_size(buffer, *needed)) {
3983 return ERROR_INSUFFICIENT_BUFFER;
3986 /* fill the buffer with the structures */
3987 for (i=0; i<*returned; i++)
3988 new_smb_io_job_info_1("", buffer, &info[i], 0);
3993 if (*needed > offered) {
3995 return ERROR_INSUFFICIENT_BUFFER;
3998 return NT_STATUS_NO_PROBLEMO;
4001 /****************************************************************************
4002 Enumjobs at level 2.
4003 ****************************************************************************/
4004 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4005 NEW_BUFFER *buffer, uint32 offered,
4006 uint32 *needed, uint32 *returned)
4011 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4015 return ERROR_NOT_ENOUGH_MEMORY;
4018 for (i=0; i<*returned; i++)
4019 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4023 /* check the required size. */
4024 for (i=0; i<*returned; i++)
4025 (*needed) += spoolss_size_job_info_2(&info[i]);
4027 if (!alloc_buffer_size(buffer, *needed)) {
4029 return ERROR_INSUFFICIENT_BUFFER;
4032 /* fill the buffer with the structures */
4033 for (i=0; i<*returned; i++)
4034 new_smb_io_job_info_2("", buffer, &info[i], 0);
4039 if (*needed > offered) {
4041 return ERROR_INSUFFICIENT_BUFFER;
4044 return NT_STATUS_NO_PROBLEMO;
4047 /****************************************************************************
4049 ****************************************************************************/
4050 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4051 NEW_BUFFER *buffer, uint32 offered,
4052 uint32 *needed, uint32 *returned)
4055 print_queue_struct *queue=NULL;
4056 print_status_struct prt_status;
4058 DEBUG(4,("_spoolss_enumjobs\n"));
4060 ZERO_STRUCT(prt_status);
4065 if (!get_printer_snum(handle, &snum))
4066 return ERROR_INVALID_HANDLE;
4068 *returned = print_queue_status(snum, &queue, &prt_status);
4069 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4071 if (*returned == 0) {
4073 return NT_STATUS_NO_PROBLEMO;
4078 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4080 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4084 return ERROR_INVALID_LEVEL;
4089 /****************************************************************************
4090 ****************************************************************************/
4091 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4096 /****************************************************************************
4097 ****************************************************************************/
4098 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4099 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4101 struct current_user user;
4102 print_status_struct prt_status;
4103 int snum, errcode = ERROR_INVALID_FUNCTION;
4105 memset(&prt_status, 0, sizeof(prt_status));
4107 if (!get_printer_snum(handle, &snum)) {
4108 return ERROR_INVALID_HANDLE;
4111 if (!print_job_exists(jobid)) {
4112 return ERROR_INVALID_PRINTER_NAME;
4115 get_current_user(&user, p);
4118 case JOB_CONTROL_CANCEL:
4119 case JOB_CONTROL_DELETE:
4120 if (print_job_delete(&user, jobid, &errcode)) {
4124 case JOB_CONTROL_PAUSE:
4125 if (print_job_pause(&user, jobid, &errcode)) {
4129 case JOB_CONTROL_RESTART:
4130 case JOB_CONTROL_RESUME:
4131 if (print_job_resume(&user, jobid, &errcode)) {
4136 return ERROR_INVALID_LEVEL;
4142 /****************************************************************************
4143 Enumerates all printer drivers at level 1.
4144 ****************************************************************************/
4145 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4150 fstring *list = NULL;
4152 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4153 DRIVER_INFO_1 *driver_info_1=NULL;
4157 #define MAX_VERSION 4
4159 for (version=0; version<MAX_VERSION; version++) {
4161 ndrivers=get_ntdrivers(&list, architecture, version);
4162 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4165 return ERROR_NOT_ENOUGH_MEMORY;
4168 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4170 return ERROR_NOT_ENOUGH_MEMORY;
4174 for (i=0; i<ndrivers; i++) {
4176 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4177 ZERO_STRUCT(driver);
4178 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4182 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4183 free_a_printer_driver(driver, 3);
4186 *returned+=ndrivers;
4190 /* check the required size. */
4191 for (i=0; i<*returned; i++) {
4192 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4193 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4196 if (!alloc_buffer_size(buffer, *needed)) {
4197 safe_free(driver_info_1);
4198 return ERROR_INSUFFICIENT_BUFFER;
4201 /* fill the buffer with the form structures */
4202 for (i=0; i<*returned; i++) {
4203 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4204 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4207 safe_free(driver_info_1);
4209 if (*needed > offered) {
4211 return ERROR_INSUFFICIENT_BUFFER;
4214 return NT_STATUS_NO_PROBLEMO;
4217 /****************************************************************************
4218 Enumerates all printer drivers at level 2.
4219 ****************************************************************************/
4220 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4225 fstring *list = NULL;
4227 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4228 DRIVER_INFO_2 *driver_info_2=NULL;
4232 #define MAX_VERSION 4
4234 for (version=0; version<MAX_VERSION; version++) {
4236 ndrivers=get_ntdrivers(&list, architecture, version);
4237 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4240 return ERROR_NOT_ENOUGH_MEMORY;
4243 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4245 return ERROR_NOT_ENOUGH_MEMORY;
4249 for (i=0; i<ndrivers; i++) {
4252 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4253 ZERO_STRUCT(driver);
4254 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4258 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4259 free_a_printer_driver(driver, 3);
4262 *returned+=ndrivers;
4266 /* check the required size. */
4267 for (i=0; i<*returned; i++) {
4268 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4269 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4272 if (!alloc_buffer_size(buffer, *needed)) {
4273 safe_free(driver_info_2);
4274 return ERROR_INSUFFICIENT_BUFFER;
4277 /* fill the buffer with the form structures */
4278 for (i=0; i<*returned; i++) {
4279 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4280 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4283 safe_free(driver_info_2);
4285 if (*needed > offered) {
4287 return ERROR_INSUFFICIENT_BUFFER;
4290 return NT_STATUS_NO_PROBLEMO;
4293 /****************************************************************************
4294 Enumerates all printer drivers at level 3.
4295 ****************************************************************************/
4296 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4301 fstring *list = NULL;
4303 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4304 DRIVER_INFO_3 *driver_info_3=NULL;
4308 #define MAX_VERSION 4
4310 for (version=0; version<MAX_VERSION; version++) {
4312 ndrivers=get_ntdrivers(&list, architecture, version);
4313 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4316 return ERROR_NOT_ENOUGH_MEMORY;
4319 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4321 return ERROR_NOT_ENOUGH_MEMORY;
4325 for (i=0; i<ndrivers; i++) {
4328 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4329 ZERO_STRUCT(driver);
4330 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4334 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4335 free_a_printer_driver(driver, 3);
4338 *returned+=ndrivers;
4342 /* check the required size. */
4343 for (i=0; i<*returned; i++) {
4344 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4345 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4348 if (!alloc_buffer_size(buffer, *needed)) {
4349 safe_free(driver_info_3);
4350 return ERROR_INSUFFICIENT_BUFFER;
4353 /* fill the buffer with the driver structures */
4354 for (i=0; i<*returned; i++) {
4355 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4356 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4359 for (i=0; i<*returned; i++)
4360 safe_free(driver_info_3[i].dependentfiles);
4362 safe_free(driver_info_3);
4364 if (*needed > offered) {
4366 return ERROR_INSUFFICIENT_BUFFER;
4369 return NT_STATUS_NO_PROBLEMO;
4372 /****************************************************************************
4373 Enumerates all printer drivers.
4374 ****************************************************************************/
4375 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4376 NEW_BUFFER *buffer, uint32 offered,
4377 uint32 *needed, uint32 *returned)
4379 fstring *list = NULL;
4381 fstring architecture;
4383 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4384 fstrcpy(servername, global_myname);
4388 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4392 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4394 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4396 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4400 return ERROR_INVALID_LEVEL;
4404 /****************************************************************************
4405 ****************************************************************************/
4406 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4408 form->flag=list->flag;
4409 init_unistr(&form->name, list->name);
4410 form->width=list->width;
4411 form->length=list->length;
4412 form->left=list->left;
4413 form->top=list->top;
4414 form->right=list->right;
4415 form->bottom=list->bottom;
4418 /****************************************************************************
4419 ****************************************************************************/
4420 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4421 NEW_BUFFER *buffer, uint32 offered,
4422 uint32 *needed, uint32 *numofforms)
4424 nt_forms_struct *list=NULL;
4429 DEBUG(4,("_new_spoolss_enumforms\n"));
4430 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4431 DEBUGADD(5,("Info level [%d]\n", level));
4433 *numofforms = get_ntforms(&list);
4434 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4436 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4440 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4442 return ERROR_NOT_ENOUGH_MEMORY;
4445 /* construct the list of form structures */
4446 for (i=0; i<*numofforms; i++) {
4447 DEBUGADD(6,("Filling form number [%d]\n",i));
4448 fill_form_1(&forms_1[i], &list[i]);
4453 /* check the required size. */
4454 for (i=0; i<*numofforms; i++) {
4455 DEBUGADD(6,("adding form [%d]'s size\n",i));
4456 buffer_size += spoolss_size_form_1(&forms_1[i]);
4459 *needed=buffer_size;
4461 if (!alloc_buffer_size(buffer, buffer_size)){
4463 return ERROR_INSUFFICIENT_BUFFER;
4466 /* fill the buffer with the form structures */
4467 for (i=0; i<*numofforms; i++) {
4468 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4469 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4474 if (*needed > offered) {
4476 return ERROR_INSUFFICIENT_BUFFER;
4479 return NT_STATUS_NO_PROBLEMO;
4483 return ERROR_INVALID_LEVEL;
4488 /****************************************************************************
4489 ****************************************************************************/
4490 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4492 nt_forms_struct *list=NULL;
4498 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4500 DEBUG(4,("_spoolss_getform\n"));
4501 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4502 DEBUGADD(5,("Info level [%d]\n", level));
4504 numofforms = get_ntforms(&list);
4505 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4507 if (numofforms == 0)
4508 return ERROR_NO_MORE_ITEMS;
4513 /* Check if the requested name is in the list of form structures */
4514 for (i=0; i<numofforms; i++) {
4516 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4518 if (strequal(form_name, list[i].name)) {
4519 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4520 fill_form_1(&form_1, &list[i]);
4527 /* check the required size. */
4529 *needed=spoolss_size_form_1(&form_1);
4531 if (!alloc_buffer_size(buffer, buffer_size)){
4532 return ERROR_INSUFFICIENT_BUFFER;
4535 if (*needed > offered) {
4536 return ERROR_INSUFFICIENT_BUFFER;
4539 /* fill the buffer with the form structures */
4540 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4541 new_smb_io_form_1("", buffer, &form_1, 0);
4543 return NT_STATUS_NO_PROBLEMO;
4547 return ERROR_INVALID_LEVEL;
4551 /****************************************************************************
4552 ****************************************************************************/
4553 static void fill_port_1(PORT_INFO_1 *port, char *name)
4555 init_unistr(&port->port_name, name);
4558 /****************************************************************************
4559 ****************************************************************************/
4560 static void fill_port_2(PORT_INFO_2 *port, char *name)
4562 init_unistr(&port->port_name, name);
4563 init_unistr(&port->monitor_name, "Local Monitor");
4564 init_unistr(&port->description, "Local Port");
4565 #define PORT_TYPE_WRITE 1
4566 port->port_type=PORT_TYPE_WRITE;
4570 /****************************************************************************
4572 ****************************************************************************/
4573 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4575 PORT_INFO_1 *ports=NULL;
4578 if (*lp_enumports_cmd()) {
4579 pid_t local_pid = sys_getpid();
4580 char *cmd = lp_enumports_cmd();
4588 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4589 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4593 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4594 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4597 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4598 ret = smbrun(command, tmp_file, False);
4599 DEBUG(10,("Returned [%d]\n", ret));
4602 /* Is this the best error to return here? */
4603 return ERROR_ACCESS_DENIED;
4607 qlines = file_lines_load(tmp_file, &numlines);
4608 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4609 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4613 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4614 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4615 file_lines_free(qlines);
4616 return ERROR_NOT_ENOUGH_MEMORY;
4619 for (i=0; i<numlines; i++) {
4620 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4621 fill_port_1(&ports[i], qlines[i]);
4624 file_lines_free(qlines);
4627 *returned = numlines;
4630 *returned = 1; /* Sole Samba port returned. */
4632 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4633 return ERROR_NOT_ENOUGH_MEMORY;
4635 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4637 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4640 /* check the required size. */
4641 for (i=0; i<*returned; i++) {
4642 DEBUGADD(6,("adding port [%d]'s size\n", i));
4643 *needed += spoolss_size_port_info_1(&ports[i]);
4646 if (!alloc_buffer_size(buffer, *needed)) {
4648 return ERROR_INSUFFICIENT_BUFFER;
4651 /* fill the buffer with the ports structures */
4652 for (i=0; i<*returned; i++) {
4653 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4654 new_smb_io_port_1("", buffer, &ports[i], 0);
4659 if (*needed > offered) {
4661 return ERROR_INSUFFICIENT_BUFFER;
4664 return NT_STATUS_NO_PROBLEMO;
4667 /****************************************************************************
4669 ****************************************************************************/
4671 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4673 PORT_INFO_2 *ports=NULL;
4676 if (*lp_enumports_cmd()) {
4677 pid_t local_pid = sys_getpid();
4678 char *cmd = lp_enumports_cmd();
4686 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4687 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4691 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4692 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4695 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4696 ret = smbrun(command, tmp_file, False);
4697 DEBUGADD(10,("returned [%d]\n", ret));
4700 /* Is this the best error to return here? */
4701 return ERROR_ACCESS_DENIED;
4705 qlines = file_lines_load(tmp_file, &numlines);
4706 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4707 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4711 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4712 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4713 file_lines_free(qlines);
4714 return ERROR_NOT_ENOUGH_MEMORY;
4717 for (i=0; i<numlines; i++) {
4718 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4719 fill_port_2(&(ports[i]), qlines[i]);
4722 file_lines_free(qlines);
4725 *returned = numlines;
4731 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4732 return ERROR_NOT_ENOUGH_MEMORY;
4734 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4736 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4739 /* check the required size. */
4740 for (i=0; i<*returned; i++) {
4741 DEBUGADD(6,("adding port [%d]'s size\n", i));
4742 *needed += spoolss_size_port_info_2(&ports[i]);
4745 if (!alloc_buffer_size(buffer, *needed)) {
4747 return ERROR_INSUFFICIENT_BUFFER;
4750 /* fill the buffer with the ports structures */
4751 for (i=0; i<*returned; i++) {
4752 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4753 new_smb_io_port_2("", buffer, &ports[i], 0);
4758 if (*needed > offered) {
4760 return ERROR_INSUFFICIENT_BUFFER;
4763 return NT_STATUS_NO_PROBLEMO;
4766 /****************************************************************************
4768 ****************************************************************************/
4769 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4770 NEW_BUFFER *buffer, uint32 offered,
4771 uint32 *needed, uint32 *returned)
4773 DEBUG(4,("_spoolss_enumports\n"));
4780 return enumports_level_1(buffer, offered, needed, returned);
4782 return enumports_level_2(buffer, offered, needed, returned);
4784 return ERROR_INVALID_LEVEL;
4788 /****************************************************************************
4789 ****************************************************************************/
4790 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4791 const SPOOL_PRINTER_INFO_LEVEL *info,
4792 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4793 uint32 user_switch, const SPOOL_USER_CTR *user,
4796 NT_PRINTER_INFO_LEVEL *printer = NULL;
4800 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4801 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4802 return ERROR_NOT_ENOUGH_MEMORY;
4805 ZERO_STRUCTP(printer);
4807 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4808 convert_printer_info(info, printer, 2);
4810 if (*lp_addprinter_cmd() )
4811 if ( !add_printer_hook(printer) ) {
4812 free_a_printer(&printer,2);
4813 return ERROR_ACCESS_DENIED;
4816 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4817 printer->info_2->sharename);
4819 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4820 free_a_printer(&printer,2);
4821 return ERROR_ACCESS_DENIED;
4824 /* you must be a printer admin to add a new printer */
4825 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4826 free_a_printer(&printer,2);
4827 return ERROR_ACCESS_DENIED;
4831 * Do sanity check on the requested changes for Samba.
4834 if (!check_printer_ok(printer->info_2, snum)) {
4835 free_a_printer(&printer,2);
4836 return ERROR_INVALID_PARAMETER;
4839 /* write the ASCII on disk */
4840 if (add_a_printer(*printer, 2) != 0) {
4841 free_a_printer(&printer,2);
4842 return ERROR_ACCESS_DENIED;
4845 if (!open_printer_hnd(handle, name)) {
4846 /* Handle open failed - remove addition. */
4847 del_a_printer(printer->info_2->sharename);
4848 free_a_printer(&printer,2);
4849 return ERROR_ACCESS_DENIED;
4852 free_a_printer(&printer,2);
4854 srv_spoolss_sendnotify(handle);
4856 return NT_STATUS_NO_PROBLEMO;
4859 /****************************************************************************
4860 ****************************************************************************/
4861 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4862 const SPOOL_PRINTER_INFO_LEVEL *info,
4863 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4864 uint32 user_switch, const SPOOL_USER_CTR *user,
4869 /* we don't handle yet */
4870 /* but I know what to do ... */
4871 return ERROR_INVALID_LEVEL;
4873 return spoolss_addprinterex_level_2(uni_srv_name, info,
4874 unk0, unk1, unk2, unk3,
4875 user_switch, user, handle);
4877 return ERROR_INVALID_LEVEL;
4881 /****************************************************************************
4882 ****************************************************************************/
4883 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4884 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4886 uint32 err = NT_STATUS_NO_PROBLEMO;
4887 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4888 struct current_user user;
4890 ZERO_STRUCT(driver);
4892 get_current_user(&user, p);
4894 convert_printer_driver_info(info, &driver, level);
4896 DEBUG(5,("Cleaning driver's information\n"));
4897 if ((err = clean_up_driver_struct(driver, level)) != NT_STATUS_NO_PROBLEMO )
4900 DEBUG(5,("Moving driver to final destination\n"));
4901 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4903 err = ERROR_ACCESS_DENIED;
4907 if (add_a_printer_driver(driver, level)!=0) {
4908 err = ERROR_ACCESS_DENIED;
4913 free_a_printer_driver(driver, level);
4917 /****************************************************************************
4918 ****************************************************************************/
4919 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4921 init_unistr(&info->name, name);
4924 /****************************************************************************
4925 ****************************************************************************/
4926 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4930 pstring short_archi;
4931 DRIVER_DIRECTORY_1 *info=NULL;
4933 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4935 if (get_short_archi(short_archi, long_archi)==FALSE)
4936 return ERROR_INVALID_ENVIRONMENT;
4938 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4939 return ERROR_NOT_ENOUGH_MEMORY;
4941 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4943 DEBUG(4,("printer driver directory: [%s]\n", path));
4945 fill_driverdir_1(info, path);
4947 *needed += spoolss_size_driverdir_info_1(info);
4949 if (!alloc_buffer_size(buffer, *needed)) {
4951 return ERROR_INSUFFICIENT_BUFFER;
4954 new_smb_io_driverdir_1("", buffer, info, 0);
4958 if (*needed > offered)
4959 return ERROR_INSUFFICIENT_BUFFER;
4961 return NT_STATUS_NO_PROBLEMO;
4964 /****************************************************************************
4965 ****************************************************************************/
4966 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4967 NEW_BUFFER *buffer, uint32 offered,
4970 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4976 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4978 return ERROR_INVALID_LEVEL;
4982 /****************************************************************************
4983 ****************************************************************************/
4984 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4985 uint32 in_value_len, uint32 in_data_len,
4986 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4988 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
4990 NT_PRINTER_INFO_LEVEL *printer = NULL;
4995 uint32 biggest_valuesize;
4996 uint32 biggest_datasize;
4998 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5003 ZERO_STRUCT(printer);
5005 *out_max_value_len=0;
5011 *out_max_data_len=0;
5015 DEBUG(5,("spoolss_enumprinterdata\n"));
5017 if (!OPEN_HANDLE(Printer)) {
5018 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5019 return ERROR_INVALID_HANDLE;
5022 if (!get_printer_snum(handle, &snum))
5023 return ERROR_INVALID_HANDLE;
5025 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5026 return ERROR_INVALID_HANDLE;
5029 * The NT machine wants to know the biggest size of value and data
5031 * cf: MSDN EnumPrinterData remark section
5033 if ( (in_value_len==0) && (in_data_len==0) ) {
5034 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5038 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5039 * if this parameter size doesn't exist.
5040 * Ok - my opinion here is that the client is not asking for the greatest
5041 * possible size of all the parameters, but is asking specifically for the size needed
5042 * for this specific parameter. In that case we can remove the loop below and
5043 * simplify this lookup code considerably. JF - comments welcome. JRA.
5046 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5048 free_a_printer(&printer, 2);
5049 return ERROR_NO_MORE_ITEMS;
5057 biggest_valuesize=0;
5060 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5061 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5062 if (data_len > biggest_datasize) biggest_datasize=data_len;
5064 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5072 * I think this is correct, it doesn't break APW and
5073 * allows Gerald's Win32 test programs to work correctly,
5074 * but may need altering.... JRA.
5077 if (param_index == 0) {
5078 /* No parameters found. */
5079 free_a_printer(&printer, 2);
5080 return ERROR_NO_MORE_ITEMS;
5083 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5084 *out_value_len=2*(1+biggest_valuesize);
5085 *out_data_len=biggest_datasize;
5087 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5089 free_a_printer(&printer, 2);
5090 return NT_STATUS_NO_PROBLEMO;
5094 * the value len is wrong in NT sp3
5095 * that's the number of bytes not the number of unicode chars
5098 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5100 free_a_printer(&printer, 2);
5101 return ERROR_NO_MORE_ITEMS;
5104 free_a_printer(&printer, 2);
5108 * - counted in bytes in the request
5109 * - counted in UNICODE chars in the max reply
5110 * - counted in bytes in the real size
5112 * take a pause *before* coding not *during* coding
5115 *out_max_value_len=(in_value_len/sizeof(uint16));
5116 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5118 return ERROR_NOT_ENOUGH_MEMORY;
5121 ZERO_STRUCTP(*out_value);
5122 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5126 /* the data is counted in bytes */
5127 *out_max_data_len=in_data_len;
5128 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5130 return ERROR_NOT_ENOUGH_MEMORY;
5133 memset(*data_out,'\0',in_data_len);
5134 memcpy(*data_out, data, (size_t)data_len);
5135 *out_data_len=data_len;
5139 return NT_STATUS_NO_PROBLEMO;
5142 /****************************************************************************
5143 ****************************************************************************/
5144 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5145 const UNISTR2 *value,
5150 uint32 numeric_data)
5152 NT_PRINTER_INFO_LEVEL *printer = NULL;
5153 NT_PRINTER_PARAM *param = NULL, old_param;
5155 uint32 status = 0x0;
5156 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5158 DEBUG(5,("spoolss_setprinterdata\n"));
5160 if (!OPEN_HANDLE(Printer)) {
5161 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5162 return ERROR_INVALID_HANDLE;
5165 if (!get_printer_snum(handle, &snum))
5166 return ERROR_INVALID_HANDLE;
5168 status = get_a_printer(&printer, 2, lp_servicename(snum));
5170 return ERROR_INVALID_NAME;
5172 convert_specific_param(¶m, value , type, data, real_len);
5174 /* Check if we are making any changes or not. Return true if
5175 nothing is actually changing. */
5177 ZERO_STRUCT(old_param);
5179 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5180 &old_param.type, &old_param.data_len)) {
5182 if (param->type == old_param.type &&
5183 param->data_len == old_param.data_len &&
5184 memcmp(param->data, old_param.data,
5185 old_param.data_len) == 0) {
5187 DEBUG(3, ("setprinterdata hasn't changed\n"));
5188 status = NT_STATUS_NO_PROBLEMO;
5195 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5196 DEBUG(3, ("security descriptor change denied by existing "
5197 "security descriptor\n"));
5198 status = ERROR_ACCESS_DENIED;
5202 unlink_specific_param_if_exist(printer->info_2, param);
5204 if (!add_a_specific_param(printer->info_2, param))
5205 status = ERROR_INVALID_PARAMETER;
5207 status = mod_a_printer(*printer, 2);
5210 free_a_printer(&printer, 2);
5211 safe_free(old_param.data);
5216 /****************************************************************************
5217 ****************************************************************************/
5218 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5220 NT_PRINTER_INFO_LEVEL *printer = NULL;
5221 NT_PRINTER_PARAM param;
5223 uint32 status = 0x0;
5224 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5226 DEBUG(5,("spoolss_deleteprinterdata\n"));
5228 if (!OPEN_HANDLE(Printer)) {
5229 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5230 return ERROR_INVALID_HANDLE;
5233 if (!get_printer_snum(handle, &snum))
5234 return ERROR_INVALID_HANDLE;
5236 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5237 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5238 "security descriptor\n"));
5239 return ERROR_ACCESS_DENIED;
5242 status = get_a_printer(&printer, 2, lp_servicename(snum));
5244 return ERROR_INVALID_NAME;
5246 ZERO_STRUCTP(¶m);
5247 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5249 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5250 status = ERROR_INVALID_PARAMETER;
5252 status = mod_a_printer(*printer, 2);
5254 free_a_printer(&printer, 2);
5258 /****************************************************************************
5259 ****************************************************************************/
5260 uint32 _spoolss_addform( POLICY_HND *handle,
5265 nt_forms_struct *list=NULL;
5266 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5268 DEBUG(5,("spoolss_addform\n"));
5270 if (!OPEN_HANDLE(Printer)) {
5271 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5272 return ERROR_INVALID_HANDLE;
5275 count=get_ntforms(&list);
5276 if(!add_a_form(&list, form, &count))
5277 return ERROR_NOT_ENOUGH_MEMORY;
5278 write_ntforms(&list, count);
5285 /****************************************************************************
5286 ****************************************************************************/
5287 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5291 nt_forms_struct *list=NULL;
5292 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5294 DEBUG(5,("spoolss_deleteform\n"));
5296 if (!OPEN_HANDLE(Printer)) {
5297 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5298 return ERROR_INVALID_HANDLE;
5301 count = get_ntforms(&list);
5302 if(!delete_a_form(&list, form_name, &count, &ret))
5303 return ERROR_INVALID_PARAMETER;
5310 /****************************************************************************
5311 ****************************************************************************/
5312 uint32 _spoolss_setform( POLICY_HND *handle,
5313 const UNISTR2 *uni_name,
5318 nt_forms_struct *list=NULL;
5319 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5321 DEBUG(5,("spoolss_setform\n"));
5323 if (!OPEN_HANDLE(Printer)) {
5324 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5325 return ERROR_INVALID_HANDLE;
5327 count=get_ntforms(&list);
5328 update_a_form(&list, form, count);
5329 write_ntforms(&list, count);
5336 /****************************************************************************
5337 enumprintprocessors level 1.
5338 ****************************************************************************/
5339 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5341 PRINTPROCESSOR_1 *info_1=NULL;
5343 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5344 return ERROR_NOT_ENOUGH_MEMORY;
5348 init_unistr(&info_1->name, "winprint");
5350 *needed += spoolss_size_printprocessor_info_1(info_1);
5352 if (!alloc_buffer_size(buffer, *needed))
5353 return ERROR_INSUFFICIENT_BUFFER;
5355 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5359 if (*needed > offered) {
5361 return ERROR_INSUFFICIENT_BUFFER;
5364 return NT_STATUS_NO_PROBLEMO;
5367 /****************************************************************************
5368 ****************************************************************************/
5369 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5370 NEW_BUFFER *buffer, uint32 offered,
5371 uint32 *needed, uint32 *returned)
5373 DEBUG(5,("spoolss_enumprintprocessors\n"));
5376 * Enumerate the print processors ...
5378 * Just reply with "winprint", to keep NT happy
5379 * and I can use my nice printer checker.
5387 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5389 return ERROR_INVALID_LEVEL;
5393 /****************************************************************************
5394 enumprintprocdatatypes level 1.
5395 ****************************************************************************/
5396 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5398 PRINTPROCDATATYPE_1 *info_1=NULL;
5400 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5401 return ERROR_NOT_ENOUGH_MEMORY;
5405 init_unistr(&info_1->name, "RAW");
5407 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5409 if (!alloc_buffer_size(buffer, *needed))
5410 return ERROR_INSUFFICIENT_BUFFER;
5412 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5416 if (*needed > offered) {
5418 return ERROR_INSUFFICIENT_BUFFER;
5421 return NT_STATUS_NO_PROBLEMO;
5424 /****************************************************************************
5425 ****************************************************************************/
5426 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5427 NEW_BUFFER *buffer, uint32 offered,
5428 uint32 *needed, uint32 *returned)
5430 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5437 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5439 return ERROR_INVALID_LEVEL;
5443 /****************************************************************************
5444 enumprintmonitors level 1.
5445 ****************************************************************************/
5446 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5448 PRINTMONITOR_1 *info_1=NULL;
5450 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5451 return ERROR_NOT_ENOUGH_MEMORY;
5455 init_unistr(&info_1->name, "Local Port");
5457 *needed += spoolss_size_printmonitor_info_1(info_1);
5459 if (!alloc_buffer_size(buffer, *needed))
5460 return ERROR_INSUFFICIENT_BUFFER;
5462 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5466 if (*needed > offered) {
5468 return ERROR_INSUFFICIENT_BUFFER;
5471 return NT_STATUS_NO_PROBLEMO;
5474 /****************************************************************************
5475 enumprintmonitors level 2.
5476 ****************************************************************************/
5477 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5479 PRINTMONITOR_2 *info_2=NULL;
5481 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5482 return ERROR_NOT_ENOUGH_MEMORY;
5486 init_unistr(&info_2->name, "Local Port");
5487 init_unistr(&info_2->environment, "Windows NT X86");
5488 init_unistr(&info_2->dll_name, "localmon.dll");
5490 *needed += spoolss_size_printmonitor_info_2(info_2);
5492 if (!alloc_buffer_size(buffer, *needed))
5493 return ERROR_INSUFFICIENT_BUFFER;
5495 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5499 if (*needed > offered) {
5501 return ERROR_INSUFFICIENT_BUFFER;
5504 return NT_STATUS_NO_PROBLEMO;
5507 /****************************************************************************
5508 ****************************************************************************/
5509 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5510 NEW_BUFFER *buffer, uint32 offered,
5511 uint32 *needed, uint32 *returned)
5513 DEBUG(5,("spoolss_enumprintmonitors\n"));
5516 * Enumerate the print monitors ...
5518 * Just reply with "Local Port", to keep NT happy
5519 * and I can use my nice printer checker.
5527 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5529 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5531 return ERROR_INVALID_LEVEL;
5535 /****************************************************************************
5536 ****************************************************************************/
5537 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5541 JOB_INFO_1 *info_1=NULL;
5543 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5545 if (info_1 == NULL) {
5547 return ERROR_NOT_ENOUGH_MEMORY;
5550 for (i=0; i<count && found==False; i++) {
5551 if (queue[i].job==(int)jobid)
5558 /* I shoud reply something else ... I can't find the good one */
5559 return NT_STATUS_NO_PROBLEMO;
5562 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5566 *needed += spoolss_size_job_info_1(info_1);
5568 if (!alloc_buffer_size(buffer, *needed)) {
5570 return ERROR_INSUFFICIENT_BUFFER;
5573 new_smb_io_job_info_1("", buffer, info_1, 0);
5577 if (*needed > offered)
5578 return ERROR_INSUFFICIENT_BUFFER;
5580 return NT_STATUS_NO_PROBLEMO;
5584 /****************************************************************************
5585 ****************************************************************************/
5586 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5591 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5593 ZERO_STRUCTP(info_2);
5595 if (info_2 == NULL) {
5597 return ERROR_NOT_ENOUGH_MEMORY;
5600 for (i=0; i<count && found==False; i++) {
5601 if (queue[i].job==(int)jobid)
5608 /* I shoud reply something else ... I can't find the good one */
5609 return NT_STATUS_NO_PROBLEMO;
5612 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5616 *needed += spoolss_size_job_info_2(info_2);
5618 if (!alloc_buffer_size(buffer, *needed)) {
5620 return ERROR_INSUFFICIENT_BUFFER;
5623 new_smb_io_job_info_2("", buffer, info_2, 0);
5625 free_dev_mode(info_2->devmode);
5628 if (*needed > offered)
5629 return ERROR_INSUFFICIENT_BUFFER;
5631 return NT_STATUS_NO_PROBLEMO;
5634 /****************************************************************************
5635 ****************************************************************************/
5636 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5637 NEW_BUFFER *buffer, uint32 offered,
5642 print_queue_struct *queue=NULL;
5643 print_status_struct prt_status;
5645 DEBUG(5,("spoolss_getjob\n"));
5647 memset(&prt_status, 0, sizeof(prt_status));
5651 if (!get_printer_snum(handle, &snum))
5652 return ERROR_INVALID_HANDLE;
5654 count = print_queue_status(snum, &queue, &prt_status);
5656 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5657 count, prt_status.status, prt_status.message));
5661 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5663 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5666 return ERROR_INVALID_LEVEL;