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++) {
410 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
413 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
415 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
418 printername=strchr(printer->info_2->printername+2, '\\');
421 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
422 printer->info_2->printername, aprinter ));
424 if ( strlen(printername) != strlen(aprinter) ) {
425 free_a_printer(&printer, 2);
429 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
430 free_a_printer(&printer, 2);
438 * if we haven't found a printer with the given handlename
439 * then it can be a share name as you can open both \\server\printer and
444 * we still check if the printer description file exists as NT won't be happy
445 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
449 DEBUGADD(5,("Printer not found, checking for share now\n"));
451 for (snum=0;snum<n_services && found==False;snum++) {
453 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
456 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
458 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
461 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
462 printer->info_2->printername, aprinter ));
464 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
465 free_a_printer(&printer, 2);
469 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
470 free_a_printer(&printer, 2);
479 DEBUGADD(4,("Printer not found\n"));
484 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
485 printer->info_2->printername, lp_servicename(snum),snum));
487 ZERO_STRUCT(Printer->dev.handlename);
488 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
490 free_a_printer(&printer, 2);
495 /****************************************************************************
496 find first available printer slot. creates a printer handle for you.
497 ****************************************************************************/
499 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
501 Printer_entry *new_printer;
503 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
505 create_printer_hnd(hnd);
507 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
510 ZERO_STRUCTP(new_printer);
512 new_printer->open = True;
513 new_printer->notify.option=NULL;
515 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
517 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
519 if (!set_printer_hnd_printertype(new_printer, name)) {
520 close_printer_handle(hnd);
524 if (!set_printer_hnd_name(new_printer, name)) {
525 close_printer_handle(hnd);
532 /********************************************************************
533 Return True is the handle is a print server.
534 ********************************************************************/
535 static BOOL handle_is_printserver(const POLICY_HND *handle)
537 Printer_entry *Printer=find_printer_index_by_hnd(handle);
539 if (!OPEN_HANDLE(Printer))
542 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
548 /****************************************************************************
549 allocate more memory for a BUFFER.
550 ****************************************************************************/
551 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
559 /* damn, I'm doing the reverse operation of prs_grow() :) */
560 if (buffer_size < prs_data_size(ps))
563 extra_space = buffer_size - prs_data_size(ps);
566 * save the offset and move to the end of the buffer
567 * prs_grow() checks the extra_space against the offset
569 old_offset=prs_offset(ps);
570 prs_set_offset(ps, prs_data_size(ps));
572 if (!prs_grow(ps, extra_space))
575 prs_set_offset(ps, old_offset);
577 buffer->string_at_end=prs_data_size(ps);
582 /***************************************************************************
583 receive the notify message
584 ****************************************************************************/
585 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
589 Printer_entry *find_printer;
592 fstrcpy(printer,buf);
595 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
599 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
601 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
603 /* Iterate the printer list. */
604 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
607 * if the entry is the given printer or if it's a printerserver
608 * we send the message
611 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
612 if (strcmp(find_printer->dev.handlename, printer))
615 if (find_printer->notify.client_connected==True)
616 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
621 /***************************************************************************
623 ****************************************************************************/
624 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
628 Printer_entry *Printer=find_printer_index_by_hnd(handle);
630 if (!OPEN_HANDLE(Printer)) {
631 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
635 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
636 fstrcpy(printer, Printer->dev.handlename);
638 fstrcpy(printer, "");
640 /*srv_spoolss_receive_message(printer);*/
641 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
643 message_send_all(MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
648 /********************************************************************
649 * spoolss_open_printer
651 * called from the spoolss dispatcher
652 ********************************************************************/
653 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername,
654 const PRINTER_DEFAULT *printer_default,
655 uint32 user_switch, SPOOL_USER_CTR user_ctr,
660 if (printername == NULL)
661 return ERROR_INVALID_PRINTER_NAME;
663 /* some sanity check because you can open a printer or a print server */
664 /* aka: \\server\printer or \\server */
665 unistr2_to_ascii(name, printername, sizeof(name)-1);
667 DEBUGADD(3,("checking name: %s\n",name));
669 if (!open_printer_hnd(handle, name))
670 return ERROR_INVALID_PRINTER_NAME;
673 if (printer_default->datatype_ptr != NULL)
675 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
676 set_printer_hnd_datatype(handle, datatype);
679 set_printer_hnd_datatype(handle, "");
682 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
683 close_printer_handle(handle);
684 return ERROR_ACCESS_DENIED;
687 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
688 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
689 Then both Win2k and WinNT clients try an OpenPrinterEx with
690 SERVER_ALL_ACCESS, which we force to fail. Then they try
691 OpenPrinterEx with SERVER_READ which we allow. This lets the
692 client view printer folder, but does not show the MSAPW.
694 Note: this test needs code to check access rights here too. Jeremy
695 could you look at this? */
697 if (handle_is_printserver(handle) &&
698 !lp_ms_add_printer_wizard()) {
699 if (printer_default->access_required == 0)
700 return NT_STATUS_NO_PROBLEMO;
701 else if (printer_default->access_required != (SERVER_READ))
702 return ERROR_ACCESS_DENIED;
705 return NT_STATUS_NO_PROBLEMO;
708 /****************************************************************************
709 ****************************************************************************/
710 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
711 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
715 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
724 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
725 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
729 printer->info_3=NULL;
730 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
733 printer->info_6=NULL;
734 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
743 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
745 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
746 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
748 nt_devmode->specversion=devmode->specversion;
749 nt_devmode->driverversion=devmode->driverversion;
750 nt_devmode->size=devmode->size;
751 nt_devmode->driverextra=devmode->driverextra;
752 nt_devmode->fields=devmode->fields;
753 nt_devmode->orientation=devmode->orientation;
754 nt_devmode->papersize=devmode->papersize;
755 nt_devmode->paperlength=devmode->paperlength;
756 nt_devmode->paperwidth=devmode->paperwidth;
757 nt_devmode->scale=devmode->scale;
758 nt_devmode->copies=devmode->copies;
759 nt_devmode->defaultsource=devmode->defaultsource;
760 nt_devmode->printquality=devmode->printquality;
761 nt_devmode->color=devmode->color;
762 nt_devmode->duplex=devmode->duplex;
763 nt_devmode->yresolution=devmode->yresolution;
764 nt_devmode->ttoption=devmode->ttoption;
765 nt_devmode->collate=devmode->collate;
767 nt_devmode->logpixels=devmode->logpixels;
768 nt_devmode->bitsperpel=devmode->bitsperpel;
769 nt_devmode->pelswidth=devmode->pelswidth;
770 nt_devmode->pelsheight=devmode->pelsheight;
771 nt_devmode->displayflags=devmode->displayflags;
772 nt_devmode->displayfrequency=devmode->displayfrequency;
773 nt_devmode->icmmethod=devmode->icmmethod;
774 nt_devmode->icmintent=devmode->icmintent;
775 nt_devmode->mediatype=devmode->mediatype;
776 nt_devmode->dithertype=devmode->dithertype;
777 nt_devmode->reserved1=devmode->reserved1;
778 nt_devmode->reserved2=devmode->reserved2;
779 nt_devmode->panningwidth=devmode->panningwidth;
780 nt_devmode->panningheight=devmode->panningheight;
782 if (nt_devmode->driverextra != 0) {
783 /* if we had a previous private delete it and make a new one */
784 safe_free(nt_devmode->private);
785 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
787 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
793 /********************************************************************
794 * api_spoolss_closeprinter
795 ********************************************************************/
796 uint32 _spoolss_closeprinter(POLICY_HND *handle)
798 Printer_entry *Printer=find_printer_index_by_hnd(handle);
800 if (Printer && Printer->document_started)
801 _spoolss_enddocprinter(handle); /* print job was not closed */
803 if (!close_printer_handle(handle))
804 return ERROR_INVALID_HANDLE;
806 return NT_STATUS_NO_PROBLEMO;
809 /********************************************************************
810 * api_spoolss_deleteprinter
811 ********************************************************************/
812 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
814 Printer_entry *Printer=find_printer_index_by_hnd(handle);
816 if (Printer && Printer->document_started)
817 _spoolss_enddocprinter(handle); /* print job was not closed */
819 if (!delete_printer_handle(handle))
820 return ERROR_INVALID_HANDLE;
822 srv_spoolss_sendnotify(handle);
824 return NT_STATUS_NO_PROBLEMO;
827 /********************************************************************
828 GetPrinterData on a printer server Handle.
829 ********************************************************************/
830 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
834 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
836 if (!strcmp(value, "BeepEnabled")) {
838 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
840 SIVAL(*data, 0, 0x01);
845 if (!strcmp(value, "EventLog")) {
847 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
849 SIVAL(*data, 0, 0x1B);
854 if (!strcmp(value, "NetPopup")) {
856 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
858 SIVAL(*data, 0, 0x01);
863 if (!strcmp(value, "MajorVersion")) {
865 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
867 SIVAL(*data, 0, 0x02);
872 if (!strcmp(value, "DefaultSpoolDirectory")) {
873 pstring string="You are using a Samba server";
875 *needed = 2*(strlen(string)+1);
876 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
878 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
880 /* it's done by hand ready to go on the wire */
881 for (i=0; i<strlen(string); i++) {
882 (*data)[2*i]=string[i];
888 if (!strcmp(value, "Architecture")) {
889 pstring string="Windows NT x86";
891 *needed = 2*(strlen(string)+1);
892 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
894 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
895 for (i=0; i<strlen(string); i++) {
896 (*data)[2*i]=string[i];
905 /********************************************************************
906 GetPrinterData on a printer Handle.
907 ********************************************************************/
908 static BOOL getprinterdata_printer(POLICY_HND *handle,
909 fstring value, uint32 *type,
910 uint8 **data, uint32 *needed, uint32 in_size )
912 NT_PRINTER_INFO_LEVEL *printer = NULL;
916 Printer_entry *Printer = find_printer_index_by_hnd(handle);
918 DEBUG(5,("getprinterdata_printer\n"));
920 if (!OPEN_HANDLE(Printer)) {
921 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
925 if(!get_printer_snum(handle, &snum))
928 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
931 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
932 free_a_printer(&printer, 2);
936 free_a_printer(&printer, 2);
938 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
941 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
945 memset(*data, 0, in_size *sizeof(uint8));
946 /* copy the min(in_size, len) */
947 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
954 DEBUG(5,("getprinterdata_printer:copy done\n"));
961 /********************************************************************
962 * spoolss_getprinterdata
963 ********************************************************************/
964 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
973 Printer_entry *Printer = find_printer_index_by_hnd(handle);
976 * Reminder: when it's a string, the length is in BYTES
977 * even if UNICODE is negociated.
984 /* in case of problem, return some default values */
988 DEBUG(4,("_spoolss_getprinterdata\n"));
990 if (!OPEN_HANDLE(Printer)) {
991 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
992 return ERROR_NOT_ENOUGH_MEMORY;
993 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
994 return ERROR_INVALID_HANDLE;
997 unistr2_to_ascii(value, valuename, sizeof(value)-1);
999 if (handle_is_printserver(handle))
1000 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1002 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
1005 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1006 /* reply this param doesn't exist */
1008 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1009 return ERROR_NOT_ENOUGH_MEMORY;
1010 memset(*data, '\0', *out_size*sizeof(uint8));
1015 return ERROR_INVALID_PARAMETER;
1018 if (*needed > *out_size)
1019 return ERROR_MORE_DATA;
1021 return NT_STATUS_NO_PROBLEMO;
1024 /***************************************************************************
1025 connect to the client
1026 ****************************************************************************/
1027 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1032 * If it's the first connection, contact the client
1033 * and connect to the IPC$ share anonumously
1035 if (smb_connections==0) {
1036 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1038 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1044 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1050 /********************************************************************
1052 * ReplyFindFirstPrinterChangeNotifyEx
1054 * jfmxxxx: before replying OK: status=0
1055 * should do a rpc call to the workstation asking ReplyOpenPrinter
1056 * have to code it, later.
1058 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1059 * called from api_spoolss_rffpcnex
1060 ********************************************************************/
1061 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1062 const UNISTR2 *localmachine, uint32 printerlocal,
1063 SPOOL_NOTIFY_OPTION *option)
1065 /* store the notify value in the printer struct */
1067 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1069 if (!OPEN_HANDLE(Printer)) {
1070 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1071 return ERROR_INVALID_HANDLE;
1074 Printer->notify.flags=flags;
1075 Printer->notify.options=options;
1076 Printer->notify.printerlocal=printerlocal;
1077 Printer->notify.option=option;
1078 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1080 /* connect to the client machine and send a ReplyOpenPrinter */
1081 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1082 Printer->notify.printerlocal, 1,
1083 &Printer->notify.client_hnd))
1084 Printer->notify.client_connected=True;
1086 return NT_STATUS_NO_PROBLEMO;
1089 /*******************************************************************
1090 * fill a notify_info_data with the servername
1091 ********************************************************************/
1092 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1093 NT_PRINTER_INFO_LEVEL *printer)
1097 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1099 data->notify_data.data.length= (uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1100 temp_name, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1103 /*******************************************************************
1104 * fill a notify_info_data with the printername (not including the servername).
1105 ********************************************************************/
1106 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1107 NT_PRINTER_INFO_LEVEL *printer)
1109 /* the notify name should not contain the \\server\ part */
1110 char *p = strrchr(printer->info_2->printername, '\\');
1112 p = printer->info_2->printername;
1117 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1118 p, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1121 /*******************************************************************
1122 * fill a notify_info_data with the servicename
1123 ********************************************************************/
1124 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1126 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1127 lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
1130 /*******************************************************************
1131 * fill a notify_info_data with the port name
1132 ********************************************************************/
1133 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1135 /* even if it's strange, that's consistant in all the code */
1137 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1138 printer->info_2->portname, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1141 /*******************************************************************
1142 * fill a notify_info_data with the printername
1143 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1144 * but it doesn't exist, have to see what to do
1145 ********************************************************************/
1146 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1148 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1149 printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1152 /*******************************************************************
1153 * fill a notify_info_data with the comment
1154 ********************************************************************/
1155 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1157 if (*printer->info_2->comment == '\0')
1158 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1159 lp_comment(snum), sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1161 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1162 printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1165 /*******************************************************************
1166 * fill a notify_info_data with the comment
1167 * jfm:xxxx incorrect, have to create a new smb.conf option
1168 * location = "Room 1, floor 2, building 3"
1169 ********************************************************************/
1170 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1172 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1173 printer->info_2->location, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1176 /*******************************************************************
1177 * fill a notify_info_data with the device mode
1178 * jfm:xxxx don't to it for know but that's a real problem !!!
1179 ********************************************************************/
1180 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1184 /*******************************************************************
1185 * fill a notify_info_data with the separator file name
1186 * jfm:xxxx just return no file could add an option to smb.conf
1187 * separator file = "separator.txt"
1188 ********************************************************************/
1189 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1191 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1192 printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True) - sizeof(uint16))/sizeof(uint16));
1195 /*******************************************************************
1196 * fill a notify_info_data with the print processor
1197 * jfm:xxxx return always winprint to indicate we don't do anything to it
1198 ********************************************************************/
1199 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1201 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1202 printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1205 /*******************************************************************
1206 * fill a notify_info_data with the print processor options
1207 * jfm:xxxx send an empty string
1208 ********************************************************************/
1209 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1211 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1212 printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1215 /*******************************************************************
1216 * fill a notify_info_data with the data type
1217 * jfm:xxxx always send RAW as data type
1218 ********************************************************************/
1219 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1221 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1222 printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1225 /*******************************************************************
1226 * fill a notify_info_data with the security descriptor
1227 * jfm:xxxx send an null pointer to say no security desc
1228 * have to implement security before !
1229 ********************************************************************/
1230 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1232 data->notify_data.data.length=0;
1233 data->notify_data.data.string[0]=0x00;
1236 /*******************************************************************
1237 * fill a notify_info_data with the attributes
1238 * jfm:xxxx a samba printer is always shared
1239 ********************************************************************/
1240 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1242 data->notify_data.value[0] = printer->info_2->attributes;
1245 /*******************************************************************
1246 * fill a notify_info_data with the priority
1247 ********************************************************************/
1248 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1250 data->notify_data.value[0] = printer->info_2->priority;
1253 /*******************************************************************
1254 * fill a notify_info_data with the default priority
1255 ********************************************************************/
1256 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1258 data->notify_data.value[0] = printer->info_2->default_priority;
1261 /*******************************************************************
1262 * fill a notify_info_data with the start time
1263 ********************************************************************/
1264 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1266 data->notify_data.value[0] = printer->info_2->starttime;
1269 /*******************************************************************
1270 * fill a notify_info_data with the until time
1271 ********************************************************************/
1272 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1274 data->notify_data.value[0] = printer->info_2->untiltime;
1277 /*******************************************************************
1278 * fill a notify_info_data with the status
1279 ********************************************************************/
1280 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1283 print_queue_struct *q=NULL;
1284 print_status_struct status;
1286 memset(&status, 0, sizeof(status));
1287 count = print_queue_status(snum, &q, &status);
1288 data->notify_data.value[0]=(uint32) status.status;
1292 /*******************************************************************
1293 * fill a notify_info_data with the number of jobs queued
1294 ********************************************************************/
1295 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1297 print_queue_struct *q=NULL;
1298 print_status_struct status;
1300 memset(&status, 0, sizeof(status));
1301 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1305 /*******************************************************************
1306 * fill a notify_info_data with the average ppm
1307 ********************************************************************/
1308 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1310 /* always respond 8 pages per minutes */
1311 /* a little hard ! */
1312 data->notify_data.value[0] = printer->info_2->averageppm;
1315 /*******************************************************************
1316 * fill a notify_info_data with username
1317 ********************************************************************/
1318 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1320 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1321 queue->user, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1324 /*******************************************************************
1325 * fill a notify_info_data with job status
1326 ********************************************************************/
1327 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1329 data->notify_data.value[0]=nt_printj_status(queue->status);
1332 /*******************************************************************
1333 * fill a notify_info_data with job name
1334 ********************************************************************/
1335 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1337 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1338 queue->file, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1341 /*******************************************************************
1342 * fill a notify_info_data with job status
1343 ********************************************************************/
1344 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1346 char *p = "unknown";
1348 switch (queue->status) {
1353 p = ""; /* NT provides the paused string */
1362 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1363 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1366 /*******************************************************************
1367 * fill a notify_info_data with job time
1368 ********************************************************************/
1369 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1371 data->notify_data.value[0]=0x0;
1374 /*******************************************************************
1375 * fill a notify_info_data with job size
1376 ********************************************************************/
1377 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1379 data->notify_data.value[0]=queue->size;
1382 /*******************************************************************
1383 * fill a notify_info_data with job position
1384 ********************************************************************/
1385 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1387 data->notify_data.value[0]=queue->job;
1390 /*******************************************************************
1391 * fill a notify_info_data with submitted time
1392 ********************************************************************/
1393 static void spoolss_notify_submitted_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1397 t=gmtime(&queue->time);
1399 data->notify_data.data.length = sizeof(SYSTEMTIME);
1400 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1405 struct s_notify_info_data_table
1411 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1412 print_queue_struct *queue,
1413 NT_PRINTER_INFO_LEVEL *printer);
1416 struct s_notify_info_data_table notify_info_data_table[] =
1418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1468 { END, END, "", END, NULL }
1471 /*******************************************************************
1472 return the size of info_data structure
1473 ********************************************************************/
1474 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1478 while (notify_info_data_table[i].type != END)
1480 if ( (notify_info_data_table[i].type == type ) &&
1481 (notify_info_data_table[i].field == field ) )
1483 return (notify_info_data_table[i].size);
1490 /*******************************************************************
1491 return the type of notify_info_data
1492 ********************************************************************/
1493 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1497 while (notify_info_data_table[i].type != END)
1499 if ( (notify_info_data_table[i].type == type ) &&
1500 (notify_info_data_table[i].field == field ) )
1502 if (notify_info_data_table[i].size == POINTER)
1516 /****************************************************************************
1517 ****************************************************************************/
1518 static int search_notify(uint16 type, uint16 field, int *value)
1523 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1525 if ( (notify_info_data_table[j].type == type ) &&
1526 (notify_info_data_table[j].field == field ) )
1531 if ( found && (notify_info_data_table[j].fn != NULL) )
1537 /****************************************************************************
1538 ****************************************************************************/
1539 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1541 info_data->type = type;
1542 info_data->field = field;
1543 info_data->reserved = 0;
1545 info_data->size = size_of_notify_info_data(type, field);
1546 info_data->enc_type = type_of_notify_info_data(type, field);
1550 /*******************************************************************
1552 * fill a notify_info struct with info asked
1554 ********************************************************************/
1555 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1561 SPOOL_NOTIFY_INFO_DATA *current_data;
1562 NT_PRINTER_INFO_LEVEL *printer = NULL;
1563 print_queue_struct *queue=NULL;
1565 DEBUG(4,("construct_notify_printer_info\n"));
1567 type=option_type->type;
1569 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1570 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1571 option_type->count, lp_servicename(snum)));
1573 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1576 for(field_num=0; field_num<option_type->count; field_num++) {
1577 field = option_type->fields[field_num];
1578 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1580 if (!search_notify(type, field, &j) )
1583 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1586 current_data=&info->data[info->count];
1588 construct_info_data(current_data, type, field, id);
1590 DEBUG(10,("construct_notify_printer_info: calling %s\n",
1591 notify_info_data_table[j].name ));
1593 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1598 free_a_printer(&printer, 2);
1602 /*******************************************************************
1604 * fill a notify_info struct with info asked
1606 ********************************************************************/
1607 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1613 SPOOL_NOTIFY_INFO_DATA *current_data;
1614 NT_PRINTER_INFO_LEVEL *printer = NULL;
1616 DEBUG(4,("construct_notify_jobs_info\n"));
1618 type = option_type->type;
1620 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1621 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1622 option_type->count));
1624 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1627 for(field_num=0; field_num<option_type->count; field_num++) {
1628 field = option_type->fields[field_num];
1630 if (!search_notify(type, field, &j) )
1633 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1637 current_data=&(info->data[info->count]);
1639 construct_info_data(current_data, type, field, id);
1640 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1644 free_a_printer(&printer, 2);
1649 * JFM: The enumeration is not that simple, it's even non obvious.
1651 * let's take an example: I want to monitor the PRINTER SERVER for
1652 * the printer's name and the number of jobs currently queued.
1653 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1654 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1656 * I have 3 printers on the back of my server.
1658 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1661 * 1 printer 1 name 1
1662 * 2 printer 1 cjob 1
1663 * 3 printer 2 name 2
1664 * 4 printer 2 cjob 2
1665 * 5 printer 3 name 3
1666 * 6 printer 3 name 3
1668 * that's the print server case, the printer case is even worse.
1673 /*******************************************************************
1675 * enumerate all printers on the printserver
1676 * fill a notify_info struct with info asked
1678 ********************************************************************/
1679 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1682 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1683 int n_services=lp_numservices();
1686 SPOOL_NOTIFY_OPTION *option;
1687 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1689 DEBUG(4,("printserver_notify_info\n"));
1691 option=Printer->notify.option;
1697 for (i=0; i<option->count; i++) {
1698 option_type=&(option->ctr.type[i]);
1700 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1703 for (snum=0; snum<n_services; snum++)
1704 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1705 if (construct_notify_printer_info(info, snum, option_type, id))
1710 * Debugging information, don't delete.
1713 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1714 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1715 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1717 for (i=0; i<info->count; i++) {
1718 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1719 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1720 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1724 return NT_STATUS_NO_PROBLEMO;
1727 /*******************************************************************
1729 * fill a notify_info struct with info asked
1731 ********************************************************************/
1732 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1735 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1738 SPOOL_NOTIFY_OPTION *option;
1739 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1741 print_queue_struct *queue=NULL;
1742 print_status_struct status;
1744 DEBUG(4,("printer_notify_info\n"));
1746 option=Printer->notify.option;
1752 get_printer_snum(hnd, &snum);
1754 for (i=0; i<option->count; i++) {
1755 option_type=&option->ctr.type[i];
1757 switch ( option_type->type ) {
1758 case PRINTER_NOTIFY_TYPE:
1759 if(construct_notify_printer_info(info, snum, option_type, id))
1763 case JOB_NOTIFY_TYPE:
1764 memset(&status, 0, sizeof(status));
1765 count = print_queue_status(snum, &queue, &status);
1766 for (j=0; j<count; j++)
1767 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1774 * Debugging information, don't delete.
1777 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1778 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1779 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1781 for (i=0; i<info->count; i++) {
1782 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1783 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1784 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1787 return NT_STATUS_NO_PROBLEMO;
1790 /********************************************************************
1792 ********************************************************************/
1793 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1794 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1796 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1798 if (!OPEN_HANDLE(Printer)) {
1799 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1800 return ERROR_INVALID_HANDLE;
1803 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1805 /* jfm: the change value isn't used right now.
1806 * we will honour it when
1807 * a) we'll be able to send notification to the client
1808 * b) we'll have a way to communicate between the spoolss process.
1810 * same thing for option->flags
1811 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1812 * I don't have a global notification system, I'm sending back all the
1813 * informations even when _NOTHING_ has changed.
1816 /* just discard the SPOOL_NOTIFY_OPTION */
1818 safe_free(option->ctr.type);
1820 switch (Printer->printer_type) {
1821 case PRINTER_HANDLE_IS_PRINTSERVER:
1822 return printserver_notify_info(handle, info);
1823 case PRINTER_HANDLE_IS_PRINTER:
1824 return printer_notify_info(handle, info);
1827 return ERROR_INVALID_HANDLE;
1830 /********************************************************************
1831 * construct_printer_info_0
1832 * fill a printer_info_0 struct
1833 ********************************************************************/
1834 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
1838 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1839 counter_printer_0 *session_counter;
1840 uint32 global_counter;
1844 print_queue_struct *queue=NULL;
1845 print_status_struct status;
1847 memset(&status, 0, sizeof(status));
1849 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1852 count = print_queue_status(snum, &queue, &status);
1854 /* check if we already have a counter for this printer */
1855 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1857 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1858 if (session_counter->snum == snum)
1862 /* it's the first time, add it to the list */
1863 if (session_counter==NULL) {
1864 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1865 free_a_printer(&ntprinter, 2);
1868 ZERO_STRUCTP(session_counter);
1869 session_counter->snum=snum;
1870 session_counter->counter=0;
1871 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1875 session_counter->counter++;
1878 * the global_counter should be stored in a TDB as it's common to all the clients
1879 * and should be zeroed on samba startup
1881 global_counter=session_counter->counter;
1883 pstrcpy(chaine,ntprinter->info_2->printername);
1885 init_unistr(&printer->printername, chaine);
1887 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
1888 init_unistr(&printer->servername, chaine);
1890 printer->cjobs = count;
1891 printer->total_jobs = 0;
1892 printer->total_bytes = 0;
1894 setuptime = (time_t)ntprinter->info_2->setuptime;
1895 t=gmtime(&setuptime);
1897 printer->year = t->tm_year+1900;
1898 printer->month = t->tm_mon+1;
1899 printer->dayofweek = t->tm_wday;
1900 printer->day = t->tm_mday;
1901 printer->hour = t->tm_hour;
1902 printer->minute = t->tm_min;
1903 printer->second = t->tm_sec;
1904 printer->milliseconds = 0;
1906 printer->global_counter = global_counter;
1907 printer->total_pages = 0;
1908 printer->major_version = 0x0004; /* NT 4 */
1909 printer->build_version = 0x0565; /* build 1381 */
1910 printer->unknown7 = 0x1;
1911 printer->unknown8 = 0x0;
1912 printer->unknown9 = 0x0;
1913 printer->session_counter = session_counter->counter;
1914 printer->unknown11 = 0x0;
1915 printer->printer_errors = 0x0; /* number of print failure */
1916 printer->unknown13 = 0x0;
1917 printer->unknown14 = 0x1;
1918 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1919 printer->unknown16 = 0x0;
1920 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1921 printer->unknown18 = 0x0;
1922 printer->status = nt_printq_status(status.status);
1923 printer->unknown20 = 0x0;
1924 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1925 printer->unknown22 = 0x0;
1926 printer->unknown23 = 0x6; /* 6 ???*/
1927 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1928 printer->unknown25 = 0;
1929 printer->unknown26 = 0;
1930 printer->unknown27 = 0;
1931 printer->unknown28 = 0;
1932 printer->unknown29 = 0;
1935 free_a_printer(&ntprinter,2);
1939 /********************************************************************
1940 * construct_printer_info_1
1941 * fill a printer_info_1 struct
1942 ********************************************************************/
1943 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
1947 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1949 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1952 printer->flags=flags;
1954 if (*ntprinter->info_2->comment == '\0') {
1955 init_unistr(&printer->comment, lp_comment(snum));
1956 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
1957 ntprinter->info_2->drivername, lp_comment(snum));
1960 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1961 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
1962 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1965 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
1967 init_unistr(&printer->description, chaine);
1968 init_unistr(&printer->name, chaine2);
1970 free_a_printer(&ntprinter,2);
1975 /****************************************************************************
1976 Free a DEVMODE struct.
1977 ****************************************************************************/
1979 static void free_dev_mode(DEVICEMODE *dev)
1985 safe_free(dev->private);
1990 /****************************************************************************
1991 Create a DEVMODE struct. Returns malloced memory.
1992 ****************************************************************************/
1994 static DEVICEMODE *construct_dev_mode(int snum)
1998 NT_PRINTER_INFO_LEVEL *printer = NULL;
1999 NT_DEVICEMODE *ntdevmode = NULL;
2000 DEVICEMODE *devmode = NULL;
2002 DEBUG(7,("construct_dev_mode\n"));
2004 DEBUGADD(8,("getting printer characteristics\n"));
2006 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2007 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2011 ZERO_STRUCTP(devmode);
2013 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2016 if (printer->info_2->devmode)
2017 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2019 if (ntdevmode == NULL)
2022 DEBUGADD(8,("loading DEVICEMODE\n"));
2024 safe_strcpy(adevice, printer->info_2->printername, sizeof(adevice));
2025 init_unistr(&devmode->devicename, adevice);
2027 snprintf(aform, sizeof(aform), ntdevmode->formname);
2028 init_unistr(&devmode->formname, aform);
2030 devmode->specversion = ntdevmode->specversion;
2031 devmode->driverversion = ntdevmode->driverversion;
2032 devmode->size = ntdevmode->size;
2033 devmode->driverextra = ntdevmode->driverextra;
2034 devmode->fields = ntdevmode->fields;
2036 devmode->orientation = ntdevmode->orientation;
2037 devmode->papersize = ntdevmode->papersize;
2038 devmode->paperlength = ntdevmode->paperlength;
2039 devmode->paperwidth = ntdevmode->paperwidth;
2040 devmode->scale = ntdevmode->scale;
2041 devmode->copies = ntdevmode->copies;
2042 devmode->defaultsource = ntdevmode->defaultsource;
2043 devmode->printquality = ntdevmode->printquality;
2044 devmode->color = ntdevmode->color;
2045 devmode->duplex = ntdevmode->duplex;
2046 devmode->yresolution = ntdevmode->yresolution;
2047 devmode->ttoption = ntdevmode->ttoption;
2048 devmode->collate = ntdevmode->collate;
2049 devmode->icmmethod = ntdevmode->icmmethod;
2050 devmode->icmintent = ntdevmode->icmintent;
2051 devmode->mediatype = ntdevmode->mediatype;
2052 devmode->dithertype = ntdevmode->dithertype;
2054 if (ntdevmode->private != NULL) {
2055 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2059 free_nt_devicemode(&ntdevmode);
2060 free_a_printer(&printer,2);
2067 free_nt_devicemode(&ntdevmode);
2069 free_a_printer(&printer,2);
2070 free_dev_mode(devmode);
2075 /********************************************************************
2076 * construct_printer_info_2
2077 * fill a printer_info_2 struct
2078 ********************************************************************/
2080 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2083 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2085 print_queue_struct *queue=NULL;
2086 print_status_struct status;
2087 memset(&status, 0, sizeof(status));
2089 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2092 memset(&status, 0, sizeof(status));
2093 count = print_queue_status(snum, &queue, &status);
2095 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2096 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2097 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2098 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2099 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2101 if (*ntprinter->info_2->comment == '\0')
2102 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2104 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2106 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2107 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2108 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2109 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2110 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2112 printer->attributes = ntprinter->info_2->attributes;
2114 printer->priority = ntprinter->info_2->priority; /* priority */
2115 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2116 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2117 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2118 printer->status = nt_printq_status(status.status); /* status */
2119 printer->cjobs = count; /* jobs */
2120 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2122 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2123 DEBUG(8, ("Returning NULL Devicemode!\n"));
2126 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2127 /* steal the printer info sec_desc structure. [badly done]. */
2128 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2129 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2130 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2131 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2134 printer->secdesc = NULL;
2137 free_a_printer(&ntprinter, 2);
2142 /********************************************************************
2143 * construct_printer_info_3
2144 * fill a printer_info_3 struct
2145 ********************************************************************/
2146 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2148 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2149 PRINTER_INFO_3 *printer = NULL;
2151 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2155 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2156 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2160 ZERO_STRUCTP(printer);
2162 printer->flags = 4; /* These are the components of the SD we are returning. */
2163 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2164 /* steal the printer info sec_desc structure. [badly done]. */
2165 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2169 * Set the flags for the components we are returning.
2172 if (printer->secdesc->owner_sid)
2173 printer->flags |= OWNER_SECURITY_INFORMATION;
2175 if (printer->secdesc->grp_sid)
2176 printer->flags |= GROUP_SECURITY_INFORMATION;
2178 if (printer->secdesc->dacl)
2179 printer->flags |= DACL_SECURITY_INFORMATION;
2181 if (printer->secdesc->sacl)
2182 printer->flags |= SACL_SECURITY_INFORMATION;
2185 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2186 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2187 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2190 free_a_printer(&ntprinter, 2);
2192 *pp_printer = printer;
2196 /********************************************************************
2197 Spoolss_enumprinters.
2198 ********************************************************************/
2199 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2203 int n_services=lp_numservices();
2204 PRINTER_INFO_1 *printers=NULL;
2205 PRINTER_INFO_1 current_prt;
2207 DEBUG(4,("enum_all_printers_info_1\n"));
2209 for (snum=0; snum<n_services; snum++) {
2210 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2211 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2213 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2214 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2216 return ERROR_NOT_ENOUGH_MEMORY;
2218 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2219 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2225 /* check the required size. */
2226 for (i=0; i<*returned; i++)
2227 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2229 if (!alloc_buffer_size(buffer, *needed))
2230 return ERROR_INSUFFICIENT_BUFFER;
2232 /* fill the buffer with the structures */
2233 for (i=0; i<*returned; i++)
2234 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2237 safe_free(printers);
2239 if (*needed > offered) {
2241 return ERROR_INSUFFICIENT_BUFFER;
2244 return NT_STATUS_NO_PROBLEMO;
2247 /********************************************************************
2248 enum_all_printers_info_1_local.
2249 *********************************************************************/
2250 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2252 DEBUG(4,("enum_all_printers_info_1_local\n"));
2254 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2257 /********************************************************************
2258 enum_all_printers_info_1_name.
2259 *********************************************************************/
2260 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2263 DEBUG(4,("enum_all_printers_info_1_name\n"));
2265 fstrcpy(temp, "\\\\");
2266 fstrcat(temp, global_myname);
2268 if (strequal(name, temp)) {
2269 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2272 return ERROR_INVALID_NAME;
2275 /********************************************************************
2276 enum_all_printers_info_1_remote.
2277 *********************************************************************/
2278 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2280 PRINTER_INFO_1 *printer;
2281 fstring printername;
2284 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2286 /* JFM: currently it's more a place holder than anything else.
2287 * In the spooler world there is a notion of server registration.
2288 * the print servers are registring (sp ?) on the PDC (in the same domain)
2290 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2293 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2294 return ERROR_NOT_ENOUGH_MEMORY;
2298 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2299 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2300 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2302 init_unistr(&printer->description, desc);
2303 init_unistr(&printer->name, printername);
2304 init_unistr(&printer->comment, comment);
2305 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2307 /* check the required size. */
2308 *needed += spoolss_size_printer_info_1(printer);
2310 if (!alloc_buffer_size(buffer, *needed)) {
2312 return ERROR_INSUFFICIENT_BUFFER;
2315 /* fill the buffer with the structures */
2316 new_smb_io_printer_info_1("", buffer, printer, 0);
2321 if (*needed > offered) {
2323 return ERROR_INSUFFICIENT_BUFFER;
2326 return NT_STATUS_NO_PROBLEMO;
2329 /********************************************************************
2330 enum_all_printers_info_1_network.
2331 *********************************************************************/
2332 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2334 DEBUG(4,("enum_all_printers_info_1_network\n"));
2336 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2339 /********************************************************************
2340 * api_spoolss_enumprinters
2342 * called from api_spoolss_enumprinters (see this to understand)
2343 ********************************************************************/
2344 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2348 int n_services=lp_numservices();
2349 PRINTER_INFO_2 *printers=NULL;
2350 PRINTER_INFO_2 current_prt;
2352 for (snum=0; snum<n_services; snum++) {
2353 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2354 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2356 if (construct_printer_info_2(¤t_prt, snum)) {
2357 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2358 return ERROR_NOT_ENOUGH_MEMORY;
2359 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2360 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2366 /* check the required size. */
2367 for (i=0; i<*returned; i++)
2368 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2370 if (!alloc_buffer_size(buffer, *needed)) {
2371 for (i=0; i<*returned; i++) {
2372 free_devmode(printers[i].devmode);
2373 free_sec_desc(&printers[i].secdesc);
2375 safe_free(printers);
2376 return ERROR_INSUFFICIENT_BUFFER;
2379 /* fill the buffer with the structures */
2380 for (i=0; i<*returned; i++)
2381 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2384 for (i=0; i<*returned; i++) {
2385 free_devmode(printers[i].devmode);
2386 free_sec_desc(&printers[i].secdesc);
2388 safe_free(printers);
2390 if (*needed > offered) {
2392 return ERROR_INSUFFICIENT_BUFFER;
2395 return NT_STATUS_NO_PROBLEMO;
2398 /********************************************************************
2399 * handle enumeration of printers at level 1
2400 ********************************************************************/
2401 static uint32 enumprinters_level1( uint32 flags, fstring name,
2402 NEW_BUFFER *buffer, uint32 offered,
2403 uint32 *needed, uint32 *returned)
2405 /* Not all the flags are equals */
2407 if (flags & PRINTER_ENUM_LOCAL)
2408 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2410 if (flags & PRINTER_ENUM_NAME)
2411 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2413 if (flags & PRINTER_ENUM_REMOTE)
2414 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2416 if (flags & PRINTER_ENUM_NETWORK)
2417 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2419 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2422 /********************************************************************
2423 * handle enumeration of printers at level 2
2424 ********************************************************************/
2425 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2426 NEW_BUFFER *buffer, uint32 offered,
2427 uint32 *needed, uint32 *returned)
2431 fstrcpy(temp, "\\\\");
2432 fstrcat(temp, global_myname);
2434 if (flags & PRINTER_ENUM_LOCAL) {
2435 if (strequal(servername, temp))
2436 return enum_all_printers_info_2(buffer, offered, needed, returned);
2438 return enum_all_printers_info_2(buffer, offered, needed, returned);
2441 if (flags & PRINTER_ENUM_NAME) {
2442 if (strequal(servername, temp))
2443 return enum_all_printers_info_2(buffer, offered, needed, returned);
2445 return ERROR_INVALID_NAME;
2448 if (flags & PRINTER_ENUM_REMOTE)
2449 return ERROR_INVALID_LEVEL;
2451 return NT_STATUS_NO_PROBLEMO;
2454 /********************************************************************
2455 * handle enumeration of printers at level 5
2456 ********************************************************************/
2457 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2458 NEW_BUFFER *buffer, uint32 offered,
2459 uint32 *needed, uint32 *returned)
2461 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2462 return NT_STATUS_NO_PROBLEMO;
2465 /********************************************************************
2466 * api_spoolss_enumprinters
2468 * called from api_spoolss_enumprinters (see this to understand)
2469 ********************************************************************/
2470 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2471 NEW_BUFFER *buffer, uint32 offered,
2472 uint32 *needed, uint32 *returned)
2476 DEBUG(4,("_spoolss_enumprinters\n"));
2483 * flags==PRINTER_ENUM_NAME
2484 * if name=="" then enumerates all printers
2485 * if name!="" then enumerate the printer
2486 * flags==PRINTER_ENUM_REMOTE
2487 * name is NULL, enumerate printers
2488 * Level 2: name!="" enumerates printers, name can't be NULL
2489 * Level 3: doesn't exist
2490 * Level 4: does a local registry lookup
2491 * Level 5: same as Level 2
2494 unistr2_to_ascii(name, servername, sizeof(name)-1);
2499 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2501 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2503 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2507 return ERROR_INVALID_LEVEL;
2511 /****************************************************************************
2512 ****************************************************************************/
2513 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2515 PRINTER_INFO_0 *printer=NULL;
2517 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2518 return ERROR_NOT_ENOUGH_MEMORY;
2520 construct_printer_info_0(printer, snum);
2522 /* check the required size. */
2523 *needed += spoolss_size_printer_info_0(printer);
2525 if (!alloc_buffer_size(buffer, *needed)) {
2527 return ERROR_INSUFFICIENT_BUFFER;
2530 /* fill the buffer with the structures */
2531 new_smb_io_printer_info_0("", buffer, printer, 0);
2536 if (*needed > offered) {
2537 return ERROR_INSUFFICIENT_BUFFER;
2540 return NT_STATUS_NO_PROBLEMO;
2543 /****************************************************************************
2544 ****************************************************************************/
2545 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2547 PRINTER_INFO_1 *printer=NULL;
2549 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2550 return ERROR_NOT_ENOUGH_MEMORY;
2552 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2554 /* check the required size. */
2555 *needed += spoolss_size_printer_info_1(printer);
2557 if (!alloc_buffer_size(buffer, *needed)) {
2559 return ERROR_INSUFFICIENT_BUFFER;
2562 /* fill the buffer with the structures */
2563 new_smb_io_printer_info_1("", buffer, printer, 0);
2568 if (*needed > offered) {
2569 return ERROR_INSUFFICIENT_BUFFER;
2572 return NT_STATUS_NO_PROBLEMO;
2575 /****************************************************************************
2576 ****************************************************************************/
2577 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2579 PRINTER_INFO_2 *printer=NULL;
2581 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2582 return ERROR_NOT_ENOUGH_MEMORY;
2584 construct_printer_info_2(printer, snum);
2586 /* check the required size. */
2587 *needed += spoolss_size_printer_info_2(printer);
2589 if (!alloc_buffer_size(buffer, *needed)) {
2590 free_printer_info_2(printer);
2591 return ERROR_INSUFFICIENT_BUFFER;
2594 /* fill the buffer with the structures */
2595 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2596 free_printer_info_2(printer);
2597 return ERROR_NOT_ENOUGH_MEMORY;
2601 free_printer_info_2(printer);
2603 if (*needed > offered) {
2604 return ERROR_INSUFFICIENT_BUFFER;
2607 return NT_STATUS_NO_PROBLEMO;
2610 /****************************************************************************
2611 ****************************************************************************/
2612 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2614 PRINTER_INFO_3 *printer=NULL;
2616 if (!construct_printer_info_3(&printer, snum))
2617 return ERROR_NOT_ENOUGH_MEMORY;
2619 /* check the required size. */
2620 *needed += spoolss_size_printer_info_3(printer);
2622 if (!alloc_buffer_size(buffer, *needed)) {
2623 free_printer_info_3(printer);
2624 return ERROR_INSUFFICIENT_BUFFER;
2627 /* fill the buffer with the structures */
2628 new_smb_io_printer_info_3("", buffer, printer, 0);
2631 free_printer_info_3(printer);
2633 if (*needed > offered) {
2634 return ERROR_INSUFFICIENT_BUFFER;
2637 return NT_STATUS_NO_PROBLEMO;
2640 /****************************************************************************
2641 ****************************************************************************/
2642 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2643 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2649 if (!get_printer_snum(handle, &snum))
2650 return ERROR_INVALID_HANDLE;
2654 return getprinter_level_0(snum, buffer, offered, needed);
2656 return getprinter_level_1(snum, buffer, offered, needed);
2658 return getprinter_level_2(snum, buffer, offered, needed);
2660 return getprinter_level_3(snum, buffer, offered, needed);
2662 return ERROR_INVALID_LEVEL;
2666 /********************************************************************
2667 * fill a DRIVER_INFO_1 struct
2668 ********************************************************************/
2669 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2671 init_unistr( &info->name, driver.info_3->name);
2674 /********************************************************************
2675 * construct_printer_driver_info_1
2676 ********************************************************************/
2677 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2679 NT_PRINTER_INFO_LEVEL *printer = NULL;
2680 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2682 ZERO_STRUCT(driver);
2684 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2685 return ERROR_INVALID_PRINTER_NAME;
2687 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2688 return ERROR_UNKNOWN_PRINTER_DRIVER;
2690 fill_printer_driver_info_1(info, driver, servername, architecture);
2692 free_a_printer(&printer,2);
2694 return NT_STATUS_NO_PROBLEMO;
2697 /********************************************************************
2698 * construct_printer_driver_info_2
2699 * fill a printer_info_2 struct
2700 ********************************************************************/
2701 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2703 pstring temp_driverpath;
2704 pstring temp_datafile;
2705 pstring temp_configfile;
2707 info->version=driver.info_3->cversion;
2709 init_unistr( &info->name, driver.info_3->name );
2710 init_unistr( &info->architecture, driver.info_3->environment );
2712 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2713 init_unistr( &info->driverpath, temp_driverpath );
2715 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2716 init_unistr( &info->datafile, temp_datafile );
2718 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2719 init_unistr( &info->configfile, temp_configfile );
2722 /********************************************************************
2723 * construct_printer_driver_info_2
2724 * fill a printer_info_2 struct
2725 ********************************************************************/
2726 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2728 NT_PRINTER_INFO_LEVEL *printer = NULL;
2729 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2731 ZERO_STRUCT(printer);
2732 ZERO_STRUCT(driver);
2734 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2735 return ERROR_INVALID_PRINTER_NAME;
2737 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2738 return ERROR_UNKNOWN_PRINTER_DRIVER;
2740 fill_printer_driver_info_2(info, driver, servername);
2742 free_a_printer(&printer,2);
2744 return NT_STATUS_NO_PROBLEMO;
2747 /********************************************************************
2748 * copy a strings array and convert to UNICODE
2750 * convert an array of ascii string to a UNICODE string
2751 ********************************************************************/
2752 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2759 DEBUG(6,("init_unistr_array\n"));
2763 if (char_array == NULL)
2767 if (!v) v = ""; /* hack to handle null lists */
2769 if (strlen(v) == 0) break;
2770 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2771 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2772 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2773 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2776 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2781 (*uni_array)[j]=0x0000;
2784 DEBUGADD(6,("last one:done\n"));
2787 /********************************************************************
2788 * construct_printer_info_3
2789 * fill a printer_info_3 struct
2790 ********************************************************************/
2791 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2793 pstring temp_driverpath;
2794 pstring temp_datafile;
2795 pstring temp_configfile;
2796 pstring temp_helpfile;
2800 info->version=driver.info_3->cversion;
2802 init_unistr( &info->name, driver.info_3->name );
2803 init_unistr( &info->architecture, driver.info_3->environment );
2805 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2806 init_unistr( &info->driverpath, temp_driverpath );
2808 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2809 init_unistr( &info->datafile, temp_datafile );
2811 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2812 init_unistr( &info->configfile, temp_configfile );
2814 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2815 init_unistr( &info->helpfile, temp_helpfile );
2817 init_unistr( &info->monitorname, driver.info_3->monitorname );
2818 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2820 info->dependentfiles=NULL;
2821 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2824 /********************************************************************
2825 * construct_printer_info_3
2826 * fill a printer_info_3 struct
2827 ********************************************************************/
2828 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2830 NT_PRINTER_INFO_LEVEL *printer = NULL;
2831 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2833 ZERO_STRUCT(driver);
2835 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2836 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2838 return ERROR_INVALID_PRINTER_NAME;
2840 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2841 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2843 free_a_printer(&printer,2);
2844 return ERROR_UNKNOWN_PRINTER_DRIVER;
2847 fill_printer_driver_info_3(info, driver, servername);
2849 free_a_printer(&printer,2);
2851 return NT_STATUS_NO_PROBLEMO;
2854 /********************************************************************
2855 * construct_printer_info_6
2856 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2857 ********************************************************************/
2859 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2861 pstring temp_driverpath;
2862 pstring temp_datafile;
2863 pstring temp_configfile;
2864 pstring temp_helpfile;
2868 memset(&nullstr, '\0', sizeof(fstring));
2870 info->version=driver.info_3->cversion;
2872 init_unistr( &info->name, driver.info_3->name );
2873 init_unistr( &info->architecture, driver.info_3->environment );
2875 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2876 init_unistr( &info->driverpath, temp_driverpath );
2878 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2879 init_unistr( &info->datafile, temp_datafile );
2881 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2882 init_unistr( &info->configfile, temp_configfile );
2884 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2885 init_unistr( &info->helpfile, temp_helpfile );
2887 init_unistr( &info->monitorname, driver.info_3->monitorname );
2888 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2890 info->dependentfiles=NULL;
2891 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2893 info->previousdrivernames=NULL;
2894 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2896 info->driver_date.low=0;
2897 info->driver_date.high=0;
2900 info->driver_version_low=0;
2901 info->driver_version_high=0;
2903 init_unistr( &info->mfgname, "");
2904 init_unistr( &info->oem_url, "");
2905 init_unistr( &info->hardware_id, "");
2906 init_unistr( &info->provider, "");
2909 /********************************************************************
2910 * construct_printer_info_6
2911 * fill a printer_info_6 struct
2912 ********************************************************************/
2913 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2915 NT_PRINTER_INFO_LEVEL *printer = NULL;
2916 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2918 ZERO_STRUCT(driver);
2920 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2921 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2923 return ERROR_INVALID_PRINTER_NAME;
2925 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2926 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2929 * Is this a W2k client ?
2933 free_a_printer(&printer,2);
2934 return ERROR_UNKNOWN_PRINTER_DRIVER;
2937 /* Yes - try again with a WinNT driver. */
2939 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2940 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2942 free_a_printer(&printer,2);
2943 return ERROR_UNKNOWN_PRINTER_DRIVER;
2947 fill_printer_driver_info_6(info, driver, servername);
2949 free_a_printer(&printer,2);
2951 return NT_STATUS_NO_PROBLEMO;
2954 /****************************************************************************
2955 ****************************************************************************/
2957 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2959 safe_free(info->dependentfiles);
2962 /****************************************************************************
2963 ****************************************************************************/
2965 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2967 safe_free(info->dependentfiles);
2971 /****************************************************************************
2972 ****************************************************************************/
2973 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2975 DRIVER_INFO_1 *info=NULL;
2978 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2979 return ERROR_NOT_ENOUGH_MEMORY;
2981 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2982 if (status != NT_STATUS_NO_PROBLEMO) {
2987 /* check the required size. */
2988 *needed += spoolss_size_printer_driver_info_1(info);
2990 if (!alloc_buffer_size(buffer, *needed)) {
2992 return ERROR_INSUFFICIENT_BUFFER;
2995 /* fill the buffer with the structures */
2996 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3001 if (*needed > offered)
3002 return ERROR_INSUFFICIENT_BUFFER;
3004 return NT_STATUS_NO_PROBLEMO;
3007 /****************************************************************************
3008 ****************************************************************************/
3009 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3011 DRIVER_INFO_2 *info=NULL;
3014 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3015 return ERROR_NOT_ENOUGH_MEMORY;
3017 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3018 if (status != NT_STATUS_NO_PROBLEMO) {
3023 /* check the required size. */
3024 *needed += spoolss_size_printer_driver_info_2(info);
3026 if (!alloc_buffer_size(buffer, *needed)) {
3028 return ERROR_INSUFFICIENT_BUFFER;
3031 /* fill the buffer with the structures */
3032 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3037 if (*needed > offered)
3038 return ERROR_INSUFFICIENT_BUFFER;
3040 return NT_STATUS_NO_PROBLEMO;
3043 /****************************************************************************
3044 ****************************************************************************/
3045 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3052 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3053 if (status != NT_STATUS_NO_PROBLEMO) {
3057 /* check the required size. */
3058 *needed += spoolss_size_printer_driver_info_3(&info);
3060 if (!alloc_buffer_size(buffer, *needed)) {
3061 free_printer_driver_info_3(&info);
3062 return ERROR_INSUFFICIENT_BUFFER;
3065 /* fill the buffer with the structures */
3066 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3068 free_printer_driver_info_3(&info);
3070 if (*needed > offered)
3071 return ERROR_INSUFFICIENT_BUFFER;
3073 return NT_STATUS_NO_PROBLEMO;
3076 /****************************************************************************
3077 ****************************************************************************/
3078 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3085 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3086 if (status != NT_STATUS_NO_PROBLEMO) {
3090 /* check the required size. */
3091 *needed += spoolss_size_printer_driver_info_6(&info);
3093 if (!alloc_buffer_size(buffer, *needed)) {
3094 free_printer_driver_info_6(&info);
3095 return ERROR_INSUFFICIENT_BUFFER;
3098 /* fill the buffer with the structures */
3099 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3101 free_printer_driver_info_6(&info);
3103 if (*needed > offered)
3104 return ERROR_INSUFFICIENT_BUFFER;
3106 return NT_STATUS_NO_PROBLEMO;
3109 /****************************************************************************
3110 ****************************************************************************/
3111 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3112 uint32 clientmajorversion, uint32 clientminorversion,
3113 NEW_BUFFER *buffer, uint32 offered,
3114 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3117 fstring architecture;
3120 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3123 *servermajorversion=0;
3124 *serverminorversion=0;
3126 pstrcpy(servername, global_myname);
3127 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3129 if (!get_printer_snum(handle, &snum))
3130 return ERROR_INVALID_HANDLE;
3134 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3136 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3138 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3140 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3142 return ERROR_INVALID_LEVEL;
3146 /****************************************************************************
3147 ****************************************************************************/
3148 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3150 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3152 if (OPEN_HANDLE(Printer)) {
3153 Printer->page_started=True;
3157 DEBUG(3,("Error in startpageprinter printer handle\n"));
3158 return ERROR_INVALID_HANDLE;
3161 /****************************************************************************
3162 ****************************************************************************/
3163 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3165 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3167 if (!OPEN_HANDLE(Printer)) {
3168 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3169 return ERROR_INVALID_HANDLE;
3172 Printer->page_started=False;
3174 return NT_STATUS_NO_PROBLEMO;
3177 /****************************************************************************
3178 Return a user struct for a pipe user.
3179 ****************************************************************************/
3181 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3183 if (p->ntlmssp_auth_validated) {
3184 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3186 extern struct current_user current_user;
3187 memcpy(user, ¤t_user, sizeof(struct current_user));
3193 /********************************************************************
3194 * api_spoolss_getprinter
3195 * called from the spoolss dispatcher
3197 ********************************************************************/
3198 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3199 pipes_struct *p, DOC_INFO *docinfo,
3202 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3206 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3207 struct current_user user;
3209 if (!OPEN_HANDLE(Printer)) {
3210 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3211 return ERROR_INVALID_HANDLE;
3214 get_current_user(&user, p);
3217 * a nice thing with NT is it doesn't listen to what you tell it.
3218 * when asked to send _only_ RAW datas, it tries to send datas
3221 * So I add checks like in NT Server ...
3223 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3224 * there's a bug in NT client-side code, so we'll fix it in the
3225 * server-side code. *nnnnnggggh!*
3228 if (info_1->p_datatype != 0) {
3229 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3230 if (strcmp(datatype, "RAW") != 0) {
3232 return ERROR_INVALID_DATATYPE;
3236 /* get the share number of the printer */
3237 if (!get_printer_snum(handle, &snum)) {
3238 return ERROR_INVALID_HANDLE;
3241 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3243 Printer->jobid = print_job_start(&user, snum, jobname);
3245 /* An error occured in print_job_start() so return an appropriate
3248 if (Printer->jobid == -1) {
3249 return map_nt_error_from_unix(errno);
3252 Printer->document_started=True;
3253 (*jobid) = Printer->jobid;
3255 srv_spoolss_sendnotify(handle);
3259 /********************************************************************
3260 * api_spoolss_getprinter
3261 * called from the spoolss dispatcher
3263 ********************************************************************/
3264 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3266 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3268 if (!OPEN_HANDLE(Printer)) {
3269 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3270 return ERROR_INVALID_HANDLE;
3273 Printer->document_started=False;
3274 print_job_end(Printer->jobid);
3275 /* error codes unhandled so far ... */
3277 srv_spoolss_sendnotify(handle);
3282 /****************************************************************************
3283 ****************************************************************************/
3284 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3287 uint32 *buffer_written)
3289 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3291 if (!OPEN_HANDLE(Printer)) {
3292 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3293 return ERROR_INVALID_HANDLE;
3296 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3302 /********************************************************************
3303 * api_spoolss_getprinter
3304 * called from the spoolss dispatcher
3306 ********************************************************************/
3307 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3310 struct current_user user;
3311 int snum, errcode = ERROR_INVALID_FUNCTION;
3312 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3314 get_current_user(&user, p);
3316 if (!OPEN_HANDLE(Printer)) {
3317 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3318 return ERROR_INVALID_HANDLE;
3321 if (!get_printer_snum(handle, &snum))
3322 return ERROR_INVALID_HANDLE;
3325 case PRINTER_CONTROL_PAUSE:
3326 if (print_queue_pause(&user, snum, &errcode)) {
3330 case PRINTER_CONTROL_RESUME:
3331 case PRINTER_CONTROL_UNPAUSE:
3332 if (print_queue_resume(&user, snum, &errcode)) {
3336 case PRINTER_CONTROL_PURGE:
3337 if (print_queue_purge(&user, snum, &errcode)) {
3342 return ERROR_INVALID_LEVEL;
3348 /********************************************************************
3349 * api_spoolss_abortprinter
3350 ********************************************************************/
3352 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3354 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3357 /********************************************************************
3358 * called by spoolss_api_setprinter
3359 * when updating a printer description
3360 ********************************************************************/
3361 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3362 const SPOOL_PRINTER_INFO_LEVEL *info,
3363 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3365 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3366 struct current_user user;
3370 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3372 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3373 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3374 OUR_HANDLE(handle)));
3376 result = ERROR_INVALID_HANDLE;
3380 /* NT seems to like setting the security descriptor even though
3381 nothing may have actually changed. This causes annoying
3382 dialog boxes when the user doesn't have permission to change
3383 the security descriptor. */
3385 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3387 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3389 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3390 result = NT_STATUS_NO_PROBLEMO;
3394 /* Work out which user is performing the operation */
3396 get_current_user(&user, p);
3398 /* Check the user has permissions to change the security
3399 descriptor. By experimentation with two NT machines, the user
3400 requires Full Access to the printer to change security
3403 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3404 result = ERROR_ACCESS_DENIED;
3408 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3411 free_sec_desc_buf(&new_secdesc_ctr);
3412 free_sec_desc_buf(&old_secdesc_ctr);
3417 /********************************************************************
3418 Do Samba sanity checks on a printer info struct.
3419 this has changed purpose: it now "canonicalises" printer
3420 info from a client rather than just checking it is correct
3421 ********************************************************************/
3423 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3425 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3426 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3428 /* we force some elements to "correct" values */
3429 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3430 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3431 global_myname, lp_servicename(snum));
3432 fstrcpy(info->sharename, lp_servicename(snum));
3433 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3434 | PRINTER_ATTRIBUTE_LOCAL \
3435 | PRINTER_ATTRIBUTE_RAW_ONLY \
3436 | PRINTER_ATTRIBUTE_QUEUED ;
3441 /****************************************************************************
3442 ****************************************************************************/
3443 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3445 pid_t local_pid = sys_getpid();
3446 char *cmd = lp_addprinter_cmd();
3451 pstring driverlocation;
3455 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3456 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3460 /* build driver path... only 9X architecture is needed for legacy reasons */
3461 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3463 /* change \ to \\ for the shell */
3464 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3466 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3467 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3468 cmd, printer->info_2->printername, printer->info_2->sharename,
3469 printer->info_2->portname, printer->info_2->drivername,
3470 printer->info_2->location, driverlocation);
3473 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3474 ret = smbrun(command, tmp_file, False);
3475 DEBUGADD(10,("returned [%d]\n", ret));
3483 qlines = file_lines_load(tmp_file, &numlines);
3484 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3485 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3489 /* Set the portname to what the script says the portname should be. */
3490 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3491 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3493 /* Send SIGHUP to process group... is there a better way? */
3498 file_lines_free(qlines);
3502 /* Return true if two devicemodes are equal */
3504 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3506 if (!strequal(d1->devicename, d2->devicename) ||
3507 !strequal(d1->formname, d2->formname)) {
3511 if (d1->specversion != d2->specversion ||
3512 d1->driverversion != d2->driverversion ||
3513 d1->size != d2->size ||
3514 d1->driverextra != d2->driverextra ||
3515 d1->orientation != d2->orientation ||
3516 d1->papersize != d2->papersize ||
3517 d1->paperlength != d2->paperlength ||
3518 d1->paperwidth != d2->paperwidth ||
3519 d1->scale != d2->scale ||
3520 d1->copies != d2->copies ||
3521 d1->defaultsource != d2->defaultsource ||
3522 d1->printquality != d2->printquality ||
3523 d1->color != d2->color ||
3524 d1->duplex != d2->duplex ||
3525 d1->yresolution != d2->yresolution ||
3526 d1->ttoption != d2->ttoption ||
3527 d1->collate != d2->collate ||
3528 d1->logpixels != d2->logpixels) {
3532 if (d1->fields != d2->fields ||
3533 d1->bitsperpel != d2->bitsperpel ||
3534 d1->pelswidth != d2->pelswidth ||
3535 d1->pelsheight != d2->pelsheight ||
3536 d1->displayflags != d2->displayflags ||
3537 d1->displayfrequency != d2->displayfrequency ||
3538 d1->icmmethod != d2->icmmethod ||
3539 d1->icmintent != d2->icmintent ||
3540 d1->mediatype != d2->mediatype ||
3541 d1->dithertype != d2->dithertype ||
3542 d1->reserved1 != d2->reserved1 ||
3543 d1->reserved2 != d2->reserved2 ||
3544 d1->panningwidth != d2->panningwidth ||
3545 d1->panningheight != d2->panningheight) {
3549 /* Not sure what to do about these fields */
3557 /* Return true if two NT_PRINTER_PARAM structures are equal */
3559 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3560 NT_PRINTER_PARAM *p2)
3562 if (!p1 && !p2) return True;
3564 if ((!p1 && p2) || (p1 && !p2)) return False;
3566 /* Compare lists of printer parameters */
3570 NT_PRINTER_PARAM *q = p1;
3572 /* Find the parameter in the second structure */
3576 if (strequal(p1->value, q->value) &&
3577 p1->type == q->type &&
3578 p1->data_len == q->data_len &&
3579 memcmp(p1->data, q->data, p1->data_len) == 0) {
3598 /********************************************************************
3599 * Called by update_printer when trying to work out whether to
3600 * actually update printer info.
3601 ********************************************************************/
3603 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3604 NT_PRINTER_INFO_LEVEL *p2)
3606 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3608 /* Trivial conditions */
3610 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3614 if ((!p1 && p2) || (p1 && !p2) ||
3615 (!p1->info_2 && p2->info_2) ||
3616 (p1->info_2 && !p2->info_2)) {
3620 /* Compare two nt_printer_info_level structures. Don't compare
3621 status or cjobs as they seem to have something to do with the
3627 if (pi1->attributes != pi2->attributes ||
3628 pi1->priority != pi2->priority ||
3629 pi1->default_priority != pi2->default_priority ||
3630 pi1->starttime != pi2->starttime ||
3631 pi1->untiltime != pi2->untiltime ||
3632 pi1->averageppm != pi2->averageppm) {
3636 /* Yuck - don't check the printername or servername as the
3637 add_a_printer() code plays games with them. You can't
3638 change the printername or the sharename through this interface
3641 if (!strequal(pi1->sharename, pi2->sharename) ||
3642 !strequal(pi1->portname, pi2->portname) ||
3643 !strequal(pi1->drivername, pi2->drivername) ||
3644 !strequal(pi1->comment, pi2->comment) ||
3645 !strequal(pi1->location, pi2->location)) {
3649 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3653 if (!strequal(pi1->sepfile, pi2->sepfile) ||
3654 !strequal(pi1->printprocessor, pi2->printprocessor) ||
3655 !strequal(pi1->datatype, pi2->datatype) ||
3656 !strequal(pi1->parameters, pi2->parameters)) {
3660 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3664 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3668 if (pi1->changeid != pi2->changeid ||
3669 pi1->c_setprinter != pi2->c_setprinter ||
3670 pi1->setuptime != pi2->setuptime) {
3677 /********************************************************************
3678 * called by spoolss_api_setprinter
3679 * when updating a printer description
3680 ********************************************************************/
3682 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3683 const SPOOL_PRINTER_INFO_LEVEL *info,
3684 DEVICEMODE *devmode)
3687 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3688 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3691 DEBUG(8,("update_printer\n"));
3693 result = NT_STATUS_NO_PROBLEMO;
3696 DEBUG(0,("Send a mail to samba@samba.org\n"));
3697 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3698 result = ERROR_INVALID_LEVEL;
3702 if (!OPEN_HANDLE(Printer)) {
3703 result = ERROR_INVALID_HANDLE;
3707 if (!get_printer_snum(handle, &snum)) {
3708 result = ERROR_INVALID_HANDLE;
3712 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3713 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3714 result = ERROR_INVALID_HANDLE;
3718 DEBUGADD(8,("Converting info_2 struct\n"));
3721 * convert_printer_info converts the incoming
3722 * info from the client and overwrites the info
3723 * just read from the tdb in the pointer 'printer'.
3726 convert_printer_info(info, printer, level);
3728 if (info->info_2->devmode_ptr != 0) {
3729 /* we have a valid devmode
3730 convert it and link it*/
3733 * Ensure printer->info_2->devmode is a valid pointer
3734 * as we will be overwriting it in convert_devicemode().
3737 if (printer->info_2->devmode == NULL)
3738 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3740 DEBUGADD(8,("Converting the devicemode struct\n"));
3741 convert_devicemode(devmode, printer->info_2->devmode);
3744 if (printer->info_2->devmode != NULL)
3745 free_nt_devicemode(&printer->info_2->devmode);
3746 printer->info_2->devmode=NULL;
3749 /* Do sanity check on the requested changes for Samba */
3751 if (!check_printer_ok(printer->info_2, snum)) {
3752 result = ERROR_INVALID_PARAMETER;
3756 /* NT likes to call this function even though nothing has actually
3757 changed. Check this so the user doesn't end up with an
3758 annoying permission denied dialog box. */
3760 if (nt_printer_info_level_equal(printer, old_printer)) {
3761 DEBUG(3, ("printer info has not changed\n"));
3762 result = NT_STATUS_NO_PROBLEMO;
3766 /* Check calling user has permission to update printer description */
3768 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3769 DEBUG(3, ("printer property change denied by security "
3771 result = ERROR_ACCESS_DENIED;
3775 /* Call addprinter hook */
3777 if (*lp_addprinter_cmd() )
3778 if ( !add_printer_hook(printer) ) {
3779 result = ERROR_ACCESS_DENIED;
3783 /* Update printer info */
3785 if (add_a_printer(*printer, 2)!=0) {
3786 /* I don't really know what to return here !!! */
3787 result = ERROR_ACCESS_DENIED;
3792 free_a_printer(&printer, 2);
3793 free_a_printer(&old_printer, 2);
3795 srv_spoolss_sendnotify(handle);
3800 /****************************************************************************
3801 ****************************************************************************/
3802 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3803 const SPOOL_PRINTER_INFO_LEVEL *info,
3804 DEVMODE_CTR devmode_ctr,
3805 SEC_DESC_BUF *secdesc_ctr,
3806 uint32 command, pipes_struct *p)
3808 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3810 if (!OPEN_HANDLE(Printer)) {
3811 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3812 return ERROR_INVALID_HANDLE;
3815 /* check the level */
3818 return control_printer(handle, command, p);
3820 return update_printer(handle, level, info, devmode_ctr.devmode);
3822 return update_printer_sec(handle, level, info, p,
3825 return ERROR_INVALID_LEVEL;
3829 /****************************************************************************
3830 ****************************************************************************/
3831 uint32 _spoolss_fcpn(POLICY_HND *handle)
3833 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3835 if (!OPEN_HANDLE(Printer)) {
3836 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3837 return ERROR_INVALID_HANDLE;
3840 if (Printer->notify.client_connected==True)
3841 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3842 return ERROR_INVALID_HANDLE;
3844 Printer->notify.flags=0;
3845 Printer->notify.options=0;
3846 Printer->notify.localmachine[0]='\0';
3847 Printer->notify.printerlocal=0;
3848 if (Printer->notify.option)
3849 safe_free(Printer->notify.option->ctr.type);
3850 safe_free(Printer->notify.option);
3851 Printer->notify.option=NULL;
3852 Printer->notify.client_connected=False;
3854 return NT_STATUS_NO_PROBLEMO;
3857 /****************************************************************************
3858 ****************************************************************************/
3859 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3860 NEW_BUFFER *buffer, uint32 offered,
3864 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3865 returns for AddJob. AddJob
3866 must fail on non-local
3870 /****************************************************************************
3871 ****************************************************************************/
3872 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3873 int position, int snum)
3879 t=gmtime(&queue->time);
3880 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3882 job_info->jobid=queue->job;
3883 init_unistr(&job_info->printername, lp_servicename(snum));
3884 init_unistr(&job_info->machinename, temp_name);
3885 init_unistr(&job_info->username, queue->user);
3886 init_unistr(&job_info->document, queue->file);
3887 init_unistr(&job_info->datatype, "RAW");
3888 init_unistr(&job_info->text_status, "");
3889 job_info->status=nt_printj_status(queue->status);
3890 job_info->priority=queue->priority;
3891 job_info->position=position;
3892 job_info->totalpages=0;
3893 job_info->pagesprinted=0;
3895 make_systemtime(&job_info->submitted, t);
3898 /****************************************************************************
3899 ****************************************************************************/
3900 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3901 int position, int snum)
3904 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3908 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3911 t=gmtime(&queue->time);
3912 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3914 job_info->jobid=queue->job;
3916 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3918 init_unistr(&job_info->printername, chaine);
3920 init_unistr(&job_info->machinename, temp_name);
3921 init_unistr(&job_info->username, queue->user);
3922 init_unistr(&job_info->document, queue->file);
3923 init_unistr(&job_info->notifyname, queue->user);
3924 init_unistr(&job_info->datatype, "RAW");
3925 init_unistr(&job_info->printprocessor, "winprint");
3926 init_unistr(&job_info->parameters, "");
3927 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3928 init_unistr(&job_info->text_status, "");
3930 /* and here the security descriptor */
3932 job_info->status=nt_printj_status(queue->status);
3933 job_info->priority=queue->priority;
3934 job_info->position=position;
3935 job_info->starttime=0;
3936 job_info->untiltime=0;
3937 job_info->totalpages=0;
3938 job_info->size=queue->size;
3939 make_systemtime(&(job_info->submitted), t);
3940 job_info->timeelapsed=0;
3941 job_info->pagesprinted=0;
3943 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
3944 free_a_printer(&ntprinter, 2);
3948 free_a_printer(&ntprinter, 2);
3952 /****************************************************************************
3953 Enumjobs at level 1.
3954 ****************************************************************************/
3955 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3956 NEW_BUFFER *buffer, uint32 offered,
3957 uint32 *needed, uint32 *returned)
3962 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3966 return ERROR_NOT_ENOUGH_MEMORY;
3969 for (i=0; i<*returned; i++)
3970 fill_job_info_1(&info[i], &queue[i], i, snum);
3974 /* check the required size. */
3975 for (i=0; i<*returned; i++)
3976 (*needed) += spoolss_size_job_info_1(&info[i]);
3978 if (!alloc_buffer_size(buffer, *needed)) {
3980 return ERROR_INSUFFICIENT_BUFFER;
3983 /* fill the buffer with the structures */
3984 for (i=0; i<*returned; i++)
3985 new_smb_io_job_info_1("", buffer, &info[i], 0);
3990 if (*needed > offered) {
3992 return ERROR_INSUFFICIENT_BUFFER;
3995 return NT_STATUS_NO_PROBLEMO;
3998 /****************************************************************************
3999 Enumjobs at level 2.
4000 ****************************************************************************/
4001 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4002 NEW_BUFFER *buffer, uint32 offered,
4003 uint32 *needed, uint32 *returned)
4008 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4012 return ERROR_NOT_ENOUGH_MEMORY;
4015 for (i=0; i<*returned; i++)
4016 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4020 /* check the required size. */
4021 for (i=0; i<*returned; i++)
4022 (*needed) += spoolss_size_job_info_2(&info[i]);
4024 if (!alloc_buffer_size(buffer, *needed)) {
4026 return ERROR_INSUFFICIENT_BUFFER;
4029 /* fill the buffer with the structures */
4030 for (i=0; i<*returned; i++)
4031 new_smb_io_job_info_2("", buffer, &info[i], 0);
4036 if (*needed > offered) {
4038 return ERROR_INSUFFICIENT_BUFFER;
4041 return NT_STATUS_NO_PROBLEMO;
4044 /****************************************************************************
4046 ****************************************************************************/
4047 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4048 NEW_BUFFER *buffer, uint32 offered,
4049 uint32 *needed, uint32 *returned)
4052 print_queue_struct *queue=NULL;
4053 print_status_struct prt_status;
4055 DEBUG(4,("_spoolss_enumjobs\n"));
4057 ZERO_STRUCT(prt_status);
4062 if (!get_printer_snum(handle, &snum))
4063 return ERROR_INVALID_HANDLE;
4065 *returned = print_queue_status(snum, &queue, &prt_status);
4066 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4068 if (*returned == 0) {
4070 return NT_STATUS_NO_PROBLEMO;
4075 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4077 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4081 return ERROR_INVALID_LEVEL;
4086 /****************************************************************************
4087 ****************************************************************************/
4088 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4093 /****************************************************************************
4094 ****************************************************************************/
4095 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4096 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4098 struct current_user user;
4099 print_status_struct prt_status;
4100 int snum, errcode = ERROR_INVALID_FUNCTION;
4102 memset(&prt_status, 0, sizeof(prt_status));
4104 if (!get_printer_snum(handle, &snum)) {
4105 return ERROR_INVALID_HANDLE;
4108 if (!print_job_exists(jobid)) {
4109 return ERROR_INVALID_PRINTER_NAME;
4112 get_current_user(&user, p);
4115 case JOB_CONTROL_CANCEL:
4116 case JOB_CONTROL_DELETE:
4117 if (print_job_delete(&user, jobid, &errcode)) {
4121 case JOB_CONTROL_PAUSE:
4122 if (print_job_pause(&user, jobid, &errcode)) {
4126 case JOB_CONTROL_RESTART:
4127 case JOB_CONTROL_RESUME:
4128 if (print_job_resume(&user, jobid, &errcode)) {
4133 return ERROR_INVALID_LEVEL;
4139 /****************************************************************************
4140 Enumerates all printer drivers at level 1.
4141 ****************************************************************************/
4142 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4147 fstring *list = NULL;
4149 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4150 DRIVER_INFO_1 *driver_info_1=NULL;
4154 #define MAX_VERSION 4
4156 for (version=0; version<MAX_VERSION; version++) {
4158 ndrivers=get_ntdrivers(&list, architecture, version);
4159 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4162 return ERROR_NOT_ENOUGH_MEMORY;
4165 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4167 return ERROR_NOT_ENOUGH_MEMORY;
4171 for (i=0; i<ndrivers; i++) {
4173 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4174 ZERO_STRUCT(driver);
4175 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4179 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4180 free_a_printer_driver(driver, 3);
4183 *returned+=ndrivers;
4187 /* check the required size. */
4188 for (i=0; i<*returned; i++) {
4189 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4190 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4193 if (!alloc_buffer_size(buffer, *needed)) {
4194 safe_free(driver_info_1);
4195 return ERROR_INSUFFICIENT_BUFFER;
4198 /* fill the buffer with the form structures */
4199 for (i=0; i<*returned; i++) {
4200 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4201 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4204 safe_free(driver_info_1);
4206 if (*needed > offered) {
4208 return ERROR_INSUFFICIENT_BUFFER;
4211 return NT_STATUS_NO_PROBLEMO;
4214 /****************************************************************************
4215 Enumerates all printer drivers at level 2.
4216 ****************************************************************************/
4217 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4222 fstring *list = NULL;
4224 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4225 DRIVER_INFO_2 *driver_info_2=NULL;
4229 #define MAX_VERSION 4
4231 for (version=0; version<MAX_VERSION; version++) {
4233 ndrivers=get_ntdrivers(&list, architecture, version);
4234 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4237 return ERROR_NOT_ENOUGH_MEMORY;
4240 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4242 return ERROR_NOT_ENOUGH_MEMORY;
4246 for (i=0; i<ndrivers; i++) {
4249 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4250 ZERO_STRUCT(driver);
4251 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4255 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4256 free_a_printer_driver(driver, 3);
4259 *returned+=ndrivers;
4263 /* check the required size. */
4264 for (i=0; i<*returned; i++) {
4265 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4266 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4269 if (!alloc_buffer_size(buffer, *needed)) {
4270 safe_free(driver_info_2);
4271 return ERROR_INSUFFICIENT_BUFFER;
4274 /* fill the buffer with the form structures */
4275 for (i=0; i<*returned; i++) {
4276 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4277 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4280 safe_free(driver_info_2);
4282 if (*needed > offered) {
4284 return ERROR_INSUFFICIENT_BUFFER;
4287 return NT_STATUS_NO_PROBLEMO;
4290 /****************************************************************************
4291 Enumerates all printer drivers at level 3.
4292 ****************************************************************************/
4293 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4298 fstring *list = NULL;
4300 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4301 DRIVER_INFO_3 *driver_info_3=NULL;
4305 #define MAX_VERSION 4
4307 for (version=0; version<MAX_VERSION; version++) {
4309 ndrivers=get_ntdrivers(&list, architecture, version);
4310 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4313 return ERROR_NOT_ENOUGH_MEMORY;
4316 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4318 return ERROR_NOT_ENOUGH_MEMORY;
4322 for (i=0; i<ndrivers; i++) {
4325 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4326 ZERO_STRUCT(driver);
4327 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4331 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4332 free_a_printer_driver(driver, 3);
4335 *returned+=ndrivers;
4339 /* check the required size. */
4340 for (i=0; i<*returned; i++) {
4341 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4342 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4345 if (!alloc_buffer_size(buffer, *needed)) {
4346 safe_free(driver_info_3);
4347 return ERROR_INSUFFICIENT_BUFFER;
4350 /* fill the buffer with the driver structures */
4351 for (i=0; i<*returned; i++) {
4352 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4353 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4356 for (i=0; i<*returned; i++)
4357 safe_free(driver_info_3[i].dependentfiles);
4359 safe_free(driver_info_3);
4361 if (*needed > offered) {
4363 return ERROR_INSUFFICIENT_BUFFER;
4366 return NT_STATUS_NO_PROBLEMO;
4369 /****************************************************************************
4370 Enumerates all printer drivers.
4371 ****************************************************************************/
4372 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4373 NEW_BUFFER *buffer, uint32 offered,
4374 uint32 *needed, uint32 *returned)
4376 fstring *list = NULL;
4378 fstring architecture;
4380 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4381 fstrcpy(servername, global_myname);
4385 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4389 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4391 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4393 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4397 return ERROR_INVALID_LEVEL;
4401 /****************************************************************************
4402 ****************************************************************************/
4403 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4405 form->flag=list->flag;
4406 init_unistr(&form->name, list->name);
4407 form->width=list->width;
4408 form->length=list->length;
4409 form->left=list->left;
4410 form->top=list->top;
4411 form->right=list->right;
4412 form->bottom=list->bottom;
4415 /****************************************************************************
4416 ****************************************************************************/
4417 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4418 NEW_BUFFER *buffer, uint32 offered,
4419 uint32 *needed, uint32 *numofforms)
4421 nt_forms_struct *list=NULL;
4426 DEBUG(4,("_new_spoolss_enumforms\n"));
4427 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4428 DEBUGADD(5,("Info level [%d]\n", level));
4430 *numofforms = get_ntforms(&list);
4431 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4433 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4437 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4439 return ERROR_NOT_ENOUGH_MEMORY;
4442 /* construct the list of form structures */
4443 for (i=0; i<*numofforms; i++) {
4444 DEBUGADD(6,("Filling form number [%d]\n",i));
4445 fill_form_1(&forms_1[i], &list[i]);
4450 /* check the required size. */
4451 for (i=0; i<*numofforms; i++) {
4452 DEBUGADD(6,("adding form [%d]'s size\n",i));
4453 buffer_size += spoolss_size_form_1(&forms_1[i]);
4456 *needed=buffer_size;
4458 if (!alloc_buffer_size(buffer, buffer_size)){
4460 return ERROR_INSUFFICIENT_BUFFER;
4463 /* fill the buffer with the form structures */
4464 for (i=0; i<*numofforms; i++) {
4465 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4466 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4471 if (*needed > offered) {
4473 return ERROR_INSUFFICIENT_BUFFER;
4476 return NT_STATUS_NO_PROBLEMO;
4480 return ERROR_INVALID_LEVEL;
4485 /****************************************************************************
4486 ****************************************************************************/
4487 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4489 nt_forms_struct *list=NULL;
4495 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4497 DEBUG(4,("_spoolss_getform\n"));
4498 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4499 DEBUGADD(5,("Info level [%d]\n", level));
4501 numofforms = get_ntforms(&list);
4502 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4504 if (numofforms == 0)
4505 return ERROR_NO_MORE_ITEMS;
4510 /* Check if the requested name is in the list of form structures */
4511 for (i=0; i<numofforms; i++) {
4513 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4515 if (strequal(form_name, list[i].name)) {
4516 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4517 fill_form_1(&form_1, &list[i]);
4524 /* check the required size. */
4526 *needed=spoolss_size_form_1(&form_1);
4528 if (!alloc_buffer_size(buffer, buffer_size)){
4529 return ERROR_INSUFFICIENT_BUFFER;
4532 if (*needed > offered) {
4533 return ERROR_INSUFFICIENT_BUFFER;
4536 /* fill the buffer with the form structures */
4537 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4538 new_smb_io_form_1("", buffer, &form_1, 0);
4540 return NT_STATUS_NO_PROBLEMO;
4544 return ERROR_INVALID_LEVEL;
4548 /****************************************************************************
4549 ****************************************************************************/
4550 static void fill_port_1(PORT_INFO_1 *port, char *name)
4552 init_unistr(&port->port_name, name);
4555 /****************************************************************************
4556 ****************************************************************************/
4557 static void fill_port_2(PORT_INFO_2 *port, char *name)
4559 init_unistr(&port->port_name, name);
4560 init_unistr(&port->monitor_name, "Local Monitor");
4561 init_unistr(&port->description, "Local Port");
4562 #define PORT_TYPE_WRITE 1
4563 port->port_type=PORT_TYPE_WRITE;
4567 /****************************************************************************
4569 ****************************************************************************/
4570 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4572 PORT_INFO_1 *ports=NULL;
4575 if (*lp_enumports_cmd()) {
4576 pid_t local_pid = sys_getpid();
4577 char *cmd = lp_enumports_cmd();
4585 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4586 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4590 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4591 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4594 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4595 ret = smbrun(command, tmp_file, False);
4596 DEBUG(10,("Returned [%d]\n", ret));
4599 /* Is this the best error to return here? */
4600 return ERROR_ACCESS_DENIED;
4604 qlines = file_lines_load(tmp_file, &numlines);
4605 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4606 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4610 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4611 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4612 file_lines_free(qlines);
4613 return ERROR_NOT_ENOUGH_MEMORY;
4616 for (i=0; i<numlines; i++) {
4617 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4618 fill_port_1(&ports[i], qlines[i]);
4621 file_lines_free(qlines);
4624 *returned = numlines;
4627 *returned = 1; /* Sole Samba port returned. */
4629 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4630 return ERROR_NOT_ENOUGH_MEMORY;
4632 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4634 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4637 /* check the required size. */
4638 for (i=0; i<*returned; i++) {
4639 DEBUGADD(6,("adding port [%d]'s size\n", i));
4640 *needed += spoolss_size_port_info_1(&ports[i]);
4643 if (!alloc_buffer_size(buffer, *needed)) {
4645 return ERROR_INSUFFICIENT_BUFFER;
4648 /* fill the buffer with the ports structures */
4649 for (i=0; i<*returned; i++) {
4650 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4651 new_smb_io_port_1("", buffer, &ports[i], 0);
4656 if (*needed > offered) {
4658 return ERROR_INSUFFICIENT_BUFFER;
4661 return NT_STATUS_NO_PROBLEMO;
4664 /****************************************************************************
4666 ****************************************************************************/
4668 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4670 PORT_INFO_2 *ports=NULL;
4673 if (*lp_enumports_cmd()) {
4674 pid_t local_pid = sys_getpid();
4675 char *cmd = lp_enumports_cmd();
4683 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4684 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4688 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4689 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4692 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4693 ret = smbrun(command, tmp_file, False);
4694 DEBUGADD(10,("returned [%d]\n", ret));
4697 /* Is this the best error to return here? */
4698 return ERROR_ACCESS_DENIED;
4702 qlines = file_lines_load(tmp_file, &numlines);
4703 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4704 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4708 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4709 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4710 file_lines_free(qlines);
4711 return ERROR_NOT_ENOUGH_MEMORY;
4714 for (i=0; i<numlines; i++) {
4715 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4716 fill_port_2(&(ports[i]), qlines[i]);
4719 file_lines_free(qlines);
4722 *returned = numlines;
4728 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4729 return ERROR_NOT_ENOUGH_MEMORY;
4731 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4733 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4736 /* check the required size. */
4737 for (i=0; i<*returned; i++) {
4738 DEBUGADD(6,("adding port [%d]'s size\n", i));
4739 *needed += spoolss_size_port_info_2(&ports[i]);
4742 if (!alloc_buffer_size(buffer, *needed)) {
4744 return ERROR_INSUFFICIENT_BUFFER;
4747 /* fill the buffer with the ports structures */
4748 for (i=0; i<*returned; i++) {
4749 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4750 new_smb_io_port_2("", buffer, &ports[i], 0);
4755 if (*needed > offered) {
4757 return ERROR_INSUFFICIENT_BUFFER;
4760 return NT_STATUS_NO_PROBLEMO;
4763 /****************************************************************************
4765 ****************************************************************************/
4766 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4767 NEW_BUFFER *buffer, uint32 offered,
4768 uint32 *needed, uint32 *returned)
4770 DEBUG(4,("_spoolss_enumports\n"));
4777 return enumports_level_1(buffer, offered, needed, returned);
4779 return enumports_level_2(buffer, offered, needed, returned);
4781 return ERROR_INVALID_LEVEL;
4785 /****************************************************************************
4786 ****************************************************************************/
4787 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4788 const SPOOL_PRINTER_INFO_LEVEL *info,
4789 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4790 uint32 user_switch, const SPOOL_USER_CTR *user,
4793 NT_PRINTER_INFO_LEVEL *printer = NULL;
4797 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4798 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4799 return ERROR_NOT_ENOUGH_MEMORY;
4802 ZERO_STRUCTP(printer);
4804 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4805 convert_printer_info(info, printer, 2);
4807 if (*lp_addprinter_cmd() )
4808 if ( !add_printer_hook(printer) ) {
4809 free_a_printer(&printer,2);
4810 return ERROR_ACCESS_DENIED;
4813 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4814 printer->info_2->sharename);
4816 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4817 free_a_printer(&printer,2);
4818 return ERROR_ACCESS_DENIED;
4821 /* you must be a printer admin to add a new printer */
4822 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4823 free_a_printer(&printer,2);
4824 return ERROR_ACCESS_DENIED;
4828 * Do sanity check on the requested changes for Samba.
4831 if (!check_printer_ok(printer->info_2, snum)) {
4832 free_a_printer(&printer,2);
4833 return ERROR_INVALID_PARAMETER;
4836 /* write the ASCII on disk */
4837 if (add_a_printer(*printer, 2) != 0) {
4838 free_a_printer(&printer,2);
4839 return ERROR_ACCESS_DENIED;
4842 if (!open_printer_hnd(handle, name)) {
4843 /* Handle open failed - remove addition. */
4844 del_a_printer(printer->info_2->sharename);
4845 free_a_printer(&printer,2);
4846 return ERROR_ACCESS_DENIED;
4849 free_a_printer(&printer,2);
4851 srv_spoolss_sendnotify(handle);
4853 return NT_STATUS_NO_PROBLEMO;
4856 /****************************************************************************
4857 ****************************************************************************/
4858 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4859 const SPOOL_PRINTER_INFO_LEVEL *info,
4860 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4861 uint32 user_switch, const SPOOL_USER_CTR *user,
4866 /* we don't handle yet */
4867 /* but I know what to do ... */
4868 return ERROR_INVALID_LEVEL;
4870 return spoolss_addprinterex_level_2(uni_srv_name, info,
4871 unk0, unk1, unk2, unk3,
4872 user_switch, user, handle);
4874 return ERROR_INVALID_LEVEL;
4878 /****************************************************************************
4879 ****************************************************************************/
4880 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4881 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4883 uint32 err = NT_STATUS_NO_PROBLEMO;
4884 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4885 struct current_user user;
4887 ZERO_STRUCT(driver);
4889 get_current_user(&user, p);
4891 convert_printer_driver_info(info, &driver, level);
4893 DEBUG(5,("Cleaning driver's information\n"));
4894 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
4897 DEBUG(5,("Moving driver to final destination\n"));
4898 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4900 err = ERROR_ACCESS_DENIED;
4904 if (add_a_printer_driver(driver, level)!=0) {
4905 err = ERROR_ACCESS_DENIED;
4910 free_a_printer_driver(driver, level);
4914 /****************************************************************************
4915 ****************************************************************************/
4916 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4918 init_unistr(&info->name, name);
4921 /****************************************************************************
4922 ****************************************************************************/
4923 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4927 pstring short_archi;
4928 DRIVER_DIRECTORY_1 *info=NULL;
4930 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4932 if (get_short_archi(short_archi, long_archi)==FALSE)
4933 return ERROR_INVALID_ENVIRONMENT;
4935 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4936 return ERROR_NOT_ENOUGH_MEMORY;
4938 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4940 DEBUG(4,("printer driver directory: [%s]\n", path));
4942 fill_driverdir_1(info, path);
4944 *needed += spoolss_size_driverdir_info_1(info);
4946 if (!alloc_buffer_size(buffer, *needed)) {
4948 return ERROR_INSUFFICIENT_BUFFER;
4951 new_smb_io_driverdir_1("", buffer, info, 0);
4955 if (*needed > offered)
4956 return ERROR_INSUFFICIENT_BUFFER;
4958 return NT_STATUS_NO_PROBLEMO;
4961 /****************************************************************************
4962 ****************************************************************************/
4963 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4964 NEW_BUFFER *buffer, uint32 offered,
4967 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4973 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4975 return ERROR_INVALID_LEVEL;
4979 /****************************************************************************
4980 ****************************************************************************/
4981 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4982 uint32 in_value_len, uint32 in_data_len,
4983 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4985 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
4987 NT_PRINTER_INFO_LEVEL *printer = NULL;
4992 uint32 biggest_valuesize;
4993 uint32 biggest_datasize;
4995 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5000 ZERO_STRUCT(printer);
5002 *out_max_value_len=0;
5008 *out_max_data_len=0;
5012 DEBUG(5,("spoolss_enumprinterdata\n"));
5014 if (!OPEN_HANDLE(Printer)) {
5015 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5016 return ERROR_INVALID_HANDLE;
5019 if (!get_printer_snum(handle, &snum))
5020 return ERROR_INVALID_HANDLE;
5022 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5023 return ERROR_INVALID_HANDLE;
5026 * The NT machine wants to know the biggest size of value and data
5028 * cf: MSDN EnumPrinterData remark section
5030 if ( (in_value_len==0) && (in_data_len==0) ) {
5031 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5035 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5036 * if this parameter size doesn't exist.
5037 * Ok - my opinion here is that the client is not asking for the greatest
5038 * possible size of all the parameters, but is asking specifically for the size needed
5039 * for this specific parameter. In that case we can remove the loop below and
5040 * simplify this lookup code considerably. JF - comments welcome. JRA.
5043 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5045 free_a_printer(&printer, 2);
5046 return ERROR_NO_MORE_ITEMS;
5054 biggest_valuesize=0;
5057 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5058 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5059 if (data_len > biggest_datasize) biggest_datasize=data_len;
5061 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5069 * I think this is correct, it doesn't break APW and
5070 * allows Gerald's Win32 test programs to work correctly,
5071 * but may need altering.... JRA.
5074 if (param_index == 0) {
5075 /* No parameters found. */
5076 free_a_printer(&printer, 2);
5077 return ERROR_NO_MORE_ITEMS;
5080 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5081 *out_value_len=2*(1+biggest_valuesize);
5082 *out_data_len=biggest_datasize;
5084 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5086 free_a_printer(&printer, 2);
5087 return NT_STATUS_NO_PROBLEMO;
5091 * the value len is wrong in NT sp3
5092 * that's the number of bytes not the number of unicode chars
5095 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5097 free_a_printer(&printer, 2);
5098 return ERROR_NO_MORE_ITEMS;
5101 free_a_printer(&printer, 2);
5105 * - counted in bytes in the request
5106 * - counted in UNICODE chars in the max reply
5107 * - counted in bytes in the real size
5109 * take a pause *before* coding not *during* coding
5112 *out_max_value_len=(in_value_len/sizeof(uint16));
5113 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5115 return ERROR_NOT_ENOUGH_MEMORY;
5118 ZERO_STRUCTP(*out_value);
5119 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5123 /* the data is counted in bytes */
5124 *out_max_data_len=in_data_len;
5125 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5127 return ERROR_NOT_ENOUGH_MEMORY;
5130 memset(*data_out,'\0',in_data_len);
5131 memcpy(*data_out, data, (size_t)data_len);
5132 *out_data_len=data_len;
5136 return NT_STATUS_NO_PROBLEMO;
5139 /****************************************************************************
5140 ****************************************************************************/
5141 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5142 const UNISTR2 *value,
5147 uint32 numeric_data)
5149 NT_PRINTER_INFO_LEVEL *printer = NULL;
5150 NT_PRINTER_PARAM *param = NULL, old_param;
5152 uint32 status = 0x0;
5153 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5155 DEBUG(5,("spoolss_setprinterdata\n"));
5157 if (!OPEN_HANDLE(Printer)) {
5158 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5159 return ERROR_INVALID_HANDLE;
5162 if (!get_printer_snum(handle, &snum))
5163 return ERROR_INVALID_HANDLE;
5165 status = get_a_printer(&printer, 2, lp_servicename(snum));
5167 return ERROR_INVALID_NAME;
5169 convert_specific_param(¶m, value , type, data, real_len);
5171 /* Check if we are making any changes or not. Return true if
5172 nothing is actually changing. */
5174 ZERO_STRUCT(old_param);
5176 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5177 &old_param.type, &old_param.data_len)) {
5179 if (param->type == old_param.type &&
5180 param->data_len == old_param.data_len &&
5181 memcmp(param->data, old_param.data,
5182 old_param.data_len) == 0) {
5184 DEBUG(3, ("setprinterdata hasn't changed\n"));
5185 status = NT_STATUS_NO_PROBLEMO;
5192 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5193 DEBUG(3, ("security descriptor change denied by existing "
5194 "security descriptor\n"));
5195 status = ERROR_ACCESS_DENIED;
5199 unlink_specific_param_if_exist(printer->info_2, param);
5201 add_a_specific_param(printer->info_2, ¶m);
5202 status = mod_a_printer(*printer, 2);
5205 free_a_printer(&printer, 2);
5207 free_nt_printer_param(¶m);
5208 safe_free(old_param.data);
5213 /****************************************************************************
5214 ****************************************************************************/
5215 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5217 NT_PRINTER_INFO_LEVEL *printer = NULL;
5218 NT_PRINTER_PARAM param;
5220 uint32 status = 0x0;
5221 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5223 DEBUG(5,("spoolss_deleteprinterdata\n"));
5225 if (!OPEN_HANDLE(Printer)) {
5226 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5227 return ERROR_INVALID_HANDLE;
5230 if (!get_printer_snum(handle, &snum))
5231 return ERROR_INVALID_HANDLE;
5233 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5234 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5235 "security descriptor\n"));
5236 return ERROR_ACCESS_DENIED;
5239 status = get_a_printer(&printer, 2, lp_servicename(snum));
5241 return ERROR_INVALID_NAME;
5243 ZERO_STRUCTP(¶m);
5244 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5246 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5247 status = ERROR_INVALID_PARAMETER;
5249 status = mod_a_printer(*printer, 2);
5251 free_a_printer(&printer, 2);
5255 /****************************************************************************
5256 ****************************************************************************/
5257 uint32 _spoolss_addform( POLICY_HND *handle,
5262 nt_forms_struct *list=NULL;
5263 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5265 DEBUG(5,("spoolss_addform\n"));
5267 if (!OPEN_HANDLE(Printer)) {
5268 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5269 return ERROR_INVALID_HANDLE;
5272 count=get_ntforms(&list);
5273 if(!add_a_form(&list, form, &count))
5274 return ERROR_NOT_ENOUGH_MEMORY;
5275 write_ntforms(&list, count);
5282 /****************************************************************************
5283 ****************************************************************************/
5284 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5288 nt_forms_struct *list=NULL;
5289 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5291 DEBUG(5,("spoolss_deleteform\n"));
5293 if (!OPEN_HANDLE(Printer)) {
5294 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5295 return ERROR_INVALID_HANDLE;
5298 count = get_ntforms(&list);
5299 if(!delete_a_form(&list, form_name, &count, &ret))
5300 return ERROR_INVALID_PARAMETER;
5307 /****************************************************************************
5308 ****************************************************************************/
5309 uint32 _spoolss_setform( POLICY_HND *handle,
5310 const UNISTR2 *uni_name,
5315 nt_forms_struct *list=NULL;
5316 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5318 DEBUG(5,("spoolss_setform\n"));
5320 if (!OPEN_HANDLE(Printer)) {
5321 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5322 return ERROR_INVALID_HANDLE;
5324 count=get_ntforms(&list);
5325 update_a_form(&list, form, count);
5326 write_ntforms(&list, count);
5333 /****************************************************************************
5334 enumprintprocessors level 1.
5335 ****************************************************************************/
5336 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5338 PRINTPROCESSOR_1 *info_1=NULL;
5340 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5341 return ERROR_NOT_ENOUGH_MEMORY;
5345 init_unistr(&info_1->name, "winprint");
5347 *needed += spoolss_size_printprocessor_info_1(info_1);
5349 if (!alloc_buffer_size(buffer, *needed))
5350 return ERROR_INSUFFICIENT_BUFFER;
5352 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5356 if (*needed > offered) {
5358 return ERROR_INSUFFICIENT_BUFFER;
5361 return NT_STATUS_NO_PROBLEMO;
5364 /****************************************************************************
5365 ****************************************************************************/
5366 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5367 NEW_BUFFER *buffer, uint32 offered,
5368 uint32 *needed, uint32 *returned)
5370 DEBUG(5,("spoolss_enumprintprocessors\n"));
5373 * Enumerate the print processors ...
5375 * Just reply with "winprint", to keep NT happy
5376 * and I can use my nice printer checker.
5384 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5386 return ERROR_INVALID_LEVEL;
5390 /****************************************************************************
5391 enumprintprocdatatypes level 1.
5392 ****************************************************************************/
5393 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5395 PRINTPROCDATATYPE_1 *info_1=NULL;
5397 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5398 return ERROR_NOT_ENOUGH_MEMORY;
5402 init_unistr(&info_1->name, "RAW");
5404 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5406 if (!alloc_buffer_size(buffer, *needed))
5407 return ERROR_INSUFFICIENT_BUFFER;
5409 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5413 if (*needed > offered) {
5415 return ERROR_INSUFFICIENT_BUFFER;
5418 return NT_STATUS_NO_PROBLEMO;
5421 /****************************************************************************
5422 ****************************************************************************/
5423 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5424 NEW_BUFFER *buffer, uint32 offered,
5425 uint32 *needed, uint32 *returned)
5427 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5434 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5436 return ERROR_INVALID_LEVEL;
5440 /****************************************************************************
5441 enumprintmonitors level 1.
5442 ****************************************************************************/
5443 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5445 PRINTMONITOR_1 *info_1=NULL;
5447 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5448 return ERROR_NOT_ENOUGH_MEMORY;
5452 init_unistr(&info_1->name, "Local Port");
5454 *needed += spoolss_size_printmonitor_info_1(info_1);
5456 if (!alloc_buffer_size(buffer, *needed))
5457 return ERROR_INSUFFICIENT_BUFFER;
5459 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5463 if (*needed > offered) {
5465 return ERROR_INSUFFICIENT_BUFFER;
5468 return NT_STATUS_NO_PROBLEMO;
5471 /****************************************************************************
5472 enumprintmonitors level 2.
5473 ****************************************************************************/
5474 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5476 PRINTMONITOR_2 *info_2=NULL;
5478 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5479 return ERROR_NOT_ENOUGH_MEMORY;
5483 init_unistr(&info_2->name, "Local Port");
5484 init_unistr(&info_2->environment, "Windows NT X86");
5485 init_unistr(&info_2->dll_name, "localmon.dll");
5487 *needed += spoolss_size_printmonitor_info_2(info_2);
5489 if (!alloc_buffer_size(buffer, *needed))
5490 return ERROR_INSUFFICIENT_BUFFER;
5492 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5496 if (*needed > offered) {
5498 return ERROR_INSUFFICIENT_BUFFER;
5501 return NT_STATUS_NO_PROBLEMO;
5504 /****************************************************************************
5505 ****************************************************************************/
5506 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5507 NEW_BUFFER *buffer, uint32 offered,
5508 uint32 *needed, uint32 *returned)
5510 DEBUG(5,("spoolss_enumprintmonitors\n"));
5513 * Enumerate the print monitors ...
5515 * Just reply with "Local Port", to keep NT happy
5516 * and I can use my nice printer checker.
5524 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5526 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5528 return ERROR_INVALID_LEVEL;
5532 /****************************************************************************
5533 ****************************************************************************/
5534 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5538 JOB_INFO_1 *info_1=NULL;
5540 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5542 if (info_1 == NULL) {
5544 return ERROR_NOT_ENOUGH_MEMORY;
5547 for (i=0; i<count && found==False; i++) {
5548 if (queue[i].job==(int)jobid)
5555 /* I shoud reply something else ... I can't find the good one */
5556 return NT_STATUS_NO_PROBLEMO;
5559 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5563 *needed += spoolss_size_job_info_1(info_1);
5565 if (!alloc_buffer_size(buffer, *needed)) {
5567 return ERROR_INSUFFICIENT_BUFFER;
5570 new_smb_io_job_info_1("", buffer, info_1, 0);
5574 if (*needed > offered)
5575 return ERROR_INSUFFICIENT_BUFFER;
5577 return NT_STATUS_NO_PROBLEMO;
5581 /****************************************************************************
5582 ****************************************************************************/
5583 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5588 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5590 ZERO_STRUCTP(info_2);
5592 if (info_2 == NULL) {
5594 return ERROR_NOT_ENOUGH_MEMORY;
5597 for (i=0; i<count && found==False; i++) {
5598 if (queue[i].job==(int)jobid)
5605 /* I shoud reply something else ... I can't find the good one */
5606 return NT_STATUS_NO_PROBLEMO;
5609 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5613 *needed += spoolss_size_job_info_2(info_2);
5615 if (!alloc_buffer_size(buffer, *needed)) {
5617 return ERROR_INSUFFICIENT_BUFFER;
5620 new_smb_io_job_info_2("", buffer, info_2, 0);
5622 free_dev_mode(info_2->devmode);
5625 if (*needed > offered)
5626 return ERROR_INSUFFICIENT_BUFFER;
5628 return NT_STATUS_NO_PROBLEMO;
5631 /****************************************************************************
5632 ****************************************************************************/
5633 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5634 NEW_BUFFER *buffer, uint32 offered,
5639 print_queue_struct *queue=NULL;
5640 print_status_struct prt_status;
5642 DEBUG(5,("spoolss_getjob\n"));
5644 memset(&prt_status, 0, sizeof(prt_status));
5648 if (!get_printer_snum(handle, &snum))
5649 return ERROR_INVALID_HANDLE;
5651 count = print_queue_status(snum, &queue, &prt_status);
5653 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5654 count, prt_status.status, prt_status.message));
5658 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5660 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5663 return ERROR_INVALID_LEVEL;