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, True);
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 (!d1 && !d2) return True; /* if both are NULL they are equal */
3507 if (!d1 ^ !d2) return False; /* if either is exclusively NULL are not equal */
3509 if (!strequal(d1->devicename, d2->devicename) ||
3510 !strequal(d1->formname, d2->formname)) {
3514 if (d1->specversion != d2->specversion ||
3515 d1->driverversion != d2->driverversion ||
3516 d1->size != d2->size ||
3517 d1->driverextra != d2->driverextra ||
3518 d1->orientation != d2->orientation ||
3519 d1->papersize != d2->papersize ||
3520 d1->paperlength != d2->paperlength ||
3521 d1->paperwidth != d2->paperwidth ||
3522 d1->scale != d2->scale ||
3523 d1->copies != d2->copies ||
3524 d1->defaultsource != d2->defaultsource ||
3525 d1->printquality != d2->printquality ||
3526 d1->color != d2->color ||
3527 d1->duplex != d2->duplex ||
3528 d1->yresolution != d2->yresolution ||
3529 d1->ttoption != d2->ttoption ||
3530 d1->collate != d2->collate ||
3531 d1->logpixels != d2->logpixels) {
3535 if (d1->fields != d2->fields ||
3536 d1->bitsperpel != d2->bitsperpel ||
3537 d1->pelswidth != d2->pelswidth ||
3538 d1->pelsheight != d2->pelsheight ||
3539 d1->displayflags != d2->displayflags ||
3540 d1->displayfrequency != d2->displayfrequency ||
3541 d1->icmmethod != d2->icmmethod ||
3542 d1->icmintent != d2->icmintent ||
3543 d1->mediatype != d2->mediatype ||
3544 d1->dithertype != d2->dithertype ||
3545 d1->reserved1 != d2->reserved1 ||
3546 d1->reserved2 != d2->reserved2 ||
3547 d1->panningwidth != d2->panningwidth ||
3548 d1->panningheight != d2->panningheight) {
3552 /* compare the private data if it exists */
3553 if (!d1->driverextra && !d2->driverextra) return True;
3554 if ( d1->driverextra != d2->driverextra) return False;
3555 if (memcmp(d1->private, d2->private, d1->driverextra)) return False;
3560 /* Return true if two NT_PRINTER_PARAM structures are equal */
3562 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3563 NT_PRINTER_PARAM *p2)
3565 if (!p1 && !p2) return True;
3567 if ((!p1 && p2) || (p1 && !p2)) return False;
3569 /* Compare lists of printer parameters */
3573 NT_PRINTER_PARAM *q = p1;
3575 /* Find the parameter in the second structure */
3579 if (strequal(p1->value, q->value) &&
3580 p1->type == q->type &&
3581 p1->data_len == q->data_len &&
3582 memcmp(p1->data, q->data, p1->data_len) == 0) {
3601 /********************************************************************
3602 * Called by update_printer when trying to work out whether to
3603 * actually update printer info.
3604 ********************************************************************/
3606 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3607 NT_PRINTER_INFO_LEVEL *p2)
3609 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3611 /* Trivial conditions */
3613 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3617 if ((!p1 && p2) || (p1 && !p2) ||
3618 (!p1->info_2 && p2->info_2) ||
3619 (p1->info_2 && !p2->info_2)) {
3623 /* Compare two nt_printer_info_level structures. Don't compare
3624 status or cjobs as they seem to have something to do with the
3630 if (pi1->attributes != pi2->attributes ||
3631 pi1->priority != pi2->priority ||
3632 pi1->default_priority != pi2->default_priority ||
3633 pi1->starttime != pi2->starttime ||
3634 pi1->untiltime != pi2->untiltime ||
3635 pi1->averageppm != pi2->averageppm) {
3639 /* Yuck - don't check the printername or servername as the
3640 add_a_printer() code plays games with them. You can't
3641 change the printername or the sharename through this interface
3644 if (!strequal(pi1->sharename, pi2->sharename) ||
3645 !strequal(pi1->portname, pi2->portname) ||
3646 !strequal(pi1->drivername, pi2->drivername) ||
3647 !strequal(pi1->comment, pi2->comment) ||
3648 !strequal(pi1->location, pi2->location)) {
3652 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3656 if (!strequal(pi1->sepfile, pi2->sepfile) ||
3657 !strequal(pi1->printprocessor, pi2->printprocessor) ||
3658 !strequal(pi1->datatype, pi2->datatype) ||
3659 !strequal(pi1->parameters, pi2->parameters)) {
3663 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3667 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3671 if (pi1->changeid != pi2->changeid ||
3672 pi1->c_setprinter != pi2->c_setprinter ||
3673 pi1->setuptime != pi2->setuptime) {
3680 /********************************************************************
3681 * called by spoolss_api_setprinter
3682 * when updating a printer description
3683 ********************************************************************/
3685 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3686 const SPOOL_PRINTER_INFO_LEVEL *info,
3687 DEVICEMODE *devmode)
3690 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3691 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3694 DEBUG(8,("update_printer\n"));
3696 result = NT_STATUS_NO_PROBLEMO;
3699 DEBUG(0,("Send a mail to samba@samba.org\n"));
3700 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3701 result = ERROR_INVALID_LEVEL;
3705 if (!OPEN_HANDLE(Printer)) {
3706 result = ERROR_INVALID_HANDLE;
3710 if (!get_printer_snum(handle, &snum)) {
3711 result = ERROR_INVALID_HANDLE;
3715 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3716 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3717 result = ERROR_INVALID_HANDLE;
3721 DEBUGADD(8,("Converting info_2 struct\n"));
3724 * convert_printer_info converts the incoming
3725 * info from the client and overwrites the info
3726 * just read from the tdb in the pointer 'printer'.
3729 convert_printer_info(info, printer, level);
3731 if (info->info_2->devmode_ptr != 0) {
3732 /* we have a valid devmode
3733 convert it and link it*/
3736 * Ensure printer->info_2->devmode is a valid pointer
3737 * as we will be overwriting it in convert_devicemode().
3740 if (printer->info_2->devmode == NULL)
3741 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3743 DEBUGADD(8,("Converting the devicemode struct\n"));
3744 convert_devicemode(devmode, printer->info_2->devmode);
3747 if (printer->info_2->devmode != NULL)
3748 free_nt_devicemode(&printer->info_2->devmode);
3749 printer->info_2->devmode=NULL;
3752 /* Do sanity check on the requested changes for Samba */
3754 if (!check_printer_ok(printer->info_2, snum)) {
3755 result = ERROR_INVALID_PARAMETER;
3759 /* NT likes to call this function even though nothing has actually
3760 changed. Check this so the user doesn't end up with an
3761 annoying permission denied dialog box. */
3763 if (nt_printer_info_level_equal(printer, old_printer)) {
3764 DEBUG(3, ("printer info has not changed\n"));
3765 result = NT_STATUS_NO_PROBLEMO;
3769 /* Check calling user has permission to update printer description */
3771 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3772 DEBUG(3, ("printer property change denied by security "
3774 result = ERROR_ACCESS_DENIED;
3778 /* Call addprinter hook */
3780 if (*lp_addprinter_cmd() )
3781 if ( !add_printer_hook(printer) ) {
3782 result = ERROR_ACCESS_DENIED;
3786 /* Update printer info */
3788 if (add_a_printer(*printer, 2)!=0) {
3789 /* I don't really know what to return here !!! */
3790 result = ERROR_ACCESS_DENIED;
3795 free_a_printer(&printer, 2);
3796 free_a_printer(&old_printer, 2);
3798 srv_spoolss_sendnotify(handle);
3803 /****************************************************************************
3804 ****************************************************************************/
3805 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3806 const SPOOL_PRINTER_INFO_LEVEL *info,
3807 DEVMODE_CTR devmode_ctr,
3808 SEC_DESC_BUF *secdesc_ctr,
3809 uint32 command, pipes_struct *p)
3811 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3813 if (!OPEN_HANDLE(Printer)) {
3814 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3815 return ERROR_INVALID_HANDLE;
3818 /* check the level */
3821 return control_printer(handle, command, p);
3823 return update_printer(handle, level, info, devmode_ctr.devmode);
3825 return update_printer_sec(handle, level, info, p,
3828 return ERROR_INVALID_LEVEL;
3832 /****************************************************************************
3833 ****************************************************************************/
3834 uint32 _spoolss_fcpn(POLICY_HND *handle)
3836 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3838 if (!OPEN_HANDLE(Printer)) {
3839 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3840 return ERROR_INVALID_HANDLE;
3843 if (Printer->notify.client_connected==True)
3844 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3845 return ERROR_INVALID_HANDLE;
3847 Printer->notify.flags=0;
3848 Printer->notify.options=0;
3849 Printer->notify.localmachine[0]='\0';
3850 Printer->notify.printerlocal=0;
3851 if (Printer->notify.option)
3852 safe_free(Printer->notify.option->ctr.type);
3853 safe_free(Printer->notify.option);
3854 Printer->notify.option=NULL;
3855 Printer->notify.client_connected=False;
3857 return NT_STATUS_NO_PROBLEMO;
3860 /****************************************************************************
3861 ****************************************************************************/
3862 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3863 NEW_BUFFER *buffer, uint32 offered,
3867 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3868 returns for AddJob. AddJob
3869 must fail on non-local
3873 /****************************************************************************
3874 ****************************************************************************/
3875 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3876 int position, int snum)
3882 t=gmtime(&queue->time);
3883 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3885 job_info->jobid=queue->job;
3886 init_unistr(&job_info->printername, lp_servicename(snum));
3887 init_unistr(&job_info->machinename, temp_name);
3888 init_unistr(&job_info->username, queue->user);
3889 init_unistr(&job_info->document, queue->file);
3890 init_unistr(&job_info->datatype, "RAW");
3891 init_unistr(&job_info->text_status, "");
3892 job_info->status=nt_printj_status(queue->status);
3893 job_info->priority=queue->priority;
3894 job_info->position=position;
3895 job_info->totalpages=0;
3896 job_info->pagesprinted=0;
3898 make_systemtime(&job_info->submitted, t);
3901 /****************************************************************************
3902 ****************************************************************************/
3903 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3904 int position, int snum)
3907 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3911 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3914 t=gmtime(&queue->time);
3915 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3917 job_info->jobid=queue->job;
3919 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3921 init_unistr(&job_info->printername, chaine);
3923 init_unistr(&job_info->machinename, temp_name);
3924 init_unistr(&job_info->username, queue->user);
3925 init_unistr(&job_info->document, queue->file);
3926 init_unistr(&job_info->notifyname, queue->user);
3927 init_unistr(&job_info->datatype, "RAW");
3928 init_unistr(&job_info->printprocessor, "winprint");
3929 init_unistr(&job_info->parameters, "");
3930 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
3931 init_unistr(&job_info->text_status, "");
3933 /* and here the security descriptor */
3935 job_info->status=nt_printj_status(queue->status);
3936 job_info->priority=queue->priority;
3937 job_info->position=position;
3938 job_info->starttime=0;
3939 job_info->untiltime=0;
3940 job_info->totalpages=0;
3941 job_info->size=queue->size;
3942 make_systemtime(&(job_info->submitted), t);
3943 job_info->timeelapsed=0;
3944 job_info->pagesprinted=0;
3946 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
3947 free_a_printer(&ntprinter, 2);
3951 free_a_printer(&ntprinter, 2);
3955 /****************************************************************************
3956 Enumjobs at level 1.
3957 ****************************************************************************/
3958 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3959 NEW_BUFFER *buffer, uint32 offered,
3960 uint32 *needed, uint32 *returned)
3965 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3969 return ERROR_NOT_ENOUGH_MEMORY;
3972 for (i=0; i<*returned; i++)
3973 fill_job_info_1(&info[i], &queue[i], i, snum);
3977 /* check the required size. */
3978 for (i=0; i<*returned; i++)
3979 (*needed) += spoolss_size_job_info_1(&info[i]);
3981 if (!alloc_buffer_size(buffer, *needed)) {
3983 return ERROR_INSUFFICIENT_BUFFER;
3986 /* fill the buffer with the structures */
3987 for (i=0; i<*returned; i++)
3988 new_smb_io_job_info_1("", buffer, &info[i], 0);
3993 if (*needed > offered) {
3995 return ERROR_INSUFFICIENT_BUFFER;
3998 return NT_STATUS_NO_PROBLEMO;
4001 /****************************************************************************
4002 Enumjobs at level 2.
4003 ****************************************************************************/
4004 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4005 NEW_BUFFER *buffer, uint32 offered,
4006 uint32 *needed, uint32 *returned)
4011 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4015 return ERROR_NOT_ENOUGH_MEMORY;
4018 for (i=0; i<*returned; i++)
4019 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4023 /* check the required size. */
4024 for (i=0; i<*returned; i++)
4025 (*needed) += spoolss_size_job_info_2(&info[i]);
4027 if (!alloc_buffer_size(buffer, *needed)) {
4029 return ERROR_INSUFFICIENT_BUFFER;
4032 /* fill the buffer with the structures */
4033 for (i=0; i<*returned; i++)
4034 new_smb_io_job_info_2("", buffer, &info[i], 0);
4039 if (*needed > offered) {
4041 return ERROR_INSUFFICIENT_BUFFER;
4044 return NT_STATUS_NO_PROBLEMO;
4047 /****************************************************************************
4049 ****************************************************************************/
4050 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4051 NEW_BUFFER *buffer, uint32 offered,
4052 uint32 *needed, uint32 *returned)
4055 print_queue_struct *queue=NULL;
4056 print_status_struct prt_status;
4058 DEBUG(4,("_spoolss_enumjobs\n"));
4060 ZERO_STRUCT(prt_status);
4065 if (!get_printer_snum(handle, &snum))
4066 return ERROR_INVALID_HANDLE;
4068 *returned = print_queue_status(snum, &queue, &prt_status);
4069 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4071 if (*returned == 0) {
4073 return NT_STATUS_NO_PROBLEMO;
4078 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4080 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4084 return ERROR_INVALID_LEVEL;
4089 /****************************************************************************
4090 ****************************************************************************/
4091 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4096 /****************************************************************************
4097 ****************************************************************************/
4098 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4099 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4101 struct current_user user;
4102 print_status_struct prt_status;
4103 int snum, errcode = ERROR_INVALID_FUNCTION;
4105 memset(&prt_status, 0, sizeof(prt_status));
4107 if (!get_printer_snum(handle, &snum)) {
4108 return ERROR_INVALID_HANDLE;
4111 if (!print_job_exists(jobid)) {
4112 return ERROR_INVALID_PRINTER_NAME;
4115 get_current_user(&user, p);
4118 case JOB_CONTROL_CANCEL:
4119 case JOB_CONTROL_DELETE:
4120 if (print_job_delete(&user, jobid, &errcode)) {
4124 case JOB_CONTROL_PAUSE:
4125 if (print_job_pause(&user, jobid, &errcode)) {
4129 case JOB_CONTROL_RESTART:
4130 case JOB_CONTROL_RESUME:
4131 if (print_job_resume(&user, jobid, &errcode)) {
4136 return ERROR_INVALID_LEVEL;
4142 /****************************************************************************
4143 Enumerates all printer drivers at level 1.
4144 ****************************************************************************/
4145 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4150 fstring *list = NULL;
4152 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4153 DRIVER_INFO_1 *driver_info_1=NULL;
4157 #define MAX_VERSION 4
4159 for (version=0; version<MAX_VERSION; version++) {
4161 ndrivers=get_ntdrivers(&list, architecture, version);
4162 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4165 return ERROR_NOT_ENOUGH_MEMORY;
4168 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4170 return ERROR_NOT_ENOUGH_MEMORY;
4174 for (i=0; i<ndrivers; i++) {
4176 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4177 ZERO_STRUCT(driver);
4178 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4182 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4183 free_a_printer_driver(driver, 3);
4186 *returned+=ndrivers;
4190 /* check the required size. */
4191 for (i=0; i<*returned; i++) {
4192 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4193 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4196 if (!alloc_buffer_size(buffer, *needed)) {
4197 safe_free(driver_info_1);
4198 return ERROR_INSUFFICIENT_BUFFER;
4201 /* fill the buffer with the form structures */
4202 for (i=0; i<*returned; i++) {
4203 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4204 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4207 safe_free(driver_info_1);
4209 if (*needed > offered) {
4211 return ERROR_INSUFFICIENT_BUFFER;
4214 return NT_STATUS_NO_PROBLEMO;
4217 /****************************************************************************
4218 Enumerates all printer drivers at level 2.
4219 ****************************************************************************/
4220 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4225 fstring *list = NULL;
4227 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4228 DRIVER_INFO_2 *driver_info_2=NULL;
4232 #define MAX_VERSION 4
4234 for (version=0; version<MAX_VERSION; version++) {
4236 ndrivers=get_ntdrivers(&list, architecture, version);
4237 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4240 return ERROR_NOT_ENOUGH_MEMORY;
4243 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4245 return ERROR_NOT_ENOUGH_MEMORY;
4249 for (i=0; i<ndrivers; i++) {
4252 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4253 ZERO_STRUCT(driver);
4254 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4258 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4259 free_a_printer_driver(driver, 3);
4262 *returned+=ndrivers;
4266 /* check the required size. */
4267 for (i=0; i<*returned; i++) {
4268 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4269 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4272 if (!alloc_buffer_size(buffer, *needed)) {
4273 safe_free(driver_info_2);
4274 return ERROR_INSUFFICIENT_BUFFER;
4277 /* fill the buffer with the form structures */
4278 for (i=0; i<*returned; i++) {
4279 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4280 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4283 safe_free(driver_info_2);
4285 if (*needed > offered) {
4287 return ERROR_INSUFFICIENT_BUFFER;
4290 return NT_STATUS_NO_PROBLEMO;
4293 /****************************************************************************
4294 Enumerates all printer drivers at level 3.
4295 ****************************************************************************/
4296 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4301 fstring *list = NULL;
4303 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4304 DRIVER_INFO_3 *driver_info_3=NULL;
4308 #define MAX_VERSION 4
4310 for (version=0; version<MAX_VERSION; version++) {
4312 ndrivers=get_ntdrivers(&list, architecture, version);
4313 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4316 return ERROR_NOT_ENOUGH_MEMORY;
4319 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4321 return ERROR_NOT_ENOUGH_MEMORY;
4325 for (i=0; i<ndrivers; i++) {
4328 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4329 ZERO_STRUCT(driver);
4330 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4334 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4335 free_a_printer_driver(driver, 3);
4338 *returned+=ndrivers;
4342 /* check the required size. */
4343 for (i=0; i<*returned; i++) {
4344 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4345 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4348 if (!alloc_buffer_size(buffer, *needed)) {
4349 safe_free(driver_info_3);
4350 return ERROR_INSUFFICIENT_BUFFER;
4353 /* fill the buffer with the driver structures */
4354 for (i=0; i<*returned; i++) {
4355 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4356 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4359 for (i=0; i<*returned; i++)
4360 safe_free(driver_info_3[i].dependentfiles);
4362 safe_free(driver_info_3);
4364 if (*needed > offered) {
4366 return ERROR_INSUFFICIENT_BUFFER;
4369 return NT_STATUS_NO_PROBLEMO;
4372 /****************************************************************************
4373 Enumerates all printer drivers.
4374 ****************************************************************************/
4375 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4376 NEW_BUFFER *buffer, uint32 offered,
4377 uint32 *needed, uint32 *returned)
4379 fstring *list = NULL;
4381 fstring architecture;
4383 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4384 fstrcpy(servername, global_myname);
4388 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4392 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4394 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4396 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4400 return ERROR_INVALID_LEVEL;
4404 /****************************************************************************
4405 ****************************************************************************/
4406 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4408 form->flag=list->flag;
4409 init_unistr(&form->name, list->name);
4410 form->width=list->width;
4411 form->length=list->length;
4412 form->left=list->left;
4413 form->top=list->top;
4414 form->right=list->right;
4415 form->bottom=list->bottom;
4418 /****************************************************************************
4419 ****************************************************************************/
4420 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4421 NEW_BUFFER *buffer, uint32 offered,
4422 uint32 *needed, uint32 *numofforms)
4424 nt_forms_struct *list=NULL;
4429 DEBUG(4,("_new_spoolss_enumforms\n"));
4430 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4431 DEBUGADD(5,("Info level [%d]\n", level));
4433 *numofforms = get_ntforms(&list);
4434 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4436 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4440 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4442 return ERROR_NOT_ENOUGH_MEMORY;
4445 /* construct the list of form structures */
4446 for (i=0; i<*numofforms; i++) {
4447 DEBUGADD(6,("Filling form number [%d]\n",i));
4448 fill_form_1(&forms_1[i], &list[i]);
4453 /* check the required size. */
4454 for (i=0; i<*numofforms; i++) {
4455 DEBUGADD(6,("adding form [%d]'s size\n",i));
4456 buffer_size += spoolss_size_form_1(&forms_1[i]);
4459 *needed=buffer_size;
4461 if (!alloc_buffer_size(buffer, buffer_size)){
4463 return ERROR_INSUFFICIENT_BUFFER;
4466 /* fill the buffer with the form structures */
4467 for (i=0; i<*numofforms; i++) {
4468 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4469 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4474 if (*needed > offered) {
4476 return ERROR_INSUFFICIENT_BUFFER;
4479 return NT_STATUS_NO_PROBLEMO;
4483 return ERROR_INVALID_LEVEL;
4488 /****************************************************************************
4489 ****************************************************************************/
4490 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4492 nt_forms_struct *list=NULL;
4498 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4500 DEBUG(4,("_spoolss_getform\n"));
4501 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4502 DEBUGADD(5,("Info level [%d]\n", level));
4504 numofforms = get_ntforms(&list);
4505 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4507 if (numofforms == 0)
4508 return ERROR_NO_MORE_ITEMS;
4513 /* Check if the requested name is in the list of form structures */
4514 for (i=0; i<numofforms; i++) {
4516 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4518 if (strequal(form_name, list[i].name)) {
4519 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4520 fill_form_1(&form_1, &list[i]);
4527 /* check the required size. */
4529 *needed=spoolss_size_form_1(&form_1);
4531 if (!alloc_buffer_size(buffer, buffer_size)){
4532 return ERROR_INSUFFICIENT_BUFFER;
4535 if (*needed > offered) {
4536 return ERROR_INSUFFICIENT_BUFFER;
4539 /* fill the buffer with the form structures */
4540 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4541 new_smb_io_form_1("", buffer, &form_1, 0);
4543 return NT_STATUS_NO_PROBLEMO;
4547 return ERROR_INVALID_LEVEL;
4551 /****************************************************************************
4552 ****************************************************************************/
4553 static void fill_port_1(PORT_INFO_1 *port, char *name)
4555 init_unistr(&port->port_name, name);
4558 /****************************************************************************
4559 ****************************************************************************/
4560 static void fill_port_2(PORT_INFO_2 *port, char *name)
4562 init_unistr(&port->port_name, name);
4563 init_unistr(&port->monitor_name, "Local Monitor");
4564 init_unistr(&port->description, "Local Port");
4565 #define PORT_TYPE_WRITE 1
4566 port->port_type=PORT_TYPE_WRITE;
4570 /****************************************************************************
4572 ****************************************************************************/
4573 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4575 PORT_INFO_1 *ports=NULL;
4578 if (*lp_enumports_cmd()) {
4579 pid_t local_pid = sys_getpid();
4580 char *cmd = lp_enumports_cmd();
4588 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4589 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4593 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4594 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4597 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4598 ret = smbrun(command, tmp_file, False);
4599 DEBUG(10,("Returned [%d]\n", ret));
4602 /* Is this the best error to return here? */
4603 return ERROR_ACCESS_DENIED;
4607 qlines = file_lines_load(tmp_file, &numlines,True);
4608 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4609 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4613 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4614 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4615 file_lines_free(qlines);
4616 return ERROR_NOT_ENOUGH_MEMORY;
4619 for (i=0; i<numlines; i++) {
4620 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4621 fill_port_1(&ports[i], qlines[i]);
4624 file_lines_free(qlines);
4627 *returned = numlines;
4630 *returned = 1; /* Sole Samba port returned. */
4632 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4633 return ERROR_NOT_ENOUGH_MEMORY;
4635 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4637 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4640 /* check the required size. */
4641 for (i=0; i<*returned; i++) {
4642 DEBUGADD(6,("adding port [%d]'s size\n", i));
4643 *needed += spoolss_size_port_info_1(&ports[i]);
4646 if (!alloc_buffer_size(buffer, *needed)) {
4648 return ERROR_INSUFFICIENT_BUFFER;
4651 /* fill the buffer with the ports structures */
4652 for (i=0; i<*returned; i++) {
4653 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4654 new_smb_io_port_1("", buffer, &ports[i], 0);
4659 if (*needed > offered) {
4661 return ERROR_INSUFFICIENT_BUFFER;
4664 return NT_STATUS_NO_PROBLEMO;
4667 /****************************************************************************
4669 ****************************************************************************/
4671 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4673 PORT_INFO_2 *ports=NULL;
4676 if (*lp_enumports_cmd()) {
4677 pid_t local_pid = sys_getpid();
4678 char *cmd = lp_enumports_cmd();
4686 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4687 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4691 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4692 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4695 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4696 ret = smbrun(command, tmp_file, False);
4697 DEBUGADD(10,("returned [%d]\n", ret));
4700 /* Is this the best error to return here? */
4701 return ERROR_ACCESS_DENIED;
4705 qlines = file_lines_load(tmp_file, &numlines,True);
4706 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4707 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4711 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4712 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4713 file_lines_free(qlines);
4714 return ERROR_NOT_ENOUGH_MEMORY;
4717 for (i=0; i<numlines; i++) {
4718 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4719 fill_port_2(&(ports[i]), qlines[i]);
4722 file_lines_free(qlines);
4725 *returned = numlines;
4731 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4732 return ERROR_NOT_ENOUGH_MEMORY;
4734 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4736 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4739 /* check the required size. */
4740 for (i=0; i<*returned; i++) {
4741 DEBUGADD(6,("adding port [%d]'s size\n", i));
4742 *needed += spoolss_size_port_info_2(&ports[i]);
4745 if (!alloc_buffer_size(buffer, *needed)) {
4747 return ERROR_INSUFFICIENT_BUFFER;
4750 /* fill the buffer with the ports structures */
4751 for (i=0; i<*returned; i++) {
4752 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4753 new_smb_io_port_2("", buffer, &ports[i], 0);
4758 if (*needed > offered) {
4760 return ERROR_INSUFFICIENT_BUFFER;
4763 return NT_STATUS_NO_PROBLEMO;
4766 /****************************************************************************
4768 ****************************************************************************/
4769 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4770 NEW_BUFFER *buffer, uint32 offered,
4771 uint32 *needed, uint32 *returned)
4773 DEBUG(4,("_spoolss_enumports\n"));
4780 return enumports_level_1(buffer, offered, needed, returned);
4782 return enumports_level_2(buffer, offered, needed, returned);
4784 return ERROR_INVALID_LEVEL;
4788 /****************************************************************************
4789 ****************************************************************************/
4790 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4791 const SPOOL_PRINTER_INFO_LEVEL *info,
4792 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4793 uint32 user_switch, const SPOOL_USER_CTR *user,
4796 NT_PRINTER_INFO_LEVEL *printer = NULL;
4800 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4801 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4802 return ERROR_NOT_ENOUGH_MEMORY;
4805 ZERO_STRUCTP(printer);
4807 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4808 convert_printer_info(info, printer, 2);
4810 if (*lp_addprinter_cmd() )
4811 if ( !add_printer_hook(printer) ) {
4812 free_a_printer(&printer,2);
4813 return ERROR_ACCESS_DENIED;
4816 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4817 printer->info_2->sharename);
4819 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4820 free_a_printer(&printer,2);
4821 return ERROR_ACCESS_DENIED;
4824 /* you must be a printer admin to add a new printer */
4825 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4826 free_a_printer(&printer,2);
4827 return ERROR_ACCESS_DENIED;
4831 * Do sanity check on the requested changes for Samba.
4834 if (!check_printer_ok(printer->info_2, snum)) {
4835 free_a_printer(&printer,2);
4836 return ERROR_INVALID_PARAMETER;
4839 /* write the ASCII on disk */
4840 if (add_a_printer(*printer, 2) != 0) {
4841 free_a_printer(&printer,2);
4842 return ERROR_ACCESS_DENIED;
4845 if (!open_printer_hnd(handle, name)) {
4846 /* Handle open failed - remove addition. */
4847 del_a_printer(printer->info_2->sharename);
4848 free_a_printer(&printer,2);
4849 return ERROR_ACCESS_DENIED;
4852 free_a_printer(&printer,2);
4854 srv_spoolss_sendnotify(handle);
4856 return NT_STATUS_NO_PROBLEMO;
4859 /****************************************************************************
4860 ****************************************************************************/
4861 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4862 const SPOOL_PRINTER_INFO_LEVEL *info,
4863 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4864 uint32 user_switch, const SPOOL_USER_CTR *user,
4869 /* we don't handle yet */
4870 /* but I know what to do ... */
4871 return ERROR_INVALID_LEVEL;
4873 return spoolss_addprinterex_level_2(uni_srv_name, info,
4874 unk0, unk1, unk2, unk3,
4875 user_switch, user, handle);
4877 return ERROR_INVALID_LEVEL;
4881 /****************************************************************************
4882 ****************************************************************************/
4883 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4884 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4886 uint32 err = NT_STATUS_NO_PROBLEMO;
4887 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4888 struct current_user user;
4890 ZERO_STRUCT(driver);
4892 get_current_user(&user, p);
4894 convert_printer_driver_info(info, &driver, level);
4896 DEBUG(5,("Cleaning driver's information\n"));
4897 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
4900 DEBUG(5,("Moving driver to final destination\n"));
4901 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4903 err = ERROR_ACCESS_DENIED;
4907 if (add_a_printer_driver(driver, level)!=0) {
4908 err = ERROR_ACCESS_DENIED;
4913 free_a_printer_driver(driver, level);
4917 /****************************************************************************
4918 ****************************************************************************/
4919 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4921 init_unistr(&info->name, name);
4924 /****************************************************************************
4925 ****************************************************************************/
4926 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4930 pstring short_archi;
4931 DRIVER_DIRECTORY_1 *info=NULL;
4933 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4935 if (get_short_archi(short_archi, long_archi)==FALSE)
4936 return ERROR_INVALID_ENVIRONMENT;
4938 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4939 return ERROR_NOT_ENOUGH_MEMORY;
4941 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4943 DEBUG(4,("printer driver directory: [%s]\n", path));
4945 fill_driverdir_1(info, path);
4947 *needed += spoolss_size_driverdir_info_1(info);
4949 if (!alloc_buffer_size(buffer, *needed)) {
4951 return ERROR_INSUFFICIENT_BUFFER;
4954 new_smb_io_driverdir_1("", buffer, info, 0);
4958 if (*needed > offered)
4959 return ERROR_INSUFFICIENT_BUFFER;
4961 return NT_STATUS_NO_PROBLEMO;
4964 /****************************************************************************
4965 ****************************************************************************/
4966 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4967 NEW_BUFFER *buffer, uint32 offered,
4970 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4976 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4978 return ERROR_INVALID_LEVEL;
4982 /****************************************************************************
4983 ****************************************************************************/
4984 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4985 uint32 in_value_len, uint32 in_data_len,
4986 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4988 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
4990 NT_PRINTER_INFO_LEVEL *printer = NULL;
4995 uint32 biggest_valuesize;
4996 uint32 biggest_datasize;
4998 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5003 ZERO_STRUCT(printer);
5005 *out_max_value_len=0;
5011 *out_max_data_len=0;
5015 DEBUG(5,("spoolss_enumprinterdata\n"));
5017 if (!OPEN_HANDLE(Printer)) {
5018 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5019 return ERROR_INVALID_HANDLE;
5022 if (!get_printer_snum(handle, &snum))
5023 return ERROR_INVALID_HANDLE;
5025 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5026 return ERROR_INVALID_HANDLE;
5029 * The NT machine wants to know the biggest size of value and data
5031 * cf: MSDN EnumPrinterData remark section
5033 if ( (in_value_len==0) && (in_data_len==0) ) {
5034 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5038 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5039 * if this parameter size doesn't exist.
5040 * Ok - my opinion here is that the client is not asking for the greatest
5041 * possible size of all the parameters, but is asking specifically for the size needed
5042 * for this specific parameter. In that case we can remove the loop below and
5043 * simplify this lookup code considerably. JF - comments welcome. JRA.
5046 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5048 free_a_printer(&printer, 2);
5049 return ERROR_NO_MORE_ITEMS;
5057 biggest_valuesize=0;
5060 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5061 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5062 if (data_len > biggest_datasize) biggest_datasize=data_len;
5064 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5072 * I think this is correct, it doesn't break APW and
5073 * allows Gerald's Win32 test programs to work correctly,
5074 * but may need altering.... JRA.
5077 if (param_index == 0) {
5078 /* No parameters found. */
5079 free_a_printer(&printer, 2);
5080 return ERROR_NO_MORE_ITEMS;
5083 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5084 *out_value_len=2*(1+biggest_valuesize);
5085 *out_data_len=biggest_datasize;
5087 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5089 free_a_printer(&printer, 2);
5090 return NT_STATUS_NO_PROBLEMO;
5094 * the value len is wrong in NT sp3
5095 * that's the number of bytes not the number of unicode chars
5098 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5100 free_a_printer(&printer, 2);
5101 return ERROR_NO_MORE_ITEMS;
5104 free_a_printer(&printer, 2);
5108 * - counted in bytes in the request
5109 * - counted in UNICODE chars in the max reply
5110 * - counted in bytes in the real size
5112 * take a pause *before* coding not *during* coding
5115 *out_max_value_len=(in_value_len/sizeof(uint16));
5116 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5118 return ERROR_NOT_ENOUGH_MEMORY;
5121 ZERO_STRUCTP(*out_value);
5122 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5126 /* the data is counted in bytes */
5127 *out_max_data_len=in_data_len;
5128 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5130 return ERROR_NOT_ENOUGH_MEMORY;
5133 memset(*data_out,'\0',in_data_len);
5134 memcpy(*data_out, data, (size_t)data_len);
5135 *out_data_len=data_len;
5139 return NT_STATUS_NO_PROBLEMO;
5142 /****************************************************************************
5143 ****************************************************************************/
5144 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5145 const UNISTR2 *value,
5150 uint32 numeric_data)
5152 NT_PRINTER_INFO_LEVEL *printer = NULL;
5153 NT_PRINTER_PARAM *param = NULL, old_param;
5155 uint32 status = 0x0;
5156 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5158 DEBUG(5,("spoolss_setprinterdata\n"));
5160 if (!OPEN_HANDLE(Printer)) {
5161 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5162 return ERROR_INVALID_HANDLE;
5165 if (!get_printer_snum(handle, &snum))
5166 return ERROR_INVALID_HANDLE;
5168 status = get_a_printer(&printer, 2, lp_servicename(snum));
5170 return ERROR_INVALID_NAME;
5172 convert_specific_param(¶m, value , type, data, real_len);
5174 /* Check if we are making any changes or not. Return true if
5175 nothing is actually changing. */
5177 ZERO_STRUCT(old_param);
5179 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5180 &old_param.type, (unsigned int *)&old_param.data_len)) {
5182 if (param->type == old_param.type &&
5183 param->data_len == old_param.data_len &&
5184 memcmp(param->data, old_param.data,
5185 old_param.data_len) == 0) {
5187 DEBUG(3, ("setprinterdata hasn't changed\n"));
5188 status = NT_STATUS_NO_PROBLEMO;
5195 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5196 DEBUG(3, ("security descriptor change denied by existing "
5197 "security descriptor\n"));
5198 status = ERROR_ACCESS_DENIED;
5202 unlink_specific_param_if_exist(printer->info_2, param);
5204 add_a_specific_param(printer->info_2, ¶m);
5205 status = mod_a_printer(*printer, 2);
5208 free_a_printer(&printer, 2);
5210 free_nt_printer_param(¶m);
5211 safe_free(old_param.data);
5216 /****************************************************************************
5217 ****************************************************************************/
5218 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5220 NT_PRINTER_INFO_LEVEL *printer = NULL;
5221 NT_PRINTER_PARAM param;
5223 uint32 status = 0x0;
5224 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5226 DEBUG(5,("spoolss_deleteprinterdata\n"));
5228 if (!OPEN_HANDLE(Printer)) {
5229 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5230 return ERROR_INVALID_HANDLE;
5233 if (!get_printer_snum(handle, &snum))
5234 return ERROR_INVALID_HANDLE;
5236 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5237 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5238 "security descriptor\n"));
5239 return ERROR_ACCESS_DENIED;
5242 status = get_a_printer(&printer, 2, lp_servicename(snum));
5244 return ERROR_INVALID_NAME;
5246 ZERO_STRUCTP(¶m);
5247 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5249 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5250 status = ERROR_INVALID_PARAMETER;
5252 status = mod_a_printer(*printer, 2);
5254 free_a_printer(&printer, 2);
5258 /****************************************************************************
5259 ****************************************************************************/
5260 uint32 _spoolss_addform( POLICY_HND *handle,
5265 nt_forms_struct *list=NULL;
5266 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5268 DEBUG(5,("spoolss_addform\n"));
5270 if (!OPEN_HANDLE(Printer)) {
5271 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5272 return ERROR_INVALID_HANDLE;
5275 count=get_ntforms(&list);
5276 if(!add_a_form(&list, form, &count))
5277 return ERROR_NOT_ENOUGH_MEMORY;
5278 write_ntforms(&list, count);
5285 /****************************************************************************
5286 ****************************************************************************/
5287 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5291 nt_forms_struct *list=NULL;
5292 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5294 DEBUG(5,("spoolss_deleteform\n"));
5296 if (!OPEN_HANDLE(Printer)) {
5297 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5298 return ERROR_INVALID_HANDLE;
5301 count = get_ntforms(&list);
5302 if(!delete_a_form(&list, form_name, &count, &ret))
5303 return ERROR_INVALID_PARAMETER;
5310 /****************************************************************************
5311 ****************************************************************************/
5312 uint32 _spoolss_setform( POLICY_HND *handle,
5313 const UNISTR2 *uni_name,
5318 nt_forms_struct *list=NULL;
5319 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5321 DEBUG(5,("spoolss_setform\n"));
5323 if (!OPEN_HANDLE(Printer)) {
5324 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5325 return ERROR_INVALID_HANDLE;
5327 count=get_ntforms(&list);
5328 update_a_form(&list, form, count);
5329 write_ntforms(&list, count);
5336 /****************************************************************************
5337 enumprintprocessors level 1.
5338 ****************************************************************************/
5339 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5341 PRINTPROCESSOR_1 *info_1=NULL;
5343 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5344 return ERROR_NOT_ENOUGH_MEMORY;
5348 init_unistr(&info_1->name, "winprint");
5350 *needed += spoolss_size_printprocessor_info_1(info_1);
5352 if (!alloc_buffer_size(buffer, *needed))
5353 return ERROR_INSUFFICIENT_BUFFER;
5355 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5359 if (*needed > offered) {
5361 return ERROR_INSUFFICIENT_BUFFER;
5364 return NT_STATUS_NO_PROBLEMO;
5367 /****************************************************************************
5368 ****************************************************************************/
5369 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5370 NEW_BUFFER *buffer, uint32 offered,
5371 uint32 *needed, uint32 *returned)
5373 DEBUG(5,("spoolss_enumprintprocessors\n"));
5376 * Enumerate the print processors ...
5378 * Just reply with "winprint", to keep NT happy
5379 * and I can use my nice printer checker.
5387 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5389 return ERROR_INVALID_LEVEL;
5393 /****************************************************************************
5394 enumprintprocdatatypes level 1.
5395 ****************************************************************************/
5396 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5398 PRINTPROCDATATYPE_1 *info_1=NULL;
5400 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5401 return ERROR_NOT_ENOUGH_MEMORY;
5405 init_unistr(&info_1->name, "RAW");
5407 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5409 if (!alloc_buffer_size(buffer, *needed))
5410 return ERROR_INSUFFICIENT_BUFFER;
5412 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5416 if (*needed > offered) {
5418 return ERROR_INSUFFICIENT_BUFFER;
5421 return NT_STATUS_NO_PROBLEMO;
5424 /****************************************************************************
5425 ****************************************************************************/
5426 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5427 NEW_BUFFER *buffer, uint32 offered,
5428 uint32 *needed, uint32 *returned)
5430 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5437 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5439 return ERROR_INVALID_LEVEL;
5443 /****************************************************************************
5444 enumprintmonitors level 1.
5445 ****************************************************************************/
5446 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5448 PRINTMONITOR_1 *info_1=NULL;
5450 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5451 return ERROR_NOT_ENOUGH_MEMORY;
5455 init_unistr(&info_1->name, "Local Port");
5457 *needed += spoolss_size_printmonitor_info_1(info_1);
5459 if (!alloc_buffer_size(buffer, *needed))
5460 return ERROR_INSUFFICIENT_BUFFER;
5462 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5466 if (*needed > offered) {
5468 return ERROR_INSUFFICIENT_BUFFER;
5471 return NT_STATUS_NO_PROBLEMO;
5474 /****************************************************************************
5475 enumprintmonitors level 2.
5476 ****************************************************************************/
5477 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5479 PRINTMONITOR_2 *info_2=NULL;
5481 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5482 return ERROR_NOT_ENOUGH_MEMORY;
5486 init_unistr(&info_2->name, "Local Port");
5487 init_unistr(&info_2->environment, "Windows NT X86");
5488 init_unistr(&info_2->dll_name, "localmon.dll");
5490 *needed += spoolss_size_printmonitor_info_2(info_2);
5492 if (!alloc_buffer_size(buffer, *needed))
5493 return ERROR_INSUFFICIENT_BUFFER;
5495 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5499 if (*needed > offered) {
5501 return ERROR_INSUFFICIENT_BUFFER;
5504 return NT_STATUS_NO_PROBLEMO;
5507 /****************************************************************************
5508 ****************************************************************************/
5509 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5510 NEW_BUFFER *buffer, uint32 offered,
5511 uint32 *needed, uint32 *returned)
5513 DEBUG(5,("spoolss_enumprintmonitors\n"));
5516 * Enumerate the print monitors ...
5518 * Just reply with "Local Port", to keep NT happy
5519 * and I can use my nice printer checker.
5527 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5529 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5531 return ERROR_INVALID_LEVEL;
5535 /****************************************************************************
5536 ****************************************************************************/
5537 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5541 JOB_INFO_1 *info_1=NULL;
5543 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5545 if (info_1 == NULL) {
5547 return ERROR_NOT_ENOUGH_MEMORY;
5550 for (i=0; i<count && found==False; i++) {
5551 if (queue[i].job==(int)jobid)
5558 /* I shoud reply something else ... I can't find the good one */
5559 return NT_STATUS_NO_PROBLEMO;
5562 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5566 *needed += spoolss_size_job_info_1(info_1);
5568 if (!alloc_buffer_size(buffer, *needed)) {
5570 return ERROR_INSUFFICIENT_BUFFER;
5573 new_smb_io_job_info_1("", buffer, info_1, 0);
5577 if (*needed > offered)
5578 return ERROR_INSUFFICIENT_BUFFER;
5580 return NT_STATUS_NO_PROBLEMO;
5584 /****************************************************************************
5585 ****************************************************************************/
5586 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5591 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5593 ZERO_STRUCTP(info_2);
5595 if (info_2 == NULL) {
5597 return ERROR_NOT_ENOUGH_MEMORY;
5600 for (i=0; i<count && found==False; i++) {
5601 if (queue[i].job==(int)jobid)
5608 /* I shoud reply something else ... I can't find the good one */
5609 return NT_STATUS_NO_PROBLEMO;
5612 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5616 *needed += spoolss_size_job_info_2(info_2);
5618 if (!alloc_buffer_size(buffer, *needed)) {
5620 return ERROR_INSUFFICIENT_BUFFER;
5623 new_smb_io_job_info_2("", buffer, info_2, 0);
5625 free_dev_mode(info_2->devmode);
5628 if (*needed > offered)
5629 return ERROR_INSUFFICIENT_BUFFER;
5631 return NT_STATUS_NO_PROBLEMO;
5634 /****************************************************************************
5635 ****************************************************************************/
5636 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5637 NEW_BUFFER *buffer, uint32 offered,
5642 print_queue_struct *queue=NULL;
5643 print_status_struct prt_status;
5645 DEBUG(5,("spoolss_getjob\n"));
5647 memset(&prt_status, 0, sizeof(prt_status));
5651 if (!get_printer_snum(handle, &snum))
5652 return ERROR_INVALID_HANDLE;
5654 count = print_queue_status(snum, &queue, &prt_status);
5656 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5657 count, prt_status.status, prt_status.message));
5661 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5663 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5666 return ERROR_INVALID_LEVEL;