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(conn_tdb_ctx(), 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 if (DEBUGLEVEL >= 10) {
3391 acl = old_secdesc_ctr->sec->dacl;
3392 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3393 PRINTERNAME(snum), acl->num_aces));
3395 for (i = 0; i < acl->num_aces; i++) {
3398 sid_to_string(sid_str, &acl->ace[i].sid);
3400 DEBUG(10, ("%s 0x%08x\n", sid_str,
3401 acl->ace[i].info.mask));
3404 acl = secdesc_ctr->sec->dacl;
3405 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3406 PRINTERNAME(snum), acl->num_aces));
3408 for (i = 0; i < acl->num_aces; i++) {
3411 sid_to_string(sid_str, &acl->ace[i].sid);
3413 DEBUG(10, ("%s 0x%08x\n", sid_str,
3414 acl->ace[i].info.mask));
3418 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3420 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3421 result = NT_STATUS_NO_PROBLEMO;
3425 /* Work out which user is performing the operation */
3427 get_current_user(&user, p);
3429 /* Check the user has permissions to change the security
3430 descriptor. By experimentation with two NT machines, the user
3431 requires Full Access to the printer to change security
3434 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3435 result = ERROR_ACCESS_DENIED;
3439 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3442 free_sec_desc_buf(&new_secdesc_ctr);
3443 free_sec_desc_buf(&old_secdesc_ctr);
3448 /********************************************************************
3449 Do Samba sanity checks on a printer info struct.
3450 this has changed purpose: it now "canonicalises" printer
3451 info from a client rather than just checking it is correct
3452 ********************************************************************/
3454 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3456 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3457 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3459 /* we force some elements to "correct" values */
3460 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3461 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3462 global_myname, lp_servicename(snum));
3463 fstrcpy(info->sharename, lp_servicename(snum));
3464 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3465 | PRINTER_ATTRIBUTE_LOCAL \
3466 | PRINTER_ATTRIBUTE_RAW_ONLY \
3467 | PRINTER_ATTRIBUTE_QUEUED ;
3472 /****************************************************************************
3473 ****************************************************************************/
3474 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3476 pid_t local_pid = sys_getpid();
3477 char *cmd = lp_addprinter_cmd();
3482 pstring driverlocation;
3486 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3487 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3491 /* build driver path... only 9X architecture is needed for legacy reasons */
3492 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3494 /* change \ to \\ for the shell */
3495 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3497 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3498 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3499 cmd, printer->info_2->printername, printer->info_2->sharename,
3500 printer->info_2->portname, printer->info_2->drivername,
3501 printer->info_2->location, driverlocation);
3504 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3505 ret = smbrun(command, tmp_file, False);
3506 DEBUGADD(10,("returned [%d]\n", ret));
3514 qlines = file_lines_load(tmp_file, &numlines, True);
3515 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3516 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3520 /* Set the portname to what the script says the portname should be. */
3521 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3522 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3524 /* Send SIGHUP to process group... is there a better way? */
3529 file_lines_free(qlines);
3533 /* Return true if two devicemodes are equal */
3535 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3537 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
3540 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3541 return False; /* if either is exclusively NULL are not equal */
3544 if (!strequal(d1->devicename, d2->devicename) ||
3545 !strequal(d1->formname, d2->formname)) {
3546 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3550 if (d1->specversion != d2->specversion ||
3551 d1->driverversion != d2->driverversion ||
3552 d1->size != d2->size ||
3553 d1->driverextra != d2->driverextra ||
3554 d1->orientation != d2->orientation ||
3555 d1->papersize != d2->papersize ||
3556 d1->paperlength != d2->paperlength ||
3557 d1->paperwidth != d2->paperwidth ||
3558 d1->scale != d2->scale ||
3559 d1->copies != d2->copies ||
3560 d1->defaultsource != d2->defaultsource ||
3561 d1->printquality != d2->printquality ||
3562 d1->color != d2->color ||
3563 d1->duplex != d2->duplex ||
3564 d1->yresolution != d2->yresolution ||
3565 d1->ttoption != d2->ttoption ||
3566 d1->collate != d2->collate ||
3567 d1->logpixels != d2->logpixels) {
3568 DEBUG(10, ("nt_devicemode_equal(): specversion-logpixels "
3573 if (d1->fields != d2->fields ||
3574 d1->bitsperpel != d2->bitsperpel ||
3575 d1->pelswidth != d2->pelswidth ||
3576 d1->pelsheight != d2->pelsheight ||
3577 d1->displayflags != d2->displayflags ||
3578 d1->displayfrequency != d2->displayfrequency ||
3579 d1->icmmethod != d2->icmmethod ||
3580 d1->icmintent != d2->icmintent ||
3581 d1->mediatype != d2->mediatype ||
3582 d1->dithertype != d2->dithertype ||
3583 d1->reserved1 != d2->reserved1 ||
3584 d1->reserved2 != d2->reserved2 ||
3585 d1->panningwidth != d2->panningwidth ||
3586 d1->panningheight != d2->panningheight) {
3587 DEBUG(10, ("nt_devicemode_equal(): fields-panningheight "
3592 /* compare the private data if it exists */
3593 if (!d1->driverextra && !d2->driverextra) goto equal;
3595 if (d1->driverextra != d2->driverextra) {
3596 DEBUG(10, ("nt_devicemode_equal(): driverextra not equal\n"));
3600 if (memcmp(d1->private, d2->private, d1->driverextra)) {
3601 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
3606 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
3610 /* Return true if two NT_PRINTER_PARAM structures are equal */
3612 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3613 NT_PRINTER_PARAM *p2)
3615 if (!p1 && !p2) goto equal;
3617 if ((!p1 && p2) || (p1 && !p2)) {
3618 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
3622 /* Compare lists of printer parameters */
3626 NT_PRINTER_PARAM *q = p1;
3628 /* Find the parameter in the second structure */
3632 if (strequal(p1->value, q->value) &&
3633 p1->type == q->type &&
3634 p1->data_len == q->data_len &&
3635 memcmp(p1->data, q->data, p1->data_len) == 0) {
3645 DEBUG(10, ("nt_printer_param_equal(): param %s "
3646 "differs\n", p1->value));
3655 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
3659 /********************************************************************
3660 * Called by update_printer when trying to work out whether to
3661 * actually update printer info.
3662 ********************************************************************/
3664 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3665 NT_PRINTER_INFO_LEVEL *p2)
3667 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3669 /* Trivial conditions */
3671 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3675 if ((!p1 && p2) || (p1 && !p2) ||
3676 (!p1->info_2 && p2->info_2) ||
3677 (p1->info_2 && !p2->info_2)) {
3678 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
3683 /* Compare two nt_printer_info_level structures. Don't compare
3684 status or cjobs as they seem to have something to do with the
3690 if (pi1->attributes != pi2->attributes ||
3691 pi1->priority != pi2->priority ||
3692 pi1->default_priority != pi2->default_priority ||
3693 pi1->starttime != pi2->starttime ||
3694 pi1->untiltime != pi2->untiltime ||
3695 pi1->averageppm != pi2->averageppm) {
3696 DEBUG(10, ("nt_printer_info_level_equal(): attr-ppm values "
3701 /* Yuck - don't check the printername or servername as the
3702 add_a_printer() code plays games with them. You can't
3703 change the printername or the sharename through this interface
3706 if (!strequal(pi1->sharename, pi2->sharename) ||
3707 !strequal(pi1->portname, pi2->portname) ||
3708 !strequal(pi1->drivername, pi2->drivername) ||
3709 !strequal(pi1->comment, pi2->comment) ||
3710 !strequal(pi1->location, pi2->location)) {
3711 DEBUG(10, ("nt_printer_info_level_equal(): values for names "
3716 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3720 if (!strequal(pi1->sepfile, pi2->sepfile) ||
3721 !strequal(pi1->printprocessor, pi2->printprocessor) ||
3722 !strequal(pi1->datatype, pi2->datatype) ||
3723 !strequal(pi1->parameters, pi2->parameters)) {
3724 DEBUG(10, ("nt_printer_info_level_equal(): sep-params values "
3729 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3733 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3737 if (pi1->changeid != pi2->changeid ||
3738 pi1->c_setprinter != pi2->c_setprinter ||
3739 pi1->setuptime != pi2->setuptime) {
3740 DEBUG(10, ("nt_printer_info_level_equal(): id-setuptime "
3741 "values differ\n"));
3746 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
3750 /********************************************************************
3751 * called by spoolss_api_setprinter
3752 * when updating a printer description
3753 ********************************************************************/
3755 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3756 const SPOOL_PRINTER_INFO_LEVEL *info,
3757 DEVICEMODE *devmode)
3760 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3761 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3764 DEBUG(8,("update_printer\n"));
3766 result = NT_STATUS_NO_PROBLEMO;
3769 DEBUG(0,("Send a mail to samba@samba.org\n"));
3770 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3771 result = ERROR_INVALID_LEVEL;
3775 if (!OPEN_HANDLE(Printer)) {
3776 result = ERROR_INVALID_HANDLE;
3780 if (!get_printer_snum(handle, &snum)) {
3781 result = ERROR_INVALID_HANDLE;
3785 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3786 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3787 result = ERROR_INVALID_HANDLE;
3791 DEBUGADD(8,("Converting info_2 struct\n"));
3794 * convert_printer_info converts the incoming
3795 * info from the client and overwrites the info
3796 * just read from the tdb in the pointer 'printer'.
3799 convert_printer_info(info, printer, level);
3801 if (info->info_2->devmode_ptr != 0) {
3802 /* we have a valid devmode
3803 convert it and link it*/
3806 * Ensure printer->info_2->devmode is a valid pointer
3807 * as we will be overwriting it in convert_devicemode().
3810 if (printer->info_2->devmode == NULL)
3811 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3813 DEBUGADD(8,("Converting the devicemode struct\n"));
3814 convert_devicemode(devmode, printer->info_2->devmode);
3817 if (printer->info_2->devmode != NULL)
3818 free_nt_devicemode(&printer->info_2->devmode);
3819 printer->info_2->devmode=NULL;
3822 /* Do sanity check on the requested changes for Samba */
3824 if (!check_printer_ok(printer->info_2, snum)) {
3825 result = ERROR_INVALID_PARAMETER;
3829 /* NT likes to call this function even though nothing has actually
3830 changed. Check this so the user doesn't end up with an
3831 annoying permission denied dialog box. */
3833 if (nt_printer_info_level_equal(printer, old_printer)) {
3834 DEBUG(3, ("printer info has not changed\n"));
3835 result = NT_STATUS_NO_PROBLEMO;
3839 /* Check calling user has permission to update printer description */
3841 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3842 DEBUG(3, ("printer property change denied by security "
3844 result = ERROR_ACCESS_DENIED;
3848 /* Call addprinter hook */
3850 if (*lp_addprinter_cmd() )
3851 if ( !add_printer_hook(printer) ) {
3852 result = ERROR_ACCESS_DENIED;
3856 /* Update printer info */
3858 if (add_a_printer(*printer, 2)!=0) {
3859 /* I don't really know what to return here !!! */
3860 result = ERROR_ACCESS_DENIED;
3865 free_a_printer(&printer, 2);
3866 free_a_printer(&old_printer, 2);
3868 srv_spoolss_sendnotify(handle);
3873 /****************************************************************************
3874 ****************************************************************************/
3875 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3876 const SPOOL_PRINTER_INFO_LEVEL *info,
3877 DEVMODE_CTR devmode_ctr,
3878 SEC_DESC_BUF *secdesc_ctr,
3879 uint32 command, pipes_struct *p)
3881 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3883 if (!OPEN_HANDLE(Printer)) {
3884 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3885 return ERROR_INVALID_HANDLE;
3888 /* check the level */
3891 return control_printer(handle, command, p);
3893 return update_printer(handle, level, info, devmode_ctr.devmode);
3895 return update_printer_sec(handle, level, info, p,
3898 return ERROR_INVALID_LEVEL;
3902 /****************************************************************************
3903 ****************************************************************************/
3904 uint32 _spoolss_fcpn(POLICY_HND *handle)
3906 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3908 if (!OPEN_HANDLE(Printer)) {
3909 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3910 return ERROR_INVALID_HANDLE;
3913 if (Printer->notify.client_connected==True)
3914 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3915 return ERROR_INVALID_HANDLE;
3917 Printer->notify.flags=0;
3918 Printer->notify.options=0;
3919 Printer->notify.localmachine[0]='\0';
3920 Printer->notify.printerlocal=0;
3921 if (Printer->notify.option)
3922 safe_free(Printer->notify.option->ctr.type);
3923 safe_free(Printer->notify.option);
3924 Printer->notify.option=NULL;
3925 Printer->notify.client_connected=False;
3927 return NT_STATUS_NO_PROBLEMO;
3930 /****************************************************************************
3931 ****************************************************************************/
3932 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3933 NEW_BUFFER *buffer, uint32 offered,
3937 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3938 returns for AddJob. AddJob
3939 must fail on non-local
3943 /****************************************************************************
3944 ****************************************************************************/
3945 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3946 int position, int snum)
3952 t=gmtime(&queue->time);
3953 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3955 job_info->jobid=queue->job;
3956 init_unistr(&job_info->printername, lp_servicename(snum));
3957 init_unistr(&job_info->machinename, temp_name);
3958 init_unistr(&job_info->username, queue->user);
3959 init_unistr(&job_info->document, queue->file);
3960 init_unistr(&job_info->datatype, "RAW");
3961 init_unistr(&job_info->text_status, "");
3962 job_info->status=nt_printj_status(queue->status);
3963 job_info->priority=queue->priority;
3964 job_info->position=position;
3965 job_info->totalpages=0;
3966 job_info->pagesprinted=0;
3968 make_systemtime(&job_info->submitted, t);
3971 /****************************************************************************
3972 ****************************************************************************/
3973 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3974 int position, int snum)
3977 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3981 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3984 t=gmtime(&queue->time);
3985 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3987 job_info->jobid=queue->job;
3989 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3991 init_unistr(&job_info->printername, chaine);
3993 init_unistr(&job_info->machinename, temp_name);
3994 init_unistr(&job_info->username, queue->user);
3995 init_unistr(&job_info->document, queue->file);
3996 init_unistr(&job_info->notifyname, queue->user);
3997 init_unistr(&job_info->datatype, "RAW");
3998 init_unistr(&job_info->printprocessor, "winprint");
3999 init_unistr(&job_info->parameters, "");
4000 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4001 init_unistr(&job_info->text_status, "");
4003 /* and here the security descriptor */
4005 job_info->status=nt_printj_status(queue->status);
4006 job_info->priority=queue->priority;
4007 job_info->position=position;
4008 job_info->starttime=0;
4009 job_info->untiltime=0;
4010 job_info->totalpages=0;
4011 job_info->size=queue->size;
4012 make_systemtime(&(job_info->submitted), t);
4013 job_info->timeelapsed=0;
4014 job_info->pagesprinted=0;
4016 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4017 free_a_printer(&ntprinter, 2);
4021 free_a_printer(&ntprinter, 2);
4025 /****************************************************************************
4026 Enumjobs at level 1.
4027 ****************************************************************************/
4028 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4029 NEW_BUFFER *buffer, uint32 offered,
4030 uint32 *needed, uint32 *returned)
4035 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4039 return ERROR_NOT_ENOUGH_MEMORY;
4042 for (i=0; i<*returned; i++)
4043 fill_job_info_1(&info[i], &queue[i], i, snum);
4047 /* check the required size. */
4048 for (i=0; i<*returned; i++)
4049 (*needed) += spoolss_size_job_info_1(&info[i]);
4051 if (!alloc_buffer_size(buffer, *needed)) {
4053 return ERROR_INSUFFICIENT_BUFFER;
4056 /* fill the buffer with the structures */
4057 for (i=0; i<*returned; i++)
4058 new_smb_io_job_info_1("", buffer, &info[i], 0);
4063 if (*needed > offered) {
4065 return ERROR_INSUFFICIENT_BUFFER;
4068 return NT_STATUS_NO_PROBLEMO;
4071 /****************************************************************************
4072 Enumjobs at level 2.
4073 ****************************************************************************/
4074 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4075 NEW_BUFFER *buffer, uint32 offered,
4076 uint32 *needed, uint32 *returned)
4081 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4085 return ERROR_NOT_ENOUGH_MEMORY;
4088 for (i=0; i<*returned; i++)
4089 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4093 /* check the required size. */
4094 for (i=0; i<*returned; i++)
4095 (*needed) += spoolss_size_job_info_2(&info[i]);
4097 if (!alloc_buffer_size(buffer, *needed)) {
4099 return ERROR_INSUFFICIENT_BUFFER;
4102 /* fill the buffer with the structures */
4103 for (i=0; i<*returned; i++)
4104 new_smb_io_job_info_2("", buffer, &info[i], 0);
4107 free_job_info_2(info);
4109 if (*needed > offered) {
4111 return ERROR_INSUFFICIENT_BUFFER;
4114 return NT_STATUS_NO_PROBLEMO;
4117 /****************************************************************************
4119 ****************************************************************************/
4120 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4121 NEW_BUFFER *buffer, uint32 offered,
4122 uint32 *needed, uint32 *returned)
4125 print_queue_struct *queue=NULL;
4126 print_status_struct prt_status;
4128 DEBUG(4,("_spoolss_enumjobs\n"));
4130 ZERO_STRUCT(prt_status);
4135 if (!get_printer_snum(handle, &snum))
4136 return ERROR_INVALID_HANDLE;
4138 *returned = print_queue_status(snum, &queue, &prt_status);
4139 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4141 if (*returned == 0) {
4143 return NT_STATUS_NO_PROBLEMO;
4148 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4150 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4154 return ERROR_INVALID_LEVEL;
4159 /****************************************************************************
4160 ****************************************************************************/
4161 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4166 /****************************************************************************
4167 ****************************************************************************/
4168 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4169 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4171 struct current_user user;
4172 print_status_struct prt_status;
4173 int snum, errcode = ERROR_INVALID_FUNCTION;
4175 memset(&prt_status, 0, sizeof(prt_status));
4177 if (!get_printer_snum(handle, &snum)) {
4178 return ERROR_INVALID_HANDLE;
4181 if (!print_job_exists(jobid)) {
4182 return ERROR_INVALID_PRINTER_NAME;
4185 get_current_user(&user, p);
4188 case JOB_CONTROL_CANCEL:
4189 case JOB_CONTROL_DELETE:
4190 if (print_job_delete(&user, jobid, &errcode)) {
4194 case JOB_CONTROL_PAUSE:
4195 if (print_job_pause(&user, jobid, &errcode)) {
4199 case JOB_CONTROL_RESTART:
4200 case JOB_CONTROL_RESUME:
4201 if (print_job_resume(&user, jobid, &errcode)) {
4206 return ERROR_INVALID_LEVEL;
4212 /****************************************************************************
4213 Enumerates all printer drivers at level 1.
4214 ****************************************************************************/
4215 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4220 fstring *list = NULL;
4222 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4223 DRIVER_INFO_1 *driver_info_1=NULL;
4227 #define MAX_VERSION 4
4229 for (version=0; version<MAX_VERSION; version++) {
4231 ndrivers=get_ntdrivers(&list, architecture, version);
4232 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4235 return ERROR_NOT_ENOUGH_MEMORY;
4238 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4240 return ERROR_NOT_ENOUGH_MEMORY;
4244 for (i=0; i<ndrivers; i++) {
4246 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4247 ZERO_STRUCT(driver);
4248 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4252 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4253 free_a_printer_driver(driver, 3);
4256 *returned+=ndrivers;
4260 /* check the required size. */
4261 for (i=0; i<*returned; i++) {
4262 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4263 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4266 if (!alloc_buffer_size(buffer, *needed)) {
4267 safe_free(driver_info_1);
4268 return ERROR_INSUFFICIENT_BUFFER;
4271 /* fill the buffer with the form structures */
4272 for (i=0; i<*returned; i++) {
4273 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4274 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4277 safe_free(driver_info_1);
4279 if (*needed > offered) {
4281 return ERROR_INSUFFICIENT_BUFFER;
4284 return NT_STATUS_NO_PROBLEMO;
4287 /****************************************************************************
4288 Enumerates all printer drivers at level 2.
4289 ****************************************************************************/
4290 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4295 fstring *list = NULL;
4297 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4298 DRIVER_INFO_2 *driver_info_2=NULL;
4302 #define MAX_VERSION 4
4304 for (version=0; version<MAX_VERSION; version++) {
4306 ndrivers=get_ntdrivers(&list, architecture, version);
4307 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4310 return ERROR_NOT_ENOUGH_MEMORY;
4313 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4315 return ERROR_NOT_ENOUGH_MEMORY;
4319 for (i=0; i<ndrivers; i++) {
4322 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4323 ZERO_STRUCT(driver);
4324 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4328 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4329 free_a_printer_driver(driver, 3);
4332 *returned+=ndrivers;
4336 /* check the required size. */
4337 for (i=0; i<*returned; i++) {
4338 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4339 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4342 if (!alloc_buffer_size(buffer, *needed)) {
4343 safe_free(driver_info_2);
4344 return ERROR_INSUFFICIENT_BUFFER;
4347 /* fill the buffer with the form structures */
4348 for (i=0; i<*returned; i++) {
4349 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4350 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4353 safe_free(driver_info_2);
4355 if (*needed > offered) {
4357 return ERROR_INSUFFICIENT_BUFFER;
4360 return NT_STATUS_NO_PROBLEMO;
4363 /****************************************************************************
4364 Enumerates all printer drivers at level 3.
4365 ****************************************************************************/
4366 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4371 fstring *list = NULL;
4373 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4374 DRIVER_INFO_3 *driver_info_3=NULL;
4378 #define MAX_VERSION 4
4380 for (version=0; version<MAX_VERSION; version++) {
4382 ndrivers=get_ntdrivers(&list, architecture, version);
4383 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4386 return ERROR_NOT_ENOUGH_MEMORY;
4389 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4391 return ERROR_NOT_ENOUGH_MEMORY;
4395 for (i=0; i<ndrivers; i++) {
4398 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4399 ZERO_STRUCT(driver);
4400 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4404 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4405 free_a_printer_driver(driver, 3);
4408 *returned+=ndrivers;
4412 /* check the required size. */
4413 for (i=0; i<*returned; i++) {
4414 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4415 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4418 if (!alloc_buffer_size(buffer, *needed)) {
4419 safe_free(driver_info_3);
4420 return ERROR_INSUFFICIENT_BUFFER;
4423 /* fill the buffer with the driver structures */
4424 for (i=0; i<*returned; i++) {
4425 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4426 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4429 for (i=0; i<*returned; i++)
4430 safe_free(driver_info_3[i].dependentfiles);
4432 safe_free(driver_info_3);
4434 if (*needed > offered) {
4436 return ERROR_INSUFFICIENT_BUFFER;
4439 return NT_STATUS_NO_PROBLEMO;
4442 /****************************************************************************
4443 Enumerates all printer drivers.
4444 ****************************************************************************/
4445 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4446 NEW_BUFFER *buffer, uint32 offered,
4447 uint32 *needed, uint32 *returned)
4449 fstring *list = NULL;
4451 fstring architecture;
4453 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4454 fstrcpy(servername, global_myname);
4458 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4462 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4464 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4466 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4470 return ERROR_INVALID_LEVEL;
4474 /****************************************************************************
4475 ****************************************************************************/
4476 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4478 form->flag=list->flag;
4479 init_unistr(&form->name, list->name);
4480 form->width=list->width;
4481 form->length=list->length;
4482 form->left=list->left;
4483 form->top=list->top;
4484 form->right=list->right;
4485 form->bottom=list->bottom;
4488 /****************************************************************************
4489 ****************************************************************************/
4490 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4491 NEW_BUFFER *buffer, uint32 offered,
4492 uint32 *needed, uint32 *numofforms)
4494 nt_forms_struct *list=NULL;
4499 DEBUG(4,("_new_spoolss_enumforms\n"));
4500 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4501 DEBUGADD(5,("Info level [%d]\n", level));
4503 *numofforms = get_ntforms(&list);
4504 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4506 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4510 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4512 return ERROR_NOT_ENOUGH_MEMORY;
4515 /* construct the list of form structures */
4516 for (i=0; i<*numofforms; i++) {
4517 DEBUGADD(6,("Filling form number [%d]\n",i));
4518 fill_form_1(&forms_1[i], &list[i]);
4523 /* check the required size. */
4524 for (i=0; i<*numofforms; i++) {
4525 DEBUGADD(6,("adding form [%d]'s size\n",i));
4526 buffer_size += spoolss_size_form_1(&forms_1[i]);
4529 *needed=buffer_size;
4531 if (!alloc_buffer_size(buffer, buffer_size)){
4533 return ERROR_INSUFFICIENT_BUFFER;
4536 /* fill the buffer with the form structures */
4537 for (i=0; i<*numofforms; i++) {
4538 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4539 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4544 if (*needed > offered) {
4546 return ERROR_INSUFFICIENT_BUFFER;
4549 return NT_STATUS_NO_PROBLEMO;
4553 return ERROR_INVALID_LEVEL;
4558 /****************************************************************************
4559 ****************************************************************************/
4560 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4562 nt_forms_struct *list=NULL;
4568 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4570 DEBUG(4,("_spoolss_getform\n"));
4571 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4572 DEBUGADD(5,("Info level [%d]\n", level));
4574 numofforms = get_ntforms(&list);
4575 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4577 if (numofforms == 0)
4578 return ERROR_NO_MORE_ITEMS;
4583 /* Check if the requested name is in the list of form structures */
4584 for (i=0; i<numofforms; i++) {
4586 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4588 if (strequal(form_name, list[i].name)) {
4589 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4590 fill_form_1(&form_1, &list[i]);
4597 /* check the required size. */
4599 *needed=spoolss_size_form_1(&form_1);
4601 if (!alloc_buffer_size(buffer, buffer_size)){
4602 return ERROR_INSUFFICIENT_BUFFER;
4605 if (*needed > offered) {
4606 return ERROR_INSUFFICIENT_BUFFER;
4609 /* fill the buffer with the form structures */
4610 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4611 new_smb_io_form_1("", buffer, &form_1, 0);
4613 return NT_STATUS_NO_PROBLEMO;
4617 return ERROR_INVALID_LEVEL;
4621 /****************************************************************************
4622 ****************************************************************************/
4623 static void fill_port_1(PORT_INFO_1 *port, char *name)
4625 init_unistr(&port->port_name, name);
4628 /****************************************************************************
4629 ****************************************************************************/
4630 static void fill_port_2(PORT_INFO_2 *port, char *name)
4632 init_unistr(&port->port_name, name);
4633 init_unistr(&port->monitor_name, "Local Monitor");
4634 init_unistr(&port->description, "Local Port");
4635 #define PORT_TYPE_WRITE 1
4636 port->port_type=PORT_TYPE_WRITE;
4640 /****************************************************************************
4642 ****************************************************************************/
4643 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4645 PORT_INFO_1 *ports=NULL;
4648 if (*lp_enumports_cmd()) {
4649 pid_t local_pid = sys_getpid();
4650 char *cmd = lp_enumports_cmd();
4658 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4659 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4663 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4664 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4667 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4668 ret = smbrun(command, tmp_file, False);
4669 DEBUG(10,("Returned [%d]\n", ret));
4672 /* Is this the best error to return here? */
4673 return ERROR_ACCESS_DENIED;
4677 qlines = file_lines_load(tmp_file, &numlines,True);
4678 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4679 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4683 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4684 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4685 file_lines_free(qlines);
4686 return ERROR_NOT_ENOUGH_MEMORY;
4689 for (i=0; i<numlines; i++) {
4690 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4691 fill_port_1(&ports[i], qlines[i]);
4694 file_lines_free(qlines);
4697 *returned = numlines;
4700 *returned = 1; /* Sole Samba port returned. */
4702 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4703 return ERROR_NOT_ENOUGH_MEMORY;
4705 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4707 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4710 /* check the required size. */
4711 for (i=0; i<*returned; i++) {
4712 DEBUGADD(6,("adding port [%d]'s size\n", i));
4713 *needed += spoolss_size_port_info_1(&ports[i]);
4716 if (!alloc_buffer_size(buffer, *needed)) {
4718 return ERROR_INSUFFICIENT_BUFFER;
4721 /* fill the buffer with the ports structures */
4722 for (i=0; i<*returned; i++) {
4723 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4724 new_smb_io_port_1("", buffer, &ports[i], 0);
4729 if (*needed > offered) {
4731 return ERROR_INSUFFICIENT_BUFFER;
4734 return NT_STATUS_NO_PROBLEMO;
4737 /****************************************************************************
4739 ****************************************************************************/
4741 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4743 PORT_INFO_2 *ports=NULL;
4746 if (*lp_enumports_cmd()) {
4747 pid_t local_pid = sys_getpid();
4748 char *cmd = lp_enumports_cmd();
4756 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4757 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4761 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4762 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4765 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4766 ret = smbrun(command, tmp_file, False);
4767 DEBUGADD(10,("returned [%d]\n", ret));
4770 /* Is this the best error to return here? */
4771 return ERROR_ACCESS_DENIED;
4775 qlines = file_lines_load(tmp_file, &numlines,True);
4776 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4777 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4781 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4782 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4783 file_lines_free(qlines);
4784 return ERROR_NOT_ENOUGH_MEMORY;
4787 for (i=0; i<numlines; i++) {
4788 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4789 fill_port_2(&(ports[i]), qlines[i]);
4792 file_lines_free(qlines);
4795 *returned = numlines;
4801 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4802 return ERROR_NOT_ENOUGH_MEMORY;
4804 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4806 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4809 /* check the required size. */
4810 for (i=0; i<*returned; i++) {
4811 DEBUGADD(6,("adding port [%d]'s size\n", i));
4812 *needed += spoolss_size_port_info_2(&ports[i]);
4815 if (!alloc_buffer_size(buffer, *needed)) {
4817 return ERROR_INSUFFICIENT_BUFFER;
4820 /* fill the buffer with the ports structures */
4821 for (i=0; i<*returned; i++) {
4822 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4823 new_smb_io_port_2("", buffer, &ports[i], 0);
4828 if (*needed > offered) {
4830 return ERROR_INSUFFICIENT_BUFFER;
4833 return NT_STATUS_NO_PROBLEMO;
4836 /****************************************************************************
4838 ****************************************************************************/
4839 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4840 NEW_BUFFER *buffer, uint32 offered,
4841 uint32 *needed, uint32 *returned)
4843 DEBUG(4,("_spoolss_enumports\n"));
4850 return enumports_level_1(buffer, offered, needed, returned);
4852 return enumports_level_2(buffer, offered, needed, returned);
4854 return ERROR_INVALID_LEVEL;
4858 /****************************************************************************
4859 ****************************************************************************/
4860 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4861 const SPOOL_PRINTER_INFO_LEVEL *info,
4862 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4863 uint32 user_switch, const SPOOL_USER_CTR *user,
4866 NT_PRINTER_INFO_LEVEL *printer = NULL;
4870 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4871 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4872 return ERROR_NOT_ENOUGH_MEMORY;
4875 ZERO_STRUCTP(printer);
4877 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4878 convert_printer_info(info, printer, 2);
4880 if (*lp_addprinter_cmd() )
4881 if ( !add_printer_hook(printer) ) {
4882 free_a_printer(&printer,2);
4883 return ERROR_ACCESS_DENIED;
4886 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4887 printer->info_2->sharename);
4889 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4890 free_a_printer(&printer,2);
4891 return ERROR_ACCESS_DENIED;
4894 /* you must be a printer admin to add a new printer */
4895 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4896 free_a_printer(&printer,2);
4897 return ERROR_ACCESS_DENIED;
4901 * Do sanity check on the requested changes for Samba.
4904 if (!check_printer_ok(printer->info_2, snum)) {
4905 free_a_printer(&printer,2);
4906 return ERROR_INVALID_PARAMETER;
4909 /* write the ASCII on disk */
4910 if (add_a_printer(*printer, 2) != 0) {
4911 free_a_printer(&printer,2);
4912 return ERROR_ACCESS_DENIED;
4915 if (!open_printer_hnd(handle, name)) {
4916 /* Handle open failed - remove addition. */
4917 del_a_printer(printer->info_2->sharename);
4918 free_a_printer(&printer,2);
4919 return ERROR_ACCESS_DENIED;
4922 free_a_printer(&printer,2);
4924 srv_spoolss_sendnotify(handle);
4926 return NT_STATUS_NO_PROBLEMO;
4929 /****************************************************************************
4930 ****************************************************************************/
4931 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4932 const SPOOL_PRINTER_INFO_LEVEL *info,
4933 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4934 uint32 user_switch, const SPOOL_USER_CTR *user,
4939 /* we don't handle yet */
4940 /* but I know what to do ... */
4941 return ERROR_INVALID_LEVEL;
4943 return spoolss_addprinterex_level_2(uni_srv_name, info,
4944 unk0, unk1, unk2, unk3,
4945 user_switch, user, handle);
4947 return ERROR_INVALID_LEVEL;
4951 /****************************************************************************
4952 ****************************************************************************/
4953 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4954 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4956 uint32 err = NT_STATUS_NO_PROBLEMO;
4957 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4958 struct current_user user;
4960 ZERO_STRUCT(driver);
4962 get_current_user(&user, p);
4964 convert_printer_driver_info(info, &driver, level);
4966 DEBUG(5,("Cleaning driver's information\n"));
4967 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
4970 DEBUG(5,("Moving driver to final destination\n"));
4971 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4973 err = ERROR_ACCESS_DENIED;
4977 if (add_a_printer_driver(driver, level)!=0) {
4978 err = ERROR_ACCESS_DENIED;
4983 free_a_printer_driver(driver, level);
4987 /****************************************************************************
4988 ****************************************************************************/
4989 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4991 init_unistr(&info->name, name);
4994 /****************************************************************************
4995 ****************************************************************************/
4996 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5000 pstring short_archi;
5001 DRIVER_DIRECTORY_1 *info=NULL;
5003 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5005 if (get_short_archi(short_archi, long_archi)==FALSE)
5006 return ERROR_INVALID_ENVIRONMENT;
5008 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5009 return ERROR_NOT_ENOUGH_MEMORY;
5011 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5013 DEBUG(4,("printer driver directory: [%s]\n", path));
5015 fill_driverdir_1(info, path);
5017 *needed += spoolss_size_driverdir_info_1(info);
5019 if (!alloc_buffer_size(buffer, *needed)) {
5021 return ERROR_INSUFFICIENT_BUFFER;
5024 new_smb_io_driverdir_1("", buffer, info, 0);
5028 if (*needed > offered)
5029 return ERROR_INSUFFICIENT_BUFFER;
5031 return NT_STATUS_NO_PROBLEMO;
5034 /****************************************************************************
5035 ****************************************************************************/
5036 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5037 NEW_BUFFER *buffer, uint32 offered,
5040 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5046 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5048 return ERROR_INVALID_LEVEL;
5052 /****************************************************************************
5053 ****************************************************************************/
5054 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5055 uint32 in_value_len, uint32 in_data_len,
5056 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5058 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5060 NT_PRINTER_INFO_LEVEL *printer = NULL;
5065 uint32 biggest_valuesize;
5066 uint32 biggest_datasize;
5068 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5073 ZERO_STRUCT(printer);
5075 *out_max_value_len=0;
5081 *out_max_data_len=0;
5085 DEBUG(5,("spoolss_enumprinterdata\n"));
5087 if (!OPEN_HANDLE(Printer)) {
5088 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5089 return ERROR_INVALID_HANDLE;
5092 if (!get_printer_snum(handle, &snum))
5093 return ERROR_INVALID_HANDLE;
5095 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5096 return ERROR_INVALID_HANDLE;
5099 * The NT machine wants to know the biggest size of value and data
5101 * cf: MSDN EnumPrinterData remark section
5103 if ( (in_value_len==0) && (in_data_len==0) ) {
5104 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5108 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5109 * if this parameter size doesn't exist.
5110 * Ok - my opinion here is that the client is not asking for the greatest
5111 * possible size of all the parameters, but is asking specifically for the size needed
5112 * for this specific parameter. In that case we can remove the loop below and
5113 * simplify this lookup code considerably. JF - comments welcome. JRA.
5116 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5118 free_a_printer(&printer, 2);
5119 return ERROR_NO_MORE_ITEMS;
5127 biggest_valuesize=0;
5130 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5131 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5132 if (data_len > biggest_datasize) biggest_datasize=data_len;
5134 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5142 * I think this is correct, it doesn't break APW and
5143 * allows Gerald's Win32 test programs to work correctly,
5144 * but may need altering.... JRA.
5147 if (param_index == 0) {
5148 /* No parameters found. */
5149 free_a_printer(&printer, 2);
5150 return ERROR_NO_MORE_ITEMS;
5153 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5154 *out_value_len=2*(1+biggest_valuesize);
5155 *out_data_len=biggest_datasize;
5157 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5159 free_a_printer(&printer, 2);
5160 return NT_STATUS_NO_PROBLEMO;
5164 * the value len is wrong in NT sp3
5165 * that's the number of bytes not the number of unicode chars
5168 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5170 free_a_printer(&printer, 2);
5171 return ERROR_NO_MORE_ITEMS;
5174 free_a_printer(&printer, 2);
5178 * - counted in bytes in the request
5179 * - counted in UNICODE chars in the max reply
5180 * - counted in bytes in the real size
5182 * take a pause *before* coding not *during* coding
5185 *out_max_value_len=(in_value_len/sizeof(uint16));
5186 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5188 return ERROR_NOT_ENOUGH_MEMORY;
5191 ZERO_STRUCTP(*out_value);
5192 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5196 /* the data is counted in bytes */
5197 *out_max_data_len=in_data_len;
5198 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5200 return ERROR_NOT_ENOUGH_MEMORY;
5203 memset(*data_out,'\0',in_data_len);
5204 memcpy(*data_out, data, (size_t)data_len);
5205 *out_data_len=data_len;
5209 return NT_STATUS_NO_PROBLEMO;
5212 /****************************************************************************
5213 ****************************************************************************/
5214 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5215 const UNISTR2 *value,
5220 uint32 numeric_data)
5222 NT_PRINTER_INFO_LEVEL *printer = NULL;
5223 NT_PRINTER_PARAM *param = NULL, old_param;
5225 uint32 status = 0x0;
5226 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5228 DEBUG(5,("spoolss_setprinterdata\n"));
5230 if (!OPEN_HANDLE(Printer)) {
5231 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5232 return ERROR_INVALID_HANDLE;
5235 if (!get_printer_snum(handle, &snum))
5236 return ERROR_INVALID_HANDLE;
5238 status = get_a_printer(&printer, 2, lp_servicename(snum));
5240 return ERROR_INVALID_NAME;
5242 convert_specific_param(¶m, value , type, data, real_len);
5244 /* Check if we are making any changes or not. Return true if
5245 nothing is actually changing. */
5247 ZERO_STRUCT(old_param);
5249 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5250 &old_param.type, (unsigned int *)&old_param.data_len)) {
5252 if (param->type == old_param.type &&
5253 param->data_len == old_param.data_len &&
5254 memcmp(param->data, old_param.data,
5255 old_param.data_len) == 0) {
5257 DEBUG(3, ("setprinterdata hasn't changed\n"));
5258 status = NT_STATUS_NO_PROBLEMO;
5265 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5266 DEBUG(3, ("security descriptor change denied by existing "
5267 "security descriptor\n"));
5268 status = ERROR_ACCESS_DENIED;
5272 unlink_specific_param_if_exist(printer->info_2, param);
5274 add_a_specific_param(printer->info_2, ¶m);
5275 status = mod_a_printer(*printer, 2);
5278 free_a_printer(&printer, 2);
5280 free_nt_printer_param(¶m);
5281 safe_free(old_param.data);
5286 /****************************************************************************
5287 ****************************************************************************/
5288 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5290 NT_PRINTER_INFO_LEVEL *printer = NULL;
5291 NT_PRINTER_PARAM param;
5293 uint32 status = 0x0;
5294 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5296 DEBUG(5,("spoolss_deleteprinterdata\n"));
5298 if (!OPEN_HANDLE(Printer)) {
5299 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5300 return ERROR_INVALID_HANDLE;
5303 if (!get_printer_snum(handle, &snum))
5304 return ERROR_INVALID_HANDLE;
5306 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5307 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5308 "security descriptor\n"));
5309 return ERROR_ACCESS_DENIED;
5312 status = get_a_printer(&printer, 2, lp_servicename(snum));
5314 return ERROR_INVALID_NAME;
5316 ZERO_STRUCTP(¶m);
5317 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5319 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5320 status = ERROR_INVALID_PARAMETER;
5322 status = mod_a_printer(*printer, 2);
5324 free_a_printer(&printer, 2);
5328 /****************************************************************************
5329 ****************************************************************************/
5330 uint32 _spoolss_addform( POLICY_HND *handle,
5335 nt_forms_struct *list=NULL;
5336 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5338 DEBUG(5,("spoolss_addform\n"));
5340 if (!OPEN_HANDLE(Printer)) {
5341 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5342 return ERROR_INVALID_HANDLE;
5345 count=get_ntforms(&list);
5346 if(!add_a_form(&list, form, &count))
5347 return ERROR_NOT_ENOUGH_MEMORY;
5348 write_ntforms(&list, count);
5355 /****************************************************************************
5356 ****************************************************************************/
5357 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5361 nt_forms_struct *list=NULL;
5362 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5364 DEBUG(5,("spoolss_deleteform\n"));
5366 if (!OPEN_HANDLE(Printer)) {
5367 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5368 return ERROR_INVALID_HANDLE;
5371 count = get_ntforms(&list);
5372 if(!delete_a_form(&list, form_name, &count, &ret))
5373 return ERROR_INVALID_PARAMETER;
5380 /****************************************************************************
5381 ****************************************************************************/
5382 uint32 _spoolss_setform( POLICY_HND *handle,
5383 const UNISTR2 *uni_name,
5388 nt_forms_struct *list=NULL;
5389 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5391 DEBUG(5,("spoolss_setform\n"));
5393 if (!OPEN_HANDLE(Printer)) {
5394 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5395 return ERROR_INVALID_HANDLE;
5397 count=get_ntforms(&list);
5398 update_a_form(&list, form, count);
5399 write_ntforms(&list, count);
5406 /****************************************************************************
5407 enumprintprocessors level 1.
5408 ****************************************************************************/
5409 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5411 PRINTPROCESSOR_1 *info_1=NULL;
5413 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5414 return ERROR_NOT_ENOUGH_MEMORY;
5418 init_unistr(&info_1->name, "winprint");
5420 *needed += spoolss_size_printprocessor_info_1(info_1);
5422 if (!alloc_buffer_size(buffer, *needed))
5423 return ERROR_INSUFFICIENT_BUFFER;
5425 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5429 if (*needed > offered) {
5431 return ERROR_INSUFFICIENT_BUFFER;
5434 return NT_STATUS_NO_PROBLEMO;
5437 /****************************************************************************
5438 ****************************************************************************/
5439 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5440 NEW_BUFFER *buffer, uint32 offered,
5441 uint32 *needed, uint32 *returned)
5443 DEBUG(5,("spoolss_enumprintprocessors\n"));
5446 * Enumerate the print processors ...
5448 * Just reply with "winprint", to keep NT happy
5449 * and I can use my nice printer checker.
5457 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5459 return ERROR_INVALID_LEVEL;
5463 /****************************************************************************
5464 enumprintprocdatatypes level 1.
5465 ****************************************************************************/
5466 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5468 PRINTPROCDATATYPE_1 *info_1=NULL;
5470 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5471 return ERROR_NOT_ENOUGH_MEMORY;
5475 init_unistr(&info_1->name, "RAW");
5477 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5479 if (!alloc_buffer_size(buffer, *needed))
5480 return ERROR_INSUFFICIENT_BUFFER;
5482 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5486 if (*needed > offered) {
5488 return ERROR_INSUFFICIENT_BUFFER;
5491 return NT_STATUS_NO_PROBLEMO;
5494 /****************************************************************************
5495 ****************************************************************************/
5496 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5497 NEW_BUFFER *buffer, uint32 offered,
5498 uint32 *needed, uint32 *returned)
5500 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5507 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5509 return ERROR_INVALID_LEVEL;
5513 /****************************************************************************
5514 enumprintmonitors level 1.
5515 ****************************************************************************/
5516 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5518 PRINTMONITOR_1 *info_1=NULL;
5520 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5521 return ERROR_NOT_ENOUGH_MEMORY;
5525 init_unistr(&info_1->name, "Local Port");
5527 *needed += spoolss_size_printmonitor_info_1(info_1);
5529 if (!alloc_buffer_size(buffer, *needed))
5530 return ERROR_INSUFFICIENT_BUFFER;
5532 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5536 if (*needed > offered) {
5538 return ERROR_INSUFFICIENT_BUFFER;
5541 return NT_STATUS_NO_PROBLEMO;
5544 /****************************************************************************
5545 enumprintmonitors level 2.
5546 ****************************************************************************/
5547 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5549 PRINTMONITOR_2 *info_2=NULL;
5551 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5552 return ERROR_NOT_ENOUGH_MEMORY;
5556 init_unistr(&info_2->name, "Local Port");
5557 init_unistr(&info_2->environment, "Windows NT X86");
5558 init_unistr(&info_2->dll_name, "localmon.dll");
5560 *needed += spoolss_size_printmonitor_info_2(info_2);
5562 if (!alloc_buffer_size(buffer, *needed))
5563 return ERROR_INSUFFICIENT_BUFFER;
5565 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5569 if (*needed > offered) {
5571 return ERROR_INSUFFICIENT_BUFFER;
5574 return NT_STATUS_NO_PROBLEMO;
5577 /****************************************************************************
5578 ****************************************************************************/
5579 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5580 NEW_BUFFER *buffer, uint32 offered,
5581 uint32 *needed, uint32 *returned)
5583 DEBUG(5,("spoolss_enumprintmonitors\n"));
5586 * Enumerate the print monitors ...
5588 * Just reply with "Local Port", to keep NT happy
5589 * and I can use my nice printer checker.
5597 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5599 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5601 return ERROR_INVALID_LEVEL;
5605 /****************************************************************************
5606 ****************************************************************************/
5607 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5611 JOB_INFO_1 *info_1=NULL;
5613 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5615 if (info_1 == NULL) {
5617 return ERROR_NOT_ENOUGH_MEMORY;
5620 for (i=0; i<count && found==False; i++) {
5621 if (queue[i].job==(int)jobid)
5628 /* I shoud reply something else ... I can't find the good one */
5629 return NT_STATUS_NO_PROBLEMO;
5632 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5636 *needed += spoolss_size_job_info_1(info_1);
5638 if (!alloc_buffer_size(buffer, *needed)) {
5640 return ERROR_INSUFFICIENT_BUFFER;
5643 new_smb_io_job_info_1("", buffer, info_1, 0);
5647 if (*needed > offered)
5648 return ERROR_INSUFFICIENT_BUFFER;
5650 return NT_STATUS_NO_PROBLEMO;
5654 /****************************************************************************
5655 ****************************************************************************/
5656 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5661 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5663 ZERO_STRUCTP(info_2);
5665 if (info_2 == NULL) {
5667 return ERROR_NOT_ENOUGH_MEMORY;
5670 for (i=0; i<count && found==False; i++) {
5671 if (queue[i].job==(int)jobid)
5678 /* I shoud reply something else ... I can't find the good one */
5679 return NT_STATUS_NO_PROBLEMO;
5682 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5686 *needed += spoolss_size_job_info_2(info_2);
5688 if (!alloc_buffer_size(buffer, *needed)) {
5690 return ERROR_INSUFFICIENT_BUFFER;
5693 new_smb_io_job_info_2("", buffer, info_2, 0);
5695 free_job_info_2(info_2);
5697 if (*needed > offered)
5698 return ERROR_INSUFFICIENT_BUFFER;
5700 return NT_STATUS_NO_PROBLEMO;
5703 /****************************************************************************
5704 ****************************************************************************/
5705 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5706 NEW_BUFFER *buffer, uint32 offered,
5711 print_queue_struct *queue=NULL;
5712 print_status_struct prt_status;
5714 DEBUG(5,("spoolss_getjob\n"));
5716 memset(&prt_status, 0, sizeof(prt_status));
5720 if (!get_printer_snum(handle, &snum))
5721 return ERROR_INVALID_HANDLE;
5723 count = print_queue_status(snum, &queue, &prt_status);
5725 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5726 count, prt_status.status, prt_status.message));
5730 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5732 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5735 return ERROR_INVALID_LEVEL;