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);
1591 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1596 free_a_printer(&printer, 2);
1600 /*******************************************************************
1602 * fill a notify_info struct with info asked
1604 ********************************************************************/
1605 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1611 SPOOL_NOTIFY_INFO_DATA *current_data;
1612 NT_PRINTER_INFO_LEVEL *printer = NULL;
1614 DEBUG(4,("construct_notify_jobs_info\n"));
1616 type = option_type->type;
1618 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1619 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1620 option_type->count));
1622 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1625 for(field_num=0; field_num<option_type->count; field_num++) {
1626 field = option_type->fields[field_num];
1628 if (!search_notify(type, field, &j) )
1631 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1635 current_data=&(info->data[info->count]);
1637 construct_info_data(current_data, type, field, id);
1638 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1642 free_a_printer(&printer, 2);
1647 * JFM: The enumeration is not that simple, it's even non obvious.
1649 * let's take an example: I want to monitor the PRINTER SERVER for
1650 * the printer's name and the number of jobs currently queued.
1651 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1652 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1654 * I have 3 printers on the back of my server.
1656 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1659 * 1 printer 1 name 1
1660 * 2 printer 1 cjob 1
1661 * 3 printer 2 name 2
1662 * 4 printer 2 cjob 2
1663 * 5 printer 3 name 3
1664 * 6 printer 3 name 3
1666 * that's the print server case, the printer case is even worse.
1671 /*******************************************************************
1673 * enumerate all printers on the printserver
1674 * fill a notify_info struct with info asked
1676 ********************************************************************/
1677 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1680 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1681 int n_services=lp_numservices();
1684 SPOOL_NOTIFY_OPTION *option;
1685 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1687 DEBUG(4,("printserver_notify_info\n"));
1689 option=Printer->notify.option;
1695 for (i=0; i<option->count; i++) {
1696 option_type=&(option->ctr.type[i]);
1698 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1701 for (snum=0; snum<n_services; snum++)
1702 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1703 if (construct_notify_printer_info(info, snum, option_type, id))
1708 * Debugging information, don't delete.
1711 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1712 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1713 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1715 for (i=0; i<info->count; i++) {
1716 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1717 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1718 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1722 return NT_STATUS_NO_PROBLEMO;
1725 /*******************************************************************
1727 * fill a notify_info struct with info asked
1729 ********************************************************************/
1730 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1733 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1736 SPOOL_NOTIFY_OPTION *option;
1737 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1739 print_queue_struct *queue=NULL;
1740 print_status_struct status;
1742 DEBUG(4,("printer_notify_info\n"));
1744 option=Printer->notify.option;
1750 get_printer_snum(hnd, &snum);
1752 for (i=0; i<option->count; i++) {
1753 option_type=&option->ctr.type[i];
1755 switch ( option_type->type ) {
1756 case PRINTER_NOTIFY_TYPE:
1757 if(construct_notify_printer_info(info, snum, option_type, id))
1761 case JOB_NOTIFY_TYPE:
1762 memset(&status, 0, sizeof(status));
1763 count = print_queue_status(snum, &queue, &status);
1764 for (j=0; j<count; j++)
1765 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1772 * Debugging information, don't delete.
1775 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1776 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1777 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1779 for (i=0; i<info->count; i++) {
1780 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1781 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1782 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1785 return NT_STATUS_NO_PROBLEMO;
1788 /********************************************************************
1790 ********************************************************************/
1791 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1792 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1794 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1796 if (!OPEN_HANDLE(Printer)) {
1797 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1798 return ERROR_INVALID_HANDLE;
1801 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1803 /* jfm: the change value isn't used right now.
1804 * we will honour it when
1805 * a) we'll be able to send notification to the client
1806 * b) we'll have a way to communicate between the spoolss process.
1808 * same thing for option->flags
1809 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1810 * I don't have a global notification system, I'm sending back all the
1811 * informations even when _NOTHING_ has changed.
1814 /* just discard the SPOOL_NOTIFY_OPTION */
1816 safe_free(option->ctr.type);
1818 switch (Printer->printer_type) {
1819 case PRINTER_HANDLE_IS_PRINTSERVER:
1820 return printserver_notify_info(handle, info);
1821 case PRINTER_HANDLE_IS_PRINTER:
1822 return printer_notify_info(handle, info);
1825 return ERROR_INVALID_HANDLE;
1828 /********************************************************************
1829 * construct_printer_info_0
1830 * fill a printer_info_1 struct
1831 ********************************************************************/
1832 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, fstring servername)
1836 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1837 counter_printer_0 *session_counter;
1838 uint32 global_counter;
1842 print_queue_struct *queue=NULL;
1843 print_status_struct status;
1845 memset(&status, 0, sizeof(status));
1847 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1850 count = print_queue_status(snum, &queue, &status);
1852 /* check if we already have a counter for this printer */
1853 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1855 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1856 if (session_counter->snum == snum)
1860 /* it's the first time, add it to the list */
1861 if (session_counter==NULL) {
1862 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1863 free_a_printer(&ntprinter, 2);
1866 ZERO_STRUCTP(session_counter);
1867 session_counter->snum=snum;
1868 session_counter->counter=0;
1869 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1873 session_counter->counter++;
1876 * the global_counter should be stored in a TDB as it's common to all the clients
1877 * and should be zeroed on samba startup
1879 global_counter=session_counter->counter;
1881 pstrcpy(chaine,ntprinter->info_2->printername);
1883 init_unistr(&printer->printername, chaine);
1885 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername);
1886 init_unistr(&printer->servername, chaine);
1888 printer->cjobs = count;
1889 printer->total_jobs = 0;
1890 printer->total_bytes = 0;
1892 setuptime = (time_t)ntprinter->info_2->setuptime;
1893 t=gmtime(&setuptime);
1895 printer->year = t->tm_year+1900;
1896 printer->month = t->tm_mon+1;
1897 printer->dayofweek = t->tm_wday;
1898 printer->day = t->tm_mday;
1899 printer->hour = t->tm_hour;
1900 printer->minute = t->tm_min;
1901 printer->second = t->tm_sec;
1902 printer->milliseconds = 0;
1904 printer->global_counter = global_counter;
1905 printer->total_pages = 0;
1906 printer->major_version = 0x0004; /* NT 4 */
1907 printer->build_version = 0x0565; /* build 1381 */
1908 printer->unknown7 = 0x1;
1909 printer->unknown8 = 0x0;
1910 printer->unknown9 = 0x0;
1911 printer->session_counter = session_counter->counter;
1912 printer->unknown11 = 0x0;
1913 printer->printer_errors = 0x0; /* number of print failure */
1914 printer->unknown13 = 0x0;
1915 printer->unknown14 = 0x1;
1916 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1917 printer->unknown16 = 0x0;
1918 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1919 printer->unknown18 = 0x0;
1920 printer->status = nt_printq_status(status.status);
1921 printer->unknown20 = 0x0;
1922 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1923 printer->unknown22 = 0x0;
1924 printer->unknown23 = 0x6; /* 6 ???*/
1925 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1926 printer->unknown25 = 0;
1927 printer->unknown26 = 0;
1928 printer->unknown27 = 0;
1929 printer->unknown28 = 0;
1930 printer->unknown29 = 0;
1933 free_a_printer(&ntprinter,2);
1937 /********************************************************************
1938 * construct_printer_info_1
1939 * fill a printer_info_1 struct
1940 ********************************************************************/
1941 static BOOL construct_printer_info_1(fstring server, uint32 flags, PRINTER_INFO_1 *printer, int snum)
1945 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1947 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1950 printer->flags=flags;
1952 if (*ntprinter->info_2->comment == '\0') {
1953 init_unistr(&printer->comment, lp_comment(snum));
1954 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1955 ntprinter->info_2->drivername, lp_comment(snum));
1958 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1959 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1960 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1963 snprintf(chaine2,sizeof(chaine)-1,"%s%s", server, ntprinter->info_2->printername);
1965 init_unistr(&printer->description, chaine);
1966 init_unistr(&printer->name, chaine2);
1968 free_a_printer(&ntprinter,2);
1973 /****************************************************************************
1974 Free a DEVMODE struct.
1975 ****************************************************************************/
1977 static void free_dev_mode(DEVICEMODE *dev)
1983 safe_free(dev->private);
1988 /****************************************************************************
1989 Create a DEVMODE struct. Returns malloced memory.
1990 ****************************************************************************/
1992 static DEVICEMODE *construct_dev_mode(int snum, char *servername)
1996 NT_PRINTER_INFO_LEVEL *printer = NULL;
1997 NT_DEVICEMODE *ntdevmode = NULL;
1998 DEVICEMODE *devmode = NULL;
2000 DEBUG(7,("construct_dev_mode\n"));
2002 DEBUGADD(8,("getting printer characteristics\n"));
2004 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2005 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2009 ZERO_STRUCTP(devmode);
2011 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2014 if (printer->info_2->devmode)
2015 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2017 if (ntdevmode == NULL)
2020 DEBUGADD(8,("loading DEVICEMODE\n"));
2022 safe_strcpy(adevice, printer->info_2->printername, sizeof(adevice));
2023 init_unistr(&devmode->devicename, adevice);
2025 snprintf(aform, sizeof(aform), ntdevmode->formname);
2026 init_unistr(&devmode->formname, aform);
2028 devmode->specversion = ntdevmode->specversion;
2029 devmode->driverversion = ntdevmode->driverversion;
2030 devmode->size = ntdevmode->size;
2031 devmode->driverextra = ntdevmode->driverextra;
2032 devmode->fields = ntdevmode->fields;
2034 devmode->orientation = ntdevmode->orientation;
2035 devmode->papersize = ntdevmode->papersize;
2036 devmode->paperlength = ntdevmode->paperlength;
2037 devmode->paperwidth = ntdevmode->paperwidth;
2038 devmode->scale = ntdevmode->scale;
2039 devmode->copies = ntdevmode->copies;
2040 devmode->defaultsource = ntdevmode->defaultsource;
2041 devmode->printquality = ntdevmode->printquality;
2042 devmode->color = ntdevmode->color;
2043 devmode->duplex = ntdevmode->duplex;
2044 devmode->yresolution = ntdevmode->yresolution;
2045 devmode->ttoption = ntdevmode->ttoption;
2046 devmode->collate = ntdevmode->collate;
2047 devmode->icmmethod = ntdevmode->icmmethod;
2048 devmode->icmintent = ntdevmode->icmintent;
2049 devmode->mediatype = ntdevmode->mediatype;
2050 devmode->dithertype = ntdevmode->dithertype;
2052 if (ntdevmode->private != NULL) {
2053 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2057 free_nt_devicemode(&ntdevmode);
2058 free_a_printer(&printer,2);
2065 free_nt_devicemode(&ntdevmode);
2067 free_a_printer(&printer,2);
2068 free_dev_mode(devmode);
2073 /********************************************************************
2074 * construct_printer_info_2
2075 * fill a printer_info_2 struct
2076 ********************************************************************/
2078 static BOOL construct_printer_info_2(fstring servername, PRINTER_INFO_2 *printer, int snum)
2084 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2086 print_queue_struct *queue=NULL;
2087 print_status_struct status;
2088 memset(&status, 0, sizeof(status));
2090 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2093 memset(&status, 0, sizeof(status));
2094 count = print_queue_status(snum, &queue, &status);
2096 snprintf(chaine, sizeof(chaine)-1, "%s", servername);
2098 if (strlen(servername)!=0)
2103 if (!strchr(ntprinter->info_2->printername, '\\')) {
2104 snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter->info_2->printername);
2106 pstrcpy(chaine2, ntprinter->info_2->printername);
2109 init_unistr(&printer->servername, chaine); /* servername*/
2110 init_unistr(&printer->printername, chaine2); /* printername*/
2111 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2112 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2113 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2115 if (*ntprinter->info_2->comment == '\0')
2116 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2118 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2120 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2121 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2122 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2123 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2124 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2126 printer->attributes = ntprinter->info_2->attributes;
2128 printer->priority = ntprinter->info_2->priority; /* priority */
2129 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2130 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2131 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2132 printer->status = nt_printq_status(status.status); /* status */
2133 printer->cjobs = count; /* jobs */
2134 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2136 if((printer->devmode = construct_dev_mode(snum, servername)) == NULL) {
2137 DEBUG(8, ("Returning NULL Devicemode!\n"));
2140 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2141 /* steal the printer info sec_desc structure. [badly done]. */
2142 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2143 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2144 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2145 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2148 printer->secdesc = NULL;
2151 free_a_printer(&ntprinter, 2);
2156 /********************************************************************
2157 * construct_printer_info_3
2158 * fill a printer_info_3 struct
2159 ********************************************************************/
2160 static BOOL construct_printer_info_3(fstring servername,
2161 PRINTER_INFO_3 **pp_printer, int snum)
2163 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2164 PRINTER_INFO_3 *printer = NULL;
2166 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2170 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2171 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2175 ZERO_STRUCTP(printer);
2177 printer->flags = 4; /* These are the components of the SD we are returning. */
2178 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2179 /* steal the printer info sec_desc structure. [badly done]. */
2180 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2184 * Set the flags for the components we are returning.
2187 if (printer->secdesc->owner_sid)
2188 printer->flags |= OWNER_SECURITY_INFORMATION;
2190 if (printer->secdesc->grp_sid)
2191 printer->flags |= GROUP_SECURITY_INFORMATION;
2193 if (printer->secdesc->dacl)
2194 printer->flags |= DACL_SECURITY_INFORMATION;
2196 if (printer->secdesc->sacl)
2197 printer->flags |= SACL_SECURITY_INFORMATION;
2200 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2201 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2202 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2205 free_a_printer(&ntprinter, 2);
2207 *pp_printer = printer;
2211 /********************************************************************
2212 Spoolss_enumprinters.
2213 ********************************************************************/
2214 static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2218 int n_services=lp_numservices();
2219 PRINTER_INFO_1 *printers=NULL;
2220 PRINTER_INFO_1 current_prt;
2222 DEBUG(4,("enum_all_printers_info_1\n"));
2224 for (snum=0; snum<n_services; snum++) {
2225 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2226 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2228 if (construct_printer_info_1(server, flags, ¤t_prt, snum)) {
2229 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2231 return ERROR_NOT_ENOUGH_MEMORY;
2233 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2234 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2240 /* check the required size. */
2241 for (i=0; i<*returned; i++)
2242 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2244 if (!alloc_buffer_size(buffer, *needed))
2245 return ERROR_INSUFFICIENT_BUFFER;
2247 /* fill the buffer with the structures */
2248 for (i=0; i<*returned; i++)
2249 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2252 safe_free(printers);
2254 if (*needed > offered) {
2256 return ERROR_INSUFFICIENT_BUFFER;
2259 return NT_STATUS_NO_PROBLEMO;
2262 /********************************************************************
2263 enum_all_printers_info_1_local.
2264 *********************************************************************/
2265 static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2268 DEBUG(4,("enum_all_printers_info_1_local\n"));
2270 fstrcpy(temp, "\\\\");
2271 fstrcat(temp, global_myname);
2273 if (!strcmp(name, temp)) {
2274 fstrcat(temp, "\\");
2275 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2278 return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2281 /********************************************************************
2282 enum_all_printers_info_1_name.
2283 *********************************************************************/
2284 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2287 DEBUG(4,("enum_all_printers_info_1_name\n"));
2289 fstrcpy(temp, "\\\\");
2290 fstrcat(temp, global_myname);
2292 if (!strcmp(name, temp)) {
2293 fstrcat(temp, "\\");
2294 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2297 return ERROR_INVALID_NAME;
2300 /********************************************************************
2301 enum_all_printers_info_1_remote.
2302 *********************************************************************/
2303 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2305 PRINTER_INFO_1 *printer;
2306 fstring printername;
2309 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2311 /* JFM: currently it's more a place holder than anything else.
2312 * In the spooler world there is a notion of server registration.
2313 * the print servers are registring (sp ?) on the PDC (in the same domain)
2315 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2318 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2319 return ERROR_NOT_ENOUGH_MEMORY;
2323 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2324 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2325 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2327 init_unistr(&printer->description, desc);
2328 init_unistr(&printer->name, printername);
2329 init_unistr(&printer->comment, comment);
2330 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2332 /* check the required size. */
2333 *needed += spoolss_size_printer_info_1(printer);
2335 if (!alloc_buffer_size(buffer, *needed)) {
2337 return ERROR_INSUFFICIENT_BUFFER;
2340 /* fill the buffer with the structures */
2341 new_smb_io_printer_info_1("", buffer, printer, 0);
2346 if (*needed > offered) {
2348 return ERROR_INSUFFICIENT_BUFFER;
2351 return NT_STATUS_NO_PROBLEMO;
2354 /********************************************************************
2355 enum_all_printers_info_1_network.
2356 *********************************************************************/
2357 static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2360 DEBUG(4,("enum_all_printers_info_1_network\n"));
2362 fstrcpy(temp, "\\\\");
2363 fstrcat(temp, global_myname);
2364 fstrcat(temp, "\\");
2365 return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2368 /********************************************************************
2369 * api_spoolss_enumprinters
2371 * called from api_spoolss_enumprinters (see this to understand)
2372 ********************************************************************/
2373 static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2377 int n_services=lp_numservices();
2378 PRINTER_INFO_2 *printers=NULL;
2379 PRINTER_INFO_2 current_prt;
2381 for (snum=0; snum<n_services; snum++) {
2382 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2383 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2385 if (construct_printer_info_2(servername, ¤t_prt, snum)) {
2386 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2387 return ERROR_NOT_ENOUGH_MEMORY;
2388 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2389 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2395 /* check the required size. */
2396 for (i=0; i<*returned; i++)
2397 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2399 if (!alloc_buffer_size(buffer, *needed)) {
2400 for (i=0; i<*returned; i++) {
2401 free_devmode(printers[i].devmode);
2402 free_sec_desc(&printers[i].secdesc);
2404 safe_free(printers);
2405 return ERROR_INSUFFICIENT_BUFFER;
2408 /* fill the buffer with the structures */
2409 for (i=0; i<*returned; i++)
2410 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2413 for (i=0; i<*returned; i++) {
2414 free_devmode(printers[i].devmode);
2415 free_sec_desc(&printers[i].secdesc);
2417 safe_free(printers);
2419 if (*needed > offered) {
2421 return ERROR_INSUFFICIENT_BUFFER;
2424 return NT_STATUS_NO_PROBLEMO;
2427 /********************************************************************
2428 * handle enumeration of printers at level 1
2429 ********************************************************************/
2430 static uint32 enumprinters_level1( uint32 flags, fstring name,
2431 NEW_BUFFER *buffer, uint32 offered,
2432 uint32 *needed, uint32 *returned)
2434 /* Not all the flags are equals */
2436 if (flags & PRINTER_ENUM_LOCAL)
2437 return enum_all_printers_info_1_local(name, buffer, offered, needed, returned);
2439 if (flags & PRINTER_ENUM_NAME)
2440 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2442 if (flags & PRINTER_ENUM_REMOTE)
2443 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2445 if (flags & PRINTER_ENUM_NETWORK)
2446 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
2448 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2451 /********************************************************************
2452 * handle enumeration of printers at level 2
2453 ********************************************************************/
2454 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2455 NEW_BUFFER *buffer, uint32 offered,
2456 uint32 *needed, uint32 *returned)
2460 fstrcpy(temp, "\\\\");
2461 fstrcat(temp, global_myname);
2463 if (flags & PRINTER_ENUM_LOCAL) {
2464 if (!strcmp(servername, temp))
2465 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2467 return enum_all_printers_info_2("", buffer, offered, needed, returned);
2470 if (flags & PRINTER_ENUM_NAME) {
2471 if (!strcmp(servername, temp))
2472 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2474 return ERROR_INVALID_NAME;
2477 if (flags & PRINTER_ENUM_REMOTE)
2478 return ERROR_INVALID_LEVEL;
2480 return NT_STATUS_NO_PROBLEMO;
2483 /********************************************************************
2484 * handle enumeration of printers at level 5
2485 ********************************************************************/
2486 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2487 NEW_BUFFER *buffer, uint32 offered,
2488 uint32 *needed, uint32 *returned)
2490 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2491 return NT_STATUS_NO_PROBLEMO;
2494 /********************************************************************
2495 * api_spoolss_enumprinters
2497 * called from api_spoolss_enumprinters (see this to understand)
2498 ********************************************************************/
2499 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2500 NEW_BUFFER *buffer, uint32 offered,
2501 uint32 *needed, uint32 *returned)
2505 DEBUG(4,("_spoolss_enumprinters\n"));
2512 * flags==PRINTER_ENUM_NAME
2513 * if name=="" then enumerates all printers
2514 * if name!="" then enumerate the printer
2515 * flags==PRINTER_ENUM_REMOTE
2516 * name is NULL, enumerate printers
2517 * Level 2: name!="" enumerates printers, name can't be NULL
2518 * Level 3: doesn't exist
2519 * Level 4: does a local registry lookup
2520 * Level 5: same as Level 2
2523 unistr2_to_ascii(name, servername, sizeof(name)-1);
2528 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2530 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2532 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2536 return ERROR_INVALID_LEVEL;
2540 /****************************************************************************
2541 ****************************************************************************/
2542 static uint32 getprinter_level_0(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2544 PRINTER_INFO_0 *printer=NULL;
2546 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2547 return ERROR_NOT_ENOUGH_MEMORY;
2549 construct_printer_info_0(printer, snum, servername);
2551 /* check the required size. */
2552 *needed += spoolss_size_printer_info_0(printer);
2554 if (!alloc_buffer_size(buffer, *needed)) {
2556 return ERROR_INSUFFICIENT_BUFFER;
2559 /* fill the buffer with the structures */
2560 new_smb_io_printer_info_0("", buffer, printer, 0);
2565 if (*needed > offered) {
2566 return ERROR_INSUFFICIENT_BUFFER;
2569 return NT_STATUS_NO_PROBLEMO;
2572 /****************************************************************************
2573 ****************************************************************************/
2574 static uint32 getprinter_level_1(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2576 PRINTER_INFO_1 *printer=NULL;
2578 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2579 return ERROR_NOT_ENOUGH_MEMORY;
2581 construct_printer_info_1(servername, PRINTER_ENUM_ICON8, printer, snum);
2583 /* check the required size. */
2584 *needed += spoolss_size_printer_info_1(printer);
2586 if (!alloc_buffer_size(buffer, *needed)) {
2588 return ERROR_INSUFFICIENT_BUFFER;
2591 /* fill the buffer with the structures */
2592 new_smb_io_printer_info_1("", buffer, printer, 0);
2597 if (*needed > offered) {
2598 return ERROR_INSUFFICIENT_BUFFER;
2601 return NT_STATUS_NO_PROBLEMO;
2604 /****************************************************************************
2605 ****************************************************************************/
2606 static uint32 getprinter_level_2(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2608 PRINTER_INFO_2 *printer=NULL;
2611 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2612 return ERROR_NOT_ENOUGH_MEMORY;
2614 fstrcpy(temp, "\\\\");
2615 fstrcat(temp, servername);
2616 construct_printer_info_2(temp, printer, snum);
2618 /* check the required size. */
2619 *needed += spoolss_size_printer_info_2(printer);
2621 if (!alloc_buffer_size(buffer, *needed)) {
2622 free_printer_info_2(printer);
2623 return ERROR_INSUFFICIENT_BUFFER;
2626 /* fill the buffer with the structures */
2627 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2628 free_printer_info_2(printer);
2629 return ERROR_NOT_ENOUGH_MEMORY;
2633 free_printer_info_2(printer);
2635 if (*needed > offered) {
2636 return ERROR_INSUFFICIENT_BUFFER;
2639 return NT_STATUS_NO_PROBLEMO;
2642 /****************************************************************************
2643 ****************************************************************************/
2644 static uint32 getprinter_level_3(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2646 PRINTER_INFO_3 *printer=NULL;
2649 fstrcpy(temp, "\\\\");
2650 fstrcat(temp, servername);
2651 if (!construct_printer_info_3(temp, &printer, snum))
2652 return ERROR_NOT_ENOUGH_MEMORY;
2654 /* check the required size. */
2655 *needed += spoolss_size_printer_info_3(printer);
2657 if (!alloc_buffer_size(buffer, *needed)) {
2658 free_printer_info_3(printer);
2659 return ERROR_INSUFFICIENT_BUFFER;
2662 /* fill the buffer with the structures */
2663 new_smb_io_printer_info_3("", buffer, printer, 0);
2666 free_printer_info_3(printer);
2668 if (*needed > offered) {
2669 return ERROR_INSUFFICIENT_BUFFER;
2672 return NT_STATUS_NO_PROBLEMO;
2675 /****************************************************************************
2676 ****************************************************************************/
2677 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2678 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2685 pstrcpy(servername, global_myname);
2687 if (!get_printer_snum(handle, &snum))
2688 return ERROR_INVALID_HANDLE;
2692 return getprinter_level_0(servername, snum, buffer, offered, needed);
2694 return getprinter_level_1(servername,snum, buffer, offered, needed);
2696 return getprinter_level_2(servername,snum, buffer, offered, needed);
2698 return getprinter_level_3(servername,snum, buffer, offered, needed);
2700 return ERROR_INVALID_LEVEL;
2704 /********************************************************************
2705 * fill a DRIVER_INFO_1 struct
2706 ********************************************************************/
2707 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2709 init_unistr( &info->name, driver.info_3->name);
2712 /********************************************************************
2713 * construct_printer_driver_info_1
2714 ********************************************************************/
2715 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2717 NT_PRINTER_INFO_LEVEL *printer = NULL;
2718 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2720 ZERO_STRUCT(driver);
2722 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2723 return ERROR_INVALID_PRINTER_NAME;
2725 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2726 return ERROR_UNKNOWN_PRINTER_DRIVER;
2728 fill_printer_driver_info_1(info, driver, servername, architecture);
2730 free_a_printer(&printer,2);
2732 return NT_STATUS_NO_PROBLEMO;
2735 /********************************************************************
2736 * construct_printer_driver_info_2
2737 * fill a printer_info_2 struct
2738 ********************************************************************/
2739 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2741 pstring temp_driverpath;
2742 pstring temp_datafile;
2743 pstring temp_configfile;
2745 info->version=driver.info_3->cversion;
2747 init_unistr( &info->name, driver.info_3->name );
2748 init_unistr( &info->architecture, driver.info_3->environment );
2750 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2751 init_unistr( &info->driverpath, temp_driverpath );
2753 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2754 init_unistr( &info->datafile, temp_datafile );
2756 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2757 init_unistr( &info->configfile, temp_configfile );
2760 /********************************************************************
2761 * construct_printer_driver_info_2
2762 * fill a printer_info_2 struct
2763 ********************************************************************/
2764 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2766 NT_PRINTER_INFO_LEVEL *printer = NULL;
2767 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2769 ZERO_STRUCT(printer);
2770 ZERO_STRUCT(driver);
2772 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2773 return ERROR_INVALID_PRINTER_NAME;
2775 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2776 return ERROR_UNKNOWN_PRINTER_DRIVER;
2778 fill_printer_driver_info_2(info, driver, servername);
2780 free_a_printer(&printer,2);
2782 return NT_STATUS_NO_PROBLEMO;
2785 /********************************************************************
2786 * copy a strings array and convert to UNICODE
2788 * convert an array of ascii string to a UNICODE string
2789 ********************************************************************/
2790 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2797 DEBUG(6,("init_unistr_array\n"));
2801 if (char_array == NULL)
2805 if (!v) v = ""; /* hack to handle null lists */
2807 if (strlen(v) == 0) break;
2808 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2809 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2810 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2811 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2814 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2819 (*uni_array)[j]=0x0000;
2822 DEBUGADD(6,("last one:done\n"));
2825 /********************************************************************
2826 * construct_printer_info_3
2827 * fill a printer_info_3 struct
2828 ********************************************************************/
2829 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2831 pstring temp_driverpath;
2832 pstring temp_datafile;
2833 pstring temp_configfile;
2834 pstring temp_helpfile;
2838 info->version=driver.info_3->cversion;
2840 init_unistr( &info->name, driver.info_3->name );
2841 init_unistr( &info->architecture, driver.info_3->environment );
2843 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2844 init_unistr( &info->driverpath, temp_driverpath );
2846 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2847 init_unistr( &info->datafile, temp_datafile );
2849 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2850 init_unistr( &info->configfile, temp_configfile );
2852 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2853 init_unistr( &info->helpfile, temp_helpfile );
2855 init_unistr( &info->monitorname, driver.info_3->monitorname );
2856 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2858 info->dependentfiles=NULL;
2859 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2862 /********************************************************************
2863 * construct_printer_info_3
2864 * fill a printer_info_3 struct
2865 ********************************************************************/
2866 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2868 NT_PRINTER_INFO_LEVEL *printer = NULL;
2869 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2871 ZERO_STRUCT(driver);
2873 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2874 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2876 return ERROR_INVALID_PRINTER_NAME;
2878 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2879 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2881 free_a_printer(&printer,2);
2882 return ERROR_UNKNOWN_PRINTER_DRIVER;
2885 fill_printer_driver_info_3(info, driver, servername);
2887 free_a_printer(&printer,2);
2889 return NT_STATUS_NO_PROBLEMO;
2892 /********************************************************************
2893 * construct_printer_info_6
2894 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2895 ********************************************************************/
2897 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2899 pstring temp_driverpath;
2900 pstring temp_datafile;
2901 pstring temp_configfile;
2902 pstring temp_helpfile;
2906 memset(&nullstr, '\0', sizeof(fstring));
2908 info->version=driver.info_3->cversion;
2910 init_unistr( &info->name, driver.info_3->name );
2911 init_unistr( &info->architecture, driver.info_3->environment );
2913 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2914 init_unistr( &info->driverpath, temp_driverpath );
2916 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2917 init_unistr( &info->datafile, temp_datafile );
2919 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2920 init_unistr( &info->configfile, temp_configfile );
2922 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2923 init_unistr( &info->helpfile, temp_helpfile );
2925 init_unistr( &info->monitorname, driver.info_3->monitorname );
2926 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2928 info->dependentfiles=NULL;
2929 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2931 info->previousdrivernames=NULL;
2932 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2934 info->driver_date.low=0;
2935 info->driver_date.high=0;
2938 info->driver_version_low=0;
2939 info->driver_version_high=0;
2941 init_unistr( &info->mfgname, "");
2942 init_unistr( &info->oem_url, "");
2943 init_unistr( &info->hardware_id, "");
2944 init_unistr( &info->provider, "");
2947 /********************************************************************
2948 * construct_printer_info_6
2949 * fill a printer_info_6 struct
2950 ********************************************************************/
2951 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2953 NT_PRINTER_INFO_LEVEL *printer = NULL;
2954 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2956 ZERO_STRUCT(driver);
2958 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2959 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2961 return ERROR_INVALID_PRINTER_NAME;
2963 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2964 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2966 free_a_printer(&printer,2);
2967 return ERROR_UNKNOWN_PRINTER_DRIVER;
2970 fill_printer_driver_info_6(info, driver, servername);
2972 free_a_printer(&printer,2);
2974 return NT_STATUS_NO_PROBLEMO;
2977 /****************************************************************************
2978 ****************************************************************************/
2980 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2982 safe_free(info->dependentfiles);
2985 /****************************************************************************
2986 ****************************************************************************/
2988 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2990 safe_free(info->dependentfiles);
2994 /****************************************************************************
2995 ****************************************************************************/
2996 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2998 DRIVER_INFO_1 *info=NULL;
3001 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3002 return ERROR_NOT_ENOUGH_MEMORY;
3004 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3005 if (status != NT_STATUS_NO_PROBLEMO) {
3010 /* check the required size. */
3011 *needed += spoolss_size_printer_driver_info_1(info);
3013 if (!alloc_buffer_size(buffer, *needed)) {
3015 return ERROR_INSUFFICIENT_BUFFER;
3018 /* fill the buffer with the structures */
3019 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3024 if (*needed > offered)
3025 return ERROR_INSUFFICIENT_BUFFER;
3027 return NT_STATUS_NO_PROBLEMO;
3030 /****************************************************************************
3031 ****************************************************************************/
3032 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3034 DRIVER_INFO_2 *info=NULL;
3037 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3038 return ERROR_NOT_ENOUGH_MEMORY;
3040 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3041 if (status != NT_STATUS_NO_PROBLEMO) {
3046 /* check the required size. */
3047 *needed += spoolss_size_printer_driver_info_2(info);
3049 if (!alloc_buffer_size(buffer, *needed)) {
3051 return ERROR_INSUFFICIENT_BUFFER;
3054 /* fill the buffer with the structures */
3055 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3060 if (*needed > offered)
3061 return ERROR_INSUFFICIENT_BUFFER;
3063 return NT_STATUS_NO_PROBLEMO;
3066 /****************************************************************************
3067 ****************************************************************************/
3068 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3075 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3076 if (status != NT_STATUS_NO_PROBLEMO) {
3080 /* check the required size. */
3081 *needed += spoolss_size_printer_driver_info_3(&info);
3083 if (!alloc_buffer_size(buffer, *needed)) {
3084 free_printer_driver_info_3(&info);
3085 return ERROR_INSUFFICIENT_BUFFER;
3088 /* fill the buffer with the structures */
3089 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3091 free_printer_driver_info_3(&info);
3093 if (*needed > offered)
3094 return ERROR_INSUFFICIENT_BUFFER;
3096 return NT_STATUS_NO_PROBLEMO;
3099 /****************************************************************************
3100 ****************************************************************************/
3101 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3108 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3109 if (status != NT_STATUS_NO_PROBLEMO) {
3113 /* check the required size. */
3114 *needed += spoolss_size_printer_driver_info_6(&info);
3116 if (!alloc_buffer_size(buffer, *needed)) {
3117 free_printer_driver_info_6(&info);
3118 return ERROR_INSUFFICIENT_BUFFER;
3121 /* fill the buffer with the structures */
3122 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3124 free_printer_driver_info_6(&info);
3126 if (*needed > offered)
3127 return ERROR_INSUFFICIENT_BUFFER;
3129 return NT_STATUS_NO_PROBLEMO;
3132 /****************************************************************************
3133 ****************************************************************************/
3134 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3135 uint32 clientmajorversion, uint32 clientminorversion,
3136 NEW_BUFFER *buffer, uint32 offered,
3137 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3140 fstring architecture;
3143 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3146 *servermajorversion=0;
3147 *serverminorversion=0;
3149 pstrcpy(servername, global_myname);
3150 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3152 if (!get_printer_snum(handle, &snum))
3153 return ERROR_INVALID_HANDLE;
3157 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3159 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3161 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3163 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3165 return ERROR_INVALID_LEVEL;
3169 /****************************************************************************
3170 ****************************************************************************/
3171 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3173 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3175 if (OPEN_HANDLE(Printer)) {
3176 Printer->page_started=True;
3180 DEBUG(3,("Error in startpageprinter printer handle\n"));
3181 return ERROR_INVALID_HANDLE;
3184 /****************************************************************************
3185 ****************************************************************************/
3186 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3188 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3190 if (!OPEN_HANDLE(Printer)) {
3191 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3192 return ERROR_INVALID_HANDLE;
3195 Printer->page_started=False;
3197 return NT_STATUS_NO_PROBLEMO;
3200 /****************************************************************************
3201 Return a user struct for a pipe user.
3202 ****************************************************************************/
3204 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3206 if (p->ntlmssp_auth_validated) {
3207 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3209 extern struct current_user current_user;
3210 memcpy(user, ¤t_user, sizeof(struct current_user));
3216 /********************************************************************
3217 * api_spoolss_getprinter
3218 * called from the spoolss dispatcher
3220 ********************************************************************/
3221 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3222 pipes_struct *p, DOC_INFO *docinfo,
3225 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3229 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3230 struct current_user user;
3232 if (!OPEN_HANDLE(Printer)) {
3233 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3234 return ERROR_INVALID_HANDLE;
3237 get_current_user(&user, p);
3240 * a nice thing with NT is it doesn't listen to what you tell it.
3241 * when asked to send _only_ RAW datas, it tries to send datas
3244 * So I add checks like in NT Server ...
3246 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3247 * there's a bug in NT client-side code, so we'll fix it in the
3248 * server-side code. *nnnnnggggh!*
3251 if (info_1->p_datatype != 0) {
3252 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3253 if (strcmp(datatype, "RAW") != 0) {
3255 return ERROR_INVALID_DATATYPE;
3259 /* get the share number of the printer */
3260 if (!get_printer_snum(handle, &snum)) {
3261 return ERROR_INVALID_HANDLE;
3264 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3266 Printer->jobid = print_job_start(&user, snum, jobname);
3268 /* An error occured in print_job_start() so return an appropriate
3271 if (Printer->jobid == -1) {
3272 return map_nt_error_from_unix(errno);
3275 Printer->document_started=True;
3276 (*jobid) = Printer->jobid;
3278 srv_spoolss_sendnotify(handle);
3282 /********************************************************************
3283 * api_spoolss_getprinter
3284 * called from the spoolss dispatcher
3286 ********************************************************************/
3287 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3289 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3291 if (!OPEN_HANDLE(Printer)) {
3292 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3293 return ERROR_INVALID_HANDLE;
3296 Printer->document_started=False;
3297 print_job_end(Printer->jobid);
3298 /* error codes unhandled so far ... */
3300 srv_spoolss_sendnotify(handle);
3305 /****************************************************************************
3306 ****************************************************************************/
3307 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3310 uint32 *buffer_written)
3312 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3314 if (!OPEN_HANDLE(Printer)) {
3315 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3316 return ERROR_INVALID_HANDLE;
3319 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3325 /********************************************************************
3326 * api_spoolss_getprinter
3327 * called from the spoolss dispatcher
3329 ********************************************************************/
3330 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3333 struct current_user user;
3334 int snum, errcode = ERROR_INVALID_FUNCTION;
3335 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3337 get_current_user(&user, p);
3339 if (!OPEN_HANDLE(Printer)) {
3340 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3341 return ERROR_INVALID_HANDLE;
3344 if (!get_printer_snum(handle, &snum))
3345 return ERROR_INVALID_HANDLE;
3348 case PRINTER_CONTROL_PAUSE:
3349 if (print_queue_pause(&user, snum, &errcode)) {
3353 case PRINTER_CONTROL_RESUME:
3354 case PRINTER_CONTROL_UNPAUSE:
3355 if (print_queue_resume(&user, snum, &errcode)) {
3359 case PRINTER_CONTROL_PURGE:
3360 if (print_queue_purge(&user, snum, &errcode)) {
3365 return ERROR_INVALID_LEVEL;
3371 /********************************************************************
3372 * api_spoolss_abortprinter
3373 ********************************************************************/
3375 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3377 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3380 /********************************************************************
3381 * called by spoolss_api_setprinter
3382 * when updating a printer description
3383 ********************************************************************/
3384 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3385 const SPOOL_PRINTER_INFO_LEVEL *info,
3386 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3388 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3389 struct current_user user;
3393 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3395 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3396 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3397 OUR_HANDLE(handle)));
3399 result = ERROR_INVALID_HANDLE;
3403 /* NT seems to like setting the security descriptor even though
3404 nothing may have actually changed. This causes annoying
3405 dialog boxes when the user doesn't have permission to change
3406 the security descriptor. */
3408 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3410 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3412 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3413 result = NT_STATUS_NO_PROBLEMO;
3417 /* Work out which user is performing the operation */
3419 get_current_user(&user, p);
3421 /* Check the user has permissions to change the security
3422 descriptor. By experimentation with two NT machines, the user
3423 requires Full Access to the printer to change security
3426 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3427 result = ERROR_ACCESS_DENIED;
3431 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3434 free_sec_desc_buf(&new_secdesc_ctr);
3435 free_sec_desc_buf(&old_secdesc_ctr);
3440 /********************************************************************
3441 Do Samba sanity checks on a printer info struct.
3442 this has changed purpose: it now "canonicalises" printer
3443 info from a client rather than just checking it is correct
3444 ********************************************************************/
3446 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3448 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3449 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3451 /* we force some elements to "correct" values */
3452 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3453 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3454 global_myname, lp_servicename(snum));
3455 fstrcpy(info->sharename, lp_servicename(snum));
3456 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3457 | PRINTER_ATTRIBUTE_LOCAL \
3458 | PRINTER_ATTRIBUTE_RAW_ONLY \
3459 | PRINTER_ATTRIBUTE_QUEUED ;
3464 /****************************************************************************
3465 ****************************************************************************/
3466 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3468 pid_t local_pid = sys_getpid();
3469 char *cmd = lp_addprinter_cmd();
3474 pstring driverlocation;
3478 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3479 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3483 /* build driver path... only 9X architecture is needed for legacy reasons */
3484 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3486 /* change \ to \\ for the shell */
3487 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3489 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3490 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3491 cmd, printer->info_2->printername, printer->info_2->sharename,
3492 printer->info_2->portname, printer->info_2->drivername,
3493 printer->info_2->location, driverlocation);
3496 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3497 ret = smbrun(command, tmp_file, False);
3498 DEBUGADD(10,("returned [%d]\n", ret));
3506 qlines = file_lines_load(tmp_file, &numlines);
3507 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3508 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3512 /* Set the portname to what the script says the portname should be. */
3513 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3514 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3516 /* Send SIGHUP to process group... is there a better way? */
3521 file_lines_free(qlines);
3525 /* Return true if two devicemodes are equal */
3527 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3529 if (!strequal(d1->devicename, d2->devicename) ||
3530 !strequal(d1->formname, d2->formname)) {
3534 if (d1->specversion != d2->specversion ||
3535 d1->driverversion != d2->driverversion ||
3536 d1->size != d2->size ||
3537 d1->driverextra != d2->driverextra ||
3538 d1->orientation != d2->orientation ||
3539 d1->papersize != d2->papersize ||
3540 d1->paperlength != d2->paperlength ||
3541 d1->paperwidth != d2->paperwidth ||
3542 d1->scale != d2->scale ||
3543 d1->copies != d2->copies ||
3544 d1->defaultsource != d2->defaultsource ||
3545 d1->printquality != d2->printquality ||
3546 d1->color != d2->color ||
3547 d1->duplex != d2->duplex ||
3548 d1->yresolution != d2->yresolution ||
3549 d1->ttoption != d2->ttoption ||
3550 d1->collate != d2->collate ||
3551 d1->logpixels != d2->logpixels) {
3555 if (d1->fields != d2->fields ||
3556 d1->bitsperpel != d2->bitsperpel ||
3557 d1->pelswidth != d2->pelswidth ||
3558 d1->pelsheight != d2->pelsheight ||
3559 d1->displayflags != d2->displayflags ||
3560 d1->displayfrequency != d2->displayfrequency ||
3561 d1->icmmethod != d2->icmmethod ||
3562 d1->icmintent != d2->icmintent ||
3563 d1->mediatype != d2->mediatype ||
3564 d1->dithertype != d2->dithertype ||
3565 d1->reserved1 != d2->reserved1 ||
3566 d1->reserved2 != d2->reserved2 ||
3567 d1->panningwidth != d2->panningwidth ||
3568 d1->panningheight != d2->panningheight) {
3572 /* Not sure what to do about these fields */
3580 /* Return true if two NT_PRINTER_PARAM structures are equal */
3582 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3583 NT_PRINTER_PARAM *p2)
3585 if (!p1 && !p2) return True;
3587 if ((!p1 && p2) || (p1 && !p2)) return False;
3589 /* Compare lists of printer parameters */
3593 NT_PRINTER_PARAM *q = p1;
3595 /* Find the parameter in the second structure */
3599 if (strequal(p1->value, q->value) &&
3600 p1->type == q->type &&
3601 p1->data_len == q->data_len &&
3602 memcmp(p1->data, q->data, p1->data_len) == 0) {
3621 /********************************************************************
3622 * Called by update_printer when trying to work out whether to
3623 * actually update printer info.
3624 ********************************************************************/
3626 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3627 NT_PRINTER_INFO_LEVEL *p2)
3629 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3631 /* Trivial conditions */
3633 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3637 if ((!p1 && p2) || (p1 && !p2) ||
3638 (!p1->info_2 && p2->info_2) ||
3639 (p1->info_2 && !p2->info_2)) {
3643 /* Compare two nt_printer_info_level structures. Don't compare
3644 status or cjobs as they seem to have something to do with the
3650 if (pi1->attributes != pi2->attributes ||
3651 pi1->priority != pi2->priority ||
3652 pi1->default_priority != pi2->default_priority ||
3653 pi1->starttime != pi2->starttime ||
3654 pi1->untiltime != pi2->untiltime ||
3655 pi1->averageppm != pi2->averageppm) {
3659 /* Yuck - don't check the printername or servername as the
3660 add_a_printer() code plays games with them. You can't
3661 change the printername or the sharename through this interface
3664 if (!strequal(pi1->sharename, pi2->sharename) ||
3665 !strequal(pi1->portname, pi2->portname) ||
3666 !strequal(pi1->drivername, pi2->drivername) ||
3667 !strequal(pi1->comment, pi2->comment) ||
3668 !strequal(pi1->location, pi2->location)) {
3672 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3676 if (!strequal(pi1->sepfile, pi2->sepfile) ||
3677 !strequal(pi1->printprocessor, pi2->printprocessor) ||
3678 !strequal(pi1->datatype, pi2->datatype) ||
3679 !strequal(pi1->parameters, pi2->parameters)) {
3683 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3687 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3691 if (pi1->changeid != pi2->changeid ||
3692 pi1->c_setprinter != pi2->c_setprinter ||
3693 pi1->setuptime != pi2->setuptime) {
3700 /********************************************************************
3701 * called by spoolss_api_setprinter
3702 * when updating a printer description
3703 ********************************************************************/
3705 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3706 const SPOOL_PRINTER_INFO_LEVEL *info,
3707 DEVICEMODE *devmode)
3710 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3711 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3714 DEBUG(8,("update_printer\n"));
3716 result = NT_STATUS_NO_PROBLEMO;
3719 DEBUG(0,("Send a mail to samba@samba.org\n"));
3720 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3721 result = ERROR_INVALID_LEVEL;
3725 if (!OPEN_HANDLE(Printer)) {
3726 result = ERROR_INVALID_HANDLE;
3730 if (!get_printer_snum(handle, &snum)) {
3731 result = ERROR_INVALID_HANDLE;
3735 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3736 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3737 result = ERROR_INVALID_HANDLE;
3741 DEBUGADD(8,("Converting info_2 struct\n"));
3744 * convert_printer_info converts the incoming
3745 * info from the client and overwrites the info
3746 * just read from the tdb in the pointer 'printer'.
3749 convert_printer_info(info, printer, level);
3751 if (info->info_2->devmode_ptr != 0) {
3752 /* we have a valid devmode
3753 convert it and link it*/
3756 * Ensure printer->info_2->devmode is a valid pointer
3757 * as we will be overwriting it in convert_devicemode().
3760 if (printer->info_2->devmode == NULL)
3761 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3763 DEBUGADD(8,("Converting the devicemode struct\n"));
3764 convert_devicemode(devmode, printer->info_2->devmode);
3767 if (printer->info_2->devmode != NULL)
3768 free_nt_devicemode(&printer->info_2->devmode);
3769 printer->info_2->devmode=NULL;
3772 /* Do sanity check on the requested changes for Samba */
3774 if (!check_printer_ok(printer->info_2, snum)) {
3775 result = ERROR_INVALID_PARAMETER;
3779 /* NT likes to call this function even though nothing has actually
3780 changed. Check this so the user doesn't end up with an
3781 annoying permission denied dialog box. */
3783 if (nt_printer_info_level_equal(printer, old_printer)) {
3784 DEBUG(3, ("printer info has not changed\n"));
3785 result = NT_STATUS_NO_PROBLEMO;
3789 /* Check calling user has permission to update printer description */
3791 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3792 DEBUG(3, ("printer property change denied by security "
3794 result = ERROR_ACCESS_DENIED;
3798 /* Call addprinter hook */
3800 if (*lp_addprinter_cmd() )
3801 if ( !add_printer_hook(printer) ) {
3802 result = ERROR_ACCESS_DENIED;
3806 /* Update printer info */
3808 if (add_a_printer(*printer, 2)!=0) {
3809 /* I don't really know what to return here !!! */
3810 result = ERROR_ACCESS_DENIED;
3815 free_a_printer(&printer, 2);
3816 free_a_printer(&old_printer, 2);
3818 srv_spoolss_sendnotify(handle);
3823 /****************************************************************************
3824 ****************************************************************************/
3825 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3826 const SPOOL_PRINTER_INFO_LEVEL *info,
3827 DEVMODE_CTR devmode_ctr,
3828 SEC_DESC_BUF *secdesc_ctr,
3829 uint32 command, pipes_struct *p)
3831 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3833 if (!OPEN_HANDLE(Printer)) {
3834 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3835 return ERROR_INVALID_HANDLE;
3838 /* check the level */
3841 return control_printer(handle, command, p);
3843 return update_printer(handle, level, info, devmode_ctr.devmode);
3845 return update_printer_sec(handle, level, info, p,
3848 return ERROR_INVALID_LEVEL;
3852 /****************************************************************************
3853 ****************************************************************************/
3854 uint32 _spoolss_fcpn(POLICY_HND *handle)
3856 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3858 if (!OPEN_HANDLE(Printer)) {
3859 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3860 return ERROR_INVALID_HANDLE;
3863 if (Printer->notify.client_connected==True)
3864 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3865 return ERROR_INVALID_HANDLE;
3867 Printer->notify.flags=0;
3868 Printer->notify.options=0;
3869 Printer->notify.localmachine[0]='\0';
3870 Printer->notify.printerlocal=0;
3871 if (Printer->notify.option)
3872 safe_free(Printer->notify.option->ctr.type);
3873 safe_free(Printer->notify.option);
3874 Printer->notify.option=NULL;
3875 Printer->notify.client_connected=False;
3877 return NT_STATUS_NO_PROBLEMO;
3880 /****************************************************************************
3881 ****************************************************************************/
3882 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3883 NEW_BUFFER *buffer, uint32 offered,
3887 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3888 returns for AddJob. AddJob
3889 must fail on non-local
3893 /****************************************************************************
3894 ****************************************************************************/
3895 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3896 int position, int snum)
3902 t=gmtime(&queue->time);
3903 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3905 job_info->jobid=queue->job;
3906 init_unistr(&job_info->printername, lp_servicename(snum));
3907 init_unistr(&job_info->machinename, temp_name);
3908 init_unistr(&job_info->username, queue->user);
3909 init_unistr(&job_info->document, queue->file);
3910 init_unistr(&job_info->datatype, "RAW");
3911 init_unistr(&job_info->text_status, "");
3912 job_info->status=nt_printj_status(queue->status);
3913 job_info->priority=queue->priority;
3914 job_info->position=position;
3915 job_info->totalpages=0;
3916 job_info->pagesprinted=0;
3918 make_systemtime(&job_info->submitted, t);
3921 /****************************************************************************
3922 ****************************************************************************/
3923 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3924 int position, int snum)
3927 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3931 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3934 t=gmtime(&queue->time);
3935 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3937 job_info->jobid=queue->job;
3939 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3941 init_unistr(&job_info->printername, chaine);
3943 init_unistr(&job_info->machinename, temp_name);
3944 init_unistr(&job_info->username, queue->user);
3945 init_unistr(&job_info->document, queue->file);
3946 init_unistr(&job_info->notifyname, queue->user);
3947 init_unistr(&job_info->datatype, "RAW");
3948 init_unistr(&job_info->printprocessor, "winprint");
3949 init_unistr(&job_info->parameters, "");
3950 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3951 init_unistr(&job_info->text_status, "");
3953 /* and here the security descriptor */
3955 job_info->status=nt_printj_status(queue->status);
3956 job_info->priority=queue->priority;
3957 job_info->position=position;
3958 job_info->starttime=0;
3959 job_info->untiltime=0;
3960 job_info->totalpages=0;
3961 job_info->size=queue->size;
3962 make_systemtime(&(job_info->submitted), t);
3963 job_info->timeelapsed=0;
3964 job_info->pagesprinted=0;
3966 if((job_info->devmode = construct_dev_mode(snum, global_myname)) == NULL) {
3967 free_a_printer(&ntprinter, 2);
3971 free_a_printer(&ntprinter, 2);
3975 /****************************************************************************
3976 Enumjobs at level 1.
3977 ****************************************************************************/
3978 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3979 NEW_BUFFER *buffer, uint32 offered,
3980 uint32 *needed, uint32 *returned)
3985 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3989 return ERROR_NOT_ENOUGH_MEMORY;
3992 for (i=0; i<*returned; i++)
3993 fill_job_info_1(&info[i], &queue[i], i, snum);
3997 /* check the required size. */
3998 for (i=0; i<*returned; i++)
3999 (*needed) += spoolss_size_job_info_1(&info[i]);
4001 if (!alloc_buffer_size(buffer, *needed)) {
4003 return ERROR_INSUFFICIENT_BUFFER;
4006 /* fill the buffer with the structures */
4007 for (i=0; i<*returned; i++)
4008 new_smb_io_job_info_1("", buffer, &info[i], 0);
4013 if (*needed > offered) {
4015 return ERROR_INSUFFICIENT_BUFFER;
4018 return NT_STATUS_NO_PROBLEMO;
4021 /****************************************************************************
4022 Enumjobs at level 2.
4023 ****************************************************************************/
4024 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4025 NEW_BUFFER *buffer, uint32 offered,
4026 uint32 *needed, uint32 *returned)
4031 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4035 return ERROR_NOT_ENOUGH_MEMORY;
4038 for (i=0; i<*returned; i++)
4039 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4043 /* check the required size. */
4044 for (i=0; i<*returned; i++)
4045 (*needed) += spoolss_size_job_info_2(&info[i]);
4047 if (!alloc_buffer_size(buffer, *needed)) {
4049 return ERROR_INSUFFICIENT_BUFFER;
4052 /* fill the buffer with the structures */
4053 for (i=0; i<*returned; i++)
4054 new_smb_io_job_info_2("", buffer, &info[i], 0);
4059 if (*needed > offered) {
4061 return ERROR_INSUFFICIENT_BUFFER;
4064 return NT_STATUS_NO_PROBLEMO;
4067 /****************************************************************************
4069 ****************************************************************************/
4070 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4071 NEW_BUFFER *buffer, uint32 offered,
4072 uint32 *needed, uint32 *returned)
4075 print_queue_struct *queue=NULL;
4076 print_status_struct prt_status;
4078 DEBUG(4,("_spoolss_enumjobs\n"));
4080 ZERO_STRUCT(prt_status);
4085 if (!get_printer_snum(handle, &snum))
4086 return ERROR_INVALID_HANDLE;
4088 *returned = print_queue_status(snum, &queue, &prt_status);
4089 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4091 if (*returned == 0) {
4093 return NT_STATUS_NO_PROBLEMO;
4098 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4100 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4104 return ERROR_INVALID_LEVEL;
4109 /****************************************************************************
4110 ****************************************************************************/
4111 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4116 /****************************************************************************
4117 ****************************************************************************/
4118 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4119 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4121 struct current_user user;
4122 print_status_struct prt_status;
4123 int snum, errcode = ERROR_INVALID_FUNCTION;
4125 memset(&prt_status, 0, sizeof(prt_status));
4127 if (!get_printer_snum(handle, &snum)) {
4128 return ERROR_INVALID_HANDLE;
4131 if (!print_job_exists(jobid)) {
4132 return ERROR_INVALID_PRINTER_NAME;
4135 get_current_user(&user, p);
4138 case JOB_CONTROL_CANCEL:
4139 case JOB_CONTROL_DELETE:
4140 if (print_job_delete(&user, jobid, &errcode)) {
4144 case JOB_CONTROL_PAUSE:
4145 if (print_job_pause(&user, jobid, &errcode)) {
4149 case JOB_CONTROL_RESTART:
4150 case JOB_CONTROL_RESUME:
4151 if (print_job_resume(&user, jobid, &errcode)) {
4156 return ERROR_INVALID_LEVEL;
4162 /****************************************************************************
4163 Enumerates all printer drivers at level 1.
4164 ****************************************************************************/
4165 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4170 fstring *list = NULL;
4172 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4173 DRIVER_INFO_1 *driver_info_1=NULL;
4177 #define MAX_VERSION 4
4179 for (version=0; version<MAX_VERSION; version++) {
4181 ndrivers=get_ntdrivers(&list, architecture, version);
4182 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4185 return ERROR_NOT_ENOUGH_MEMORY;
4188 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4190 return ERROR_NOT_ENOUGH_MEMORY;
4194 for (i=0; i<ndrivers; i++) {
4196 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4197 ZERO_STRUCT(driver);
4198 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4202 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4203 free_a_printer_driver(driver, 3);
4206 *returned+=ndrivers;
4210 /* check the required size. */
4211 for (i=0; i<*returned; i++) {
4212 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4213 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4216 if (!alloc_buffer_size(buffer, *needed)) {
4217 safe_free(driver_info_1);
4218 return ERROR_INSUFFICIENT_BUFFER;
4221 /* fill the buffer with the form structures */
4222 for (i=0; i<*returned; i++) {
4223 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4224 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4227 safe_free(driver_info_1);
4229 if (*needed > offered) {
4231 return ERROR_INSUFFICIENT_BUFFER;
4234 return NT_STATUS_NO_PROBLEMO;
4237 /****************************************************************************
4238 Enumerates all printer drivers at level 2.
4239 ****************************************************************************/
4240 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4245 fstring *list = NULL;
4247 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4248 DRIVER_INFO_2 *driver_info_2=NULL;
4252 #define MAX_VERSION 4
4254 for (version=0; version<MAX_VERSION; version++) {
4256 ndrivers=get_ntdrivers(&list, architecture, version);
4257 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4260 return ERROR_NOT_ENOUGH_MEMORY;
4263 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4265 return ERROR_NOT_ENOUGH_MEMORY;
4269 for (i=0; i<ndrivers; i++) {
4272 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4273 ZERO_STRUCT(driver);
4274 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4278 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4279 free_a_printer_driver(driver, 3);
4282 *returned+=ndrivers;
4286 /* check the required size. */
4287 for (i=0; i<*returned; i++) {
4288 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4289 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4292 if (!alloc_buffer_size(buffer, *needed)) {
4293 safe_free(driver_info_2);
4294 return ERROR_INSUFFICIENT_BUFFER;
4297 /* fill the buffer with the form structures */
4298 for (i=0; i<*returned; i++) {
4299 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4300 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4303 safe_free(driver_info_2);
4305 if (*needed > offered) {
4307 return ERROR_INSUFFICIENT_BUFFER;
4310 return NT_STATUS_NO_PROBLEMO;
4313 /****************************************************************************
4314 Enumerates all printer drivers at level 3.
4315 ****************************************************************************/
4316 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4321 fstring *list = NULL;
4323 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4324 DRIVER_INFO_3 *driver_info_3=NULL;
4328 #define MAX_VERSION 4
4330 for (version=0; version<MAX_VERSION; version++) {
4332 ndrivers=get_ntdrivers(&list, architecture, version);
4333 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4336 return ERROR_NOT_ENOUGH_MEMORY;
4339 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4341 return ERROR_NOT_ENOUGH_MEMORY;
4345 for (i=0; i<ndrivers; i++) {
4348 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4349 ZERO_STRUCT(driver);
4350 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4354 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4355 free_a_printer_driver(driver, 3);
4358 *returned+=ndrivers;
4362 /* check the required size. */
4363 for (i=0; i<*returned; i++) {
4364 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4365 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4368 if (!alloc_buffer_size(buffer, *needed)) {
4369 safe_free(driver_info_3);
4370 return ERROR_INSUFFICIENT_BUFFER;
4373 /* fill the buffer with the driver structures */
4374 for (i=0; i<*returned; i++) {
4375 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4376 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4379 for (i=0; i<*returned; i++)
4380 safe_free(driver_info_3[i].dependentfiles);
4382 safe_free(driver_info_3);
4384 if (*needed > offered) {
4386 return ERROR_INSUFFICIENT_BUFFER;
4389 return NT_STATUS_NO_PROBLEMO;
4392 /****************************************************************************
4393 Enumerates all printer drivers.
4394 ****************************************************************************/
4395 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4396 NEW_BUFFER *buffer, uint32 offered,
4397 uint32 *needed, uint32 *returned)
4399 fstring *list = NULL;
4401 fstring architecture;
4403 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4404 fstrcpy(servername, global_myname);
4408 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4412 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4414 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4416 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4420 return ERROR_INVALID_LEVEL;
4424 /****************************************************************************
4425 ****************************************************************************/
4426 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4428 form->flag=list->flag;
4429 init_unistr(&form->name, list->name);
4430 form->width=list->width;
4431 form->length=list->length;
4432 form->left=list->left;
4433 form->top=list->top;
4434 form->right=list->right;
4435 form->bottom=list->bottom;
4438 /****************************************************************************
4439 ****************************************************************************/
4440 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4441 NEW_BUFFER *buffer, uint32 offered,
4442 uint32 *needed, uint32 *numofforms)
4444 nt_forms_struct *list=NULL;
4449 DEBUG(4,("_new_spoolss_enumforms\n"));
4450 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4451 DEBUGADD(5,("Info level [%d]\n", level));
4453 *numofforms = get_ntforms(&list);
4454 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4456 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4460 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4462 return ERROR_NOT_ENOUGH_MEMORY;
4465 /* construct the list of form structures */
4466 for (i=0; i<*numofforms; i++) {
4467 DEBUGADD(6,("Filling form number [%d]\n",i));
4468 fill_form_1(&forms_1[i], &list[i]);
4473 /* check the required size. */
4474 for (i=0; i<*numofforms; i++) {
4475 DEBUGADD(6,("adding form [%d]'s size\n",i));
4476 buffer_size += spoolss_size_form_1(&forms_1[i]);
4479 *needed=buffer_size;
4481 if (!alloc_buffer_size(buffer, buffer_size)){
4483 return ERROR_INSUFFICIENT_BUFFER;
4486 /* fill the buffer with the form structures */
4487 for (i=0; i<*numofforms; i++) {
4488 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4489 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4494 if (*needed > offered) {
4496 return ERROR_INSUFFICIENT_BUFFER;
4499 return NT_STATUS_NO_PROBLEMO;
4503 return ERROR_INVALID_LEVEL;
4508 /****************************************************************************
4509 ****************************************************************************/
4510 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4512 nt_forms_struct *list=NULL;
4518 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4520 DEBUG(4,("_spoolss_getform\n"));
4521 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4522 DEBUGADD(5,("Info level [%d]\n", level));
4524 numofforms = get_ntforms(&list);
4525 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4527 if (numofforms == 0)
4528 return ERROR_NO_MORE_ITEMS;
4533 /* Check if the requested name is in the list of form structures */
4534 for (i=0; i<numofforms; i++) {
4536 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4538 if (strequal(form_name, list[i].name)) {
4539 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4540 fill_form_1(&form_1, &list[i]);
4547 /* check the required size. */
4549 *needed=spoolss_size_form_1(&form_1);
4551 if (!alloc_buffer_size(buffer, buffer_size)){
4552 return ERROR_INSUFFICIENT_BUFFER;
4555 if (*needed > offered) {
4556 return ERROR_INSUFFICIENT_BUFFER;
4559 /* fill the buffer with the form structures */
4560 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4561 new_smb_io_form_1("", buffer, &form_1, 0);
4563 return NT_STATUS_NO_PROBLEMO;
4567 return ERROR_INVALID_LEVEL;
4571 /****************************************************************************
4572 ****************************************************************************/
4573 static void fill_port_1(PORT_INFO_1 *port, char *name)
4575 init_unistr(&port->port_name, name);
4578 /****************************************************************************
4579 ****************************************************************************/
4580 static void fill_port_2(PORT_INFO_2 *port, char *name)
4582 init_unistr(&port->port_name, name);
4583 init_unistr(&port->monitor_name, "Local Monitor");
4584 init_unistr(&port->description, "Local Port");
4585 #define PORT_TYPE_WRITE 1
4586 port->port_type=PORT_TYPE_WRITE;
4590 /****************************************************************************
4592 ****************************************************************************/
4593 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4595 PORT_INFO_1 *ports=NULL;
4598 if (*lp_enumports_cmd()) {
4599 pid_t local_pid = sys_getpid();
4600 char *cmd = lp_enumports_cmd();
4608 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4609 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4613 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4614 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4617 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4618 ret = smbrun(command, tmp_file, False);
4619 DEBUG(10,("Returned [%d]\n", ret));
4622 /* Is this the best error to return here? */
4623 return ERROR_ACCESS_DENIED;
4627 qlines = file_lines_load(tmp_file, &numlines);
4628 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4629 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4633 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4634 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4635 file_lines_free(qlines);
4636 return ERROR_NOT_ENOUGH_MEMORY;
4639 for (i=0; i<numlines; i++) {
4640 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4641 fill_port_1(&ports[i], qlines[i]);
4644 file_lines_free(qlines);
4647 *returned = numlines;
4650 *returned = 1; /* Sole Samba port returned. */
4652 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4653 return ERROR_NOT_ENOUGH_MEMORY;
4655 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4657 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4660 /* check the required size. */
4661 for (i=0; i<*returned; i++) {
4662 DEBUGADD(6,("adding port [%d]'s size\n", i));
4663 *needed += spoolss_size_port_info_1(&ports[i]);
4666 if (!alloc_buffer_size(buffer, *needed)) {
4668 return ERROR_INSUFFICIENT_BUFFER;
4671 /* fill the buffer with the ports structures */
4672 for (i=0; i<*returned; i++) {
4673 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4674 new_smb_io_port_1("", buffer, &ports[i], 0);
4679 if (*needed > offered) {
4681 return ERROR_INSUFFICIENT_BUFFER;
4684 return NT_STATUS_NO_PROBLEMO;
4687 /****************************************************************************
4689 ****************************************************************************/
4691 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4693 PORT_INFO_2 *ports=NULL;
4696 if (*lp_enumports_cmd()) {
4697 pid_t local_pid = sys_getpid();
4698 char *cmd = lp_enumports_cmd();
4706 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4707 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4711 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4712 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4715 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4716 ret = smbrun(command, tmp_file, False);
4717 DEBUGADD(10,("returned [%d]\n", ret));
4720 /* Is this the best error to return here? */
4721 return ERROR_ACCESS_DENIED;
4725 qlines = file_lines_load(tmp_file, &numlines);
4726 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4727 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4731 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4732 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4733 file_lines_free(qlines);
4734 return ERROR_NOT_ENOUGH_MEMORY;
4737 for (i=0; i<numlines; i++) {
4738 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4739 fill_port_2(&(ports[i]), qlines[i]);
4742 file_lines_free(qlines);
4745 *returned = numlines;
4751 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4752 return ERROR_NOT_ENOUGH_MEMORY;
4754 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4756 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4759 /* check the required size. */
4760 for (i=0; i<*returned; i++) {
4761 DEBUGADD(6,("adding port [%d]'s size\n", i));
4762 *needed += spoolss_size_port_info_2(&ports[i]);
4765 if (!alloc_buffer_size(buffer, *needed)) {
4767 return ERROR_INSUFFICIENT_BUFFER;
4770 /* fill the buffer with the ports structures */
4771 for (i=0; i<*returned; i++) {
4772 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4773 new_smb_io_port_2("", buffer, &ports[i], 0);
4778 if (*needed > offered) {
4780 return ERROR_INSUFFICIENT_BUFFER;
4783 return NT_STATUS_NO_PROBLEMO;
4786 /****************************************************************************
4788 ****************************************************************************/
4789 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4790 NEW_BUFFER *buffer, uint32 offered,
4791 uint32 *needed, uint32 *returned)
4793 DEBUG(4,("_spoolss_enumports\n"));
4800 return enumports_level_1(buffer, offered, needed, returned);
4802 return enumports_level_2(buffer, offered, needed, returned);
4804 return ERROR_INVALID_LEVEL;
4808 /****************************************************************************
4809 ****************************************************************************/
4810 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4811 const SPOOL_PRINTER_INFO_LEVEL *info,
4812 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4813 uint32 user_switch, const SPOOL_USER_CTR *user,
4816 NT_PRINTER_INFO_LEVEL *printer = NULL;
4820 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4821 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4822 return ERROR_NOT_ENOUGH_MEMORY;
4825 ZERO_STRUCTP(printer);
4827 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4828 convert_printer_info(info, printer, 2);
4830 if (*lp_addprinter_cmd() )
4831 if ( !add_printer_hook(printer) ) {
4832 free_a_printer(&printer,2);
4833 return ERROR_ACCESS_DENIED;
4836 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4837 printer->info_2->sharename);
4839 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4840 free_a_printer(&printer,2);
4841 return ERROR_ACCESS_DENIED;
4844 /* you must be a printer admin to add a new printer */
4845 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4846 free_a_printer(&printer,2);
4847 return ERROR_ACCESS_DENIED;
4851 * Do sanity check on the requested changes for Samba.
4854 if (!check_printer_ok(printer->info_2, snum)) {
4855 free_a_printer(&printer,2);
4856 return ERROR_INVALID_PARAMETER;
4859 /* write the ASCII on disk */
4860 if (add_a_printer(*printer, 2) != 0) {
4861 free_a_printer(&printer,2);
4862 return ERROR_ACCESS_DENIED;
4865 if (!open_printer_hnd(handle, name)) {
4866 /* Handle open failed - remove addition. */
4867 del_a_printer(printer->info_2->sharename);
4868 free_a_printer(&printer,2);
4869 return ERROR_ACCESS_DENIED;
4872 free_a_printer(&printer,2);
4874 srv_spoolss_sendnotify(handle);
4876 return NT_STATUS_NO_PROBLEMO;
4879 /****************************************************************************
4880 ****************************************************************************/
4881 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4882 const SPOOL_PRINTER_INFO_LEVEL *info,
4883 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4884 uint32 user_switch, const SPOOL_USER_CTR *user,
4889 /* we don't handle yet */
4890 /* but I know what to do ... */
4891 return ERROR_INVALID_LEVEL;
4893 return spoolss_addprinterex_level_2(uni_srv_name, info,
4894 unk0, unk1, unk2, unk3,
4895 user_switch, user, handle);
4897 return ERROR_INVALID_LEVEL;
4901 /****************************************************************************
4902 ****************************************************************************/
4903 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4904 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4906 uint32 err = NT_STATUS_NO_PROBLEMO;
4907 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4908 struct current_user user;
4910 ZERO_STRUCT(driver);
4912 get_current_user(&user, p);
4914 convert_printer_driver_info(info, &driver, level);
4916 DEBUG(5,("Cleaning driver's information\n"));
4917 if ((err = clean_up_driver_struct(driver, level)) != NT_STATUS_NO_PROBLEMO )
4920 DEBUG(5,("Moving driver to final destination\n"));
4921 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4923 err = ERROR_ACCESS_DENIED;
4927 if (add_a_printer_driver(driver, level)!=0) {
4928 err = ERROR_ACCESS_DENIED;
4933 free_a_printer_driver(driver, level);
4937 /****************************************************************************
4938 ****************************************************************************/
4939 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4941 init_unistr(&info->name, name);
4944 /****************************************************************************
4945 ****************************************************************************/
4946 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4950 pstring short_archi;
4951 DRIVER_DIRECTORY_1 *info=NULL;
4953 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4955 if (get_short_archi(short_archi, long_archi)==FALSE)
4956 return ERROR_INVALID_ENVIRONMENT;
4958 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4959 return ERROR_NOT_ENOUGH_MEMORY;
4961 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4963 DEBUG(4,("printer driver directory: [%s]\n", path));
4965 fill_driverdir_1(info, path);
4967 *needed += spoolss_size_driverdir_info_1(info);
4969 if (!alloc_buffer_size(buffer, *needed)) {
4971 return ERROR_INSUFFICIENT_BUFFER;
4974 new_smb_io_driverdir_1("", buffer, info, 0);
4978 if (*needed > offered)
4979 return ERROR_INSUFFICIENT_BUFFER;
4981 return NT_STATUS_NO_PROBLEMO;
4984 /****************************************************************************
4985 ****************************************************************************/
4986 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4987 NEW_BUFFER *buffer, uint32 offered,
4990 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4996 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4998 return ERROR_INVALID_LEVEL;
5002 /****************************************************************************
5003 ****************************************************************************/
5004 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5005 uint32 in_value_len, uint32 in_data_len,
5006 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5008 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5010 NT_PRINTER_INFO_LEVEL *printer = NULL;
5015 uint32 biggest_valuesize;
5016 uint32 biggest_datasize;
5018 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5023 ZERO_STRUCT(printer);
5025 *out_max_value_len=0;
5031 *out_max_data_len=0;
5035 DEBUG(5,("spoolss_enumprinterdata\n"));
5037 if (!OPEN_HANDLE(Printer)) {
5038 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5039 return ERROR_INVALID_HANDLE;
5042 if (!get_printer_snum(handle, &snum))
5043 return ERROR_INVALID_HANDLE;
5045 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5046 return ERROR_INVALID_HANDLE;
5049 * The NT machine wants to know the biggest size of value and data
5051 * cf: MSDN EnumPrinterData remark section
5053 if ( (in_value_len==0) && (in_data_len==0) ) {
5054 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5058 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5059 * if this parameter size doesn't exist.
5060 * Ok - my opinion here is that the client is not asking for the greatest
5061 * possible size of all the parameters, but is asking specifically for the size needed
5062 * for this specific parameter. In that case we can remove the loop below and
5063 * simplify this lookup code considerably. JF - comments welcome. JRA.
5066 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5068 free_a_printer(&printer, 2);
5069 return ERROR_NO_MORE_ITEMS;
5077 biggest_valuesize=0;
5080 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5081 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5082 if (data_len > biggest_datasize) biggest_datasize=data_len;
5084 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5092 * I think this is correct, it doesn't break APW and
5093 * allows Gerald's Win32 test programs to work correctly,
5094 * but may need altering.... JRA.
5097 if (param_index == 0) {
5098 /* No parameters found. */
5099 free_a_printer(&printer, 2);
5100 return ERROR_NO_MORE_ITEMS;
5103 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5104 *out_value_len=2*(1+biggest_valuesize);
5105 *out_data_len=biggest_datasize;
5107 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5109 free_a_printer(&printer, 2);
5110 return NT_STATUS_NO_PROBLEMO;
5114 * the value len is wrong in NT sp3
5115 * that's the number of bytes not the number of unicode chars
5118 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5120 free_a_printer(&printer, 2);
5121 return ERROR_NO_MORE_ITEMS;
5124 free_a_printer(&printer, 2);
5128 * - counted in bytes in the request
5129 * - counted in UNICODE chars in the max reply
5130 * - counted in bytes in the real size
5132 * take a pause *before* coding not *during* coding
5135 *out_max_value_len=(in_value_len/sizeof(uint16));
5136 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5138 return ERROR_NOT_ENOUGH_MEMORY;
5141 ZERO_STRUCTP(*out_value);
5142 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5146 /* the data is counted in bytes */
5147 *out_max_data_len=in_data_len;
5148 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5150 return ERROR_NOT_ENOUGH_MEMORY;
5153 memset(*data_out,'\0',in_data_len);
5154 memcpy(*data_out, data, (size_t)data_len);
5155 *out_data_len=data_len;
5159 return NT_STATUS_NO_PROBLEMO;
5162 /****************************************************************************
5163 ****************************************************************************/
5164 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5165 const UNISTR2 *value,
5170 uint32 numeric_data)
5172 NT_PRINTER_INFO_LEVEL *printer = NULL;
5173 NT_PRINTER_PARAM *param = NULL, old_param;
5175 uint32 status = 0x0;
5176 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5178 DEBUG(5,("spoolss_setprinterdata\n"));
5180 if (!OPEN_HANDLE(Printer)) {
5181 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5182 return ERROR_INVALID_HANDLE;
5185 if (!get_printer_snum(handle, &snum))
5186 return ERROR_INVALID_HANDLE;
5188 status = get_a_printer(&printer, 2, lp_servicename(snum));
5190 return ERROR_INVALID_NAME;
5192 convert_specific_param(¶m, value , type, data, real_len);
5194 /* Check if we are making any changes or not. Return true if
5195 nothing is actually changing. */
5197 ZERO_STRUCT(old_param);
5199 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5200 &old_param.type, &old_param.data_len)) {
5202 if (param->type == old_param.type &&
5203 param->data_len == old_param.data_len &&
5204 memcmp(param->data, old_param.data,
5205 old_param.data_len) == 0) {
5207 DEBUG(3, ("setprinterdata hasn't changed\n"));
5208 status = NT_STATUS_NO_PROBLEMO;
5215 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5216 DEBUG(3, ("security descriptor change denied by existing "
5217 "security descriptor\n"));
5218 status = ERROR_ACCESS_DENIED;
5222 unlink_specific_param_if_exist(printer->info_2, param);
5224 if (!add_a_specific_param(printer->info_2, param))
5225 status = ERROR_INVALID_PARAMETER;
5227 status = mod_a_printer(*printer, 2);
5230 free_a_printer(&printer, 2);
5231 safe_free(old_param.data);
5236 /****************************************************************************
5237 ****************************************************************************/
5238 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5240 NT_PRINTER_INFO_LEVEL *printer = NULL;
5241 NT_PRINTER_PARAM param;
5243 uint32 status = 0x0;
5244 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5246 DEBUG(5,("spoolss_deleteprinterdata\n"));
5248 if (!OPEN_HANDLE(Printer)) {
5249 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5250 return ERROR_INVALID_HANDLE;
5253 if (!get_printer_snum(handle, &snum))
5254 return ERROR_INVALID_HANDLE;
5256 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5257 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5258 "security descriptor\n"));
5259 return ERROR_ACCESS_DENIED;
5262 status = get_a_printer(&printer, 2, lp_servicename(snum));
5264 return ERROR_INVALID_NAME;
5266 ZERO_STRUCTP(¶m);
5267 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5269 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5270 status = ERROR_INVALID_PARAMETER;
5272 status = mod_a_printer(*printer, 2);
5274 free_a_printer(&printer, 2);
5278 /****************************************************************************
5279 ****************************************************************************/
5280 uint32 _spoolss_addform( POLICY_HND *handle,
5285 nt_forms_struct *list=NULL;
5286 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5288 DEBUG(5,("spoolss_addform\n"));
5290 if (!OPEN_HANDLE(Printer)) {
5291 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5292 return ERROR_INVALID_HANDLE;
5295 count=get_ntforms(&list);
5296 if(!add_a_form(&list, form, &count))
5297 return ERROR_NOT_ENOUGH_MEMORY;
5298 write_ntforms(&list, count);
5305 /****************************************************************************
5306 ****************************************************************************/
5307 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5311 nt_forms_struct *list=NULL;
5312 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5314 DEBUG(5,("spoolss_deleteform\n"));
5316 if (!OPEN_HANDLE(Printer)) {
5317 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5318 return ERROR_INVALID_HANDLE;
5321 count = get_ntforms(&list);
5322 if(!delete_a_form(&list, form_name, &count, &ret))
5323 return ERROR_INVALID_PARAMETER;
5330 /****************************************************************************
5331 ****************************************************************************/
5332 uint32 _spoolss_setform( POLICY_HND *handle,
5333 const UNISTR2 *uni_name,
5338 nt_forms_struct *list=NULL;
5339 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5341 DEBUG(5,("spoolss_setform\n"));
5343 if (!OPEN_HANDLE(Printer)) {
5344 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5345 return ERROR_INVALID_HANDLE;
5347 count=get_ntforms(&list);
5348 update_a_form(&list, form, count);
5349 write_ntforms(&list, count);
5356 /****************************************************************************
5357 enumprintprocessors level 1.
5358 ****************************************************************************/
5359 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5361 PRINTPROCESSOR_1 *info_1=NULL;
5363 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5364 return ERROR_NOT_ENOUGH_MEMORY;
5368 init_unistr(&info_1->name, "winprint");
5370 *needed += spoolss_size_printprocessor_info_1(info_1);
5372 if (!alloc_buffer_size(buffer, *needed))
5373 return ERROR_INSUFFICIENT_BUFFER;
5375 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5379 if (*needed > offered) {
5381 return ERROR_INSUFFICIENT_BUFFER;
5384 return NT_STATUS_NO_PROBLEMO;
5387 /****************************************************************************
5388 ****************************************************************************/
5389 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5390 NEW_BUFFER *buffer, uint32 offered,
5391 uint32 *needed, uint32 *returned)
5393 DEBUG(5,("spoolss_enumprintprocessors\n"));
5396 * Enumerate the print processors ...
5398 * Just reply with "winprint", to keep NT happy
5399 * and I can use my nice printer checker.
5407 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5409 return ERROR_INVALID_LEVEL;
5413 /****************************************************************************
5414 enumprintprocdatatypes level 1.
5415 ****************************************************************************/
5416 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5418 PRINTPROCDATATYPE_1 *info_1=NULL;
5420 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5421 return ERROR_NOT_ENOUGH_MEMORY;
5425 init_unistr(&info_1->name, "RAW");
5427 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5429 if (!alloc_buffer_size(buffer, *needed))
5430 return ERROR_INSUFFICIENT_BUFFER;
5432 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5436 if (*needed > offered) {
5438 return ERROR_INSUFFICIENT_BUFFER;
5441 return NT_STATUS_NO_PROBLEMO;
5444 /****************************************************************************
5445 ****************************************************************************/
5446 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5447 NEW_BUFFER *buffer, uint32 offered,
5448 uint32 *needed, uint32 *returned)
5450 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5457 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5459 return ERROR_INVALID_LEVEL;
5463 /****************************************************************************
5464 enumprintmonitors level 1.
5465 ****************************************************************************/
5466 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5468 PRINTMONITOR_1 *info_1=NULL;
5470 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5471 return ERROR_NOT_ENOUGH_MEMORY;
5475 init_unistr(&info_1->name, "Local Port");
5477 *needed += spoolss_size_printmonitor_info_1(info_1);
5479 if (!alloc_buffer_size(buffer, *needed))
5480 return ERROR_INSUFFICIENT_BUFFER;
5482 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5486 if (*needed > offered) {
5488 return ERROR_INSUFFICIENT_BUFFER;
5491 return NT_STATUS_NO_PROBLEMO;
5494 /****************************************************************************
5495 enumprintmonitors level 2.
5496 ****************************************************************************/
5497 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5499 PRINTMONITOR_2 *info_2=NULL;
5501 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5502 return ERROR_NOT_ENOUGH_MEMORY;
5506 init_unistr(&info_2->name, "Local Port");
5507 init_unistr(&info_2->environment, "Windows NT X86");
5508 init_unistr(&info_2->dll_name, "localmon.dll");
5510 *needed += spoolss_size_printmonitor_info_2(info_2);
5512 if (!alloc_buffer_size(buffer, *needed))
5513 return ERROR_INSUFFICIENT_BUFFER;
5515 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5519 if (*needed > offered) {
5521 return ERROR_INSUFFICIENT_BUFFER;
5524 return NT_STATUS_NO_PROBLEMO;
5527 /****************************************************************************
5528 ****************************************************************************/
5529 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5530 NEW_BUFFER *buffer, uint32 offered,
5531 uint32 *needed, uint32 *returned)
5533 DEBUG(5,("spoolss_enumprintmonitors\n"));
5536 * Enumerate the print monitors ...
5538 * Just reply with "Local Port", to keep NT happy
5539 * and I can use my nice printer checker.
5547 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5549 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5551 return ERROR_INVALID_LEVEL;
5555 /****************************************************************************
5556 ****************************************************************************/
5557 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5561 JOB_INFO_1 *info_1=NULL;
5563 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5565 if (info_1 == NULL) {
5567 return ERROR_NOT_ENOUGH_MEMORY;
5570 for (i=0; i<count && found==False; i++) {
5571 if (queue[i].job==(int)jobid)
5578 /* I shoud reply something else ... I can't find the good one */
5579 return NT_STATUS_NO_PROBLEMO;
5582 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5586 *needed += spoolss_size_job_info_1(info_1);
5588 if (!alloc_buffer_size(buffer, *needed)) {
5590 return ERROR_INSUFFICIENT_BUFFER;
5593 new_smb_io_job_info_1("", buffer, info_1, 0);
5597 if (*needed > offered)
5598 return ERROR_INSUFFICIENT_BUFFER;
5600 return NT_STATUS_NO_PROBLEMO;
5604 /****************************************************************************
5605 ****************************************************************************/
5606 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5611 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5613 ZERO_STRUCTP(info_2);
5615 if (info_2 == NULL) {
5617 return ERROR_NOT_ENOUGH_MEMORY;
5620 for (i=0; i<count && found==False; i++) {
5621 if (queue[i].job==(int)jobid)
5628 /* I shoud reply something else ... I can't find the good one */
5629 return NT_STATUS_NO_PROBLEMO;
5632 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5636 *needed += spoolss_size_job_info_2(info_2);
5638 if (!alloc_buffer_size(buffer, *needed)) {
5640 return ERROR_INSUFFICIENT_BUFFER;
5643 new_smb_io_job_info_2("", buffer, info_2, 0);
5645 free_dev_mode(info_2->devmode);
5648 if (*needed > offered)
5649 return ERROR_INSUFFICIENT_BUFFER;
5651 return NT_STATUS_NO_PROBLEMO;
5654 /****************************************************************************
5655 ****************************************************************************/
5656 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5657 NEW_BUFFER *buffer, uint32 offered,
5662 print_queue_struct *queue=NULL;
5663 print_status_struct prt_status;
5665 DEBUG(5,("spoolss_getjob\n"));
5667 memset(&prt_status, 0, sizeof(prt_status));
5671 if (!get_printer_snum(handle, &snum))
5672 return ERROR_INVALID_HANDLE;
5674 count = print_queue_status(snum, &queue, &prt_status);
5676 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5677 count, prt_status.status, prt_status.message));
5681 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5683 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5686 return ERROR_INVALID_LEVEL;