3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8 * Copyright (C) Jean François Micouleau 1998-2000.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
34 #define PRINTER_HANDLE_IS_PRINTER 0
35 #define PRINTER_HANDLE_IS_PRINTSERVER 1
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer{
46 BOOL document_started;
48 int jobid; /* jobid in printing backend */
49 POLICY_HND printer_hnd;
53 fstring printerservername;
62 SPOOL_NOTIFY_OPTION *option;
63 POLICY_HND client_hnd;
64 uint32 client_connected;
72 typedef struct _counter_printer_0 {
80 static ubi_dlList Printer_list;
81 static ubi_dlList counter_list;
83 static struct cli_state cli;
84 static uint32 smb_connections=0;
86 #define OPEN_HANDLE(pnum) ((pnum!=NULL) && (pnum->open!=False) && (IVAL(pnum->printer_hnd.data,16)==(uint32)sys_getpid()))
87 #define OUR_HANDLE(pnum) ((pnum==NULL)?"NULL":(IVAL(pnum->data,16)==sys_getpid()?"OURS":"OTHER"))
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
94 return PRINTER_STATUS_PAUSED;
103 static int nt_printq_status(int v)
107 return PRINTER_STATUS_PAUSED;
116 /****************************************************************************
117 initialise printer handle states...
118 ****************************************************************************/
119 void init_printer_hnd(void)
121 ubi_dlInitList(&Printer_list);
122 ubi_dlInitList(&counter_list);
125 /****************************************************************************
126 create a unique printer handle
127 ****************************************************************************/
128 static void create_printer_hnd(POLICY_HND *hnd)
130 static uint32 prt_hnd_low = 0;
131 static uint32 prt_hnd_high = 0;
133 if (hnd == NULL) return;
135 /* i severely doubt that prt_hnd_high will ever be non-zero... */
137 if (prt_hnd_low == 0) prt_hnd_high++;
139 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
140 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
141 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
142 SIVAL(hnd->data, 12, time(NULL)); /* something random */
143 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
146 /****************************************************************************
147 find printer index by handle
148 ****************************************************************************/
149 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
151 Printer_entry *find_printer;
153 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
155 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
157 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
158 DEBUG(4,("Found printer handle \n"));
159 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
164 DEBUG(3,("Whoops, Printer handle not found: "));
165 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
169 /****************************************************************************
171 ****************************************************************************/
172 static void clear_handle(POLICY_HND *hnd)
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
180 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
184 /* weird if the test succeds !!! */
185 if (smb_connections==0) {
186 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
190 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
195 if(!spoolss_disconnect_from_client(&cli))
198 message_deregister(MSG_PRINTER_NOTIFY);
206 /****************************************************************************
207 close printer index by handle
208 ****************************************************************************/
209 static BOOL close_printer_handle(POLICY_HND *hnd)
211 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
213 if (!OPEN_HANDLE(Printer)) {
214 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
218 if (Printer->notify.client_connected==True)
219 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
220 return ERROR_INVALID_HANDLE;
223 Printer->notify.flags=0;
224 Printer->notify.options=0;
225 Printer->notify.localmachine[0]='\0';
226 Printer->notify.printerlocal=0;
227 safe_free(Printer->notify.option);
228 Printer->notify.option=NULL;
229 Printer->notify.client_connected=False;
233 ubi_dlRemThis(&Printer_list, Printer);
240 /****************************************************************************
241 delete a printer given a handle
242 ****************************************************************************/
243 static BOOL delete_printer_handle(POLICY_HND *hnd)
245 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
247 if (!OPEN_HANDLE(Printer)) {
248 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
252 if (del_a_printer(Printer->dev.handlename) != 0) {
253 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
257 if (*lp_deleteprinter_cmd()) {
259 pid_t local_pid = sys_getpid();
260 char *cmd = lp_deleteprinter_cmd();
267 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
268 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
272 /* Printer->dev.handlename equals portname equals sharename */
273 slprintf(command, sizeof(command), "%s \"%s\"", cmd,
274 Printer->dev.handlename);
275 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
278 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
279 ret = smbrun(command, tmp_file, False);
284 DEBUGADD(10,("returned [%d]\n", ret));
285 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
288 /* Send SIGHUP to process group... is there a better way? */
291 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
292 lp_remove_service( i );
302 /****************************************************************************
303 return the snum of a printer corresponding to an handle
304 ****************************************************************************/
305 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
307 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
309 if (!OPEN_HANDLE(Printer)) {
310 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
314 switch (Printer->printer_type) {
315 case PRINTER_HANDLE_IS_PRINTER:
316 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
317 *number = print_queue_snum(Printer->dev.handlename);
318 return (*number != -1);
319 case PRINTER_HANDLE_IS_PRINTSERVER:
326 /****************************************************************************
327 set printer handle type.
328 ****************************************************************************/
329 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
331 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
333 if (!OPEN_HANDLE(Printer)) {
334 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
338 DEBUG(4,("Setting printer access=%x\n", access_required));
339 Printer->access = access_required;
343 /****************************************************************************
344 Set printer handle type.
345 Check if it's \\server or \\server\printer
346 ****************************************************************************/
348 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
350 DEBUG(3,("Setting printer type=%s\n", handlename));
352 if ( strlen(handlename) < 3 ) {
353 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
357 /* it's a print server */
358 if (!strchr(handlename+2, '\\')) {
359 DEBUGADD(4,("Printer is a print server\n"));
360 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
364 DEBUGADD(4,("Printer is a printer\n"));
365 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
371 /****************************************************************************
372 Set printer handle name.
373 ****************************************************************************/
375 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
377 NT_PRINTER_INFO_LEVEL *printer = NULL;
379 int n_services=lp_numservices();
383 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
385 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
386 ZERO_STRUCT(Printer->dev.printerservername);
387 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
391 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
394 aprinter=strchr(handlename+2, '\\');
397 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
400 * store the Samba share name in it
401 * in back we have the long printer name
402 * need to iterate all the snum and do a
403 * get_a_printer each time to find the printer
404 * faster to do it here than later.
407 for (snum=0;snum<n_services && found==False;snum++) {
409 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
412 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
414 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
417 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
418 printer->info_2->printername, aprinter ));
420 if ( strlen(printer->info_2->printername) != strlen(aprinter) ) {
421 free_a_printer(&printer, 2);
425 if ( strncasecmp(printer->info_2->printername, aprinter, strlen(aprinter))) {
426 free_a_printer(&printer, 2);
434 * if we haven't found a printer with the given handlename
435 * then it can be a share name as you can open both \\server\printer and
440 * we still check if the printer description file exists as NT won't be happy
441 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
445 DEBUGADD(5,("Printer not found, checking for share now\n"));
447 for (snum=0;snum<n_services && found==False;snum++) {
449 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
452 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
454 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
457 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
458 printer->info_2->printername, aprinter ));
460 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
461 free_a_printer(&printer, 2);
465 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
466 free_a_printer(&printer, 2);
475 DEBUGADD(4,("Printer not found\n"));
480 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
481 printer->info_2->printername, lp_servicename(snum),snum));
483 ZERO_STRUCT(Printer->dev.handlename);
484 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
486 free_a_printer(&printer, 2);
491 /****************************************************************************
492 find first available printer slot. creates a printer handle for you.
493 ****************************************************************************/
495 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
497 Printer_entry *new_printer;
499 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
501 create_printer_hnd(hnd);
503 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
506 ZERO_STRUCTP(new_printer);
508 new_printer->open = True;
509 new_printer->notify.option=NULL;
511 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
513 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
515 if (!set_printer_hnd_printertype(new_printer, name)) {
516 close_printer_handle(hnd);
520 if (!set_printer_hnd_name(new_printer, name)) {
521 close_printer_handle(hnd);
528 /********************************************************************
529 Return True is the handle is a print server.
530 ********************************************************************/
531 static BOOL handle_is_printserver(const POLICY_HND *handle)
533 Printer_entry *Printer=find_printer_index_by_hnd(handle);
535 if (!OPEN_HANDLE(Printer))
538 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
544 /****************************************************************************
545 allocate more memory for a BUFFER.
546 ****************************************************************************/
547 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
555 /* damn, I'm doing the reverse operation of prs_grow() :) */
556 if (buffer_size < prs_data_size(ps))
559 extra_space = buffer_size - prs_data_size(ps);
562 * save the offset and move to the end of the buffer
563 * prs_grow() checks the extra_space against the offset
565 old_offset=prs_offset(ps);
566 prs_set_offset(ps, prs_data_size(ps));
568 if (!prs_grow(ps, extra_space))
571 prs_set_offset(ps, old_offset);
573 buffer->string_at_end=prs_data_size(ps);
578 /***************************************************************************
579 receive the notify message
580 ****************************************************************************/
581 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
585 Printer_entry *find_printer;
588 fstrcpy(printer,buf);
591 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
595 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
597 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
599 /* Iterate the printer list. */
600 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
603 * if the entry is the given printer or if it's a printerserver
604 * we send the message
607 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
608 if (strcmp(find_printer->dev.handlename, printer))
611 if (find_printer->notify.client_connected==True)
612 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
617 /***************************************************************************
619 ****************************************************************************/
620 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
624 Printer_entry *Printer=find_printer_index_by_hnd(handle);
626 if (!OPEN_HANDLE(Printer)) {
627 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
631 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
632 fstrcpy(printer, Printer->dev.handlename);
634 fstrcpy(printer, "");
636 /*srv_spoolss_receive_message(printer);*/
637 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
639 message_send_all(MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1); /* Null terminate... */
644 /********************************************************************
645 * spoolss_open_printer
647 * called from the spoolss dispatcher
648 ********************************************************************/
649 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername,
650 const PRINTER_DEFAULT *printer_default,
651 uint32 user_switch, SPOOL_USER_CTR user_ctr,
656 if (printername == NULL)
657 return ERROR_INVALID_PRINTER_NAME;
659 /* some sanity check because you can open a printer or a print server */
660 /* aka: \\server\printer or \\server */
661 unistr2_to_ascii(name, printername, sizeof(name)-1);
663 DEBUGADD(3,("checking name: %s\n",name));
665 if (!open_printer_hnd(handle, name))
666 return ERROR_INVALID_PRINTER_NAME;
669 if (printer_default->datatype_ptr != NULL)
671 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
672 set_printer_hnd_datatype(handle, datatype);
675 set_printer_hnd_datatype(handle, "");
678 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
679 close_printer_handle(handle);
680 return ERROR_ACCESS_DENIED;
683 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
684 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
685 Then both Win2k and WinNT clients try an OpenPrinterEx with
686 SERVER_ALL_ACCESS, which we force to fail. Then they try
687 OpenPrinterEx with SERVER_READ which we allow. This lets the
688 client view printer folder, but does not show the MSAPW.
690 Note: this test needs code to check access rights here too. Jeremy
691 could you look at this? */
693 if (handle_is_printserver(handle) &&
694 !lp_ms_add_printer_wizard()) {
695 if (printer_default->access_required == 0)
696 return NT_STATUS_NO_PROBLEMO;
697 else if (printer_default->access_required != (SERVER_READ))
698 return ERROR_ACCESS_DENIED;
701 return NT_STATUS_NO_PROBLEMO;
704 /****************************************************************************
705 ****************************************************************************/
706 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
707 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
711 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
720 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
721 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
725 printer->info_3=NULL;
726 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
729 printer->info_6=NULL;
730 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
739 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
741 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
742 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
744 nt_devmode->specversion=devmode->specversion;
745 nt_devmode->driverversion=devmode->driverversion;
746 nt_devmode->size=devmode->size;
747 nt_devmode->driverextra=devmode->driverextra;
748 nt_devmode->fields=devmode->fields;
749 nt_devmode->orientation=devmode->orientation;
750 nt_devmode->papersize=devmode->papersize;
751 nt_devmode->paperlength=devmode->paperlength;
752 nt_devmode->paperwidth=devmode->paperwidth;
753 nt_devmode->scale=devmode->scale;
754 nt_devmode->copies=devmode->copies;
755 nt_devmode->defaultsource=devmode->defaultsource;
756 nt_devmode->printquality=devmode->printquality;
757 nt_devmode->color=devmode->color;
758 nt_devmode->duplex=devmode->duplex;
759 nt_devmode->yresolution=devmode->yresolution;
760 nt_devmode->ttoption=devmode->ttoption;
761 nt_devmode->collate=devmode->collate;
763 nt_devmode->logpixels=devmode->logpixels;
764 nt_devmode->bitsperpel=devmode->bitsperpel;
765 nt_devmode->pelswidth=devmode->pelswidth;
766 nt_devmode->pelsheight=devmode->pelsheight;
767 nt_devmode->displayflags=devmode->displayflags;
768 nt_devmode->displayfrequency=devmode->displayfrequency;
769 nt_devmode->icmmethod=devmode->icmmethod;
770 nt_devmode->icmintent=devmode->icmintent;
771 nt_devmode->mediatype=devmode->mediatype;
772 nt_devmode->dithertype=devmode->dithertype;
773 nt_devmode->reserved1=devmode->reserved1;
774 nt_devmode->reserved2=devmode->reserved2;
775 nt_devmode->panningwidth=devmode->panningwidth;
776 nt_devmode->panningheight=devmode->panningheight;
778 if (nt_devmode->driverextra != 0) {
779 /* if we had a previous private delete it and make a new one */
780 safe_free(nt_devmode->private);
781 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
783 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
789 /********************************************************************
790 * api_spoolss_closeprinter
791 ********************************************************************/
792 uint32 _spoolss_closeprinter(POLICY_HND *handle)
794 Printer_entry *Printer=find_printer_index_by_hnd(handle);
796 if (Printer && Printer->document_started)
797 _spoolss_enddocprinter(handle); /* print job was not closed */
799 if (!close_printer_handle(handle))
800 return ERROR_INVALID_HANDLE;
802 return NT_STATUS_NO_PROBLEMO;
805 /********************************************************************
806 * api_spoolss_deleteprinter
807 ********************************************************************/
808 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
810 Printer_entry *Printer=find_printer_index_by_hnd(handle);
812 if (Printer && Printer->document_started)
813 _spoolss_enddocprinter(handle); /* print job was not closed */
815 if (!delete_printer_handle(handle))
816 return ERROR_INVALID_HANDLE;
818 srv_spoolss_sendnotify(handle);
820 return NT_STATUS_NO_PROBLEMO;
823 /********************************************************************
824 GetPrinterData on a printer server Handle.
825 ********************************************************************/
826 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
830 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
832 if (!strcmp(value, "BeepEnabled")) {
834 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
836 SIVAL(*data, 0, 0x01);
841 if (!strcmp(value, "EventLog")) {
843 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
845 SIVAL(*data, 0, 0x1B);
850 if (!strcmp(value, "NetPopup")) {
852 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
854 SIVAL(*data, 0, 0x01);
859 if (!strcmp(value, "MajorVersion")) {
861 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
863 SIVAL(*data, 0, 0x02);
868 if (!strcmp(value, "DefaultSpoolDirectory")) {
869 pstring string="You are using a Samba server";
871 *needed = 2*(strlen(string)+1);
872 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
874 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
876 /* it's done by hand ready to go on the wire */
877 for (i=0; i<strlen(string); i++) {
878 (*data)[2*i]=string[i];
884 if (!strcmp(value, "Architecture")) {
885 pstring string="Windows NT x86";
887 *needed = 2*(strlen(string)+1);
888 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
890 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
891 for (i=0; i<strlen(string); i++) {
892 (*data)[2*i]=string[i];
901 /********************************************************************
902 GetPrinterData on a printer Handle.
903 ********************************************************************/
904 static BOOL getprinterdata_printer(POLICY_HND *handle,
905 fstring value, uint32 *type,
906 uint8 **data, uint32 *needed, uint32 in_size )
908 NT_PRINTER_INFO_LEVEL *printer = NULL;
912 Printer_entry *Printer = find_printer_index_by_hnd(handle);
914 DEBUG(5,("getprinterdata_printer\n"));
916 if (!OPEN_HANDLE(Printer)) {
917 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
921 if(!get_printer_snum(handle, &snum))
924 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
927 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
928 free_a_printer(&printer, 2);
932 free_a_printer(&printer, 2);
934 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
937 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
941 memset(*data, 0, in_size *sizeof(uint8));
942 /* copy the min(in_size, len) */
943 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
950 DEBUG(5,("getprinterdata_printer:copy done\n"));
957 /********************************************************************
958 * spoolss_getprinterdata
959 ********************************************************************/
960 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
969 Printer_entry *Printer = find_printer_index_by_hnd(handle);
972 * Reminder: when it's a string, the length is in BYTES
973 * even if UNICODE is negociated.
980 /* in case of problem, return some default values */
984 DEBUG(4,("_spoolss_getprinterdata\n"));
986 if (!OPEN_HANDLE(Printer)) {
987 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
988 return ERROR_NOT_ENOUGH_MEMORY;
989 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
990 return ERROR_INVALID_HANDLE;
993 unistr2_to_ascii(value, valuename, sizeof(value)-1);
995 if (handle_is_printserver(handle))
996 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
998 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
1001 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1002 /* reply this param doesn't exist */
1004 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1005 return ERROR_NOT_ENOUGH_MEMORY;
1006 memset(*data, '\0', *out_size*sizeof(uint8));
1011 return ERROR_INVALID_PARAMETER;
1014 if (*needed > *out_size)
1015 return ERROR_MORE_DATA;
1017 return NT_STATUS_NO_PROBLEMO;
1020 /***************************************************************************
1021 connect to the client
1022 ****************************************************************************/
1023 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1028 * If it's the first connection, contact the client
1029 * and connect to the IPC$ share anonumously
1031 if (smb_connections==0) {
1032 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1034 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1040 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1046 /********************************************************************
1048 * ReplyFindFirstPrinterChangeNotifyEx
1050 * jfmxxxx: before replying OK: status=0
1051 * should do a rpc call to the workstation asking ReplyOpenPrinter
1052 * have to code it, later.
1054 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1055 * called from api_spoolss_rffpcnex
1056 ********************************************************************/
1057 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1058 const UNISTR2 *localmachine, uint32 printerlocal,
1059 SPOOL_NOTIFY_OPTION *option)
1061 /* store the notify value in the printer struct */
1063 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1065 if (!OPEN_HANDLE(Printer)) {
1066 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1067 return ERROR_INVALID_HANDLE;
1070 Printer->notify.flags=flags;
1071 Printer->notify.options=options;
1072 Printer->notify.printerlocal=printerlocal;
1073 Printer->notify.option=option;
1074 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1076 /* connect to the client machine and send a ReplyOpenPrinter */
1077 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1078 Printer->notify.printerlocal, 1,
1079 &Printer->notify.client_hnd))
1080 Printer->notify.client_connected=True;
1082 return NT_STATUS_NO_PROBLEMO;
1085 /*******************************************************************
1086 * fill a notify_info_data with the servername
1087 ********************************************************************/
1088 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1089 NT_PRINTER_INFO_LEVEL *printer)
1093 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1095 data->notify_data.data.length= (uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1096 temp_name, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1099 /*******************************************************************
1100 * fill a notify_info_data with the servicename
1101 * jfmxxxx: it's incorrect should be long_printername
1102 ********************************************************************/
1103 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1104 NT_PRINTER_INFO_LEVEL *printer)
1107 data->notify_data.data.length=strlen(lp_servicename(snum));
1108 dos_PutUniCode(data->notify_data.data.string, lp_servicename(snum), sizeof(data->notify_data.data.string), True);
1110 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1111 printer->info_2->printername, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1114 /*******************************************************************
1115 * fill a notify_info_data with the servicename
1116 ********************************************************************/
1117 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1119 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1120 lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
1123 /*******************************************************************
1124 * fill a notify_info_data with the port name
1125 ********************************************************************/
1126 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1128 /* even if it's strange, that's consistant in all the code */
1130 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1131 lp_servicename(snum), sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1134 /*******************************************************************
1135 * fill a notify_info_data with the printername
1136 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1137 * but it doesn't exist, have to see what to do
1138 ********************************************************************/
1139 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1141 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1142 printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1145 /*******************************************************************
1146 * fill a notify_info_data with the comment
1147 ********************************************************************/
1148 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1150 if (*printer->info_2->comment == '\0')
1151 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1152 lp_comment(snum), sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1154 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1155 printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1158 /*******************************************************************
1159 * fill a notify_info_data with the comment
1160 * jfm:xxxx incorrect, have to create a new smb.conf option
1161 * location = "Room 1, floor 2, building 3"
1162 ********************************************************************/
1163 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1165 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1166 printer->info_2->location, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1169 /*******************************************************************
1170 * fill a notify_info_data with the device mode
1171 * jfm:xxxx don't to it for know but that's a real problem !!!
1172 ********************************************************************/
1173 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1177 /*******************************************************************
1178 * fill a notify_info_data with the separator file name
1179 * jfm:xxxx just return no file could add an option to smb.conf
1180 * separator file = "separator.txt"
1181 ********************************************************************/
1182 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1184 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1185 printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True) - sizeof(uint16))/sizeof(uint16));
1188 /*******************************************************************
1189 * fill a notify_info_data with the print processor
1190 * jfm:xxxx return always winprint to indicate we don't do anything to it
1191 ********************************************************************/
1192 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1194 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1195 printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1198 /*******************************************************************
1199 * fill a notify_info_data with the print processor options
1200 * jfm:xxxx send an empty string
1201 ********************************************************************/
1202 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1204 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1205 printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1208 /*******************************************************************
1209 * fill a notify_info_data with the data type
1210 * jfm:xxxx always send RAW as data type
1211 ********************************************************************/
1212 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1214 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1215 printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1218 /*******************************************************************
1219 * fill a notify_info_data with the security descriptor
1220 * jfm:xxxx send an null pointer to say no security desc
1221 * have to implement security before !
1222 ********************************************************************/
1223 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1225 data->notify_data.data.length=0;
1226 data->notify_data.data.string[0]=0x00;
1229 /*******************************************************************
1230 * fill a notify_info_data with the attributes
1231 * jfm:xxxx a samba printer is always shared
1232 ********************************************************************/
1233 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1235 data->notify_data.value[0] = PRINTER_ATTRIBUTE_SHARED \
1236 | PRINTER_ATTRIBUTE_LOCAL \
1237 | PRINTER_ATTRIBUTE_RAW_ONLY ;
1240 /*******************************************************************
1241 * fill a notify_info_data with the priority
1242 ********************************************************************/
1243 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1245 data->notify_data.value[0] = printer->info_2->priority;
1248 /*******************************************************************
1249 * fill a notify_info_data with the default priority
1250 ********************************************************************/
1251 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1253 data->notify_data.value[0] = printer->info_2->default_priority;
1256 /*******************************************************************
1257 * fill a notify_info_data with the start time
1258 ********************************************************************/
1259 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1261 data->notify_data.value[0] = printer->info_2->starttime;
1264 /*******************************************************************
1265 * fill a notify_info_data with the until time
1266 ********************************************************************/
1267 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1269 data->notify_data.value[0] = printer->info_2->untiltime;
1272 /*******************************************************************
1273 * fill a notify_info_data with the status
1274 ********************************************************************/
1275 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1278 print_queue_struct *q=NULL;
1279 print_status_struct status;
1281 memset(&status, 0, sizeof(status));
1282 count = print_queue_status(snum, &q, &status);
1283 data->notify_data.value[0]=(uint32) status.status;
1287 /*******************************************************************
1288 * fill a notify_info_data with the number of jobs queued
1289 ********************************************************************/
1290 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1292 print_queue_struct *q=NULL;
1293 print_status_struct status;
1295 memset(&status, 0, sizeof(status));
1296 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1300 /*******************************************************************
1301 * fill a notify_info_data with the average ppm
1302 ********************************************************************/
1303 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1305 /* always respond 8 pages per minutes */
1306 /* a little hard ! */
1307 data->notify_data.value[0] = printer->info_2->averageppm;
1310 /*******************************************************************
1311 * fill a notify_info_data with username
1312 ********************************************************************/
1313 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1315 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1316 queue->user, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1319 /*******************************************************************
1320 * fill a notify_info_data with job status
1321 ********************************************************************/
1322 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1324 data->notify_data.value[0]=nt_printj_status(queue->status);
1327 /*******************************************************************
1328 * fill a notify_info_data with job name
1329 ********************************************************************/
1330 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1332 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1333 queue->file, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1336 /*******************************************************************
1337 * fill a notify_info_data with job status
1338 ********************************************************************/
1339 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1341 char *p = "unknown";
1343 switch (queue->status) {
1348 p = ""; /* NT provides the paused string */
1357 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1358 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1361 /*******************************************************************
1362 * fill a notify_info_data with job time
1363 ********************************************************************/
1364 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1366 data->notify_data.value[0]=0x0;
1369 /*******************************************************************
1370 * fill a notify_info_data with job size
1371 ********************************************************************/
1372 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1374 data->notify_data.value[0]=queue->size;
1377 /*******************************************************************
1378 * fill a notify_info_data with job position
1379 ********************************************************************/
1380 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1382 data->notify_data.value[0]=queue->job;
1385 /*******************************************************************
1386 * fill a notify_info_data with submitted time
1387 ********************************************************************/
1388 static void spoolss_notify_submitted_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1392 t=gmtime(&queue->time);
1394 data->notify_data.data.length = sizeof(SYSTEMTIME);
1395 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1400 struct s_notify_info_data_table
1406 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1407 print_queue_struct *queue,
1408 NT_PRINTER_INFO_LEVEL *printer);
1411 struct s_notify_info_data_table notify_info_data_table[] =
1413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1463 { END, END, "", END, NULL }
1466 /*******************************************************************
1467 return the size of info_data structure
1468 ********************************************************************/
1469 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1473 while (notify_info_data_table[i].type != END)
1475 if ( (notify_info_data_table[i].type == type ) &&
1476 (notify_info_data_table[i].field == field ) )
1478 return (notify_info_data_table[i].size);
1485 /*******************************************************************
1486 return the type of notify_info_data
1487 ********************************************************************/
1488 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1492 while (notify_info_data_table[i].type != END)
1494 if ( (notify_info_data_table[i].type == type ) &&
1495 (notify_info_data_table[i].field == field ) )
1497 if (notify_info_data_table[i].size == POINTER)
1511 /****************************************************************************
1512 ****************************************************************************/
1513 static int search_notify(uint16 type, uint16 field, int *value)
1518 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1520 if ( (notify_info_data_table[j].type == type ) &&
1521 (notify_info_data_table[j].field == field ) )
1526 if ( found && (notify_info_data_table[j].fn != NULL) )
1532 /****************************************************************************
1533 ****************************************************************************/
1534 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1536 info_data->type = type;
1537 info_data->field = field;
1538 info_data->reserved = 0;
1540 info_data->size = size_of_notify_info_data(type, field);
1541 info_data->enc_type = type_of_notify_info_data(type, field);
1545 /*******************************************************************
1547 * fill a notify_info struct with info asked
1549 ********************************************************************/
1550 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1556 SPOOL_NOTIFY_INFO_DATA *current_data;
1557 NT_PRINTER_INFO_LEVEL *printer = NULL;
1558 print_queue_struct *queue=NULL;
1560 DEBUG(4,("construct_notify_printer_info\n"));
1562 type=option_type->type;
1564 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1565 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1566 option_type->count, lp_servicename(snum)));
1568 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1571 for(field_num=0; field_num<option_type->count; field_num++) {
1572 field = option_type->fields[field_num];
1573 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1575 if (!search_notify(type, field, &j) )
1578 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1581 current_data=&info->data[info->count];
1583 construct_info_data(current_data, type, field, id);
1584 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1589 free_a_printer(&printer, 2);
1593 /*******************************************************************
1595 * fill a notify_info struct with info asked
1597 ********************************************************************/
1598 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1604 SPOOL_NOTIFY_INFO_DATA *current_data;
1605 NT_PRINTER_INFO_LEVEL *printer = NULL;
1607 DEBUG(4,("construct_notify_jobs_info\n"));
1609 type = option_type->type;
1611 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1612 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1613 option_type->count));
1615 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1618 for(field_num=0; field_num<option_type->count; field_num++) {
1619 field = option_type->fields[field_num];
1621 if (!search_notify(type, field, &j) )
1624 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1628 current_data=&(info->data[info->count]);
1630 construct_info_data(current_data, type, field, id);
1631 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1635 free_a_printer(&printer, 2);
1640 * JFM: The enumeration is not that simple, it's even non obvious.
1642 * let's take an example: I want to monitor the PRINTER SERVER for
1643 * the printer's name and the number of jobs currently queued.
1644 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1645 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1647 * I have 3 printers on the back of my server.
1649 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1652 * 1 printer 1 name 1
1653 * 2 printer 1 cjob 1
1654 * 3 printer 2 name 2
1655 * 4 printer 2 cjob 2
1656 * 5 printer 3 name 3
1657 * 6 printer 3 name 3
1659 * that's the print server case, the printer case is even worse.
1664 /*******************************************************************
1666 * enumerate all printers on the printserver
1667 * fill a notify_info struct with info asked
1669 ********************************************************************/
1670 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1673 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1674 int n_services=lp_numservices();
1677 SPOOL_NOTIFY_OPTION *option;
1678 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1680 DEBUG(4,("printserver_notify_info\n"));
1682 option=Printer->notify.option;
1688 for (i=0; i<option->count; i++) {
1689 option_type=&(option->ctr.type[i]);
1691 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1694 for (snum=0; snum<n_services; snum++)
1695 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1696 if (construct_notify_printer_info(info, snum, option_type, id))
1701 * Debugging information, don't delete.
1704 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1705 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1706 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1708 for (i=0; i<info->count; i++) {
1709 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1710 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1711 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1715 return NT_STATUS_NO_PROBLEMO;
1718 /*******************************************************************
1720 * fill a notify_info struct with info asked
1722 ********************************************************************/
1723 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1726 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1729 SPOOL_NOTIFY_OPTION *option;
1730 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1732 print_queue_struct *queue=NULL;
1733 print_status_struct status;
1735 DEBUG(4,("printer_notify_info\n"));
1737 option=Printer->notify.option;
1743 get_printer_snum(hnd, &snum);
1745 for (i=0; i<option->count; i++) {
1746 option_type=&option->ctr.type[i];
1748 switch ( option_type->type ) {
1749 case PRINTER_NOTIFY_TYPE:
1750 if(construct_notify_printer_info(info, snum, option_type, id))
1754 case JOB_NOTIFY_TYPE:
1755 memset(&status, 0, sizeof(status));
1756 count = print_queue_status(snum, &queue, &status);
1757 for (j=0; j<count; j++)
1758 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1765 * Debugging information, don't delete.
1768 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1769 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1770 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1772 for (i=0; i<info->count; i++) {
1773 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1774 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1775 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1778 return NT_STATUS_NO_PROBLEMO;
1781 /********************************************************************
1783 ********************************************************************/
1784 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1785 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1787 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1789 if (!OPEN_HANDLE(Printer)) {
1790 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1791 return ERROR_INVALID_HANDLE;
1794 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1796 /* jfm: the change value isn't used right now.
1797 * we will honour it when
1798 * a) we'll be able to send notification to the client
1799 * b) we'll have a way to communicate between the spoolss process.
1801 * same thing for option->flags
1802 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1803 * I don't have a global notification system, I'm sending back all the
1804 * informations even when _NOTHING_ has changed.
1807 /* just discard the SPOOL_NOTIFY_OPTION */
1809 safe_free(option->ctr.type);
1811 switch (Printer->printer_type) {
1812 case PRINTER_HANDLE_IS_PRINTSERVER:
1813 return printserver_notify_info(handle, info);
1814 case PRINTER_HANDLE_IS_PRINTER:
1815 return printer_notify_info(handle, info);
1818 return ERROR_INVALID_HANDLE;
1821 /********************************************************************
1822 * construct_printer_info_0
1823 * fill a printer_info_1 struct
1824 ********************************************************************/
1825 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, fstring servername)
1829 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1830 counter_printer_0 *session_counter;
1831 uint32 global_counter;
1835 print_queue_struct *queue=NULL;
1836 print_status_struct status;
1838 memset(&status, 0, sizeof(status));
1840 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1843 count = print_queue_status(snum, &queue, &status);
1845 /* check if we already have a counter for this printer */
1846 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1848 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1849 if (session_counter->snum == snum)
1853 /* it's the first time, add it to the list */
1854 if (session_counter==NULL) {
1855 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1856 free_a_printer(&ntprinter, 2);
1859 ZERO_STRUCTP(session_counter);
1860 session_counter->snum=snum;
1861 session_counter->counter=0;
1862 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1866 session_counter->counter++;
1869 * the global_counter should be stored in a TDB as it's common to all the clients
1870 * and should be zeroed on samba startup
1872 global_counter=session_counter->counter;
1874 /* the description and the name are of the form \\server\share */
1875 slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter->info_2->printername);
1877 init_unistr(&printer->printername, chaine);
1879 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername);
1880 init_unistr(&printer->servername, chaine);
1882 printer->cjobs = count;
1883 printer->total_jobs = 0;
1884 printer->total_bytes = 0;
1886 setuptime = (time_t)ntprinter->info_2->setuptime;
1887 t=gmtime(&setuptime);
1889 printer->year = t->tm_year+1900;
1890 printer->month = t->tm_mon+1;
1891 printer->dayofweek = t->tm_wday;
1892 printer->day = t->tm_mday;
1893 printer->hour = t->tm_hour;
1894 printer->minute = t->tm_min;
1895 printer->second = t->tm_sec;
1896 printer->milliseconds = 0;
1898 printer->global_counter = global_counter;
1899 printer->total_pages = 0;
1900 printer->major_version = 0x0004; /* NT 4 */
1901 printer->build_version = 0x0565; /* build 1381 */
1902 printer->unknown7 = 0x1;
1903 printer->unknown8 = 0x0;
1904 printer->unknown9 = 0x0;
1905 printer->session_counter = session_counter->counter;
1906 printer->unknown11 = 0x0;
1907 printer->printer_errors = 0x0; /* number of print failure */
1908 printer->unknown13 = 0x0;
1909 printer->unknown14 = 0x1;
1910 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1911 printer->unknown16 = 0x0;
1912 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1913 printer->unknown18 = 0x0;
1914 printer->status = nt_printq_status(status.status);
1915 printer->unknown20 = 0x0;
1916 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1917 printer->unknown22 = 0x0;
1918 printer->unknown23 = 0x6; /* 6 ???*/
1919 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1920 printer->unknown25 = 0;
1921 printer->unknown26 = 0;
1922 printer->unknown27 = 0;
1923 printer->unknown28 = 0;
1924 printer->unknown29 = 0;
1927 free_a_printer(&ntprinter,2);
1931 /********************************************************************
1932 * construct_printer_info_1
1933 * fill a printer_info_1 struct
1934 ********************************************************************/
1935 static BOOL construct_printer_info_1(fstring server, uint32 flags, PRINTER_INFO_1 *printer, int snum)
1939 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1941 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1944 printer->flags=flags;
1946 if (*ntprinter->info_2->comment == '\0') {
1947 init_unistr(&printer->comment, lp_comment(snum));
1948 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1949 ntprinter->info_2->drivername, lp_comment(snum));
1952 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1953 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1954 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1957 snprintf(chaine2,sizeof(chaine)-1,"%s%s", server, ntprinter->info_2->printername);
1959 init_unistr(&printer->description, chaine);
1960 init_unistr(&printer->name, chaine2);
1962 free_a_printer(&ntprinter,2);
1967 /****************************************************************************
1968 Free a DEVMODE struct.
1969 ****************************************************************************/
1971 static void free_dev_mode(DEVICEMODE *dev)
1977 safe_free(dev->private);
1982 /****************************************************************************
1983 Create a DEVMODE struct. Returns malloced memory.
1984 ****************************************************************************/
1986 static DEVICEMODE *construct_dev_mode(int snum, char *servername)
1990 NT_PRINTER_INFO_LEVEL *printer = NULL;
1991 NT_DEVICEMODE *ntdevmode = NULL;
1992 DEVICEMODE *devmode = NULL;
1994 DEBUG(7,("construct_dev_mode\n"));
1996 DEBUGADD(8,("getting printer characteristics\n"));
1998 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
1999 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2003 ZERO_STRUCTP(devmode);
2005 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2008 if (printer->info_2->devmode)
2009 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2011 if (ntdevmode == NULL)
2014 DEBUGADD(8,("loading DEVICEMODE\n"));
2016 snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, printer->info_2->printername);
2017 init_unistr(&devmode->devicename, adevice);
2019 snprintf(aform, sizeof(aform), ntdevmode->formname);
2020 init_unistr(&devmode->formname, aform);
2022 devmode->specversion = ntdevmode->specversion;
2023 devmode->driverversion = ntdevmode->driverversion;
2024 devmode->size = ntdevmode->size;
2025 devmode->driverextra = ntdevmode->driverextra;
2026 devmode->fields = ntdevmode->fields;
2028 devmode->orientation = ntdevmode->orientation;
2029 devmode->papersize = ntdevmode->papersize;
2030 devmode->paperlength = ntdevmode->paperlength;
2031 devmode->paperwidth = ntdevmode->paperwidth;
2032 devmode->scale = ntdevmode->scale;
2033 devmode->copies = ntdevmode->copies;
2034 devmode->defaultsource = ntdevmode->defaultsource;
2035 devmode->printquality = ntdevmode->printquality;
2036 devmode->color = ntdevmode->color;
2037 devmode->duplex = ntdevmode->duplex;
2038 devmode->yresolution = ntdevmode->yresolution;
2039 devmode->ttoption = ntdevmode->ttoption;
2040 devmode->collate = ntdevmode->collate;
2041 devmode->icmmethod = ntdevmode->icmmethod;
2042 devmode->icmintent = ntdevmode->icmintent;
2043 devmode->mediatype = ntdevmode->mediatype;
2044 devmode->dithertype = ntdevmode->dithertype;
2046 if (ntdevmode->private != NULL) {
2047 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2051 free_nt_devicemode(&ntdevmode);
2052 free_a_printer(&printer,2);
2059 free_nt_devicemode(&ntdevmode);
2061 free_a_printer(&printer,2);
2062 free_dev_mode(devmode);
2067 /********************************************************************
2068 * construct_printer_info_2
2069 * fill a printer_info_2 struct
2070 ********************************************************************/
2072 static BOOL construct_printer_info_2(fstring servername, PRINTER_INFO_2 *printer, int snum)
2078 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2080 print_queue_struct *queue=NULL;
2081 print_status_struct status;
2082 memset(&status, 0, sizeof(status));
2084 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2087 memset(&status, 0, sizeof(status));
2088 count = print_queue_status(snum, &queue, &status);
2090 snprintf(chaine, sizeof(chaine)-1, "%s", servername);
2092 if (strlen(servername)!=0)
2097 if (!strchr(ntprinter->info_2->printername, '\\')) {
2098 snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter->info_2->printername);
2100 pstrcpy(chaine2, ntprinter->info_2->printername);
2103 init_unistr(&printer->servername, chaine); /* servername*/
2104 init_unistr(&printer->printername, chaine2); /* printername*/
2105 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2106 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2107 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2109 if (*ntprinter->info_2->comment == '\0')
2110 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2112 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2114 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2115 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2116 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2117 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2118 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2120 printer->attributes = ntprinter->info_2->attributes;
2122 printer->priority = ntprinter->info_2->priority; /* priority */
2123 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2124 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2125 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2126 printer->status = nt_printq_status(status.status); /* status */
2127 printer->cjobs = count; /* jobs */
2128 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2130 if((printer->devmode = construct_dev_mode(snum, servername)) == NULL) {
2131 DEBUG(8, ("Returning NULL Devicemode!\n"));
2134 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2135 /* steal the printer info sec_desc structure. [badly done]. */
2136 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2137 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2138 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2139 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2142 printer->secdesc = NULL;
2145 free_a_printer(&ntprinter, 2);
2150 /********************************************************************
2151 * construct_printer_info_3
2152 * fill a printer_info_3 struct
2153 ********************************************************************/
2154 static BOOL construct_printer_info_3(fstring servername,
2155 PRINTER_INFO_3 **pp_printer, int snum)
2157 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2158 PRINTER_INFO_3 *printer = NULL;
2160 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2164 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2165 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2169 ZERO_STRUCTP(printer);
2171 printer->flags = 4; /* These are the components of the SD we are returning. */
2172 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2173 /* steal the printer info sec_desc structure. [badly done]. */
2174 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2178 * Set the flags for the components we are returning.
2181 if (printer->secdesc->owner_sid)
2182 printer->flags |= OWNER_SECURITY_INFORMATION;
2184 if (printer->secdesc->grp_sid)
2185 printer->flags |= GROUP_SECURITY_INFORMATION;
2187 if (printer->secdesc->dacl)
2188 printer->flags |= DACL_SECURITY_INFORMATION;
2190 if (printer->secdesc->sacl)
2191 printer->flags |= SACL_SECURITY_INFORMATION;
2194 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2195 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2196 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2199 free_a_printer(&ntprinter, 2);
2201 *pp_printer = printer;
2205 /********************************************************************
2206 Spoolss_enumprinters.
2207 ********************************************************************/
2208 static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2212 int n_services=lp_numservices();
2213 PRINTER_INFO_1 *printers=NULL;
2214 PRINTER_INFO_1 current_prt;
2216 DEBUG(4,("enum_all_printers_info_1\n"));
2218 for (snum=0; snum<n_services; snum++) {
2219 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2220 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2222 if (construct_printer_info_1(server, flags, ¤t_prt, snum)) {
2223 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2225 return ERROR_NOT_ENOUGH_MEMORY;
2227 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2228 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2234 /* check the required size. */
2235 for (i=0; i<*returned; i++)
2236 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2238 if (!alloc_buffer_size(buffer, *needed))
2239 return ERROR_INSUFFICIENT_BUFFER;
2241 /* fill the buffer with the structures */
2242 for (i=0; i<*returned; i++)
2243 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2246 safe_free(printers);
2248 if (*needed > offered) {
2250 return ERROR_INSUFFICIENT_BUFFER;
2253 return NT_STATUS_NO_PROBLEMO;
2256 /********************************************************************
2257 enum_all_printers_info_1_local.
2258 *********************************************************************/
2259 static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2262 DEBUG(4,("enum_all_printers_info_1_local\n"));
2264 fstrcpy(temp, "\\\\");
2265 fstrcat(temp, global_myname);
2267 if (!strcmp(name, temp)) {
2268 fstrcat(temp, "\\");
2269 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2272 return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2275 /********************************************************************
2276 enum_all_printers_info_1_name.
2277 *********************************************************************/
2278 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2281 DEBUG(4,("enum_all_printers_info_1_name\n"));
2283 fstrcpy(temp, "\\\\");
2284 fstrcat(temp, global_myname);
2286 if (!strcmp(name, temp)) {
2287 fstrcat(temp, "\\");
2288 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2291 return ERROR_INVALID_NAME;
2294 /********************************************************************
2295 enum_all_printers_info_1_remote.
2296 *********************************************************************/
2297 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2299 PRINTER_INFO_1 *printer;
2300 fstring printername;
2303 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2305 /* JFM: currently it's more a place holder than anything else.
2306 * In the spooler world there is a notion of server registration.
2307 * the print servers are registring (sp ?) on the PDC (in the same domain)
2309 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2312 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2313 return ERROR_NOT_ENOUGH_MEMORY;
2317 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2318 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2319 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2321 init_unistr(&printer->description, desc);
2322 init_unistr(&printer->name, printername);
2323 init_unistr(&printer->comment, comment);
2324 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2326 /* check the required size. */
2327 *needed += spoolss_size_printer_info_1(printer);
2329 if (!alloc_buffer_size(buffer, *needed)) {
2331 return ERROR_INSUFFICIENT_BUFFER;
2334 /* fill the buffer with the structures */
2335 new_smb_io_printer_info_1("", buffer, printer, 0);
2340 if (*needed > offered) {
2342 return ERROR_INSUFFICIENT_BUFFER;
2345 return NT_STATUS_NO_PROBLEMO;
2348 /********************************************************************
2349 enum_all_printers_info_1_network.
2350 *********************************************************************/
2351 static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2354 DEBUG(4,("enum_all_printers_info_1_network\n"));
2356 fstrcpy(temp, "\\\\");
2357 fstrcat(temp, global_myname);
2358 fstrcat(temp, "\\");
2359 return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2362 /********************************************************************
2363 * api_spoolss_enumprinters
2365 * called from api_spoolss_enumprinters (see this to understand)
2366 ********************************************************************/
2367 static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2371 int n_services=lp_numservices();
2372 PRINTER_INFO_2 *printers=NULL;
2373 PRINTER_INFO_2 current_prt;
2375 for (snum=0; snum<n_services; snum++) {
2376 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2377 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2379 if (construct_printer_info_2(servername, ¤t_prt, snum)) {
2380 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2381 return ERROR_NOT_ENOUGH_MEMORY;
2382 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2383 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2389 /* check the required size. */
2390 for (i=0; i<*returned; i++)
2391 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2393 if (!alloc_buffer_size(buffer, *needed)) {
2394 for (i=0; i<*returned; i++) {
2395 free_devmode(printers[i].devmode);
2396 free_sec_desc(&printers[i].secdesc);
2398 safe_free(printers);
2399 return ERROR_INSUFFICIENT_BUFFER;
2402 /* fill the buffer with the structures */
2403 for (i=0; i<*returned; i++)
2404 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2407 for (i=0; i<*returned; i++) {
2408 free_devmode(printers[i].devmode);
2409 free_sec_desc(&printers[i].secdesc);
2411 safe_free(printers);
2413 if (*needed > offered) {
2415 return ERROR_INSUFFICIENT_BUFFER;
2418 return NT_STATUS_NO_PROBLEMO;
2421 /********************************************************************
2422 * handle enumeration of printers at level 1
2423 ********************************************************************/
2424 static uint32 enumprinters_level1( uint32 flags, fstring name,
2425 NEW_BUFFER *buffer, uint32 offered,
2426 uint32 *needed, uint32 *returned)
2428 /* Not all the flags are equals */
2430 if (flags & PRINTER_ENUM_LOCAL)
2431 return enum_all_printers_info_1_local(name, buffer, offered, needed, returned);
2433 if (flags & PRINTER_ENUM_NAME)
2434 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2436 if (flags & PRINTER_ENUM_REMOTE)
2437 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2439 if (flags & PRINTER_ENUM_NETWORK)
2440 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
2442 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2445 /********************************************************************
2446 * handle enumeration of printers at level 2
2447 ********************************************************************/
2448 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2449 NEW_BUFFER *buffer, uint32 offered,
2450 uint32 *needed, uint32 *returned)
2454 fstrcpy(temp, "\\\\");
2455 fstrcat(temp, global_myname);
2457 if (flags & PRINTER_ENUM_LOCAL) {
2458 if (!strcmp(servername, temp))
2459 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2461 return enum_all_printers_info_2("", buffer, offered, needed, returned);
2464 if (flags & PRINTER_ENUM_NAME) {
2465 if (!strcmp(servername, temp))
2466 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2468 return ERROR_INVALID_NAME;
2471 if (flags & PRINTER_ENUM_REMOTE)
2472 return ERROR_INVALID_LEVEL;
2474 return NT_STATUS_NO_PROBLEMO;
2477 /********************************************************************
2478 * handle enumeration of printers at level 5
2479 ********************************************************************/
2480 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2481 NEW_BUFFER *buffer, uint32 offered,
2482 uint32 *needed, uint32 *returned)
2484 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2485 return NT_STATUS_NO_PROBLEMO;
2488 /********************************************************************
2489 * api_spoolss_enumprinters
2491 * called from api_spoolss_enumprinters (see this to understand)
2492 ********************************************************************/
2493 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2494 NEW_BUFFER *buffer, uint32 offered,
2495 uint32 *needed, uint32 *returned)
2499 DEBUG(4,("_spoolss_enumprinters\n"));
2506 * flags==PRINTER_ENUM_NAME
2507 * if name=="" then enumerates all printers
2508 * if name!="" then enumerate the printer
2509 * flags==PRINTER_ENUM_REMOTE
2510 * name is NULL, enumerate printers
2511 * Level 2: name!="" enumerates printers, name can't be NULL
2512 * Level 3: doesn't exist
2513 * Level 4: does a local registry lookup
2514 * Level 5: same as Level 2
2517 unistr2_to_ascii(name, servername, sizeof(name)-1);
2522 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2524 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2526 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2530 return ERROR_INVALID_LEVEL;
2534 /****************************************************************************
2535 ****************************************************************************/
2536 static uint32 getprinter_level_0(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2538 PRINTER_INFO_0 *printer=NULL;
2540 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2541 return ERROR_NOT_ENOUGH_MEMORY;
2543 construct_printer_info_0(printer, snum, servername);
2545 /* check the required size. */
2546 *needed += spoolss_size_printer_info_0(printer);
2548 if (!alloc_buffer_size(buffer, *needed)) {
2550 return ERROR_INSUFFICIENT_BUFFER;
2553 /* fill the buffer with the structures */
2554 new_smb_io_printer_info_0("", buffer, printer, 0);
2559 if (*needed > offered) {
2560 return ERROR_INSUFFICIENT_BUFFER;
2563 return NT_STATUS_NO_PROBLEMO;
2566 /****************************************************************************
2567 ****************************************************************************/
2568 static uint32 getprinter_level_1(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2570 PRINTER_INFO_1 *printer=NULL;
2572 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2573 return ERROR_NOT_ENOUGH_MEMORY;
2575 construct_printer_info_1(servername, PRINTER_ENUM_ICON8, printer, snum);
2577 /* check the required size. */
2578 *needed += spoolss_size_printer_info_1(printer);
2580 if (!alloc_buffer_size(buffer, *needed)) {
2582 return ERROR_INSUFFICIENT_BUFFER;
2585 /* fill the buffer with the structures */
2586 new_smb_io_printer_info_1("", buffer, printer, 0);
2591 if (*needed > offered) {
2592 return ERROR_INSUFFICIENT_BUFFER;
2595 return NT_STATUS_NO_PROBLEMO;
2598 /****************************************************************************
2599 ****************************************************************************/
2600 static uint32 getprinter_level_2(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2602 PRINTER_INFO_2 *printer=NULL;
2605 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2606 return ERROR_NOT_ENOUGH_MEMORY;
2608 fstrcpy(temp, "\\\\");
2609 fstrcat(temp, servername);
2610 construct_printer_info_2(temp, printer, snum);
2612 /* check the required size. */
2613 *needed += spoolss_size_printer_info_2(printer);
2615 if (!alloc_buffer_size(buffer, *needed)) {
2616 free_printer_info_2(printer);
2617 return ERROR_INSUFFICIENT_BUFFER;
2620 /* fill the buffer with the structures */
2621 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2622 free_printer_info_2(printer);
2623 return ERROR_NOT_ENOUGH_MEMORY;
2627 free_printer_info_2(printer);
2629 if (*needed > offered) {
2630 return ERROR_INSUFFICIENT_BUFFER;
2633 return NT_STATUS_NO_PROBLEMO;
2636 /****************************************************************************
2637 ****************************************************************************/
2638 static uint32 getprinter_level_3(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2640 PRINTER_INFO_3 *printer=NULL;
2643 fstrcpy(temp, "\\\\");
2644 fstrcat(temp, servername);
2645 if (!construct_printer_info_3(temp, &printer, snum))
2646 return ERROR_NOT_ENOUGH_MEMORY;
2648 /* check the required size. */
2649 *needed += spoolss_size_printer_info_3(printer);
2651 if (!alloc_buffer_size(buffer, *needed)) {
2652 free_printer_info_3(printer);
2653 return ERROR_INSUFFICIENT_BUFFER;
2656 /* fill the buffer with the structures */
2657 new_smb_io_printer_info_3("", buffer, printer, 0);
2660 free_printer_info_3(printer);
2662 if (*needed > offered) {
2663 return ERROR_INSUFFICIENT_BUFFER;
2666 return NT_STATUS_NO_PROBLEMO;
2669 /****************************************************************************
2670 ****************************************************************************/
2671 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2672 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2679 pstrcpy(servername, global_myname);
2681 if (!get_printer_snum(handle, &snum))
2682 return ERROR_INVALID_HANDLE;
2686 return getprinter_level_0(servername, snum, buffer, offered, needed);
2688 return getprinter_level_1(servername,snum, buffer, offered, needed);
2690 return getprinter_level_2(servername,snum, buffer, offered, needed);
2692 return getprinter_level_3(servername,snum, buffer, offered, needed);
2694 return ERROR_INVALID_LEVEL;
2698 /********************************************************************
2699 * fill a DRIVER_INFO_1 struct
2700 ********************************************************************/
2701 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2703 init_unistr( &info->name, driver.info_3->name);
2706 /********************************************************************
2707 * construct_printer_driver_info_1
2708 ********************************************************************/
2709 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2711 NT_PRINTER_INFO_LEVEL *printer = NULL;
2712 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2714 ZERO_STRUCT(driver);
2716 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2717 return ERROR_INVALID_PRINTER_NAME;
2719 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2720 return ERROR_UNKNOWN_PRINTER_DRIVER;
2722 fill_printer_driver_info_1(info, driver, servername, architecture);
2724 free_a_printer(&printer,2);
2726 return NT_STATUS_NO_PROBLEMO;
2729 /********************************************************************
2730 * construct_printer_driver_info_2
2731 * fill a printer_info_2 struct
2732 ********************************************************************/
2733 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2735 pstring temp_driverpath;
2736 pstring temp_datafile;
2737 pstring temp_configfile;
2739 info->version=driver.info_3->cversion;
2741 init_unistr( &info->name, driver.info_3->name );
2742 init_unistr( &info->architecture, driver.info_3->environment );
2744 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2745 init_unistr( &info->driverpath, temp_driverpath );
2747 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2748 init_unistr( &info->datafile, temp_datafile );
2750 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2751 init_unistr( &info->configfile, temp_configfile );
2754 /********************************************************************
2755 * construct_printer_driver_info_2
2756 * fill a printer_info_2 struct
2757 ********************************************************************/
2758 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2760 NT_PRINTER_INFO_LEVEL *printer = NULL;
2761 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2763 ZERO_STRUCT(printer);
2764 ZERO_STRUCT(driver);
2766 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2767 return ERROR_INVALID_PRINTER_NAME;
2769 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2770 return ERROR_UNKNOWN_PRINTER_DRIVER;
2772 fill_printer_driver_info_2(info, driver, servername);
2774 free_a_printer(&printer,2);
2776 return NT_STATUS_NO_PROBLEMO;
2779 /********************************************************************
2780 * copy a strings array and convert to UNICODE
2782 * convert an array of ascii string to a UNICODE string
2783 ********************************************************************/
2784 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2791 DEBUG(6,("init_unistr_array\n"));
2795 if (char_array == NULL)
2799 if (!v) v = ""; /* hack to handle null lists */
2801 if (strlen(v) == 0) break;
2802 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2803 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2804 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2805 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2808 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2813 (*uni_array)[j]=0x0000;
2816 DEBUGADD(6,("last one:done\n"));
2819 /********************************************************************
2820 * construct_printer_info_3
2821 * fill a printer_info_3 struct
2822 ********************************************************************/
2823 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2825 pstring temp_driverpath;
2826 pstring temp_datafile;
2827 pstring temp_configfile;
2828 pstring temp_helpfile;
2832 info->version=driver.info_3->cversion;
2834 init_unistr( &info->name, driver.info_3->name );
2835 init_unistr( &info->architecture, driver.info_3->environment );
2837 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2838 init_unistr( &info->driverpath, temp_driverpath );
2840 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2841 init_unistr( &info->datafile, temp_datafile );
2843 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2844 init_unistr( &info->configfile, temp_configfile );
2846 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2847 init_unistr( &info->helpfile, temp_helpfile );
2849 init_unistr( &info->monitorname, driver.info_3->monitorname );
2850 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2852 info->dependentfiles=NULL;
2853 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2856 /********************************************************************
2857 * construct_printer_info_3
2858 * fill a printer_info_3 struct
2859 ********************************************************************/
2860 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2862 NT_PRINTER_INFO_LEVEL *printer = NULL;
2863 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2865 ZERO_STRUCT(driver);
2867 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2868 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2870 return ERROR_INVALID_PRINTER_NAME;
2872 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2873 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2875 free_a_printer(&printer,2);
2876 return ERROR_UNKNOWN_PRINTER_DRIVER;
2879 fill_printer_driver_info_3(info, driver, servername);
2881 free_a_printer(&printer,2);
2883 return NT_STATUS_NO_PROBLEMO;
2886 /********************************************************************
2887 * construct_printer_info_6
2888 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2889 ********************************************************************/
2891 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2893 pstring temp_driverpath;
2894 pstring temp_datafile;
2895 pstring temp_configfile;
2896 pstring temp_helpfile;
2900 memset(&nullstr, '\0', sizeof(fstring));
2902 info->version=driver.info_3->cversion;
2904 init_unistr( &info->name, driver.info_3->name );
2905 init_unistr( &info->architecture, driver.info_3->environment );
2907 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2908 init_unistr( &info->driverpath, temp_driverpath );
2910 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2911 init_unistr( &info->datafile, temp_datafile );
2913 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2914 init_unistr( &info->configfile, temp_configfile );
2916 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2917 init_unistr( &info->helpfile, temp_helpfile );
2919 init_unistr( &info->monitorname, driver.info_3->monitorname );
2920 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2922 info->dependentfiles=NULL;
2923 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2925 info->previousdrivernames=NULL;
2926 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2928 info->driver_date.low=0;
2929 info->driver_date.high=0;
2932 info->driver_version_low=0;
2933 info->driver_version_high=0;
2935 init_unistr( &info->mfgname, "");
2936 init_unistr( &info->oem_url, "");
2937 init_unistr( &info->hardware_id, "");
2938 init_unistr( &info->provider, "");
2941 /********************************************************************
2942 * construct_printer_info_6
2943 * fill a printer_info_6 struct
2944 ********************************************************************/
2945 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2947 NT_PRINTER_INFO_LEVEL *printer = NULL;
2948 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2950 ZERO_STRUCT(driver);
2952 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2953 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2955 return ERROR_INVALID_PRINTER_NAME;
2957 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2958 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2960 free_a_printer(&printer,2);
2961 return ERROR_UNKNOWN_PRINTER_DRIVER;
2964 fill_printer_driver_info_6(info, driver, servername);
2966 free_a_printer(&printer,2);
2968 return NT_STATUS_NO_PROBLEMO;
2971 /****************************************************************************
2972 ****************************************************************************/
2974 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2976 safe_free(info->dependentfiles);
2979 /****************************************************************************
2980 ****************************************************************************/
2982 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2984 safe_free(info->dependentfiles);
2988 /****************************************************************************
2989 ****************************************************************************/
2990 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2992 DRIVER_INFO_1 *info=NULL;
2995 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2996 return ERROR_NOT_ENOUGH_MEMORY;
2998 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2999 if (status != NT_STATUS_NO_PROBLEMO) {
3004 /* check the required size. */
3005 *needed += spoolss_size_printer_driver_info_1(info);
3007 if (!alloc_buffer_size(buffer, *needed)) {
3009 return ERROR_INSUFFICIENT_BUFFER;
3012 /* fill the buffer with the structures */
3013 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3018 if (*needed > offered)
3019 return ERROR_INSUFFICIENT_BUFFER;
3021 return NT_STATUS_NO_PROBLEMO;
3024 /****************************************************************************
3025 ****************************************************************************/
3026 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3028 DRIVER_INFO_2 *info=NULL;
3031 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3032 return ERROR_NOT_ENOUGH_MEMORY;
3034 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3035 if (status != NT_STATUS_NO_PROBLEMO) {
3040 /* check the required size. */
3041 *needed += spoolss_size_printer_driver_info_2(info);
3043 if (!alloc_buffer_size(buffer, *needed)) {
3045 return ERROR_INSUFFICIENT_BUFFER;
3048 /* fill the buffer with the structures */
3049 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3054 if (*needed > offered)
3055 return ERROR_INSUFFICIENT_BUFFER;
3057 return NT_STATUS_NO_PROBLEMO;
3060 /****************************************************************************
3061 ****************************************************************************/
3062 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3069 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3070 if (status != NT_STATUS_NO_PROBLEMO) {
3074 /* check the required size. */
3075 *needed += spoolss_size_printer_driver_info_3(&info);
3077 if (!alloc_buffer_size(buffer, *needed)) {
3078 free_printer_driver_info_3(&info);
3079 return ERROR_INSUFFICIENT_BUFFER;
3082 /* fill the buffer with the structures */
3083 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3085 free_printer_driver_info_3(&info);
3087 if (*needed > offered)
3088 return ERROR_INSUFFICIENT_BUFFER;
3090 return NT_STATUS_NO_PROBLEMO;
3093 /****************************************************************************
3094 ****************************************************************************/
3095 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3102 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3103 if (status != NT_STATUS_NO_PROBLEMO) {
3107 /* check the required size. */
3108 *needed += spoolss_size_printer_driver_info_6(&info);
3110 if (!alloc_buffer_size(buffer, *needed)) {
3111 free_printer_driver_info_6(&info);
3112 return ERROR_INSUFFICIENT_BUFFER;
3115 /* fill the buffer with the structures */
3116 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3118 free_printer_driver_info_6(&info);
3120 if (*needed > offered)
3121 return ERROR_INSUFFICIENT_BUFFER;
3123 return NT_STATUS_NO_PROBLEMO;
3126 /****************************************************************************
3127 ****************************************************************************/
3128 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3129 uint32 clientmajorversion, uint32 clientminorversion,
3130 NEW_BUFFER *buffer, uint32 offered,
3131 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3134 fstring architecture;
3137 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3140 *servermajorversion=0;
3141 *serverminorversion=0;
3143 pstrcpy(servername, global_myname);
3144 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3146 if (!get_printer_snum(handle, &snum))
3147 return ERROR_INVALID_HANDLE;
3151 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3153 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3155 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3157 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3159 return ERROR_INVALID_LEVEL;
3163 /****************************************************************************
3164 ****************************************************************************/
3165 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3167 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3169 if (OPEN_HANDLE(Printer)) {
3170 Printer->page_started=True;
3174 DEBUG(3,("Error in startpageprinter printer handle\n"));
3175 return ERROR_INVALID_HANDLE;
3178 /****************************************************************************
3179 ****************************************************************************/
3180 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3182 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3184 if (!OPEN_HANDLE(Printer)) {
3185 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3186 return ERROR_INVALID_HANDLE;
3189 Printer->page_started=False;
3191 return NT_STATUS_NO_PROBLEMO;
3194 /****************************************************************************
3195 Return a user struct for a pipe user.
3196 ****************************************************************************/
3198 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3200 if (p->ntlmssp_auth_validated) {
3201 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3203 extern struct current_user current_user;
3204 memcpy(user, ¤t_user, sizeof(struct current_user));
3210 /********************************************************************
3211 * api_spoolss_getprinter
3212 * called from the spoolss dispatcher
3214 ********************************************************************/
3215 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3216 pipes_struct *p, DOC_INFO *docinfo,
3219 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3223 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3224 struct current_user user;
3226 if (!OPEN_HANDLE(Printer)) {
3227 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3228 return ERROR_INVALID_HANDLE;
3231 get_current_user(&user, p);
3234 * a nice thing with NT is it doesn't listen to what you tell it.
3235 * when asked to send _only_ RAW datas, it tries to send datas
3238 * So I add checks like in NT Server ...
3240 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3241 * there's a bug in NT client-side code, so we'll fix it in the
3242 * server-side code. *nnnnnggggh!*
3245 if (info_1->p_datatype != 0) {
3246 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3247 if (strcmp(datatype, "RAW") != 0) {
3249 return ERROR_INVALID_DATATYPE;
3253 /* get the share number of the printer */
3254 if (!get_printer_snum(handle, &snum)) {
3255 return ERROR_INVALID_HANDLE;
3258 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3260 Printer->jobid = print_job_start(&user, snum, jobname);
3262 /* An error occured in print_job_start() so return an appropriate
3265 if (Printer->jobid == -1) {
3266 return map_nt_error_from_unix(errno);
3269 Printer->document_started=True;
3270 (*jobid) = Printer->jobid;
3272 srv_spoolss_sendnotify(handle);
3276 /********************************************************************
3277 * api_spoolss_getprinter
3278 * called from the spoolss dispatcher
3280 ********************************************************************/
3281 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3283 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3285 if (!OPEN_HANDLE(Printer)) {
3286 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3287 return ERROR_INVALID_HANDLE;
3290 Printer->document_started=False;
3291 print_job_end(Printer->jobid);
3292 /* error codes unhandled so far ... */
3294 srv_spoolss_sendnotify(handle);
3299 /****************************************************************************
3300 ****************************************************************************/
3301 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3304 uint32 *buffer_written)
3306 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3308 if (!OPEN_HANDLE(Printer)) {
3309 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3310 return ERROR_INVALID_HANDLE;
3313 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3319 /********************************************************************
3320 * api_spoolss_getprinter
3321 * called from the spoolss dispatcher
3323 ********************************************************************/
3324 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3327 struct current_user user;
3328 int snum, errcode = ERROR_INVALID_FUNCTION;
3329 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3331 get_current_user(&user, p);
3333 if (!OPEN_HANDLE(Printer)) {
3334 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3335 return ERROR_INVALID_HANDLE;
3338 if (!get_printer_snum(handle, &snum))
3339 return ERROR_INVALID_HANDLE;
3342 case PRINTER_CONTROL_PAUSE:
3343 if (print_queue_pause(&user, snum, &errcode)) {
3347 case PRINTER_CONTROL_RESUME:
3348 case PRINTER_CONTROL_UNPAUSE:
3349 if (print_queue_resume(&user, snum, &errcode)) {
3353 case PRINTER_CONTROL_PURGE:
3354 if (print_queue_purge(&user, snum, &errcode)) {
3359 return ERROR_INVALID_LEVEL;
3365 /********************************************************************
3366 * api_spoolss_abortprinter
3367 ********************************************************************/
3369 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3371 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3374 /********************************************************************
3375 * called by spoolss_api_setprinter
3376 * when updating a printer description
3377 ********************************************************************/
3378 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3379 const SPOOL_PRINTER_INFO_LEVEL *info,
3380 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3382 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3383 struct current_user user;
3387 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3389 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3390 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3391 OUR_HANDLE(handle)));
3393 result = ERROR_INVALID_HANDLE;
3397 /* NT seems to like setting the security descriptor even though
3398 nothing may have actually changed. This causes annoying
3399 dialog boxes when the user doesn't have permission to change
3400 the security descriptor. */
3402 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3404 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3406 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3407 result = NT_STATUS_NO_PROBLEMO;
3411 /* Work out which user is performing the operation */
3413 get_current_user(&user, p);
3415 /* Check the user has permissions to change the security
3416 descriptor. By experimentation with two NT machines, the user
3417 requires Full Access to the printer to change security
3420 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3421 result = ERROR_ACCESS_DENIED;
3425 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3428 free_sec_desc_buf(&new_secdesc_ctr);
3429 free_sec_desc_buf(&old_secdesc_ctr);
3434 /********************************************************************
3435 Do Samba sanity checks on a printer info struct.
3436 ********************************************************************/
3438 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3441 * Ensure that this printer is shared under the correct name
3442 * as this is what Samba insists upon.
3445 if (!(info->attributes & (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_NETWORK))) {
3446 DEBUG(10,("check_printer_ok: SHARED/NETWORK check failed (%x).\n",
3447 (unsigned int)info->attributes ));
3451 if (!(info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY)) {
3452 /* NT forgets to set the raw attribute but sends the correct type. */
3453 if (strequal(info->datatype, "RAW"))
3454 info->attributes |= PRINTER_ATTRIBUTE_RAW_ONLY;
3456 DEBUG(10,("check_printer_ok: RAW check failed (%x).\n", (unsigned int)info->attributes ));
3462 * Sometimes the NT client doesn't set the sharename, but
3463 * includes the sharename in the printername. This could
3464 * cause SETPRINTER to fail which causes problems with the
3465 * client getting confused between local/remote printers...
3468 if (*info->sharename == '\0') {
3469 char *p = strrchr(info->printername, '\\');
3471 fstrcpy(info->sharename, p+1);
3474 if (!strequal(info->sharename, lp_servicename(snum))) {
3475 DEBUG(10,("check_printer_ok: NAME check failed (%s) (%s).\n",
3476 info->sharename, lp_servicename(snum)));
3483 /****************************************************************************
3484 ****************************************************************************/
3485 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3487 pid_t local_pid = sys_getpid();
3488 char *cmd = lp_addprinter_cmd();
3493 pstring driverlocation;
3497 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3498 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3502 /* build driver path... only 9X architecture is needed for legacy reasons */
3503 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3505 /* change \ to \\ for the shell */
3506 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3508 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3509 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3510 cmd, printer->info_2->printername, printer->info_2->sharename,
3511 printer->info_2->portname, printer->info_2->drivername,
3512 printer->info_2->location, driverlocation);
3515 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3516 ret = smbrun(command, tmp_file, False);
3517 DEBUGADD(10,("returned [%d]\n", ret));
3525 qlines = file_lines_load(tmp_file, &numlines);
3526 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3527 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3531 /* Set the portname to what the script says the portname should be. */
3532 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3533 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3535 /* Send SIGHUP to process group... is there a better way? */
3540 file_lines_free(qlines);
3544 /* Return true if two devicemodes are equal */
3546 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3548 if (!strequal(d1->devicename, d2->devicename) ||
3549 !strequal(d1->formname, d2->formname)) {
3553 if (d1->specversion != d2->specversion ||
3554 d1->driverversion != d2->driverversion ||
3555 d1->size != d2->size ||
3556 d1->driverextra != d2->driverextra ||
3557 d1->orientation != d2->orientation ||
3558 d1->papersize != d2->papersize ||
3559 d1->paperlength != d2->paperlength ||
3560 d1->paperwidth != d2->paperwidth ||
3561 d1->scale != d2->scale ||
3562 d1->copies != d2->copies ||
3563 d1->defaultsource != d2->defaultsource ||
3564 d1->printquality != d2->printquality ||
3565 d1->color != d2->color ||
3566 d1->duplex != d2->duplex ||
3567 d1->yresolution != d2->yresolution ||
3568 d1->ttoption != d2->ttoption ||
3569 d1->collate != d2->collate ||
3570 d1->logpixels != d2->logpixels) {
3574 if (d1->fields != d2->fields ||
3575 d1->bitsperpel != d2->bitsperpel ||
3576 d1->pelswidth != d2->pelswidth ||
3577 d1->pelsheight != d2->pelsheight ||
3578 d1->displayflags != d2->displayflags ||
3579 d1->displayfrequency != d2->displayfrequency ||
3580 d1->icmmethod != d2->icmmethod ||
3581 d1->icmintent != d2->icmintent ||
3582 d1->mediatype != d2->mediatype ||
3583 d1->dithertype != d2->dithertype ||
3584 d1->reserved1 != d2->reserved1 ||
3585 d1->reserved2 != d2->reserved2 ||
3586 d1->panningwidth != d2->panningwidth ||
3587 d1->panningheight != d2->panningheight) {
3591 /* Not sure what to do about these fields */
3599 /* Return true if two NT_PRINTER_PARAM structures are equal */
3601 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3602 NT_PRINTER_PARAM *p2)
3604 if (!p1 && !p2) return True;
3606 if ((!p1 && p2) || (p1 && !p2)) return False;
3608 /* Compare lists of printer parameters */
3612 NT_PRINTER_PARAM *q = p1;
3614 /* Find the parameter in the second structure */
3618 if (strequal(p1->value, q->value) &&
3619 p1->type == q->type &&
3620 p1->data_len == q->data_len &&
3621 memcmp(p1->data, q->data, p1->data_len) == 0) {
3640 /********************************************************************
3641 * Called by update_printer when trying to work out whether to
3642 * actually update printer info.
3643 ********************************************************************/
3645 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3646 NT_PRINTER_INFO_LEVEL *p2)
3648 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3650 /* Trivial conditions */
3652 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3656 if ((!p1 && p2) || (p1 && !p2) ||
3657 (!p1->info_2 && p2->info_2) ||
3658 (p1->info_2 && !p2->info_2)) {
3662 /* Compare two nt_printer_info_level structures. Don't compare
3663 status or cjobs as they seem to have something to do with the
3669 if (pi1->attributes != pi2->attributes ||
3670 pi1->priority != pi2->priority ||
3671 pi1->default_priority != pi2->default_priority ||
3672 pi1->starttime != pi2->starttime ||
3673 pi1->untiltime != pi2->untiltime ||
3674 pi1->averageppm != pi2->averageppm) {
3678 /* Yuck - don't check the printername or servername as the
3679 add_a_printer() code plays games with them. You can't
3680 change the printername or the sharename through this interface
3683 if (!strequal(pi1->sharename, pi2->sharename) ||
3684 !strequal(pi1->portname, pi2->portname) ||
3685 !strequal(pi1->drivername, pi2->drivername) ||
3686 !strequal(pi1->comment, pi2->comment) ||
3687 !strequal(pi1->location, pi2->location)) {
3691 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3695 if (!strequal(pi1->sepfile, pi2->sepfile) ||
3696 !strequal(pi1->printprocessor, pi2->printprocessor) ||
3697 !strequal(pi1->datatype, pi2->datatype) ||
3698 !strequal(pi1->parameters, pi2->parameters)) {
3702 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3706 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3710 if (pi1->changeid != pi2->changeid ||
3711 pi1->c_setprinter != pi2->c_setprinter ||
3712 pi1->setuptime != pi2->setuptime) {
3719 /********************************************************************
3720 * called by spoolss_api_setprinter
3721 * when updating a printer description
3722 ********************************************************************/
3724 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3725 const SPOOL_PRINTER_INFO_LEVEL *info,
3726 DEVICEMODE *devmode)
3729 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3730 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3733 DEBUG(8,("update_printer\n"));
3735 result = NT_STATUS_NO_PROBLEMO;
3738 DEBUG(0,("Send a mail to samba@samba.org\n"));
3739 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3740 result = ERROR_INVALID_LEVEL;
3744 if (!OPEN_HANDLE(Printer)) {
3745 result = ERROR_INVALID_HANDLE;
3749 if (!get_printer_snum(handle, &snum)) {
3750 result = ERROR_INVALID_HANDLE;
3754 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3755 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3756 result = ERROR_INVALID_HANDLE;
3760 DEBUGADD(8,("Converting info_2 struct\n"));
3763 * convert_printer_info converts the incoming
3764 * info from the client and overwrites the info
3765 * just read from the tdb in the pointer 'printer'.
3768 convert_printer_info(info, printer, level);
3770 if (info->info_2->devmode_ptr != 0) {
3771 /* we have a valid devmode
3772 convert it and link it*/
3775 * Ensure printer->info_2->devmode is a valid pointer
3776 * as we will be overwriting it in convert_devicemode().
3779 if (printer->info_2->devmode == NULL)
3780 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3782 DEBUGADD(8,("Converting the devicemode struct\n"));
3783 convert_devicemode(devmode, printer->info_2->devmode);
3786 if (printer->info_2->devmode != NULL)
3787 free_nt_devicemode(&printer->info_2->devmode);
3788 printer->info_2->devmode=NULL;
3791 /* Do sanity check on the requested changes for Samba */
3793 if (!check_printer_ok(printer->info_2, snum)) {
3794 result = ERROR_INVALID_PARAMETER;
3798 /* NT likes to call this function even though nothing has actually
3799 changed. Check this so the user doesn't end up with an
3800 annoying permission denied dialog box. */
3802 if (nt_printer_info_level_equal(printer, old_printer)) {
3803 DEBUG(3, ("printer info has not changed\n"));
3804 result = NT_STATUS_NO_PROBLEMO;
3808 /* Check calling user has permission to update printer description */
3810 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3811 DEBUG(3, ("printer property change denied by security "
3813 result = ERROR_ACCESS_DENIED;
3817 /* Call addprinter hook */
3819 if (*lp_addprinter_cmd() )
3820 if ( !add_printer_hook(printer) ) {
3821 result = ERROR_ACCESS_DENIED;
3825 /* Update printer info */
3827 if (add_a_printer(*printer, 2)!=0) {
3828 /* I don't really know what to return here !!! */
3829 result = ERROR_ACCESS_DENIED;
3834 free_a_printer(&printer, 2);
3835 free_a_printer(&old_printer, 2);
3837 srv_spoolss_sendnotify(handle);
3842 /****************************************************************************
3843 ****************************************************************************/
3844 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3845 const SPOOL_PRINTER_INFO_LEVEL *info,
3846 DEVMODE_CTR devmode_ctr,
3847 SEC_DESC_BUF *secdesc_ctr,
3848 uint32 command, pipes_struct *p)
3850 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3852 if (!OPEN_HANDLE(Printer)) {
3853 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3854 return ERROR_INVALID_HANDLE;
3857 /* check the level */
3860 return control_printer(handle, command, p);
3862 return update_printer(handle, level, info, devmode_ctr.devmode);
3864 return update_printer_sec(handle, level, info, p,
3867 return ERROR_INVALID_LEVEL;
3871 /****************************************************************************
3872 ****************************************************************************/
3873 uint32 _spoolss_fcpn(POLICY_HND *handle)
3875 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3877 if (!OPEN_HANDLE(Printer)) {
3878 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3879 return ERROR_INVALID_HANDLE;
3882 if (Printer->notify.client_connected==True)
3883 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3884 return ERROR_INVALID_HANDLE;
3886 Printer->notify.flags=0;
3887 Printer->notify.options=0;
3888 Printer->notify.localmachine[0]='\0';
3889 Printer->notify.printerlocal=0;
3890 if (Printer->notify.option)
3891 safe_free(Printer->notify.option->ctr.type);
3892 safe_free(Printer->notify.option);
3893 Printer->notify.option=NULL;
3894 Printer->notify.client_connected=False;
3896 return NT_STATUS_NO_PROBLEMO;
3899 /****************************************************************************
3900 ****************************************************************************/
3901 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3902 NEW_BUFFER *buffer, uint32 offered,
3906 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3907 returns for AddJob. AddJob
3908 must fail on non-local
3912 /****************************************************************************
3913 ****************************************************************************/
3914 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3915 int position, int snum)
3921 t=gmtime(&queue->time);
3922 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3924 job_info->jobid=queue->job;
3925 init_unistr(&job_info->printername, lp_servicename(snum));
3926 init_unistr(&job_info->machinename, temp_name);
3927 init_unistr(&job_info->username, queue->user);
3928 init_unistr(&job_info->document, queue->file);
3929 init_unistr(&job_info->datatype, "RAW");
3930 init_unistr(&job_info->text_status, "");
3931 job_info->status=nt_printj_status(queue->status);
3932 job_info->priority=queue->priority;
3933 job_info->position=position;
3934 job_info->totalpages=0;
3935 job_info->pagesprinted=0;
3937 make_systemtime(&job_info->submitted, t);
3940 /****************************************************************************
3941 ****************************************************************************/
3942 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3943 int position, int snum)
3946 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3950 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3953 t=gmtime(&queue->time);
3954 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3956 job_info->jobid=queue->job;
3958 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3960 init_unistr(&job_info->printername, chaine);
3962 init_unistr(&job_info->machinename, temp_name);
3963 init_unistr(&job_info->username, queue->user);
3964 init_unistr(&job_info->document, queue->file);
3965 init_unistr(&job_info->notifyname, queue->user);
3966 init_unistr(&job_info->datatype, "RAW");
3967 init_unistr(&job_info->printprocessor, "winprint");
3968 init_unistr(&job_info->parameters, "");
3969 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3970 init_unistr(&job_info->text_status, "");
3972 /* and here the security descriptor */
3974 job_info->status=nt_printj_status(queue->status);
3975 job_info->priority=queue->priority;
3976 job_info->position=position;
3977 job_info->starttime=0;
3978 job_info->untiltime=0;
3979 job_info->totalpages=0;
3980 job_info->size=queue->size;
3981 make_systemtime(&(job_info->submitted), t);
3982 job_info->timeelapsed=0;
3983 job_info->pagesprinted=0;
3985 if((job_info->devmode = construct_dev_mode(snum, global_myname)) == NULL) {
3986 free_a_printer(&ntprinter, 2);
3990 free_a_printer(&ntprinter, 2);
3994 /****************************************************************************
3995 Enumjobs at level 1.
3996 ****************************************************************************/
3997 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3998 NEW_BUFFER *buffer, uint32 offered,
3999 uint32 *needed, uint32 *returned)
4004 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4008 return ERROR_NOT_ENOUGH_MEMORY;
4011 for (i=0; i<*returned; i++)
4012 fill_job_info_1(&info[i], &queue[i], i, snum);
4016 /* check the required size. */
4017 for (i=0; i<*returned; i++)
4018 (*needed) += spoolss_size_job_info_1(&info[i]);
4020 if (!alloc_buffer_size(buffer, *needed)) {
4022 return ERROR_INSUFFICIENT_BUFFER;
4025 /* fill the buffer with the structures */
4026 for (i=0; i<*returned; i++)
4027 new_smb_io_job_info_1("", buffer, &info[i], 0);
4032 if (*needed > offered) {
4034 return ERROR_INSUFFICIENT_BUFFER;
4037 return NT_STATUS_NO_PROBLEMO;
4040 /****************************************************************************
4041 Enumjobs at level 2.
4042 ****************************************************************************/
4043 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4044 NEW_BUFFER *buffer, uint32 offered,
4045 uint32 *needed, uint32 *returned)
4050 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4054 return ERROR_NOT_ENOUGH_MEMORY;
4057 for (i=0; i<*returned; i++)
4058 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4062 /* check the required size. */
4063 for (i=0; i<*returned; i++)
4064 (*needed) += spoolss_size_job_info_2(&info[i]);
4066 if (!alloc_buffer_size(buffer, *needed)) {
4068 return ERROR_INSUFFICIENT_BUFFER;
4071 /* fill the buffer with the structures */
4072 for (i=0; i<*returned; i++)
4073 new_smb_io_job_info_2("", buffer, &info[i], 0);
4078 if (*needed > offered) {
4080 return ERROR_INSUFFICIENT_BUFFER;
4083 return NT_STATUS_NO_PROBLEMO;
4086 /****************************************************************************
4088 ****************************************************************************/
4089 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4090 NEW_BUFFER *buffer, uint32 offered,
4091 uint32 *needed, uint32 *returned)
4094 print_queue_struct *queue=NULL;
4095 print_status_struct prt_status;
4097 DEBUG(4,("_spoolss_enumjobs\n"));
4099 ZERO_STRUCT(prt_status);
4104 if (!get_printer_snum(handle, &snum))
4105 return ERROR_INVALID_HANDLE;
4107 *returned = print_queue_status(snum, &queue, &prt_status);
4108 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4110 if (*returned == 0) {
4112 return NT_STATUS_NO_PROBLEMO;
4117 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4119 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4123 return ERROR_INVALID_LEVEL;
4128 /****************************************************************************
4129 ****************************************************************************/
4130 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4135 /****************************************************************************
4136 ****************************************************************************/
4137 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4138 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4140 struct current_user user;
4141 print_status_struct prt_status;
4142 int snum, errcode = ERROR_INVALID_FUNCTION;
4144 memset(&prt_status, 0, sizeof(prt_status));
4146 if (!get_printer_snum(handle, &snum)) {
4147 return ERROR_INVALID_HANDLE;
4150 if (!print_job_exists(jobid)) {
4151 return ERROR_INVALID_PRINTER_NAME;
4154 get_current_user(&user, p);
4157 case JOB_CONTROL_CANCEL:
4158 case JOB_CONTROL_DELETE:
4159 if (print_job_delete(&user, jobid, &errcode)) {
4163 case JOB_CONTROL_PAUSE:
4164 if (print_job_pause(&user, jobid, &errcode)) {
4168 case JOB_CONTROL_RESTART:
4169 case JOB_CONTROL_RESUME:
4170 if (print_job_resume(&user, jobid, &errcode)) {
4175 return ERROR_INVALID_LEVEL;
4181 /****************************************************************************
4182 Enumerates all printer drivers at level 1.
4183 ****************************************************************************/
4184 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4189 fstring *list = NULL;
4191 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4192 DRIVER_INFO_1 *driver_info_1=NULL;
4196 #define MAX_VERSION 4
4198 for (version=0; version<MAX_VERSION; version++) {
4200 ndrivers=get_ntdrivers(&list, architecture, version);
4201 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4204 return ERROR_NOT_ENOUGH_MEMORY;
4207 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4209 return ERROR_NOT_ENOUGH_MEMORY;
4213 for (i=0; i<ndrivers; i++) {
4215 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4216 ZERO_STRUCT(driver);
4217 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4221 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4222 free_a_printer_driver(driver, 3);
4225 *returned+=ndrivers;
4229 /* check the required size. */
4230 for (i=0; i<*returned; i++) {
4231 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4232 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4235 if (!alloc_buffer_size(buffer, *needed)) {
4236 safe_free(driver_info_1);
4237 return ERROR_INSUFFICIENT_BUFFER;
4240 /* fill the buffer with the form structures */
4241 for (i=0; i<*returned; i++) {
4242 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4243 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4246 safe_free(driver_info_1);
4248 if (*needed > offered) {
4250 return ERROR_INSUFFICIENT_BUFFER;
4253 return NT_STATUS_NO_PROBLEMO;
4256 /****************************************************************************
4257 Enumerates all printer drivers at level 2.
4258 ****************************************************************************/
4259 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4264 fstring *list = NULL;
4266 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4267 DRIVER_INFO_2 *driver_info_2=NULL;
4271 #define MAX_VERSION 4
4273 for (version=0; version<MAX_VERSION; version++) {
4275 ndrivers=get_ntdrivers(&list, architecture, version);
4276 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4279 return ERROR_NOT_ENOUGH_MEMORY;
4282 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4284 return ERROR_NOT_ENOUGH_MEMORY;
4288 for (i=0; i<ndrivers; i++) {
4291 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4292 ZERO_STRUCT(driver);
4293 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4297 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4298 free_a_printer_driver(driver, 3);
4301 *returned+=ndrivers;
4305 /* check the required size. */
4306 for (i=0; i<*returned; i++) {
4307 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4308 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4311 if (!alloc_buffer_size(buffer, *needed)) {
4312 safe_free(driver_info_2);
4313 return ERROR_INSUFFICIENT_BUFFER;
4316 /* fill the buffer with the form structures */
4317 for (i=0; i<*returned; i++) {
4318 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4319 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4322 safe_free(driver_info_2);
4324 if (*needed > offered) {
4326 return ERROR_INSUFFICIENT_BUFFER;
4329 return NT_STATUS_NO_PROBLEMO;
4332 /****************************************************************************
4333 Enumerates all printer drivers at level 3.
4334 ****************************************************************************/
4335 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4340 fstring *list = NULL;
4342 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4343 DRIVER_INFO_3 *driver_info_3=NULL;
4347 #define MAX_VERSION 4
4349 for (version=0; version<MAX_VERSION; version++) {
4351 ndrivers=get_ntdrivers(&list, architecture, version);
4352 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4355 return ERROR_NOT_ENOUGH_MEMORY;
4358 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4360 return ERROR_NOT_ENOUGH_MEMORY;
4364 for (i=0; i<ndrivers; i++) {
4367 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4368 ZERO_STRUCT(driver);
4369 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4373 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4374 free_a_printer_driver(driver, 3);
4377 *returned+=ndrivers;
4381 /* check the required size. */
4382 for (i=0; i<*returned; i++) {
4383 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4384 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4387 if (!alloc_buffer_size(buffer, *needed)) {
4388 safe_free(driver_info_3);
4389 return ERROR_INSUFFICIENT_BUFFER;
4392 /* fill the buffer with the driver structures */
4393 for (i=0; i<*returned; i++) {
4394 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4395 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4398 for (i=0; i<*returned; i++)
4399 safe_free(driver_info_3[i].dependentfiles);
4401 safe_free(driver_info_3);
4403 if (*needed > offered) {
4405 return ERROR_INSUFFICIENT_BUFFER;
4408 return NT_STATUS_NO_PROBLEMO;
4411 /****************************************************************************
4412 Enumerates all printer drivers.
4413 ****************************************************************************/
4414 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4415 NEW_BUFFER *buffer, uint32 offered,
4416 uint32 *needed, uint32 *returned)
4418 fstring *list = NULL;
4420 fstring architecture;
4422 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4423 fstrcpy(servername, global_myname);
4427 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4431 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4433 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4435 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4439 return ERROR_INVALID_LEVEL;
4443 /****************************************************************************
4444 ****************************************************************************/
4445 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4447 form->flag=list->flag;
4448 init_unistr(&form->name, list->name);
4449 form->width=list->width;
4450 form->length=list->length;
4451 form->left=list->left;
4452 form->top=list->top;
4453 form->right=list->right;
4454 form->bottom=list->bottom;
4457 /****************************************************************************
4458 ****************************************************************************/
4459 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4460 NEW_BUFFER *buffer, uint32 offered,
4461 uint32 *needed, uint32 *numofforms)
4463 nt_forms_struct *list=NULL;
4468 DEBUG(4,("_new_spoolss_enumforms\n"));
4469 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4470 DEBUGADD(5,("Info level [%d]\n", level));
4472 *numofforms = get_ntforms(&list);
4473 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4475 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4479 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4481 return ERROR_NOT_ENOUGH_MEMORY;
4484 /* construct the list of form structures */
4485 for (i=0; i<*numofforms; i++) {
4486 DEBUGADD(6,("Filling form number [%d]\n",i));
4487 fill_form_1(&forms_1[i], &list[i]);
4492 /* check the required size. */
4493 for (i=0; i<*numofforms; i++) {
4494 DEBUGADD(6,("adding form [%d]'s size\n",i));
4495 buffer_size += spoolss_size_form_1(&forms_1[i]);
4498 *needed=buffer_size;
4500 if (!alloc_buffer_size(buffer, buffer_size)){
4502 return ERROR_INSUFFICIENT_BUFFER;
4505 /* fill the buffer with the form structures */
4506 for (i=0; i<*numofforms; i++) {
4507 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4508 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4513 if (*needed > offered) {
4515 return ERROR_INSUFFICIENT_BUFFER;
4518 return NT_STATUS_NO_PROBLEMO;
4522 return ERROR_INVALID_LEVEL;
4527 /****************************************************************************
4528 ****************************************************************************/
4529 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4531 nt_forms_struct *list=NULL;
4537 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4539 DEBUG(4,("_spoolss_getform\n"));
4540 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4541 DEBUGADD(5,("Info level [%d]\n", level));
4543 numofforms = get_ntforms(&list);
4544 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4546 if (numofforms == 0)
4547 return ERROR_NO_MORE_ITEMS;
4552 /* Check if the requested name is in the list of form structures */
4553 for (i=0; i<numofforms; i++) {
4555 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4557 if (strequal(form_name, list[i].name)) {
4558 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4559 fill_form_1(&form_1, &list[i]);
4566 /* check the required size. */
4568 *needed=spoolss_size_form_1(&form_1);
4570 if (!alloc_buffer_size(buffer, buffer_size)){
4571 return ERROR_INSUFFICIENT_BUFFER;
4574 if (*needed > offered) {
4575 return ERROR_INSUFFICIENT_BUFFER;
4578 /* fill the buffer with the form structures */
4579 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4580 new_smb_io_form_1("", buffer, &form_1, 0);
4582 return NT_STATUS_NO_PROBLEMO;
4586 return ERROR_INVALID_LEVEL;
4590 /****************************************************************************
4591 ****************************************************************************/
4592 static void fill_port_1(PORT_INFO_1 *port, char *name)
4594 init_unistr(&port->port_name, name);
4597 /****************************************************************************
4598 ****************************************************************************/
4599 static void fill_port_2(PORT_INFO_2 *port, char *name)
4601 init_unistr(&port->port_name, name);
4602 init_unistr(&port->monitor_name, "Local Monitor");
4603 init_unistr(&port->description, "Local Port");
4604 #define PORT_TYPE_WRITE 1
4605 port->port_type=PORT_TYPE_WRITE;
4609 /****************************************************************************
4611 ****************************************************************************/
4612 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4614 PORT_INFO_1 *ports=NULL;
4617 if (*lp_enumports_cmd()) {
4618 pid_t local_pid = sys_getpid();
4619 char *cmd = lp_enumports_cmd();
4627 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4628 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4632 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4633 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4636 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4637 ret = smbrun(command, tmp_file, False);
4638 DEBUG(10,("Returned [%d]\n", ret));
4641 /* Is this the best error to return here? */
4642 return ERROR_ACCESS_DENIED;
4646 qlines = file_lines_load(tmp_file, &numlines);
4647 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4648 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4652 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4653 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4654 file_lines_free(qlines);
4655 return ERROR_NOT_ENOUGH_MEMORY;
4658 for (i=0; i<numlines; i++) {
4659 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4660 fill_port_1(&ports[i], qlines[i]);
4663 file_lines_free(qlines);
4666 *returned = numlines;
4669 *returned = 1; /* Sole Samba port returned. */
4671 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4672 return ERROR_NOT_ENOUGH_MEMORY;
4674 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4676 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4679 /* check the required size. */
4680 for (i=0; i<*returned; i++) {
4681 DEBUGADD(6,("adding port [%d]'s size\n", i));
4682 *needed += spoolss_size_port_info_1(&ports[i]);
4685 if (!alloc_buffer_size(buffer, *needed)) {
4687 return ERROR_INSUFFICIENT_BUFFER;
4690 /* fill the buffer with the ports structures */
4691 for (i=0; i<*returned; i++) {
4692 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4693 new_smb_io_port_1("", buffer, &ports[i], 0);
4698 if (*needed > offered) {
4700 return ERROR_INSUFFICIENT_BUFFER;
4703 return NT_STATUS_NO_PROBLEMO;
4706 /****************************************************************************
4708 ****************************************************************************/
4710 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4712 PORT_INFO_2 *ports=NULL;
4715 if (*lp_enumports_cmd()) {
4716 pid_t local_pid = sys_getpid();
4717 char *cmd = lp_enumports_cmd();
4725 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4726 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4730 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4731 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4734 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4735 ret = smbrun(command, tmp_file, False);
4736 DEBUGADD(10,("returned [%d]\n", ret));
4739 /* Is this the best error to return here? */
4740 return ERROR_ACCESS_DENIED;
4744 qlines = file_lines_load(tmp_file, &numlines);
4745 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4746 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4750 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4751 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4752 file_lines_free(qlines);
4753 return ERROR_NOT_ENOUGH_MEMORY;
4756 for (i=0; i<numlines; i++) {
4757 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4758 fill_port_2(&(ports[i]), qlines[i]);
4761 file_lines_free(qlines);
4764 *returned = numlines;
4770 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4771 return ERROR_NOT_ENOUGH_MEMORY;
4773 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4775 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4778 /* check the required size. */
4779 for (i=0; i<*returned; i++) {
4780 DEBUGADD(6,("adding port [%d]'s size\n", i));
4781 *needed += spoolss_size_port_info_2(&ports[i]);
4784 if (!alloc_buffer_size(buffer, *needed)) {
4786 return ERROR_INSUFFICIENT_BUFFER;
4789 /* fill the buffer with the ports structures */
4790 for (i=0; i<*returned; i++) {
4791 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4792 new_smb_io_port_2("", buffer, &ports[i], 0);
4797 if (*needed > offered) {
4799 return ERROR_INSUFFICIENT_BUFFER;
4802 return NT_STATUS_NO_PROBLEMO;
4805 /****************************************************************************
4807 ****************************************************************************/
4808 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4809 NEW_BUFFER *buffer, uint32 offered,
4810 uint32 *needed, uint32 *returned)
4812 DEBUG(4,("_spoolss_enumports\n"));
4819 return enumports_level_1(buffer, offered, needed, returned);
4821 return enumports_level_2(buffer, offered, needed, returned);
4823 return ERROR_INVALID_LEVEL;
4827 /****************************************************************************
4828 ****************************************************************************/
4829 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4830 const SPOOL_PRINTER_INFO_LEVEL *info,
4831 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4832 uint32 user_switch, const SPOOL_USER_CTR *user,
4835 NT_PRINTER_INFO_LEVEL *printer = NULL;
4839 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4840 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4841 return ERROR_NOT_ENOUGH_MEMORY;
4844 ZERO_STRUCTP(printer);
4846 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4847 convert_printer_info(info, printer, 2);
4849 if (*lp_addprinter_cmd() )
4850 if ( !add_printer_hook(printer) ) {
4851 free_a_printer(&printer,2);
4852 return ERROR_ACCESS_DENIED;
4855 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4856 printer->info_2->sharename);
4858 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4859 free_a_printer(&printer,2);
4860 return ERROR_ACCESS_DENIED;
4863 /* you must be a printer admin to add a new printer */
4864 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4865 free_a_printer(&printer,2);
4866 return ERROR_ACCESS_DENIED;
4870 * Do sanity check on the requested changes for Samba.
4873 if (!check_printer_ok(printer->info_2, snum)) {
4874 free_a_printer(&printer,2);
4875 return ERROR_INVALID_PARAMETER;
4878 /* write the ASCII on disk */
4879 if (add_a_printer(*printer, 2) != 0) {
4880 free_a_printer(&printer,2);
4881 return ERROR_ACCESS_DENIED;
4884 if (!open_printer_hnd(handle, name)) {
4885 /* Handle open failed - remove addition. */
4886 del_a_printer(printer->info_2->sharename);
4887 free_a_printer(&printer,2);
4888 return ERROR_ACCESS_DENIED;
4891 free_a_printer(&printer,2);
4893 srv_spoolss_sendnotify(handle);
4895 return NT_STATUS_NO_PROBLEMO;
4898 /****************************************************************************
4899 ****************************************************************************/
4900 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4901 const SPOOL_PRINTER_INFO_LEVEL *info,
4902 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4903 uint32 user_switch, const SPOOL_USER_CTR *user,
4908 /* we don't handle yet */
4909 /* but I know what to do ... */
4910 return ERROR_INVALID_LEVEL;
4912 return spoolss_addprinterex_level_2(uni_srv_name, info,
4913 unk0, unk1, unk2, unk3,
4914 user_switch, user, handle);
4916 return ERROR_INVALID_LEVEL;
4920 /****************************************************************************
4921 ****************************************************************************/
4922 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4923 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4925 uint32 err = NT_STATUS_NO_PROBLEMO;
4926 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4927 struct current_user user;
4929 ZERO_STRUCT(driver);
4931 get_current_user(&user, p);
4933 convert_printer_driver_info(info, &driver, level);
4935 DEBUG(5,("Cleaning driver's information\n"));
4936 if ((err = clean_up_driver_struct(driver, level)) != NT_STATUS_NO_PROBLEMO )
4939 DEBUG(5,("Moving driver to final destination\n"));
4940 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4942 err = ERROR_ACCESS_DENIED;
4946 if (add_a_printer_driver(driver, level)!=0) {
4947 err = ERROR_ACCESS_DENIED;
4952 free_a_printer_driver(driver, level);
4956 /****************************************************************************
4957 ****************************************************************************/
4958 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4960 init_unistr(&info->name, name);
4963 /****************************************************************************
4964 ****************************************************************************/
4965 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4969 pstring short_archi;
4970 DRIVER_DIRECTORY_1 *info=NULL;
4972 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4974 if (get_short_archi(short_archi, long_archi)==FALSE)
4975 return ERROR_INVALID_ENVIRONMENT;
4977 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4978 return ERROR_NOT_ENOUGH_MEMORY;
4980 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4982 DEBUG(4,("printer driver directory: [%s]\n", path));
4984 fill_driverdir_1(info, path);
4986 *needed += spoolss_size_driverdir_info_1(info);
4988 if (!alloc_buffer_size(buffer, *needed)) {
4990 return ERROR_INSUFFICIENT_BUFFER;
4993 new_smb_io_driverdir_1("", buffer, info, 0);
4997 if (*needed > offered)
4998 return ERROR_INSUFFICIENT_BUFFER;
5000 return NT_STATUS_NO_PROBLEMO;
5003 /****************************************************************************
5004 ****************************************************************************/
5005 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5006 NEW_BUFFER *buffer, uint32 offered,
5009 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5015 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5017 return ERROR_INVALID_LEVEL;
5021 /****************************************************************************
5022 ****************************************************************************/
5023 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5024 uint32 in_value_len, uint32 in_data_len,
5025 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5027 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5029 NT_PRINTER_INFO_LEVEL *printer = NULL;
5034 uint32 biggest_valuesize;
5035 uint32 biggest_datasize;
5037 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5042 ZERO_STRUCT(printer);
5044 *out_max_value_len=0;
5050 *out_max_data_len=0;
5054 DEBUG(5,("spoolss_enumprinterdata\n"));
5056 if (!OPEN_HANDLE(Printer)) {
5057 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5058 return ERROR_INVALID_HANDLE;
5061 if (!get_printer_snum(handle, &snum))
5062 return ERROR_INVALID_HANDLE;
5064 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5065 return ERROR_INVALID_HANDLE;
5068 * The NT machine wants to know the biggest size of value and data
5070 * cf: MSDN EnumPrinterData remark section
5072 if ( (in_value_len==0) && (in_data_len==0) ) {
5073 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5077 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5078 * if this parameter size doesn't exist.
5079 * Ok - my opinion here is that the client is not asking for the greatest
5080 * possible size of all the parameters, but is asking specifically for the size needed
5081 * for this specific parameter. In that case we can remove the loop below and
5082 * simplify this lookup code considerably. JF - comments welcome. JRA.
5085 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5087 free_a_printer(&printer, 2);
5088 return ERROR_NO_MORE_ITEMS;
5096 biggest_valuesize=0;
5099 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5100 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5101 if (data_len > biggest_datasize) biggest_datasize=data_len;
5103 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5111 * I think this is correct, it doesn't break APW and
5112 * allows Gerald's Win32 test programs to work correctly,
5113 * but may need altering.... JRA.
5116 if (param_index == 0) {
5117 /* No parameters found. */
5118 free_a_printer(&printer, 2);
5119 return ERROR_NO_MORE_ITEMS;
5122 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5123 *out_value_len=2*(1+biggest_valuesize);
5124 *out_data_len=biggest_datasize;
5126 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5128 free_a_printer(&printer, 2);
5129 return NT_STATUS_NO_PROBLEMO;
5133 * the value len is wrong in NT sp3
5134 * that's the number of bytes not the number of unicode chars
5137 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5139 free_a_printer(&printer, 2);
5140 return ERROR_NO_MORE_ITEMS;
5143 free_a_printer(&printer, 2);
5147 * - counted in bytes in the request
5148 * - counted in UNICODE chars in the max reply
5149 * - counted in bytes in the real size
5151 * take a pause *before* coding not *during* coding
5154 *out_max_value_len=(in_value_len/sizeof(uint16));
5155 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5157 return ERROR_NOT_ENOUGH_MEMORY;
5160 ZERO_STRUCTP(*out_value);
5161 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5165 /* the data is counted in bytes */
5166 *out_max_data_len=in_data_len;
5167 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5169 return ERROR_NOT_ENOUGH_MEMORY;
5172 memset(*data_out,'\0',in_data_len);
5173 memcpy(*data_out, data, (size_t)data_len);
5174 *out_data_len=data_len;
5178 return NT_STATUS_NO_PROBLEMO;
5181 /****************************************************************************
5182 ****************************************************************************/
5183 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5184 const UNISTR2 *value,
5189 uint32 numeric_data)
5191 NT_PRINTER_INFO_LEVEL *printer = NULL;
5192 NT_PRINTER_PARAM *param = NULL, old_param;
5194 uint32 status = 0x0;
5195 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5197 DEBUG(5,("spoolss_setprinterdata\n"));
5199 if (!OPEN_HANDLE(Printer)) {
5200 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5201 return ERROR_INVALID_HANDLE;
5204 if (!get_printer_snum(handle, &snum))
5205 return ERROR_INVALID_HANDLE;
5207 status = get_a_printer(&printer, 2, lp_servicename(snum));
5209 return ERROR_INVALID_NAME;
5211 convert_specific_param(¶m, value , type, data, real_len);
5213 /* Check if we are making any changes or not. Return true if
5214 nothing is actually changing. */
5216 ZERO_STRUCT(old_param);
5218 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5219 &old_param.type, &old_param.data_len)) {
5221 if (param->type == old_param.type &&
5222 param->data_len == old_param.data_len &&
5223 memcmp(param->data, old_param.data,
5224 old_param.data_len) == 0) {
5226 DEBUG(3, ("setprinterdata hasn't changed\n"));
5227 status = NT_STATUS_NO_PROBLEMO;
5234 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5235 DEBUG(3, ("security descriptor change denied by existing "
5236 "security descriptor\n"));
5237 status = ERROR_ACCESS_DENIED;
5241 unlink_specific_param_if_exist(printer->info_2, param);
5243 if (!add_a_specific_param(printer->info_2, param))
5244 status = ERROR_INVALID_PARAMETER;
5246 status = mod_a_printer(*printer, 2);
5249 free_a_printer(&printer, 2);
5250 safe_free(old_param.data);
5255 /****************************************************************************
5256 ****************************************************************************/
5257 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5259 NT_PRINTER_INFO_LEVEL *printer = NULL;
5260 NT_PRINTER_PARAM param;
5262 uint32 status = 0x0;
5263 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5265 DEBUG(5,("spoolss_deleteprinterdata\n"));
5267 if (!OPEN_HANDLE(Printer)) {
5268 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5269 return ERROR_INVALID_HANDLE;
5272 if (!get_printer_snum(handle, &snum))
5273 return ERROR_INVALID_HANDLE;
5275 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5276 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5277 "security descriptor\n"));
5278 return ERROR_ACCESS_DENIED;
5281 status = get_a_printer(&printer, 2, lp_servicename(snum));
5283 return ERROR_INVALID_NAME;
5285 ZERO_STRUCTP(¶m);
5286 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5288 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5289 status = ERROR_INVALID_PARAMETER;
5291 status = mod_a_printer(*printer, 2);
5293 free_a_printer(&printer, 2);
5297 /****************************************************************************
5298 ****************************************************************************/
5299 uint32 _spoolss_addform( POLICY_HND *handle,
5304 nt_forms_struct *list=NULL;
5305 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5307 DEBUG(5,("spoolss_addform\n"));
5309 if (!OPEN_HANDLE(Printer)) {
5310 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5311 return ERROR_INVALID_HANDLE;
5314 count=get_ntforms(&list);
5315 if(!add_a_form(&list, form, &count))
5316 return ERROR_NOT_ENOUGH_MEMORY;
5317 write_ntforms(&list, count);
5324 /****************************************************************************
5325 ****************************************************************************/
5326 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5330 nt_forms_struct *list=NULL;
5331 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5333 DEBUG(5,("spoolss_deleteform\n"));
5335 if (!OPEN_HANDLE(Printer)) {
5336 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5337 return ERROR_INVALID_HANDLE;
5340 count = get_ntforms(&list);
5341 if(!delete_a_form(&list, form_name, &count, &ret))
5342 return ERROR_INVALID_PARAMETER;
5349 /****************************************************************************
5350 ****************************************************************************/
5351 uint32 _spoolss_setform( POLICY_HND *handle,
5352 const UNISTR2 *uni_name,
5357 nt_forms_struct *list=NULL;
5358 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5360 DEBUG(5,("spoolss_setform\n"));
5362 if (!OPEN_HANDLE(Printer)) {
5363 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5364 return ERROR_INVALID_HANDLE;
5366 count=get_ntforms(&list);
5367 update_a_form(&list, form, count);
5368 write_ntforms(&list, count);
5375 /****************************************************************************
5376 enumprintprocessors level 1.
5377 ****************************************************************************/
5378 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5380 PRINTPROCESSOR_1 *info_1=NULL;
5382 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5383 return ERROR_NOT_ENOUGH_MEMORY;
5387 init_unistr(&info_1->name, "winprint");
5389 *needed += spoolss_size_printprocessor_info_1(info_1);
5391 if (!alloc_buffer_size(buffer, *needed))
5392 return ERROR_INSUFFICIENT_BUFFER;
5394 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5398 if (*needed > offered) {
5400 return ERROR_INSUFFICIENT_BUFFER;
5403 return NT_STATUS_NO_PROBLEMO;
5406 /****************************************************************************
5407 ****************************************************************************/
5408 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5409 NEW_BUFFER *buffer, uint32 offered,
5410 uint32 *needed, uint32 *returned)
5412 DEBUG(5,("spoolss_enumprintprocessors\n"));
5415 * Enumerate the print processors ...
5417 * Just reply with "winprint", to keep NT happy
5418 * and I can use my nice printer checker.
5426 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5428 return ERROR_INVALID_LEVEL;
5432 /****************************************************************************
5433 enumprintprocdatatypes level 1.
5434 ****************************************************************************/
5435 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5437 PRINTPROCDATATYPE_1 *info_1=NULL;
5439 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5440 return ERROR_NOT_ENOUGH_MEMORY;
5444 init_unistr(&info_1->name, "RAW");
5446 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5448 if (!alloc_buffer_size(buffer, *needed))
5449 return ERROR_INSUFFICIENT_BUFFER;
5451 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5455 if (*needed > offered) {
5457 return ERROR_INSUFFICIENT_BUFFER;
5460 return NT_STATUS_NO_PROBLEMO;
5463 /****************************************************************************
5464 ****************************************************************************/
5465 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5466 NEW_BUFFER *buffer, uint32 offered,
5467 uint32 *needed, uint32 *returned)
5469 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5476 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5478 return ERROR_INVALID_LEVEL;
5482 /****************************************************************************
5483 enumprintmonitors level 1.
5484 ****************************************************************************/
5485 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5487 PRINTMONITOR_1 *info_1=NULL;
5489 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5490 return ERROR_NOT_ENOUGH_MEMORY;
5494 init_unistr(&info_1->name, "Local Port");
5496 *needed += spoolss_size_printmonitor_info_1(info_1);
5498 if (!alloc_buffer_size(buffer, *needed))
5499 return ERROR_INSUFFICIENT_BUFFER;
5501 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5505 if (*needed > offered) {
5507 return ERROR_INSUFFICIENT_BUFFER;
5510 return NT_STATUS_NO_PROBLEMO;
5513 /****************************************************************************
5514 enumprintmonitors level 2.
5515 ****************************************************************************/
5516 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5518 PRINTMONITOR_2 *info_2=NULL;
5520 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5521 return ERROR_NOT_ENOUGH_MEMORY;
5525 init_unistr(&info_2->name, "Local Port");
5526 init_unistr(&info_2->environment, "Windows NT X86");
5527 init_unistr(&info_2->dll_name, "localmon.dll");
5529 *needed += spoolss_size_printmonitor_info_2(info_2);
5531 if (!alloc_buffer_size(buffer, *needed))
5532 return ERROR_INSUFFICIENT_BUFFER;
5534 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5538 if (*needed > offered) {
5540 return ERROR_INSUFFICIENT_BUFFER;
5543 return NT_STATUS_NO_PROBLEMO;
5546 /****************************************************************************
5547 ****************************************************************************/
5548 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5549 NEW_BUFFER *buffer, uint32 offered,
5550 uint32 *needed, uint32 *returned)
5552 DEBUG(5,("spoolss_enumprintmonitors\n"));
5555 * Enumerate the print monitors ...
5557 * Just reply with "Local Port", to keep NT happy
5558 * and I can use my nice printer checker.
5566 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5568 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5570 return ERROR_INVALID_LEVEL;
5574 /****************************************************************************
5575 ****************************************************************************/
5576 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5580 JOB_INFO_1 *info_1=NULL;
5582 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5584 if (info_1 == NULL) {
5586 return ERROR_NOT_ENOUGH_MEMORY;
5589 for (i=0; i<count && found==False; i++) {
5590 if (queue[i].job==(int)jobid)
5597 /* I shoud reply something else ... I can't find the good one */
5598 return NT_STATUS_NO_PROBLEMO;
5601 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5605 *needed += spoolss_size_job_info_1(info_1);
5607 if (!alloc_buffer_size(buffer, *needed)) {
5609 return ERROR_INSUFFICIENT_BUFFER;
5612 new_smb_io_job_info_1("", buffer, info_1, 0);
5616 if (*needed > offered)
5617 return ERROR_INSUFFICIENT_BUFFER;
5619 return NT_STATUS_NO_PROBLEMO;
5623 /****************************************************************************
5624 ****************************************************************************/
5625 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5630 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5632 ZERO_STRUCTP(info_2);
5634 if (info_2 == NULL) {
5636 return ERROR_NOT_ENOUGH_MEMORY;
5639 for (i=0; i<count && found==False; i++) {
5640 if (queue[i].job==(int)jobid)
5647 /* I shoud reply something else ... I can't find the good one */
5648 return NT_STATUS_NO_PROBLEMO;
5651 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5655 *needed += spoolss_size_job_info_2(info_2);
5657 if (!alloc_buffer_size(buffer, *needed)) {
5659 return ERROR_INSUFFICIENT_BUFFER;
5662 new_smb_io_job_info_2("", buffer, info_2, 0);
5664 free_dev_mode(info_2->devmode);
5667 if (*needed > offered)
5668 return ERROR_INSUFFICIENT_BUFFER;
5670 return NT_STATUS_NO_PROBLEMO;
5673 /****************************************************************************
5674 ****************************************************************************/
5675 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5676 NEW_BUFFER *buffer, uint32 offered,
5681 print_queue_struct *queue=NULL;
5682 print_status_struct prt_status;
5684 DEBUG(5,("spoolss_getjob\n"));
5686 memset(&prt_status, 0, sizeof(prt_status));
5690 if (!get_printer_snum(handle, &snum))
5691 return ERROR_INVALID_HANDLE;
5693 count = print_queue_status(snum, &queue, &prt_status);
5695 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5696 count, prt_status.status, prt_status.message));
5700 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5702 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5705 return ERROR_INVALID_LEVEL;