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";
1342 switch (queue->status) {
1356 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1357 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1360 /*******************************************************************
1361 * fill a notify_info_data with job time
1362 ********************************************************************/
1363 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1365 data->notify_data.value[0]=0x0;
1368 /*******************************************************************
1369 * fill a notify_info_data with job size
1370 ********************************************************************/
1371 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1373 data->notify_data.value[0]=queue->size;
1376 /*******************************************************************
1377 * fill a notify_info_data with job position
1378 ********************************************************************/
1379 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1381 data->notify_data.value[0]=queue->job;
1384 /*******************************************************************
1385 * fill a notify_info_data with submitted time
1386 ********************************************************************/
1387 static void spoolss_notify_submitted_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1391 t=gmtime(&queue->time);
1393 data->notify_data.data.length = sizeof(SYSTEMTIME);
1394 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1399 struct s_notify_info_data_table
1405 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1406 print_queue_struct *queue,
1407 NT_PRINTER_INFO_LEVEL *printer);
1410 struct s_notify_info_data_table notify_info_data_table[] =
1412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1462 { END, END, "", END, NULL }
1465 /*******************************************************************
1466 return the size of info_data structure
1467 ********************************************************************/
1468 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1472 while (notify_info_data_table[i].type != END)
1474 if ( (notify_info_data_table[i].type == type ) &&
1475 (notify_info_data_table[i].field == field ) )
1477 return (notify_info_data_table[i].size);
1484 /*******************************************************************
1485 return the type of notify_info_data
1486 ********************************************************************/
1487 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1491 while (notify_info_data_table[i].type != END)
1493 if ( (notify_info_data_table[i].type == type ) &&
1494 (notify_info_data_table[i].field == field ) )
1496 if (notify_info_data_table[i].size == POINTER)
1510 /****************************************************************************
1511 ****************************************************************************/
1512 static int search_notify(uint16 type, uint16 field, int *value)
1517 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1519 if ( (notify_info_data_table[j].type == type ) &&
1520 (notify_info_data_table[j].field == field ) )
1525 if ( found && (notify_info_data_table[j].fn != NULL) )
1531 /****************************************************************************
1532 ****************************************************************************/
1533 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1535 info_data->type = type;
1536 info_data->field = field;
1537 info_data->reserved = 0;
1539 info_data->size = size_of_notify_info_data(type, field);
1540 info_data->enc_type = type_of_notify_info_data(type, field);
1544 /*******************************************************************
1546 * fill a notify_info struct with info asked
1548 ********************************************************************/
1549 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1555 SPOOL_NOTIFY_INFO_DATA *current_data;
1556 NT_PRINTER_INFO_LEVEL *printer = NULL;
1557 print_queue_struct *queue=NULL;
1559 DEBUG(4,("construct_notify_printer_info\n"));
1561 type=option_type->type;
1563 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1564 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1565 option_type->count, lp_servicename(snum)));
1567 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1570 for(field_num=0; field_num<option_type->count; field_num++) {
1571 field = option_type->fields[field_num];
1572 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1574 if (!search_notify(type, field, &j) )
1577 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1580 current_data=&info->data[info->count];
1582 construct_info_data(current_data, type, field, id);
1583 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1588 free_a_printer(&printer, 2);
1592 /*******************************************************************
1594 * fill a notify_info struct with info asked
1596 ********************************************************************/
1597 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1603 SPOOL_NOTIFY_INFO_DATA *current_data;
1604 NT_PRINTER_INFO_LEVEL *printer = NULL;
1606 DEBUG(4,("construct_notify_jobs_info\n"));
1608 type = option_type->type;
1610 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1611 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1612 option_type->count));
1614 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1617 for(field_num=0; field_num<option_type->count; field_num++) {
1618 field = option_type->fields[field_num];
1620 if (!search_notify(type, field, &j) )
1623 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1627 current_data=&(info->data[info->count]);
1629 construct_info_data(current_data, type, field, id);
1630 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1634 free_a_printer(&printer, 2);
1639 * JFM: The enumeration is not that simple, it's even non obvious.
1641 * let's take an example: I want to monitor the PRINTER SERVER for
1642 * the printer's name and the number of jobs currently queued.
1643 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1644 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1646 * I have 3 printers on the back of my server.
1648 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1651 * 1 printer 1 name 1
1652 * 2 printer 1 cjob 1
1653 * 3 printer 2 name 2
1654 * 4 printer 2 cjob 2
1655 * 5 printer 3 name 3
1656 * 6 printer 3 name 3
1658 * that's the print server case, the printer case is even worse.
1663 /*******************************************************************
1665 * enumerate all printers on the printserver
1666 * fill a notify_info struct with info asked
1668 ********************************************************************/
1669 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1672 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1673 int n_services=lp_numservices();
1676 SPOOL_NOTIFY_OPTION *option;
1677 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1679 DEBUG(4,("printserver_notify_info\n"));
1681 option=Printer->notify.option;
1687 for (i=0; i<option->count; i++) {
1688 option_type=&(option->ctr.type[i]);
1690 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1693 for (snum=0; snum<n_services; snum++)
1694 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1695 if (construct_notify_printer_info(info, snum, option_type, id))
1700 * Debugging information, don't delete.
1703 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1704 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1705 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1707 for (i=0; i<info->count; i++) {
1708 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1709 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1710 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1714 return NT_STATUS_NO_PROBLEMO;
1717 /*******************************************************************
1719 * fill a notify_info struct with info asked
1721 ********************************************************************/
1722 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1725 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1728 SPOOL_NOTIFY_OPTION *option;
1729 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1731 print_queue_struct *queue=NULL;
1732 print_status_struct status;
1734 DEBUG(4,("printer_notify_info\n"));
1736 option=Printer->notify.option;
1742 get_printer_snum(hnd, &snum);
1744 for (i=0; i<option->count; i++) {
1745 option_type=&option->ctr.type[i];
1747 switch ( option_type->type ) {
1748 case PRINTER_NOTIFY_TYPE:
1749 if(construct_notify_printer_info(info, snum, option_type, id))
1753 case JOB_NOTIFY_TYPE:
1754 memset(&status, 0, sizeof(status));
1755 count = print_queue_status(snum, &queue, &status);
1756 for (j=0; j<count; j++)
1757 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1764 * Debugging information, don't delete.
1767 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1768 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1769 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1771 for (i=0; i<info->count; i++) {
1772 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1773 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1774 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1777 return NT_STATUS_NO_PROBLEMO;
1780 /********************************************************************
1782 ********************************************************************/
1783 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1784 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1786 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1788 if (!OPEN_HANDLE(Printer)) {
1789 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1790 return ERROR_INVALID_HANDLE;
1793 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1795 /* jfm: the change value isn't used right now.
1796 * we will honour it when
1797 * a) we'll be able to send notification to the client
1798 * b) we'll have a way to communicate between the spoolss process.
1800 * same thing for option->flags
1801 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1802 * I don't have a global notification system, I'm sending back all the
1803 * informations even when _NOTHING_ has changed.
1806 /* just discard the SPOOL_NOTIFY_OPTION */
1808 safe_free(option->ctr.type);
1810 switch (Printer->printer_type) {
1811 case PRINTER_HANDLE_IS_PRINTSERVER:
1812 return printserver_notify_info(handle, info);
1813 case PRINTER_HANDLE_IS_PRINTER:
1814 return printer_notify_info(handle, info);
1817 return ERROR_INVALID_HANDLE;
1820 /********************************************************************
1821 * construct_printer_info_0
1822 * fill a printer_info_1 struct
1823 ********************************************************************/
1824 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, fstring servername)
1828 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1829 counter_printer_0 *session_counter;
1830 uint32 global_counter;
1834 print_queue_struct *queue=NULL;
1835 print_status_struct status;
1837 memset(&status, 0, sizeof(status));
1839 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1842 count = print_queue_status(snum, &queue, &status);
1844 /* check if we already have a counter for this printer */
1845 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1847 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1848 if (session_counter->snum == snum)
1852 /* it's the first time, add it to the list */
1853 if (session_counter==NULL) {
1854 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1855 free_a_printer(&ntprinter, 2);
1858 ZERO_STRUCTP(session_counter);
1859 session_counter->snum=snum;
1860 session_counter->counter=0;
1861 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1865 session_counter->counter++;
1868 * the global_counter should be stored in a TDB as it's common to all the clients
1869 * and should be zeroed on samba startup
1871 global_counter=session_counter->counter;
1873 /* the description and the name are of the form \\server\share */
1874 slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter->info_2->printername);
1876 init_unistr(&printer->printername, chaine);
1878 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername);
1879 init_unistr(&printer->servername, chaine);
1881 printer->cjobs = count;
1882 printer->total_jobs = 0;
1883 printer->total_bytes = 0;
1885 setuptime = (time_t)ntprinter->info_2->setuptime;
1886 t=gmtime(&setuptime);
1888 printer->year = t->tm_year+1900;
1889 printer->month = t->tm_mon+1;
1890 printer->dayofweek = t->tm_wday;
1891 printer->day = t->tm_mday;
1892 printer->hour = t->tm_hour;
1893 printer->minute = t->tm_min;
1894 printer->second = t->tm_sec;
1895 printer->milliseconds = 0;
1897 printer->global_counter = global_counter;
1898 printer->total_pages = 0;
1899 printer->major_version = 0x0004; /* NT 4 */
1900 printer->build_version = 0x0565; /* build 1381 */
1901 printer->unknown7 = 0x1;
1902 printer->unknown8 = 0x0;
1903 printer->unknown9 = 0x0;
1904 printer->session_counter = session_counter->counter;
1905 printer->unknown11 = 0x0;
1906 printer->printer_errors = 0x0; /* number of print failure */
1907 printer->unknown13 = 0x0;
1908 printer->unknown14 = 0x1;
1909 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1910 printer->unknown16 = 0x0;
1911 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1912 printer->unknown18 = 0x0;
1913 printer->status = nt_printq_status(status.status);
1914 printer->unknown20 = 0x0;
1915 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1916 printer->unknown22 = 0x0;
1917 printer->unknown23 = 0x6; /* 6 ???*/
1918 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1919 printer->unknown25 = 0;
1920 printer->unknown26 = 0;
1921 printer->unknown27 = 0;
1922 printer->unknown28 = 0;
1923 printer->unknown29 = 0;
1926 free_a_printer(&ntprinter,2);
1930 /********************************************************************
1931 * construct_printer_info_1
1932 * fill a printer_info_1 struct
1933 ********************************************************************/
1934 static BOOL construct_printer_info_1(fstring server, uint32 flags, PRINTER_INFO_1 *printer, int snum)
1938 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1940 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1943 printer->flags=flags;
1945 if (*ntprinter->info_2->comment == '\0') {
1946 init_unistr(&printer->comment, lp_comment(snum));
1947 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1948 ntprinter->info_2->drivername, lp_comment(snum));
1951 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1952 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1953 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1956 snprintf(chaine2,sizeof(chaine)-1,"%s%s", server, ntprinter->info_2->printername);
1958 init_unistr(&printer->description, chaine);
1959 init_unistr(&printer->name, chaine2);
1961 free_a_printer(&ntprinter,2);
1966 /****************************************************************************
1967 Free a DEVMODE struct.
1968 ****************************************************************************/
1970 static void free_dev_mode(DEVICEMODE *dev)
1976 safe_free(dev->private);
1981 /****************************************************************************
1982 Create a DEVMODE struct. Returns malloced memory.
1983 ****************************************************************************/
1985 static DEVICEMODE *construct_dev_mode(int snum, char *servername)
1989 NT_PRINTER_INFO_LEVEL *printer = NULL;
1990 NT_DEVICEMODE *ntdevmode = NULL;
1991 DEVICEMODE *devmode = NULL;
1993 DEBUG(7,("construct_dev_mode\n"));
1995 DEBUGADD(8,("getting printer characteristics\n"));
1997 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
1998 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2002 ZERO_STRUCTP(devmode);
2004 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2007 if (printer->info_2->devmode)
2008 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2010 if (ntdevmode == NULL)
2013 DEBUGADD(8,("loading DEVICEMODE\n"));
2015 snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, printer->info_2->printername);
2016 init_unistr(&devmode->devicename, adevice);
2018 snprintf(aform, sizeof(aform), ntdevmode->formname);
2019 init_unistr(&devmode->formname, aform);
2021 devmode->specversion = ntdevmode->specversion;
2022 devmode->driverversion = ntdevmode->driverversion;
2023 devmode->size = ntdevmode->size;
2024 devmode->driverextra = ntdevmode->driverextra;
2025 devmode->fields = ntdevmode->fields;
2027 devmode->orientation = ntdevmode->orientation;
2028 devmode->papersize = ntdevmode->papersize;
2029 devmode->paperlength = ntdevmode->paperlength;
2030 devmode->paperwidth = ntdevmode->paperwidth;
2031 devmode->scale = ntdevmode->scale;
2032 devmode->copies = ntdevmode->copies;
2033 devmode->defaultsource = ntdevmode->defaultsource;
2034 devmode->printquality = ntdevmode->printquality;
2035 devmode->color = ntdevmode->color;
2036 devmode->duplex = ntdevmode->duplex;
2037 devmode->yresolution = ntdevmode->yresolution;
2038 devmode->ttoption = ntdevmode->ttoption;
2039 devmode->collate = ntdevmode->collate;
2040 devmode->icmmethod = ntdevmode->icmmethod;
2041 devmode->icmintent = ntdevmode->icmintent;
2042 devmode->mediatype = ntdevmode->mediatype;
2043 devmode->dithertype = ntdevmode->dithertype;
2045 if (ntdevmode->private != NULL) {
2046 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2050 free_nt_devicemode(&ntdevmode);
2051 free_a_printer(&printer,2);
2058 free_nt_devicemode(&ntdevmode);
2060 free_a_printer(&printer,2);
2061 free_dev_mode(devmode);
2066 /********************************************************************
2067 * construct_printer_info_2
2068 * fill a printer_info_2 struct
2069 ********************************************************************/
2071 static BOOL construct_printer_info_2(fstring servername, PRINTER_INFO_2 *printer, int snum)
2077 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2079 print_queue_struct *queue=NULL;
2080 print_status_struct status;
2081 memset(&status, 0, sizeof(status));
2083 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2086 memset(&status, 0, sizeof(status));
2087 count = print_queue_status(snum, &queue, &status);
2089 snprintf(chaine, sizeof(chaine)-1, "%s", servername);
2091 if (strlen(servername)!=0)
2096 if (!strchr(ntprinter->info_2->printername, '\\')) {
2097 snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter->info_2->printername);
2099 pstrcpy(chaine2, ntprinter->info_2->printername);
2102 init_unistr(&printer->servername, chaine); /* servername*/
2103 init_unistr(&printer->printername, chaine2); /* printername*/
2104 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2105 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2106 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2108 if (*ntprinter->info_2->comment == '\0')
2109 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2111 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2113 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2114 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2115 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2116 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2117 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2119 printer->attributes = ntprinter->info_2->attributes;
2121 printer->priority = ntprinter->info_2->priority; /* priority */
2122 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2123 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2124 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2125 printer->status = nt_printq_status(status.status); /* status */
2126 printer->cjobs = count; /* jobs */
2127 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2129 if((printer->devmode = construct_dev_mode(snum, servername)) == NULL) {
2130 DEBUG(8, ("Returning NULL Devicemode!\n"));
2133 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2134 /* steal the printer info sec_desc structure. [badly done]. */
2135 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2136 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2137 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2138 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2141 printer->secdesc = NULL;
2144 free_a_printer(&ntprinter, 2);
2149 /********************************************************************
2150 * construct_printer_info_3
2151 * fill a printer_info_3 struct
2152 ********************************************************************/
2153 static BOOL construct_printer_info_3(fstring servername,
2154 PRINTER_INFO_3 **pp_printer, int snum)
2156 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2157 PRINTER_INFO_3 *printer = NULL;
2159 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2163 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2164 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2168 ZERO_STRUCTP(printer);
2170 printer->flags = 4; /* These are the components of the SD we are returning. */
2171 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2172 /* steal the printer info sec_desc structure. [badly done]. */
2173 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2177 * Set the flags for the components we are returning.
2180 if (printer->secdesc->owner_sid)
2181 printer->flags |= OWNER_SECURITY_INFORMATION;
2183 if (printer->secdesc->grp_sid)
2184 printer->flags |= GROUP_SECURITY_INFORMATION;
2186 if (printer->secdesc->dacl)
2187 printer->flags |= DACL_SECURITY_INFORMATION;
2189 if (printer->secdesc->sacl)
2190 printer->flags |= SACL_SECURITY_INFORMATION;
2193 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2194 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2195 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2198 free_a_printer(&ntprinter, 2);
2200 *pp_printer = printer;
2204 /********************************************************************
2205 Spoolss_enumprinters.
2206 ********************************************************************/
2207 static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2211 int n_services=lp_numservices();
2212 PRINTER_INFO_1 *printers=NULL;
2213 PRINTER_INFO_1 current_prt;
2215 DEBUG(4,("enum_all_printers_info_1\n"));
2217 for (snum=0; snum<n_services; snum++) {
2218 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2219 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2221 if (construct_printer_info_1(server, flags, ¤t_prt, snum)) {
2222 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2224 return ERROR_NOT_ENOUGH_MEMORY;
2226 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2227 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2233 /* check the required size. */
2234 for (i=0; i<*returned; i++)
2235 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2237 if (!alloc_buffer_size(buffer, *needed))
2238 return ERROR_INSUFFICIENT_BUFFER;
2240 /* fill the buffer with the structures */
2241 for (i=0; i<*returned; i++)
2242 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2245 safe_free(printers);
2247 if (*needed > offered) {
2249 return ERROR_INSUFFICIENT_BUFFER;
2252 return NT_STATUS_NO_PROBLEMO;
2255 /********************************************************************
2256 enum_all_printers_info_1_local.
2257 *********************************************************************/
2258 static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2261 DEBUG(4,("enum_all_printers_info_1_local\n"));
2263 fstrcpy(temp, "\\\\");
2264 fstrcat(temp, global_myname);
2266 if (!strcmp(name, temp)) {
2267 fstrcat(temp, "\\");
2268 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2271 return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2274 /********************************************************************
2275 enum_all_printers_info_1_name.
2276 *********************************************************************/
2277 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2280 DEBUG(4,("enum_all_printers_info_1_name\n"));
2282 fstrcpy(temp, "\\\\");
2283 fstrcat(temp, global_myname);
2285 if (!strcmp(name, temp)) {
2286 fstrcat(temp, "\\");
2287 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2290 return ERROR_INVALID_NAME;
2293 /********************************************************************
2294 enum_all_printers_info_1_remote.
2295 *********************************************************************/
2296 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2298 PRINTER_INFO_1 *printer;
2299 fstring printername;
2302 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2304 /* JFM: currently it's more a place holder than anything else.
2305 * In the spooler world there is a notion of server registration.
2306 * the print servers are registring (sp ?) on the PDC (in the same domain)
2308 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2311 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2312 return ERROR_NOT_ENOUGH_MEMORY;
2316 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2317 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2318 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2320 init_unistr(&printer->description, desc);
2321 init_unistr(&printer->name, printername);
2322 init_unistr(&printer->comment, comment);
2323 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2325 /* check the required size. */
2326 *needed += spoolss_size_printer_info_1(printer);
2328 if (!alloc_buffer_size(buffer, *needed)) {
2330 return ERROR_INSUFFICIENT_BUFFER;
2333 /* fill the buffer with the structures */
2334 new_smb_io_printer_info_1("", buffer, printer, 0);
2339 if (*needed > offered) {
2341 return ERROR_INSUFFICIENT_BUFFER;
2344 return NT_STATUS_NO_PROBLEMO;
2347 /********************************************************************
2348 enum_all_printers_info_1_network.
2349 *********************************************************************/
2350 static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2353 DEBUG(4,("enum_all_printers_info_1_network\n"));
2355 fstrcpy(temp, "\\\\");
2356 fstrcat(temp, global_myname);
2357 fstrcat(temp, "\\");
2358 return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2361 /********************************************************************
2362 * api_spoolss_enumprinters
2364 * called from api_spoolss_enumprinters (see this to understand)
2365 ********************************************************************/
2366 static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2370 int n_services=lp_numservices();
2371 PRINTER_INFO_2 *printers=NULL;
2372 PRINTER_INFO_2 current_prt;
2374 for (snum=0; snum<n_services; snum++) {
2375 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2376 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2378 if (construct_printer_info_2(servername, ¤t_prt, snum)) {
2379 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2380 return ERROR_NOT_ENOUGH_MEMORY;
2381 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2382 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2388 /* check the required size. */
2389 for (i=0; i<*returned; i++)
2390 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2392 if (!alloc_buffer_size(buffer, *needed)) {
2393 for (i=0; i<*returned; i++) {
2394 free_devmode(printers[i].devmode);
2395 free_sec_desc(&printers[i].secdesc);
2397 safe_free(printers);
2398 return ERROR_INSUFFICIENT_BUFFER;
2401 /* fill the buffer with the structures */
2402 for (i=0; i<*returned; i++)
2403 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2406 for (i=0; i<*returned; i++) {
2407 free_devmode(printers[i].devmode);
2408 free_sec_desc(&printers[i].secdesc);
2410 safe_free(printers);
2412 if (*needed > offered) {
2414 return ERROR_INSUFFICIENT_BUFFER;
2417 return NT_STATUS_NO_PROBLEMO;
2420 /********************************************************************
2421 * handle enumeration of printers at level 1
2422 ********************************************************************/
2423 static uint32 enumprinters_level1( uint32 flags, fstring name,
2424 NEW_BUFFER *buffer, uint32 offered,
2425 uint32 *needed, uint32 *returned)
2427 /* Not all the flags are equals */
2429 if (flags & PRINTER_ENUM_LOCAL)
2430 return enum_all_printers_info_1_local(name, buffer, offered, needed, returned);
2432 if (flags & PRINTER_ENUM_NAME)
2433 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2435 if (flags & PRINTER_ENUM_REMOTE)
2436 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2438 if (flags & PRINTER_ENUM_NETWORK)
2439 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
2441 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2444 /********************************************************************
2445 * handle enumeration of printers at level 2
2446 ********************************************************************/
2447 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2448 NEW_BUFFER *buffer, uint32 offered,
2449 uint32 *needed, uint32 *returned)
2453 fstrcpy(temp, "\\\\");
2454 fstrcat(temp, global_myname);
2456 if (flags & PRINTER_ENUM_LOCAL) {
2457 if (!strcmp(servername, temp))
2458 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2460 return enum_all_printers_info_2("", buffer, offered, needed, returned);
2463 if (flags & PRINTER_ENUM_NAME) {
2464 if (!strcmp(servername, temp))
2465 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2467 return ERROR_INVALID_NAME;
2470 if (flags & PRINTER_ENUM_REMOTE)
2471 return ERROR_INVALID_LEVEL;
2473 return NT_STATUS_NO_PROBLEMO;
2476 /********************************************************************
2477 * handle enumeration of printers at level 5
2478 ********************************************************************/
2479 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2480 NEW_BUFFER *buffer, uint32 offered,
2481 uint32 *needed, uint32 *returned)
2483 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2484 return NT_STATUS_NO_PROBLEMO;
2487 /********************************************************************
2488 * api_spoolss_enumprinters
2490 * called from api_spoolss_enumprinters (see this to understand)
2491 ********************************************************************/
2492 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2493 NEW_BUFFER *buffer, uint32 offered,
2494 uint32 *needed, uint32 *returned)
2498 DEBUG(4,("_spoolss_enumprinters\n"));
2505 * flags==PRINTER_ENUM_NAME
2506 * if name=="" then enumerates all printers
2507 * if name!="" then enumerate the printer
2508 * flags==PRINTER_ENUM_REMOTE
2509 * name is NULL, enumerate printers
2510 * Level 2: name!="" enumerates printers, name can't be NULL
2511 * Level 3: doesn't exist
2512 * Level 4: does a local registry lookup
2513 * Level 5: same as Level 2
2516 unistr2_to_ascii(name, servername, sizeof(name)-1);
2521 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2523 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2525 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2529 return ERROR_INVALID_LEVEL;
2533 /****************************************************************************
2534 ****************************************************************************/
2535 static uint32 getprinter_level_0(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2537 PRINTER_INFO_0 *printer=NULL;
2539 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2540 return ERROR_NOT_ENOUGH_MEMORY;
2542 construct_printer_info_0(printer, snum, servername);
2544 /* check the required size. */
2545 *needed += spoolss_size_printer_info_0(printer);
2547 if (!alloc_buffer_size(buffer, *needed)) {
2549 return ERROR_INSUFFICIENT_BUFFER;
2552 /* fill the buffer with the structures */
2553 new_smb_io_printer_info_0("", buffer, printer, 0);
2558 if (*needed > offered) {
2559 return ERROR_INSUFFICIENT_BUFFER;
2562 return NT_STATUS_NO_PROBLEMO;
2565 /****************************************************************************
2566 ****************************************************************************/
2567 static uint32 getprinter_level_1(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2569 PRINTER_INFO_1 *printer=NULL;
2571 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2572 return ERROR_NOT_ENOUGH_MEMORY;
2574 construct_printer_info_1(servername, PRINTER_ENUM_ICON8, printer, snum);
2576 /* check the required size. */
2577 *needed += spoolss_size_printer_info_1(printer);
2579 if (!alloc_buffer_size(buffer, *needed)) {
2581 return ERROR_INSUFFICIENT_BUFFER;
2584 /* fill the buffer with the structures */
2585 new_smb_io_printer_info_1("", buffer, printer, 0);
2590 if (*needed > offered) {
2591 return ERROR_INSUFFICIENT_BUFFER;
2594 return NT_STATUS_NO_PROBLEMO;
2597 /****************************************************************************
2598 ****************************************************************************/
2599 static uint32 getprinter_level_2(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2601 PRINTER_INFO_2 *printer=NULL;
2604 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2605 return ERROR_NOT_ENOUGH_MEMORY;
2607 fstrcpy(temp, "\\\\");
2608 fstrcat(temp, servername);
2609 construct_printer_info_2(temp, printer, snum);
2611 /* check the required size. */
2612 *needed += spoolss_size_printer_info_2(printer);
2614 if (!alloc_buffer_size(buffer, *needed)) {
2615 free_printer_info_2(printer);
2616 return ERROR_INSUFFICIENT_BUFFER;
2619 /* fill the buffer with the structures */
2620 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2621 free_printer_info_2(printer);
2622 return ERROR_NOT_ENOUGH_MEMORY;
2626 free_printer_info_2(printer);
2628 if (*needed > offered) {
2629 return ERROR_INSUFFICIENT_BUFFER;
2632 return NT_STATUS_NO_PROBLEMO;
2635 /****************************************************************************
2636 ****************************************************************************/
2637 static uint32 getprinter_level_3(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2639 PRINTER_INFO_3 *printer=NULL;
2642 fstrcpy(temp, "\\\\");
2643 fstrcat(temp, servername);
2644 if (!construct_printer_info_3(temp, &printer, snum))
2645 return ERROR_NOT_ENOUGH_MEMORY;
2647 /* check the required size. */
2648 *needed += spoolss_size_printer_info_3(printer);
2650 if (!alloc_buffer_size(buffer, *needed)) {
2651 free_printer_info_3(printer);
2652 return ERROR_INSUFFICIENT_BUFFER;
2655 /* fill the buffer with the structures */
2656 new_smb_io_printer_info_3("", buffer, printer, 0);
2659 free_printer_info_3(printer);
2661 if (*needed > offered) {
2662 return ERROR_INSUFFICIENT_BUFFER;
2665 return NT_STATUS_NO_PROBLEMO;
2668 /****************************************************************************
2669 ****************************************************************************/
2670 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2671 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2678 pstrcpy(servername, global_myname);
2680 if (!get_printer_snum(handle, &snum))
2681 return ERROR_INVALID_HANDLE;
2685 return getprinter_level_0(servername, snum, buffer, offered, needed);
2687 return getprinter_level_1(servername,snum, buffer, offered, needed);
2689 return getprinter_level_2(servername,snum, buffer, offered, needed);
2691 return getprinter_level_3(servername,snum, buffer, offered, needed);
2693 return ERROR_INVALID_LEVEL;
2697 /********************************************************************
2698 * fill a DRIVER_INFO_1 struct
2699 ********************************************************************/
2700 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2702 init_unistr( &info->name, driver.info_3->name);
2705 /********************************************************************
2706 * construct_printer_driver_info_1
2707 ********************************************************************/
2708 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2710 NT_PRINTER_INFO_LEVEL *printer = NULL;
2711 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2713 ZERO_STRUCT(driver);
2715 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2716 return ERROR_INVALID_PRINTER_NAME;
2718 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2719 return ERROR_UNKNOWN_PRINTER_DRIVER;
2721 fill_printer_driver_info_1(info, driver, servername, architecture);
2723 free_a_printer(&printer,2);
2725 return NT_STATUS_NO_PROBLEMO;
2728 /********************************************************************
2729 * construct_printer_driver_info_2
2730 * fill a printer_info_2 struct
2731 ********************************************************************/
2732 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2734 pstring temp_driverpath;
2735 pstring temp_datafile;
2736 pstring temp_configfile;
2738 info->version=driver.info_3->cversion;
2740 init_unistr( &info->name, driver.info_3->name );
2741 init_unistr( &info->architecture, driver.info_3->environment );
2743 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2744 init_unistr( &info->driverpath, temp_driverpath );
2746 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2747 init_unistr( &info->datafile, temp_datafile );
2749 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2750 init_unistr( &info->configfile, temp_configfile );
2753 /********************************************************************
2754 * construct_printer_driver_info_2
2755 * fill a printer_info_2 struct
2756 ********************************************************************/
2757 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2759 NT_PRINTER_INFO_LEVEL *printer = NULL;
2760 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2762 ZERO_STRUCT(printer);
2763 ZERO_STRUCT(driver);
2765 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2766 return ERROR_INVALID_PRINTER_NAME;
2768 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2769 return ERROR_UNKNOWN_PRINTER_DRIVER;
2771 fill_printer_driver_info_2(info, driver, servername);
2773 free_a_printer(&printer,2);
2775 return NT_STATUS_NO_PROBLEMO;
2778 /********************************************************************
2779 * copy a strings array and convert to UNICODE
2781 * convert an array of ascii string to a UNICODE string
2782 ********************************************************************/
2783 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2790 DEBUG(6,("init_unistr_array\n"));
2794 if (char_array == NULL)
2798 if (!v) v = ""; /* hack to handle null lists */
2800 if (strlen(v) == 0) break;
2801 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2802 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2803 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2804 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2807 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2812 (*uni_array)[j]=0x0000;
2815 DEBUGADD(6,("last one:done\n"));
2818 /********************************************************************
2819 * construct_printer_info_3
2820 * fill a printer_info_3 struct
2821 ********************************************************************/
2822 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2824 pstring temp_driverpath;
2825 pstring temp_datafile;
2826 pstring temp_configfile;
2827 pstring temp_helpfile;
2831 info->version=driver.info_3->cversion;
2833 init_unistr( &info->name, driver.info_3->name );
2834 init_unistr( &info->architecture, driver.info_3->environment );
2836 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2837 init_unistr( &info->driverpath, temp_driverpath );
2839 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2840 init_unistr( &info->datafile, temp_datafile );
2842 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2843 init_unistr( &info->configfile, temp_configfile );
2845 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2846 init_unistr( &info->helpfile, temp_helpfile );
2848 init_unistr( &info->monitorname, driver.info_3->monitorname );
2849 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2851 info->dependentfiles=NULL;
2852 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2855 /********************************************************************
2856 * construct_printer_info_3
2857 * fill a printer_info_3 struct
2858 ********************************************************************/
2859 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2861 NT_PRINTER_INFO_LEVEL *printer = NULL;
2862 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2864 ZERO_STRUCT(driver);
2866 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2867 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2869 return ERROR_INVALID_PRINTER_NAME;
2871 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2872 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2874 free_a_printer(&printer,2);
2875 return ERROR_UNKNOWN_PRINTER_DRIVER;
2878 fill_printer_driver_info_3(info, driver, servername);
2880 free_a_printer(&printer,2);
2882 return NT_STATUS_NO_PROBLEMO;
2885 /********************************************************************
2886 * construct_printer_info_6
2887 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2888 ********************************************************************/
2890 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2892 pstring temp_driverpath;
2893 pstring temp_datafile;
2894 pstring temp_configfile;
2895 pstring temp_helpfile;
2899 memset(&nullstr, '\0', sizeof(fstring));
2901 info->version=driver.info_3->cversion;
2903 init_unistr( &info->name, driver.info_3->name );
2904 init_unistr( &info->architecture, driver.info_3->environment );
2906 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2907 init_unistr( &info->driverpath, temp_driverpath );
2909 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2910 init_unistr( &info->datafile, temp_datafile );
2912 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2913 init_unistr( &info->configfile, temp_configfile );
2915 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2916 init_unistr( &info->helpfile, temp_helpfile );
2918 init_unistr( &info->monitorname, driver.info_3->monitorname );
2919 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2921 info->dependentfiles=NULL;
2922 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2924 info->previousdrivernames=NULL;
2925 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2927 info->driver_date.low=0;
2928 info->driver_date.high=0;
2931 info->driver_version_low=0;
2932 info->driver_version_high=0;
2934 init_unistr( &info->mfgname, "");
2935 init_unistr( &info->oem_url, "");
2936 init_unistr( &info->hardware_id, "");
2937 init_unistr( &info->provider, "");
2940 /********************************************************************
2941 * construct_printer_info_6
2942 * fill a printer_info_6 struct
2943 ********************************************************************/
2944 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2946 NT_PRINTER_INFO_LEVEL *printer = NULL;
2947 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2949 ZERO_STRUCT(driver);
2951 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2952 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2954 return ERROR_INVALID_PRINTER_NAME;
2956 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2957 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2959 free_a_printer(&printer,2);
2960 return ERROR_UNKNOWN_PRINTER_DRIVER;
2963 fill_printer_driver_info_6(info, driver, servername);
2965 free_a_printer(&printer,2);
2967 return NT_STATUS_NO_PROBLEMO;
2970 /****************************************************************************
2971 ****************************************************************************/
2973 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2975 safe_free(info->dependentfiles);
2978 /****************************************************************************
2979 ****************************************************************************/
2981 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2983 safe_free(info->dependentfiles);
2987 /****************************************************************************
2988 ****************************************************************************/
2989 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2991 DRIVER_INFO_1 *info=NULL;
2994 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2995 return ERROR_NOT_ENOUGH_MEMORY;
2997 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2998 if (status != NT_STATUS_NO_PROBLEMO) {
3003 /* check the required size. */
3004 *needed += spoolss_size_printer_driver_info_1(info);
3006 if (!alloc_buffer_size(buffer, *needed)) {
3008 return ERROR_INSUFFICIENT_BUFFER;
3011 /* fill the buffer with the structures */
3012 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3017 if (*needed > offered)
3018 return ERROR_INSUFFICIENT_BUFFER;
3020 return NT_STATUS_NO_PROBLEMO;
3023 /****************************************************************************
3024 ****************************************************************************/
3025 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3027 DRIVER_INFO_2 *info=NULL;
3030 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3031 return ERROR_NOT_ENOUGH_MEMORY;
3033 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3034 if (status != NT_STATUS_NO_PROBLEMO) {
3039 /* check the required size. */
3040 *needed += spoolss_size_printer_driver_info_2(info);
3042 if (!alloc_buffer_size(buffer, *needed)) {
3044 return ERROR_INSUFFICIENT_BUFFER;
3047 /* fill the buffer with the structures */
3048 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3053 if (*needed > offered)
3054 return ERROR_INSUFFICIENT_BUFFER;
3056 return NT_STATUS_NO_PROBLEMO;
3059 /****************************************************************************
3060 ****************************************************************************/
3061 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3068 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3069 if (status != NT_STATUS_NO_PROBLEMO) {
3073 /* check the required size. */
3074 *needed += spoolss_size_printer_driver_info_3(&info);
3076 if (!alloc_buffer_size(buffer, *needed)) {
3077 free_printer_driver_info_3(&info);
3078 return ERROR_INSUFFICIENT_BUFFER;
3081 /* fill the buffer with the structures */
3082 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3084 free_printer_driver_info_3(&info);
3086 if (*needed > offered)
3087 return ERROR_INSUFFICIENT_BUFFER;
3089 return NT_STATUS_NO_PROBLEMO;
3092 /****************************************************************************
3093 ****************************************************************************/
3094 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3101 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3102 if (status != NT_STATUS_NO_PROBLEMO) {
3106 /* check the required size. */
3107 *needed += spoolss_size_printer_driver_info_6(&info);
3109 if (!alloc_buffer_size(buffer, *needed)) {
3110 free_printer_driver_info_6(&info);
3111 return ERROR_INSUFFICIENT_BUFFER;
3114 /* fill the buffer with the structures */
3115 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3117 free_printer_driver_info_6(&info);
3119 if (*needed > offered)
3120 return ERROR_INSUFFICIENT_BUFFER;
3122 return NT_STATUS_NO_PROBLEMO;
3125 /****************************************************************************
3126 ****************************************************************************/
3127 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3128 uint32 clientmajorversion, uint32 clientminorversion,
3129 NEW_BUFFER *buffer, uint32 offered,
3130 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3133 fstring architecture;
3136 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3139 *servermajorversion=0;
3140 *serverminorversion=0;
3142 pstrcpy(servername, global_myname);
3143 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3145 if (!get_printer_snum(handle, &snum))
3146 return ERROR_INVALID_HANDLE;
3150 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3152 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3154 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3156 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3158 return ERROR_INVALID_LEVEL;
3162 /****************************************************************************
3163 ****************************************************************************/
3164 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3166 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3168 if (OPEN_HANDLE(Printer)) {
3169 Printer->page_started=True;
3173 DEBUG(3,("Error in startpageprinter printer handle\n"));
3174 return ERROR_INVALID_HANDLE;
3177 /****************************************************************************
3178 ****************************************************************************/
3179 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3181 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3183 if (!OPEN_HANDLE(Printer)) {
3184 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3185 return ERROR_INVALID_HANDLE;
3188 Printer->page_started=False;
3190 return NT_STATUS_NO_PROBLEMO;
3193 /****************************************************************************
3194 Return a user struct for a pipe user.
3195 ****************************************************************************/
3197 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3199 if (p->ntlmssp_auth_validated) {
3200 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3202 extern struct current_user current_user;
3203 memcpy(user, ¤t_user, sizeof(struct current_user));
3209 /********************************************************************
3210 * api_spoolss_getprinter
3211 * called from the spoolss dispatcher
3213 ********************************************************************/
3214 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3215 pipes_struct *p, DOC_INFO *docinfo,
3218 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3222 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3223 struct current_user user;
3225 if (!OPEN_HANDLE(Printer)) {
3226 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3227 return ERROR_INVALID_HANDLE;
3230 get_current_user(&user, p);
3233 * a nice thing with NT is it doesn't listen to what you tell it.
3234 * when asked to send _only_ RAW datas, it tries to send datas
3237 * So I add checks like in NT Server ...
3239 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3240 * there's a bug in NT client-side code, so we'll fix it in the
3241 * server-side code. *nnnnnggggh!*
3244 if (info_1->p_datatype != 0) {
3245 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3246 if (strcmp(datatype, "RAW") != 0) {
3248 return ERROR_INVALID_DATATYPE;
3252 /* get the share number of the printer */
3253 if (!get_printer_snum(handle, &snum)) {
3254 return ERROR_INVALID_HANDLE;
3257 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3259 Printer->jobid = print_job_start(&user, snum, jobname);
3261 /* An error occured in print_job_start() so return an appropriate
3264 if (Printer->jobid == -1) {
3265 return map_nt_error_from_unix(errno);
3268 Printer->document_started=True;
3269 (*jobid) = Printer->jobid;
3271 srv_spoolss_sendnotify(handle);
3275 /********************************************************************
3276 * api_spoolss_getprinter
3277 * called from the spoolss dispatcher
3279 ********************************************************************/
3280 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3282 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3284 if (!OPEN_HANDLE(Printer)) {
3285 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3286 return ERROR_INVALID_HANDLE;
3289 Printer->document_started=False;
3290 print_job_end(Printer->jobid);
3291 /* error codes unhandled so far ... */
3293 srv_spoolss_sendnotify(handle);
3298 /****************************************************************************
3299 ****************************************************************************/
3300 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3303 uint32 *buffer_written)
3305 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3307 if (!OPEN_HANDLE(Printer)) {
3308 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3309 return ERROR_INVALID_HANDLE;
3312 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3318 /********************************************************************
3319 * api_spoolss_getprinter
3320 * called from the spoolss dispatcher
3322 ********************************************************************/
3323 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3326 struct current_user user;
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)) {
3344 srv_spoolss_sendnotify(handle);
3348 case PRINTER_CONTROL_RESUME:
3349 case PRINTER_CONTROL_UNPAUSE:
3350 if (print_queue_resume(&user, snum, &errcode)) {
3351 srv_spoolss_sendnotify(handle);
3355 case PRINTER_CONTROL_PURGE:
3356 if (print_queue_purge(&user, snum, &errcode)) {
3357 srv_spoolss_sendnotify(handle);
3364 return (uint32)errcode;
3366 return ERROR_INVALID_FUNCTION;
3369 /********************************************************************
3370 * api_spoolss_abortprinter
3371 ********************************************************************/
3373 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3375 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3378 /********************************************************************
3379 * called by spoolss_api_setprinter
3380 * when updating a printer description
3381 ********************************************************************/
3382 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3383 const SPOOL_PRINTER_INFO_LEVEL *info,
3384 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3386 struct current_user user;
3390 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3392 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3393 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3394 return ERROR_INVALID_HANDLE;
3397 /* Work out which user is performing the operation */
3398 get_current_user(&user, p);
3400 /* Check the user has permissions to change the security
3401 descriptor. By experimentation with two NT machines, the user
3402 requires Full Access to the printer to change security
3404 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3405 result = ERROR_ACCESS_DENIED;
3409 result = nt_printing_setsec(Printer->dev.handlename, secdesc_ctr);
3415 /********************************************************************
3416 Do Samba sanity checks on a printer info struct.
3417 ********************************************************************/
3419 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3422 * Ensure that this printer is shared under the correct name
3423 * as this is what Samba insists upon.
3426 if (!(info->attributes & (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_NETWORK))) {
3427 DEBUG(10,("check_printer_ok: SHARED/NETWORK check failed (%x).\n",
3428 (unsigned int)info->attributes ));
3432 if (!(info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY)) {
3433 /* NT forgets to set the raw attribute but sends the correct type. */
3434 if (strequal(info->datatype, "RAW"))
3435 info->attributes |= PRINTER_ATTRIBUTE_RAW_ONLY;
3437 DEBUG(10,("check_printer_ok: RAW check failed (%x).\n", (unsigned int)info->attributes ));
3443 * Sometimes the NT client doesn't set the sharename, but
3444 * includes the sharename in the printername. This could
3445 * cause SETPRINTER to fail which causes problems with the
3446 * client getting confused between local/remote printers...
3449 if (*info->sharename == '\0') {
3450 char *p = strrchr(info->printername, '\\');
3452 fstrcpy(info->sharename, p+1);
3455 if (!strequal(info->sharename, lp_servicename(snum))) {
3456 DEBUG(10,("check_printer_ok: NAME check failed (%s) (%s).\n",
3457 info->sharename, lp_servicename(snum)));
3464 /****************************************************************************
3465 ****************************************************************************/
3466 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3468 pid_t local_pid = sys_getpid();
3469 char *cmd = lp_addprinter_cmd();
3474 pstring driverlocation;
3478 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3479 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3483 /* build driver path... only 9X architecture is needed for legacy reasons */
3484 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3486 /* change \ to \\ for the shell */
3487 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3489 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3490 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3491 cmd, printer->info_2->printername, printer->info_2->sharename,
3492 printer->info_2->portname, printer->info_2->drivername,
3493 printer->info_2->location, driverlocation);
3496 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3497 ret = smbrun(command, tmp_file, False);
3498 DEBUGADD(10,("returned [%d]\n", ret));
3506 qlines = file_lines_load(tmp_file, &numlines);
3507 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3508 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3512 /* Set the portname to what the script says the portname should be. */
3513 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3514 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3516 /* Send SIGHUP to process group... is there a better way? */
3521 file_lines_free(qlines);
3525 /********************************************************************
3526 * called by spoolss_api_setprinter
3527 * when updating a printer description
3528 ********************************************************************/
3530 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3531 const SPOOL_PRINTER_INFO_LEVEL *info,
3532 DEVICEMODE *devmode)
3535 NT_PRINTER_INFO_LEVEL *printer = NULL;
3536 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3539 DEBUG(8,("update_printer\n"));
3541 result = NT_STATUS_NO_PROBLEMO;
3543 /* Check calling user has permission to update printer description */
3546 DEBUG(0,("Send a mail to samba@samba.org\n"));
3547 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3548 result = ERROR_INVALID_LEVEL;
3552 if (!OPEN_HANDLE(Printer)) {
3553 result = ERROR_INVALID_HANDLE;
3557 if (!get_printer_snum(handle, &snum)) {
3558 result = ERROR_INVALID_HANDLE;
3562 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3563 DEBUG(3, ("printer property change denied by security "
3565 result = ERROR_ACCESS_DENIED;
3569 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0) {
3570 result = ERROR_INVALID_HANDLE;
3574 DEBUGADD(8,("Converting info_2 struct\n"));
3577 * convert_printer_info converts the incoming
3578 * info from the client and overwrites the info
3579 * just read from the tdb in the pointer 'printer'.
3582 convert_printer_info(info, printer, level);
3584 if (info->info_2->devmode_ptr != 0) {
3585 /* we have a valid devmode
3586 convert it and link it*/
3589 * Ensure printer->info_2->devmode is a valid pointer
3590 * as we will be overwriting it in convert_devicemode().
3593 if (printer->info_2->devmode == NULL)
3594 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3596 DEBUGADD(8,("Converting the devicemode struct\n"));
3597 convert_devicemode(devmode, printer->info_2->devmode);
3600 if (printer->info_2->devmode != NULL)
3601 free_nt_devicemode(&printer->info_2->devmode);
3602 printer->info_2->devmode=NULL;
3606 * Do sanity check on the requested changes for Samba.
3609 if (!check_printer_ok(printer->info_2, snum)) {
3610 result = ERROR_INVALID_PARAMETER;
3614 if (*lp_addprinter_cmd() )
3615 if ( !add_printer_hook(printer) ) {
3616 result = ERROR_ACCESS_DENIED;
3620 if (add_a_printer(*printer, 2)!=0) {
3621 /* I don't really know what to return here !!! */
3622 result = ERROR_ACCESS_DENIED;
3627 free_a_printer(&printer, 2);
3629 srv_spoolss_sendnotify(handle);
3634 /****************************************************************************
3635 ****************************************************************************/
3636 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3637 const SPOOL_PRINTER_INFO_LEVEL *info,
3638 DEVMODE_CTR devmode_ctr,
3639 SEC_DESC_BUF *secdesc_ctr,
3640 uint32 command, pipes_struct *p)
3642 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3644 if (!OPEN_HANDLE(Printer)) {
3645 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3646 return ERROR_INVALID_HANDLE;
3649 /* check the level */
3652 return control_printer(handle, command, p);
3654 return update_printer(handle, level, info, devmode_ctr.devmode);
3656 return update_printer_sec(handle, level, info, p,
3659 return ERROR_INVALID_LEVEL;
3663 /****************************************************************************
3664 ****************************************************************************/
3665 uint32 _spoolss_fcpn(POLICY_HND *handle)
3667 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3669 if (!OPEN_HANDLE(Printer)) {
3670 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3671 return ERROR_INVALID_HANDLE;
3674 if (Printer->notify.client_connected==True)
3675 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3676 return ERROR_INVALID_HANDLE;
3678 Printer->notify.flags=0;
3679 Printer->notify.options=0;
3680 Printer->notify.localmachine[0]='\0';
3681 Printer->notify.printerlocal=0;
3682 if (Printer->notify.option)
3683 safe_free(Printer->notify.option->ctr.type);
3684 safe_free(Printer->notify.option);
3685 Printer->notify.option=NULL;
3686 Printer->notify.client_connected=False;
3688 return NT_STATUS_NO_PROBLEMO;
3691 /****************************************************************************
3692 ****************************************************************************/
3693 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3694 NEW_BUFFER *buffer, uint32 offered,
3698 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3699 returns for AddJob. AddJob
3700 must fail on non-local
3704 /****************************************************************************
3705 ****************************************************************************/
3706 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3707 int position, int snum)
3713 t=gmtime(&queue->time);
3714 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3716 job_info->jobid=queue->job;
3717 init_unistr(&job_info->printername, lp_servicename(snum));
3718 init_unistr(&job_info->machinename, temp_name);
3719 init_unistr(&job_info->username, queue->user);
3720 init_unistr(&job_info->document, queue->file);
3721 init_unistr(&job_info->datatype, "RAW");
3722 init_unistr(&job_info->text_status, "");
3723 job_info->status=nt_printj_status(queue->status);
3724 job_info->priority=queue->priority;
3725 job_info->position=position;
3726 job_info->totalpages=0;
3727 job_info->pagesprinted=0;
3729 make_systemtime(&job_info->submitted, t);
3732 /****************************************************************************
3733 ****************************************************************************/
3734 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3735 int position, int snum)
3738 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3742 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3745 t=gmtime(&queue->time);
3746 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3748 job_info->jobid=queue->job;
3750 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3752 init_unistr(&job_info->printername, chaine);
3754 init_unistr(&job_info->machinename, temp_name);
3755 init_unistr(&job_info->username, queue->user);
3756 init_unistr(&job_info->document, queue->file);
3757 init_unistr(&job_info->notifyname, queue->user);
3758 init_unistr(&job_info->datatype, "RAW");
3759 init_unistr(&job_info->printprocessor, "winprint");
3760 init_unistr(&job_info->parameters, "");
3761 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3762 init_unistr(&job_info->text_status, "");
3764 /* and here the security descriptor */
3766 job_info->status=nt_printj_status(queue->status);
3767 job_info->priority=queue->priority;
3768 job_info->position=position;
3769 job_info->starttime=0;
3770 job_info->untiltime=0;
3771 job_info->totalpages=0;
3772 job_info->size=queue->size;
3773 make_systemtime(&(job_info->submitted), t);
3774 job_info->timeelapsed=0;
3775 job_info->pagesprinted=0;
3777 if((job_info->devmode = construct_dev_mode(snum, global_myname)) == NULL) {
3778 free_a_printer(&ntprinter, 2);
3782 free_a_printer(&ntprinter, 2);
3786 /****************************************************************************
3787 Enumjobs at level 1.
3788 ****************************************************************************/
3789 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3790 NEW_BUFFER *buffer, uint32 offered,
3791 uint32 *needed, uint32 *returned)
3796 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3800 return ERROR_NOT_ENOUGH_MEMORY;
3803 for (i=0; i<*returned; i++)
3804 fill_job_info_1(&info[i], &queue[i], i, snum);
3808 /* check the required size. */
3809 for (i=0; i<*returned; i++)
3810 (*needed) += spoolss_size_job_info_1(&info[i]);
3812 if (!alloc_buffer_size(buffer, *needed)) {
3814 return ERROR_INSUFFICIENT_BUFFER;
3817 /* fill the buffer with the structures */
3818 for (i=0; i<*returned; i++)
3819 new_smb_io_job_info_1("", buffer, &info[i], 0);
3824 if (*needed > offered) {
3826 return ERROR_INSUFFICIENT_BUFFER;
3829 return NT_STATUS_NO_PROBLEMO;
3832 /****************************************************************************
3833 Enumjobs at level 2.
3834 ****************************************************************************/
3835 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
3836 NEW_BUFFER *buffer, uint32 offered,
3837 uint32 *needed, uint32 *returned)
3842 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
3846 return ERROR_NOT_ENOUGH_MEMORY;
3849 for (i=0; i<*returned; i++)
3850 fill_job_info_2(&(info[i]), &queue[i], i, snum);
3854 /* check the required size. */
3855 for (i=0; i<*returned; i++)
3856 (*needed) += spoolss_size_job_info_2(&info[i]);
3858 if (!alloc_buffer_size(buffer, *needed)) {
3860 return ERROR_INSUFFICIENT_BUFFER;
3863 /* fill the buffer with the structures */
3864 for (i=0; i<*returned; i++)
3865 new_smb_io_job_info_2("", buffer, &info[i], 0);
3870 if (*needed > offered) {
3872 return ERROR_INSUFFICIENT_BUFFER;
3875 return NT_STATUS_NO_PROBLEMO;
3878 /****************************************************************************
3880 ****************************************************************************/
3881 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
3882 NEW_BUFFER *buffer, uint32 offered,
3883 uint32 *needed, uint32 *returned)
3886 print_queue_struct *queue=NULL;
3887 print_status_struct prt_status;
3889 DEBUG(4,("_spoolss_enumjobs\n"));
3891 ZERO_STRUCT(prt_status);
3896 if (!get_printer_snum(handle, &snum))
3897 return ERROR_INVALID_HANDLE;
3899 *returned = print_queue_status(snum, &queue, &prt_status);
3900 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
3902 if (*returned == 0) {
3904 return NT_STATUS_NO_PROBLEMO;
3909 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
3911 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
3915 return ERROR_INVALID_LEVEL;
3920 /****************************************************************************
3921 ****************************************************************************/
3922 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
3927 /****************************************************************************
3928 ****************************************************************************/
3929 uint32 _spoolss_setjob( POLICY_HND *handle,
3937 struct current_user user;
3939 print_status_struct prt_status;
3941 memset(&prt_status, 0, sizeof(prt_status));
3943 if (!get_printer_snum(handle, &snum)) {
3944 return ERROR_INVALID_HANDLE;
3947 if (!print_job_exists(jobid)) {
3948 return ERROR_INVALID_PRINTER_NAME;
3951 get_current_user(&user, p);
3954 case JOB_CONTROL_CANCEL:
3955 case JOB_CONTROL_DELETE:
3956 if (print_job_delete(&user, jobid)) {
3957 srv_spoolss_sendnotify(handle);
3961 case JOB_CONTROL_PAUSE:
3962 if (print_job_pause(&user, jobid)) {
3963 srv_spoolss_sendnotify(handle);
3967 case JOB_CONTROL_RESUME:
3968 if (print_job_resume(&user, jobid)) {
3969 srv_spoolss_sendnotify(handle);
3974 return ERROR_INVALID_LEVEL;
3977 return ERROR_INVALID_HANDLE;
3980 /****************************************************************************
3981 Enumerates all printer drivers at level 1.
3982 ****************************************************************************/
3983 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3988 fstring *list = NULL;
3990 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3991 DRIVER_INFO_1 *driver_info_1=NULL;
3995 #define MAX_VERSION 4
3997 for (version=0; version<MAX_VERSION; version++) {
3999 ndrivers=get_ntdrivers(&list, architecture, version);
4000 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4003 return ERROR_NOT_ENOUGH_MEMORY;
4006 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4008 return ERROR_NOT_ENOUGH_MEMORY;
4012 for (i=0; i<ndrivers; i++) {
4014 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4015 ZERO_STRUCT(driver);
4016 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4020 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4021 free_a_printer_driver(driver, 3);
4024 *returned+=ndrivers;
4028 /* check the required size. */
4029 for (i=0; i<*returned; i++) {
4030 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4031 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4034 if (!alloc_buffer_size(buffer, *needed)) {
4035 safe_free(driver_info_1);
4036 return ERROR_INSUFFICIENT_BUFFER;
4039 /* fill the buffer with the form structures */
4040 for (i=0; i<*returned; i++) {
4041 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4042 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4045 safe_free(driver_info_1);
4047 if (*needed > offered) {
4049 return ERROR_INSUFFICIENT_BUFFER;
4052 return NT_STATUS_NO_PROBLEMO;
4055 /****************************************************************************
4056 Enumerates all printer drivers at level 2.
4057 ****************************************************************************/
4058 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4063 fstring *list = NULL;
4065 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4066 DRIVER_INFO_2 *driver_info_2=NULL;
4070 #define MAX_VERSION 4
4072 for (version=0; version<MAX_VERSION; version++) {
4074 ndrivers=get_ntdrivers(&list, architecture, version);
4075 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4078 return ERROR_NOT_ENOUGH_MEMORY;
4081 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4083 return ERROR_NOT_ENOUGH_MEMORY;
4087 for (i=0; i<ndrivers; i++) {
4090 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4091 ZERO_STRUCT(driver);
4092 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4096 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4097 free_a_printer_driver(driver, 3);
4100 *returned+=ndrivers;
4104 /* check the required size. */
4105 for (i=0; i<*returned; i++) {
4106 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4107 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4110 if (!alloc_buffer_size(buffer, *needed)) {
4111 safe_free(driver_info_2);
4112 return ERROR_INSUFFICIENT_BUFFER;
4115 /* fill the buffer with the form structures */
4116 for (i=0; i<*returned; i++) {
4117 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4118 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4121 safe_free(driver_info_2);
4123 if (*needed > offered) {
4125 return ERROR_INSUFFICIENT_BUFFER;
4128 return NT_STATUS_NO_PROBLEMO;
4131 /****************************************************************************
4132 Enumerates all printer drivers at level 3.
4133 ****************************************************************************/
4134 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4139 fstring *list = NULL;
4141 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4142 DRIVER_INFO_3 *driver_info_3=NULL;
4146 #define MAX_VERSION 4
4148 for (version=0; version<MAX_VERSION; version++) {
4150 ndrivers=get_ntdrivers(&list, architecture, version);
4151 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4154 return ERROR_NOT_ENOUGH_MEMORY;
4157 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4159 return ERROR_NOT_ENOUGH_MEMORY;
4163 for (i=0; i<ndrivers; i++) {
4166 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4167 ZERO_STRUCT(driver);
4168 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4172 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4173 free_a_printer_driver(driver, 3);
4176 *returned+=ndrivers;
4180 /* check the required size. */
4181 for (i=0; i<*returned; i++) {
4182 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4183 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4186 if (!alloc_buffer_size(buffer, *needed)) {
4187 safe_free(driver_info_3);
4188 return ERROR_INSUFFICIENT_BUFFER;
4191 /* fill the buffer with the driver structures */
4192 for (i=0; i<*returned; i++) {
4193 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4194 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4197 for (i=0; i<*returned; i++)
4198 safe_free(driver_info_3[i].dependentfiles);
4200 safe_free(driver_info_3);
4202 if (*needed > offered) {
4204 return ERROR_INSUFFICIENT_BUFFER;
4207 return NT_STATUS_NO_PROBLEMO;
4210 /****************************************************************************
4211 Enumerates all printer drivers.
4212 ****************************************************************************/
4213 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4214 NEW_BUFFER *buffer, uint32 offered,
4215 uint32 *needed, uint32 *returned)
4217 fstring *list = NULL;
4219 fstring architecture;
4221 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4222 fstrcpy(servername, global_myname);
4226 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4230 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4232 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4234 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4238 return ERROR_INVALID_LEVEL;
4242 /****************************************************************************
4243 ****************************************************************************/
4244 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4246 form->flag=list->flag;
4247 init_unistr(&form->name, list->name);
4248 form->width=list->width;
4249 form->length=list->length;
4250 form->left=list->left;
4251 form->top=list->top;
4252 form->right=list->right;
4253 form->bottom=list->bottom;
4256 /****************************************************************************
4257 ****************************************************************************/
4258 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4259 NEW_BUFFER *buffer, uint32 offered,
4260 uint32 *needed, uint32 *numofforms)
4262 nt_forms_struct *list=NULL;
4267 DEBUG(4,("_new_spoolss_enumforms\n"));
4268 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4269 DEBUGADD(5,("Info level [%d]\n", level));
4271 *numofforms = get_ntforms(&list);
4272 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4274 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4278 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4280 return ERROR_NOT_ENOUGH_MEMORY;
4283 /* construct the list of form structures */
4284 for (i=0; i<*numofforms; i++) {
4285 DEBUGADD(6,("Filling form number [%d]\n",i));
4286 fill_form_1(&forms_1[i], &list[i]);
4291 /* check the required size. */
4292 for (i=0; i<*numofforms; i++) {
4293 DEBUGADD(6,("adding form [%d]'s size\n",i));
4294 buffer_size += spoolss_size_form_1(&forms_1[i]);
4297 *needed=buffer_size;
4299 if (!alloc_buffer_size(buffer, buffer_size)){
4301 return ERROR_INSUFFICIENT_BUFFER;
4304 /* fill the buffer with the form structures */
4305 for (i=0; i<*numofforms; i++) {
4306 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4307 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4312 if (*needed > offered) {
4314 return ERROR_INSUFFICIENT_BUFFER;
4317 return NT_STATUS_NO_PROBLEMO;
4321 return ERROR_INVALID_LEVEL;
4326 /****************************************************************************
4327 ****************************************************************************/
4328 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4330 nt_forms_struct *list=NULL;
4336 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4338 DEBUG(4,("_spoolss_getform\n"));
4339 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4340 DEBUGADD(5,("Info level [%d]\n", level));
4342 numofforms = get_ntforms(&list);
4343 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4345 if (numofforms == 0)
4346 return ERROR_NO_MORE_ITEMS;
4351 /* Check if the requested name is in the list of form structures */
4352 for (i=0; i<numofforms; i++) {
4354 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4356 if (strequal(form_name, list[i].name)) {
4357 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4358 fill_form_1(&form_1, &list[i]);
4365 /* check the required size. */
4367 *needed=spoolss_size_form_1(&form_1);
4369 if (!alloc_buffer_size(buffer, buffer_size)){
4370 return ERROR_INSUFFICIENT_BUFFER;
4373 if (*needed > offered) {
4374 return ERROR_INSUFFICIENT_BUFFER;
4377 /* fill the buffer with the form structures */
4378 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4379 new_smb_io_form_1("", buffer, &form_1, 0);
4381 return NT_STATUS_NO_PROBLEMO;
4385 return ERROR_INVALID_LEVEL;
4389 /****************************************************************************
4390 ****************************************************************************/
4391 static void fill_port_1(PORT_INFO_1 *port, char *name)
4393 init_unistr(&port->port_name, name);
4396 /****************************************************************************
4397 ****************************************************************************/
4398 static void fill_port_2(PORT_INFO_2 *port, char *name)
4400 init_unistr(&port->port_name, name);
4401 init_unistr(&port->monitor_name, "Local Monitor");
4402 init_unistr(&port->description, "Local Port");
4403 #define PORT_TYPE_WRITE 1
4404 port->port_type=PORT_TYPE_WRITE;
4408 /****************************************************************************
4410 ****************************************************************************/
4411 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4413 PORT_INFO_1 *ports=NULL;
4416 if (*lp_enumports_cmd()) {
4417 pid_t local_pid = sys_getpid();
4418 char *cmd = lp_enumports_cmd();
4426 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4427 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4431 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4432 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4435 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4436 ret = smbrun(command, tmp_file, False);
4437 DEBUG(10,("Returned [%d]\n", ret));
4440 /* Is this the best error to return here? */
4441 return ERROR_ACCESS_DENIED;
4445 qlines = file_lines_load(tmp_file, &numlines);
4446 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4447 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4451 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4452 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4453 file_lines_free(qlines);
4454 return ERROR_NOT_ENOUGH_MEMORY;
4457 for (i=0; i<numlines; i++) {
4458 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4459 fill_port_1(&ports[i], qlines[i]);
4462 file_lines_free(qlines);
4465 *returned = numlines;
4468 *returned = 1; /* Sole Samba port returned. */
4470 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4471 return ERROR_NOT_ENOUGH_MEMORY;
4473 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4475 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4478 /* check the required size. */
4479 for (i=0; i<*returned; i++) {
4480 DEBUGADD(6,("adding port [%d]'s size\n", i));
4481 *needed += spoolss_size_port_info_1(&ports[i]);
4484 if (!alloc_buffer_size(buffer, *needed)) {
4486 return ERROR_INSUFFICIENT_BUFFER;
4489 /* fill the buffer with the ports structures */
4490 for (i=0; i<*returned; i++) {
4491 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4492 new_smb_io_port_1("", buffer, &ports[i], 0);
4497 if (*needed > offered) {
4499 return ERROR_INSUFFICIENT_BUFFER;
4502 return NT_STATUS_NO_PROBLEMO;
4505 /****************************************************************************
4507 ****************************************************************************/
4509 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4511 PORT_INFO_2 *ports=NULL;
4514 if (*lp_enumports_cmd()) {
4515 pid_t local_pid = sys_getpid();
4516 char *cmd = lp_enumports_cmd();
4524 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4525 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4529 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4530 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4533 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4534 ret = smbrun(command, tmp_file, False);
4535 DEBUGADD(10,("returned [%d]\n", ret));
4538 /* Is this the best error to return here? */
4539 return ERROR_ACCESS_DENIED;
4543 qlines = file_lines_load(tmp_file, &numlines);
4544 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4545 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4549 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4550 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4551 file_lines_free(qlines);
4552 return ERROR_NOT_ENOUGH_MEMORY;
4555 for (i=0; i<numlines; i++) {
4556 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4557 fill_port_2(&(ports[i]), qlines[i]);
4560 file_lines_free(qlines);
4563 *returned = numlines;
4569 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4570 return ERROR_NOT_ENOUGH_MEMORY;
4572 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4574 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4577 /* check the required size. */
4578 for (i=0; i<*returned; i++) {
4579 DEBUGADD(6,("adding port [%d]'s size\n", i));
4580 *needed += spoolss_size_port_info_2(&ports[i]);
4583 if (!alloc_buffer_size(buffer, *needed)) {
4585 return ERROR_INSUFFICIENT_BUFFER;
4588 /* fill the buffer with the ports structures */
4589 for (i=0; i<*returned; i++) {
4590 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4591 new_smb_io_port_2("", buffer, &ports[i], 0);
4596 if (*needed > offered) {
4598 return ERROR_INSUFFICIENT_BUFFER;
4601 return NT_STATUS_NO_PROBLEMO;
4604 /****************************************************************************
4606 ****************************************************************************/
4607 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4608 NEW_BUFFER *buffer, uint32 offered,
4609 uint32 *needed, uint32 *returned)
4611 DEBUG(4,("_spoolss_enumports\n"));
4618 return enumports_level_1(buffer, offered, needed, returned);
4620 return enumports_level_2(buffer, offered, needed, returned);
4622 return ERROR_INVALID_LEVEL;
4626 /****************************************************************************
4627 ****************************************************************************/
4628 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4629 const SPOOL_PRINTER_INFO_LEVEL *info,
4630 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4631 uint32 user_switch, const SPOOL_USER_CTR *user,
4634 NT_PRINTER_INFO_LEVEL *printer = NULL;
4638 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4639 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4640 return ERROR_NOT_ENOUGH_MEMORY;
4643 ZERO_STRUCTP(printer);
4645 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4646 convert_printer_info(info, printer, 2);
4648 if (*lp_addprinter_cmd() )
4649 if ( !add_printer_hook(printer) ) {
4650 free_a_printer(&printer,2);
4651 return ERROR_ACCESS_DENIED;
4654 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4655 printer->info_2->sharename);
4657 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4658 free_a_printer(&printer,2);
4659 return ERROR_ACCESS_DENIED;
4662 /* you must be a printer admin to add a new printer */
4663 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4664 free_a_printer(&printer,2);
4665 return ERROR_ACCESS_DENIED;
4669 * Do sanity check on the requested changes for Samba.
4672 if (!check_printer_ok(printer->info_2, snum)) {
4673 free_a_printer(&printer,2);
4674 return ERROR_INVALID_PARAMETER;
4677 /* write the ASCII on disk */
4678 if (add_a_printer(*printer, 2) != 0) {
4679 free_a_printer(&printer,2);
4680 return ERROR_ACCESS_DENIED;
4683 if (!open_printer_hnd(handle, name)) {
4684 /* Handle open failed - remove addition. */
4685 del_a_printer(printer->info_2->sharename);
4686 free_a_printer(&printer,2);
4687 return ERROR_ACCESS_DENIED;
4690 free_a_printer(&printer,2);
4692 srv_spoolss_sendnotify(handle);
4694 return NT_STATUS_NO_PROBLEMO;
4697 /****************************************************************************
4698 ****************************************************************************/
4699 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4700 const SPOOL_PRINTER_INFO_LEVEL *info,
4701 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4702 uint32 user_switch, const SPOOL_USER_CTR *user,
4707 /* we don't handle yet */
4708 /* but I know what to do ... */
4709 return ERROR_INVALID_LEVEL;
4711 return spoolss_addprinterex_level_2(uni_srv_name, info,
4712 unk0, unk1, unk2, unk3,
4713 user_switch, user, handle);
4715 return ERROR_INVALID_LEVEL;
4719 /****************************************************************************
4720 ****************************************************************************/
4721 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4722 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4724 uint32 err = NT_STATUS_NO_PROBLEMO;
4725 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4726 struct current_user user;
4728 ZERO_STRUCT(driver);
4730 get_current_user(&user, p);
4732 convert_printer_driver_info(info, &driver, level);
4734 DEBUG(5,("Cleaning driver's information\n"));
4735 if ((err = clean_up_driver_struct(driver, level)) != NT_STATUS_NO_PROBLEMO )
4738 DEBUG(5,("Moving driver to final destination\n"));
4739 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4741 err = ERROR_ACCESS_DENIED;
4745 if (add_a_printer_driver(driver, level)!=0) {
4746 err = ERROR_ACCESS_DENIED;
4751 free_a_printer_driver(driver, level);
4755 /****************************************************************************
4756 ****************************************************************************/
4757 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4759 init_unistr(&info->name, name);
4762 /****************************************************************************
4763 ****************************************************************************/
4764 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4768 pstring short_archi;
4769 DRIVER_DIRECTORY_1 *info=NULL;
4771 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4773 if (get_short_archi(short_archi, long_archi)==FALSE)
4774 return ERROR_INVALID_ENVIRONMENT;
4776 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4777 return ERROR_NOT_ENOUGH_MEMORY;
4779 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4781 DEBUG(4,("printer driver directory: [%s]\n", path));
4783 fill_driverdir_1(info, path);
4785 *needed += spoolss_size_driverdir_info_1(info);
4787 if (!alloc_buffer_size(buffer, *needed)) {
4789 return ERROR_INSUFFICIENT_BUFFER;
4792 new_smb_io_driverdir_1("", buffer, info, 0);
4796 if (*needed > offered)
4797 return ERROR_INSUFFICIENT_BUFFER;
4799 return NT_STATUS_NO_PROBLEMO;
4802 /****************************************************************************
4803 ****************************************************************************/
4804 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4805 NEW_BUFFER *buffer, uint32 offered,
4808 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4814 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4816 return ERROR_INVALID_LEVEL;
4820 /****************************************************************************
4821 ****************************************************************************/
4822 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4823 uint32 in_value_len, uint32 in_data_len,
4824 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4826 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
4828 NT_PRINTER_INFO_LEVEL *printer = NULL;
4833 uint32 biggest_valuesize;
4834 uint32 biggest_datasize;
4836 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4841 ZERO_STRUCT(printer);
4843 *out_max_value_len=0;
4849 *out_max_data_len=0;
4853 DEBUG(5,("spoolss_enumprinterdata\n"));
4855 if (!OPEN_HANDLE(Printer)) {
4856 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4857 return ERROR_INVALID_HANDLE;
4860 if (!get_printer_snum(handle, &snum))
4861 return ERROR_INVALID_HANDLE;
4863 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
4864 return ERROR_INVALID_HANDLE;
4867 * The NT machine wants to know the biggest size of value and data
4869 * cf: MSDN EnumPrinterData remark section
4871 if ( (in_value_len==0) && (in_data_len==0) ) {
4872 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
4876 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
4877 * if this parameter size doesn't exist.
4878 * Ok - my opinion here is that the client is not asking for the greatest
4879 * possible size of all the parameters, but is asking specifically for the size needed
4880 * for this specific parameter. In that case we can remove the loop below and
4881 * simplify this lookup code considerably. JF - comments welcome. JRA.
4884 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4886 free_a_printer(&printer, 2);
4887 return ERROR_NO_MORE_ITEMS;
4895 biggest_valuesize=0;
4898 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
4899 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
4900 if (data_len > biggest_datasize) biggest_datasize=data_len;
4902 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
4910 * I think this is correct, it doesn't break APW and
4911 * allows Gerald's Win32 test programs to work correctly,
4912 * but may need altering.... JRA.
4915 if (param_index == 0) {
4916 /* No parameters found. */
4917 free_a_printer(&printer, 2);
4918 return ERROR_NO_MORE_ITEMS;
4921 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
4922 *out_value_len=2*(1+biggest_valuesize);
4923 *out_data_len=biggest_datasize;
4925 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
4927 free_a_printer(&printer, 2);
4928 return NT_STATUS_NO_PROBLEMO;
4932 * the value len is wrong in NT sp3
4933 * that's the number of bytes not the number of unicode chars
4936 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4938 free_a_printer(&printer, 2);
4939 return ERROR_NO_MORE_ITEMS;
4942 free_a_printer(&printer, 2);
4946 * - counted in bytes in the request
4947 * - counted in UNICODE chars in the max reply
4948 * - counted in bytes in the real size
4950 * take a pause *before* coding not *during* coding
4953 *out_max_value_len=(in_value_len/sizeof(uint16));
4954 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
4956 return ERROR_NOT_ENOUGH_MEMORY;
4959 ZERO_STRUCTP(*out_value);
4960 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
4964 /* the data is counted in bytes */
4965 *out_max_data_len=in_data_len;
4966 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
4968 return ERROR_NOT_ENOUGH_MEMORY;
4971 memset(*data_out,'\0',in_data_len);
4972 memcpy(*data_out, data, (size_t)data_len);
4973 *out_data_len=data_len;
4977 return NT_STATUS_NO_PROBLEMO;
4980 /****************************************************************************
4981 ****************************************************************************/
4982 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
4983 const UNISTR2 *value,
4988 uint32 numeric_data)
4990 NT_PRINTER_INFO_LEVEL *printer = NULL;
4991 NT_PRINTER_PARAM *param = NULL;
4993 uint32 status = 0x0;
4994 Printer_entry *Printer=find_printer_index_by_hnd(handle);
4996 DEBUG(5,("spoolss_setprinterdata\n"));
4999 if (!OPEN_HANDLE(Printer)) {
5000 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5001 return ERROR_INVALID_HANDLE;
5004 if (!get_printer_snum(handle, &snum))
5005 return ERROR_INVALID_HANDLE;
5007 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5008 DEBUG(3, ("security descriptor change denied by existing "
5009 "security descriptor\n"));
5010 return ERROR_ACCESS_DENIED;
5013 status = get_a_printer(&printer, 2, lp_servicename(snum));
5015 return ERROR_INVALID_NAME;
5017 convert_specific_param(¶m, value , type, data, real_len);
5018 unlink_specific_param_if_exist(printer->info_2, param);
5020 if (!add_a_specific_param(printer->info_2, param))
5021 status = ERROR_INVALID_PARAMETER;
5023 status = mod_a_printer(*printer, 2);
5025 free_a_printer(&printer, 2);
5029 /****************************************************************************
5030 ****************************************************************************/
5031 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5033 NT_PRINTER_INFO_LEVEL *printer = NULL;
5034 NT_PRINTER_PARAM param;
5036 uint32 status = 0x0;
5037 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5039 DEBUG(5,("spoolss_deleteprinterdata\n"));
5041 if (!OPEN_HANDLE(Printer)) {
5042 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5043 return ERROR_INVALID_HANDLE;
5046 if (!get_printer_snum(handle, &snum))
5047 return ERROR_INVALID_HANDLE;
5049 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5050 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5051 "security descriptor\n"));
5052 return ERROR_ACCESS_DENIED;
5055 status = get_a_printer(&printer, 2, lp_servicename(snum));
5057 return ERROR_INVALID_NAME;
5059 ZERO_STRUCTP(¶m);
5060 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5062 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5063 status = ERROR_INVALID_PARAMETER;
5065 status = mod_a_printer(*printer, 2);
5067 free_a_printer(&printer, 2);
5071 /****************************************************************************
5072 ****************************************************************************/
5073 uint32 _spoolss_addform( POLICY_HND *handle,
5078 nt_forms_struct *list=NULL;
5079 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5081 DEBUG(5,("spoolss_addform\n"));
5083 if (!OPEN_HANDLE(Printer)) {
5084 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5085 return ERROR_INVALID_HANDLE;
5088 count=get_ntforms(&list);
5089 if(!add_a_form(&list, form, &count))
5090 return ERROR_NOT_ENOUGH_MEMORY;
5091 write_ntforms(&list, count);
5098 /****************************************************************************
5099 ****************************************************************************/
5100 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5104 nt_forms_struct *list=NULL;
5105 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5107 DEBUG(5,("spoolss_deleteform\n"));
5109 if (!OPEN_HANDLE(Printer)) {
5110 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5111 return ERROR_INVALID_HANDLE;
5114 count = get_ntforms(&list);
5115 if(!delete_a_form(&list, form_name, &count, &ret))
5116 return ERROR_INVALID_PARAMETER;
5123 /****************************************************************************
5124 ****************************************************************************/
5125 uint32 _spoolss_setform( POLICY_HND *handle,
5126 const UNISTR2 *uni_name,
5131 nt_forms_struct *list=NULL;
5132 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5134 DEBUG(5,("spoolss_setform\n"));
5136 if (!OPEN_HANDLE(Printer)) {
5137 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5138 return ERROR_INVALID_HANDLE;
5140 count=get_ntforms(&list);
5141 update_a_form(&list, form, count);
5142 write_ntforms(&list, count);
5149 /****************************************************************************
5150 enumprintprocessors level 1.
5151 ****************************************************************************/
5152 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5154 PRINTPROCESSOR_1 *info_1=NULL;
5156 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5157 return ERROR_NOT_ENOUGH_MEMORY;
5161 init_unistr(&info_1->name, "winprint");
5163 *needed += spoolss_size_printprocessor_info_1(info_1);
5165 if (!alloc_buffer_size(buffer, *needed))
5166 return ERROR_INSUFFICIENT_BUFFER;
5168 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5172 if (*needed > offered) {
5174 return ERROR_INSUFFICIENT_BUFFER;
5177 return NT_STATUS_NO_PROBLEMO;
5180 /****************************************************************************
5181 ****************************************************************************/
5182 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5183 NEW_BUFFER *buffer, uint32 offered,
5184 uint32 *needed, uint32 *returned)
5186 DEBUG(5,("spoolss_enumprintprocessors\n"));
5189 * Enumerate the print processors ...
5191 * Just reply with "winprint", to keep NT happy
5192 * and I can use my nice printer checker.
5200 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5202 return ERROR_INVALID_LEVEL;
5206 /****************************************************************************
5207 enumprintprocdatatypes level 1.
5208 ****************************************************************************/
5209 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5211 PRINTPROCDATATYPE_1 *info_1=NULL;
5213 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5214 return ERROR_NOT_ENOUGH_MEMORY;
5218 init_unistr(&info_1->name, "RAW");
5220 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5222 if (!alloc_buffer_size(buffer, *needed))
5223 return ERROR_INSUFFICIENT_BUFFER;
5225 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5229 if (*needed > offered) {
5231 return ERROR_INSUFFICIENT_BUFFER;
5234 return NT_STATUS_NO_PROBLEMO;
5237 /****************************************************************************
5238 ****************************************************************************/
5239 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5240 NEW_BUFFER *buffer, uint32 offered,
5241 uint32 *needed, uint32 *returned)
5243 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5250 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5252 return ERROR_INVALID_LEVEL;
5256 /****************************************************************************
5257 enumprintmonitors level 1.
5258 ****************************************************************************/
5259 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5261 PRINTMONITOR_1 *info_1=NULL;
5263 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5264 return ERROR_NOT_ENOUGH_MEMORY;
5268 init_unistr(&info_1->name, "Local Port");
5270 *needed += spoolss_size_printmonitor_info_1(info_1);
5272 if (!alloc_buffer_size(buffer, *needed))
5273 return ERROR_INSUFFICIENT_BUFFER;
5275 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5279 if (*needed > offered) {
5281 return ERROR_INSUFFICIENT_BUFFER;
5284 return NT_STATUS_NO_PROBLEMO;
5287 /****************************************************************************
5288 enumprintmonitors level 2.
5289 ****************************************************************************/
5290 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5292 PRINTMONITOR_2 *info_2=NULL;
5294 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5295 return ERROR_NOT_ENOUGH_MEMORY;
5299 init_unistr(&info_2->name, "Local Port");
5300 init_unistr(&info_2->environment, "Windows NT X86");
5301 init_unistr(&info_2->dll_name, "localmon.dll");
5303 *needed += spoolss_size_printmonitor_info_2(info_2);
5305 if (!alloc_buffer_size(buffer, *needed))
5306 return ERROR_INSUFFICIENT_BUFFER;
5308 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5312 if (*needed > offered) {
5314 return ERROR_INSUFFICIENT_BUFFER;
5317 return NT_STATUS_NO_PROBLEMO;
5320 /****************************************************************************
5321 ****************************************************************************/
5322 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5323 NEW_BUFFER *buffer, uint32 offered,
5324 uint32 *needed, uint32 *returned)
5326 DEBUG(5,("spoolss_enumprintmonitors\n"));
5329 * Enumerate the print monitors ...
5331 * Just reply with "Local Port", to keep NT happy
5332 * and I can use my nice printer checker.
5340 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5342 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5344 return ERROR_INVALID_LEVEL;
5348 /****************************************************************************
5349 ****************************************************************************/
5350 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5354 JOB_INFO_1 *info_1=NULL;
5356 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5358 if (info_1 == NULL) {
5360 return ERROR_NOT_ENOUGH_MEMORY;
5363 for (i=0; i<count && found==False; i++) {
5364 if (queue[i].job==(int)jobid)
5371 /* I shoud reply something else ... I can't find the good one */
5372 return NT_STATUS_NO_PROBLEMO;
5375 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5379 *needed += spoolss_size_job_info_1(info_1);
5381 if (!alloc_buffer_size(buffer, *needed)) {
5383 return ERROR_INSUFFICIENT_BUFFER;
5386 new_smb_io_job_info_1("", buffer, info_1, 0);
5390 if (*needed > offered)
5391 return ERROR_INSUFFICIENT_BUFFER;
5393 return NT_STATUS_NO_PROBLEMO;
5397 /****************************************************************************
5398 ****************************************************************************/
5399 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5404 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5406 ZERO_STRUCTP(info_2);
5408 if (info_2 == NULL) {
5410 return ERROR_NOT_ENOUGH_MEMORY;
5413 for (i=0; i<count && found==False; i++) {
5414 if (queue[i].job==(int)jobid)
5421 /* I shoud reply something else ... I can't find the good one */
5422 return NT_STATUS_NO_PROBLEMO;
5425 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5429 *needed += spoolss_size_job_info_2(info_2);
5431 if (!alloc_buffer_size(buffer, *needed)) {
5433 return ERROR_INSUFFICIENT_BUFFER;
5436 new_smb_io_job_info_2("", buffer, info_2, 0);
5438 free_dev_mode(info_2->devmode);
5441 if (*needed > offered)
5442 return ERROR_INSUFFICIENT_BUFFER;
5444 return NT_STATUS_NO_PROBLEMO;
5447 /****************************************************************************
5448 ****************************************************************************/
5449 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5450 NEW_BUFFER *buffer, uint32 offered,
5455 print_queue_struct *queue=NULL;
5456 print_status_struct prt_status;
5458 DEBUG(5,("spoolss_getjob\n"));
5460 memset(&prt_status, 0, sizeof(prt_status));
5464 if (!get_printer_snum(handle, &snum))
5465 return ERROR_INVALID_HANDLE;
5467 count = print_queue_status(snum, &queue, &prt_status);
5469 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5470 count, prt_status.status, prt_status.message));
5474 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5476 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5479 return ERROR_INVALID_LEVEL;