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,
658 uint32 result = NT_STATUS_NO_PROBLEMO;
659 SEC_DESC_BUF *sec_desc = NULL;
660 uint32 acc_granted, status;
662 extern struct current_user current_user;
664 if (printername == NULL) {
665 result = ERROR_INVALID_PRINTER_NAME;
669 /* some sanity check because you can open a printer or a print server */
670 /* aka: \\server\printer or \\server */
671 unistr2_to_ascii(name, printername, sizeof(name)-1);
673 DEBUGADD(3,("checking name: %s\n",name));
675 if (!open_printer_hnd(handle, name)) {
676 result = ERROR_INVALID_PRINTER_NAME;
681 if (printer_default->datatype_ptr != NULL)
683 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
684 set_printer_hnd_datatype(handle, datatype);
687 set_printer_hnd_datatype(handle, "");
690 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
691 close_printer_handle(handle);
692 result = ERROR_ACCESS_DENIED;
696 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
697 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
698 Then both Win2k and WinNT clients try an OpenPrinterEx with
699 SERVER_ALL_ACCESS, which we force to fail. Then they try
700 OpenPrinterEx with SERVER_READ which we allow. This lets the
701 client view printer folder, but does not show the MSAPW.
703 Note: this test needs code to check access rights here too. Jeremy
704 could you look at this? */
706 if (handle_is_printserver(handle) &&
707 !lp_ms_add_printer_wizard()) {
708 if (printer_default->access_required == 0) {
711 else if (printer_default->access_required != (SERVER_READ)) {
712 close_printer_handle(handle);
713 result = ERROR_ACCESS_DENIED;
718 /* NT doesn't let us connect to a printer if the connecting user
719 doesn't have print permission. If no security descriptor just
722 if (!nt_printing_getsec(name, &sec_desc)) {
726 /* Yuck - we should use the pipe_user rather than current_user but
727 it doesn't seem to be filled in correctly. )-: */
729 map_printer_permissions(sec_desc->sec);
731 if (!se_access_check(sec_desc->sec, ¤t_user, PRINTER_ACCESS_USE,
732 &acc_granted, &status)) {
733 DEBUG(3, ("access DENIED for printer open\n"));
734 close_printer_handle(handle);
735 result = ERROR_ACCESS_DENIED;
740 free_sec_desc_buf(&sec_desc);
745 /****************************************************************************
746 ****************************************************************************/
747 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
748 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
752 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
761 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
762 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
766 printer->info_3=NULL;
767 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
770 printer->info_6=NULL;
771 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
780 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
782 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
783 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
785 nt_devmode->specversion=devmode->specversion;
786 nt_devmode->driverversion=devmode->driverversion;
787 nt_devmode->size=devmode->size;
788 nt_devmode->driverextra=devmode->driverextra;
789 nt_devmode->fields=devmode->fields;
790 nt_devmode->orientation=devmode->orientation;
791 nt_devmode->papersize=devmode->papersize;
792 nt_devmode->paperlength=devmode->paperlength;
793 nt_devmode->paperwidth=devmode->paperwidth;
794 nt_devmode->scale=devmode->scale;
795 nt_devmode->copies=devmode->copies;
796 nt_devmode->defaultsource=devmode->defaultsource;
797 nt_devmode->printquality=devmode->printquality;
798 nt_devmode->color=devmode->color;
799 nt_devmode->duplex=devmode->duplex;
800 nt_devmode->yresolution=devmode->yresolution;
801 nt_devmode->ttoption=devmode->ttoption;
802 nt_devmode->collate=devmode->collate;
804 nt_devmode->logpixels=devmode->logpixels;
805 nt_devmode->bitsperpel=devmode->bitsperpel;
806 nt_devmode->pelswidth=devmode->pelswidth;
807 nt_devmode->pelsheight=devmode->pelsheight;
808 nt_devmode->displayflags=devmode->displayflags;
809 nt_devmode->displayfrequency=devmode->displayfrequency;
810 nt_devmode->icmmethod=devmode->icmmethod;
811 nt_devmode->icmintent=devmode->icmintent;
812 nt_devmode->mediatype=devmode->mediatype;
813 nt_devmode->dithertype=devmode->dithertype;
814 nt_devmode->reserved1=devmode->reserved1;
815 nt_devmode->reserved2=devmode->reserved2;
816 nt_devmode->panningwidth=devmode->panningwidth;
817 nt_devmode->panningheight=devmode->panningheight;
819 safe_free(nt_devmode->private);
820 if (nt_devmode->driverextra != 0) {
821 /* if we had a previous private delete it and make a new one */
822 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
824 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
827 nt_devmode->private = NULL;
833 /********************************************************************
834 * api_spoolss_closeprinter
835 ********************************************************************/
836 uint32 _spoolss_closeprinter(POLICY_HND *handle)
838 Printer_entry *Printer=find_printer_index_by_hnd(handle);
840 if (Printer && Printer->document_started)
841 _spoolss_enddocprinter(handle); /* print job was not closed */
843 if (!close_printer_handle(handle))
844 return ERROR_INVALID_HANDLE;
846 return NT_STATUS_NO_PROBLEMO;
849 /********************************************************************
850 * api_spoolss_deleteprinter
851 ********************************************************************/
852 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
854 Printer_entry *Printer=find_printer_index_by_hnd(handle);
856 if (Printer && Printer->document_started)
857 _spoolss_enddocprinter(handle); /* print job was not closed */
859 if (!delete_printer_handle(handle))
860 return ERROR_INVALID_HANDLE;
862 srv_spoolss_sendnotify(handle);
864 return NT_STATUS_NO_PROBLEMO;
867 /********************************************************************
868 GetPrinterData on a printer server Handle.
869 ********************************************************************/
870 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
874 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
876 if (!strcmp(value, "BeepEnabled")) {
878 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
880 SIVAL(*data, 0, 0x01);
885 if (!strcmp(value, "EventLog")) {
887 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
889 SIVAL(*data, 0, 0x1B);
894 if (!strcmp(value, "NetPopup")) {
896 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
898 SIVAL(*data, 0, 0x01);
903 if (!strcmp(value, "MajorVersion")) {
905 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
907 SIVAL(*data, 0, 0x02);
912 if (!strcmp(value, "DefaultSpoolDirectory")) {
913 pstring string="You are using a Samba server";
915 *needed = 2*(strlen(string)+1);
916 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
918 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
920 /* it's done by hand ready to go on the wire */
921 for (i=0; i<strlen(string); i++) {
922 (*data)[2*i]=string[i];
928 if (!strcmp(value, "Architecture")) {
929 pstring string="Windows NT x86";
931 *needed = 2*(strlen(string)+1);
932 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
934 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
935 for (i=0; i<strlen(string); i++) {
936 (*data)[2*i]=string[i];
945 /********************************************************************
946 GetPrinterData on a printer Handle.
947 ********************************************************************/
948 static BOOL getprinterdata_printer(POLICY_HND *handle,
949 fstring value, uint32 *type,
950 uint8 **data, uint32 *needed, uint32 in_size )
952 NT_PRINTER_INFO_LEVEL *printer = NULL;
956 Printer_entry *Printer = find_printer_index_by_hnd(handle);
958 DEBUG(5,("getprinterdata_printer\n"));
960 if (!OPEN_HANDLE(Printer)) {
961 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
965 if(!get_printer_snum(handle, &snum))
968 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
971 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
972 free_a_printer(&printer, 2);
976 free_a_printer(&printer, 2);
978 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
981 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
985 memset(*data, 0, in_size *sizeof(uint8));
986 /* copy the min(in_size, len) */
987 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
994 DEBUG(5,("getprinterdata_printer:copy done\n"));
1001 /********************************************************************
1002 * spoolss_getprinterdata
1003 ********************************************************************/
1004 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
1013 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1016 * Reminder: when it's a string, the length is in BYTES
1017 * even if UNICODE is negociated.
1024 /* in case of problem, return some default values */
1028 DEBUG(4,("_spoolss_getprinterdata\n"));
1030 if (!OPEN_HANDLE(Printer)) {
1031 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1032 return ERROR_NOT_ENOUGH_MEMORY;
1033 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1034 return ERROR_INVALID_HANDLE;
1037 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1039 if (handle_is_printserver(handle))
1040 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1042 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
1045 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1046 /* reply this param doesn't exist */
1048 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1049 return ERROR_NOT_ENOUGH_MEMORY;
1050 memset(*data, '\0', *out_size*sizeof(uint8));
1055 return ERROR_INVALID_PARAMETER;
1058 if (*needed > *out_size)
1059 return ERROR_MORE_DATA;
1061 return NT_STATUS_NO_PROBLEMO;
1064 /***************************************************************************
1065 connect to the client
1066 ****************************************************************************/
1067 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1072 * If it's the first connection, contact the client
1073 * and connect to the IPC$ share anonumously
1075 if (smb_connections==0) {
1076 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1078 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1084 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1090 /********************************************************************
1092 * ReplyFindFirstPrinterChangeNotifyEx
1094 * jfmxxxx: before replying OK: status=0
1095 * should do a rpc call to the workstation asking ReplyOpenPrinter
1096 * have to code it, later.
1098 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1099 * called from api_spoolss_rffpcnex
1100 ********************************************************************/
1101 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1102 const UNISTR2 *localmachine, uint32 printerlocal,
1103 SPOOL_NOTIFY_OPTION *option)
1105 /* store the notify value in the printer struct */
1107 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1109 if (!OPEN_HANDLE(Printer)) {
1110 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1111 return ERROR_INVALID_HANDLE;
1114 Printer->notify.flags=flags;
1115 Printer->notify.options=options;
1116 Printer->notify.printerlocal=printerlocal;
1117 Printer->notify.option=option;
1118 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1120 /* connect to the client machine and send a ReplyOpenPrinter */
1121 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1122 Printer->notify.printerlocal, 1,
1123 &Printer->notify.client_hnd))
1124 Printer->notify.client_connected=True;
1126 return NT_STATUS_NO_PROBLEMO;
1129 /*******************************************************************
1130 * fill a notify_info_data with the servername
1131 ********************************************************************/
1132 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1133 NT_PRINTER_INFO_LEVEL *printer)
1137 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1139 data->notify_data.data.length= (uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1140 temp_name, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1143 /*******************************************************************
1144 * fill a notify_info_data with the printername (not including the servername).
1145 ********************************************************************/
1146 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1147 NT_PRINTER_INFO_LEVEL *printer)
1149 /* the notify name should not contain the \\server\ part */
1150 char *p = strrchr(printer->info_2->printername, '\\');
1152 p = printer->info_2->printername;
1157 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1158 p, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1161 /*******************************************************************
1162 * fill a notify_info_data with the servicename
1163 ********************************************************************/
1164 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1166 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1167 lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
1170 /*******************************************************************
1171 * fill a notify_info_data with the port name
1172 ********************************************************************/
1173 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1175 /* even if it's strange, that's consistant in all the code */
1177 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1178 printer->info_2->portname, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1181 /*******************************************************************
1182 * fill a notify_info_data with the printername
1183 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1184 * but it doesn't exist, have to see what to do
1185 ********************************************************************/
1186 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1188 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1189 printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1192 /*******************************************************************
1193 * fill a notify_info_data with the comment
1194 ********************************************************************/
1195 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1197 if (*printer->info_2->comment == '\0')
1198 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1199 lp_comment(snum), sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1201 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1202 printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1205 /*******************************************************************
1206 * fill a notify_info_data with the comment
1207 * jfm:xxxx incorrect, have to create a new smb.conf option
1208 * location = "Room 1, floor 2, building 3"
1209 ********************************************************************/
1210 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1212 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1213 printer->info_2->location, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1216 /*******************************************************************
1217 * fill a notify_info_data with the device mode
1218 * jfm:xxxx don't to it for know but that's a real problem !!!
1219 ********************************************************************/
1220 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1224 /*******************************************************************
1225 * fill a notify_info_data with the separator file name
1226 * jfm:xxxx just return no file could add an option to smb.conf
1227 * separator file = "separator.txt"
1228 ********************************************************************/
1229 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1231 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1232 printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True) - sizeof(uint16))/sizeof(uint16));
1235 /*******************************************************************
1236 * fill a notify_info_data with the print processor
1237 * jfm:xxxx return always winprint to indicate we don't do anything to it
1238 ********************************************************************/
1239 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1241 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1242 printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1245 /*******************************************************************
1246 * fill a notify_info_data with the print processor options
1247 * jfm:xxxx send an empty string
1248 ********************************************************************/
1249 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1251 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1252 printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1255 /*******************************************************************
1256 * fill a notify_info_data with the data type
1257 * jfm:xxxx always send RAW as data type
1258 ********************************************************************/
1259 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1261 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1262 printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1265 /*******************************************************************
1266 * fill a notify_info_data with the security descriptor
1267 * jfm:xxxx send an null pointer to say no security desc
1268 * have to implement security before !
1269 ********************************************************************/
1270 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1272 data->notify_data.data.length=0;
1273 data->notify_data.data.string[0]=0x00;
1276 /*******************************************************************
1277 * fill a notify_info_data with the attributes
1278 * jfm:xxxx a samba printer is always shared
1279 ********************************************************************/
1280 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1282 data->notify_data.value[0] = printer->info_2->attributes;
1285 /*******************************************************************
1286 * fill a notify_info_data with the priority
1287 ********************************************************************/
1288 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1290 data->notify_data.value[0] = printer->info_2->priority;
1293 /*******************************************************************
1294 * fill a notify_info_data with the default priority
1295 ********************************************************************/
1296 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1298 data->notify_data.value[0] = printer->info_2->default_priority;
1301 /*******************************************************************
1302 * fill a notify_info_data with the start time
1303 ********************************************************************/
1304 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1306 data->notify_data.value[0] = printer->info_2->starttime;
1309 /*******************************************************************
1310 * fill a notify_info_data with the until time
1311 ********************************************************************/
1312 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1314 data->notify_data.value[0] = printer->info_2->untiltime;
1317 /*******************************************************************
1318 * fill a notify_info_data with the status
1319 ********************************************************************/
1320 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1323 print_queue_struct *q=NULL;
1324 print_status_struct status;
1326 memset(&status, 0, sizeof(status));
1327 count = print_queue_status(snum, &q, &status);
1328 data->notify_data.value[0]=(uint32) status.status;
1332 /*******************************************************************
1333 * fill a notify_info_data with the number of jobs queued
1334 ********************************************************************/
1335 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1337 print_queue_struct *q=NULL;
1338 print_status_struct status;
1340 memset(&status, 0, sizeof(status));
1341 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1345 /*******************************************************************
1346 * fill a notify_info_data with the average ppm
1347 ********************************************************************/
1348 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1350 /* always respond 8 pages per minutes */
1351 /* a little hard ! */
1352 data->notify_data.value[0] = printer->info_2->averageppm;
1355 /*******************************************************************
1356 * fill a notify_info_data with username
1357 ********************************************************************/
1358 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1360 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1361 queue->user, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1364 /*******************************************************************
1365 * fill a notify_info_data with job status
1366 ********************************************************************/
1367 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1369 data->notify_data.value[0]=nt_printj_status(queue->status);
1372 /*******************************************************************
1373 * fill a notify_info_data with job name
1374 ********************************************************************/
1375 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1377 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1378 queue->file, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1381 /*******************************************************************
1382 * fill a notify_info_data with job status
1383 ********************************************************************/
1384 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1386 char *p = "unknown";
1388 switch (queue->status) {
1393 p = ""; /* NT provides the paused string */
1402 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1403 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1406 /*******************************************************************
1407 * fill a notify_info_data with job time
1408 ********************************************************************/
1409 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1411 data->notify_data.value[0]=0x0;
1414 /*******************************************************************
1415 * fill a notify_info_data with job size
1416 ********************************************************************/
1417 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1419 data->notify_data.value[0]=queue->size;
1422 /*******************************************************************
1423 * fill a notify_info_data with job position
1424 ********************************************************************/
1425 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1427 data->notify_data.value[0]=queue->job;
1430 /*******************************************************************
1431 * fill a notify_info_data with submitted time
1432 ********************************************************************/
1433 static void spoolss_notify_submitted_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1437 t=gmtime(&queue->time);
1439 data->notify_data.data.length = sizeof(SYSTEMTIME);
1440 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1445 struct s_notify_info_data_table
1451 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1452 print_queue_struct *queue,
1453 NT_PRINTER_INFO_LEVEL *printer);
1456 struct s_notify_info_data_table notify_info_data_table[] =
1458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1508 { END, END, "", END, NULL }
1511 /*******************************************************************
1512 return the size of info_data structure
1513 ********************************************************************/
1514 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1518 while (notify_info_data_table[i].type != END)
1520 if ( (notify_info_data_table[i].type == type ) &&
1521 (notify_info_data_table[i].field == field ) )
1523 return (notify_info_data_table[i].size);
1530 /*******************************************************************
1531 return the type of notify_info_data
1532 ********************************************************************/
1533 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1537 while (notify_info_data_table[i].type != END)
1539 if ( (notify_info_data_table[i].type == type ) &&
1540 (notify_info_data_table[i].field == field ) )
1542 if (notify_info_data_table[i].size == POINTER)
1556 /****************************************************************************
1557 ****************************************************************************/
1558 static int search_notify(uint16 type, uint16 field, int *value)
1563 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1565 if ( (notify_info_data_table[j].type == type ) &&
1566 (notify_info_data_table[j].field == field ) )
1571 if ( found && (notify_info_data_table[j].fn != NULL) )
1577 /****************************************************************************
1578 ****************************************************************************/
1579 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1581 info_data->type = type;
1582 info_data->field = field;
1583 info_data->reserved = 0;
1585 info_data->size = size_of_notify_info_data(type, field);
1586 info_data->enc_type = type_of_notify_info_data(type, field);
1590 /*******************************************************************
1592 * fill a notify_info struct with info asked
1594 ********************************************************************/
1595 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1601 SPOOL_NOTIFY_INFO_DATA *current_data;
1602 NT_PRINTER_INFO_LEVEL *printer = NULL;
1603 print_queue_struct *queue=NULL;
1605 DEBUG(4,("construct_notify_printer_info\n"));
1607 type=option_type->type;
1609 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1610 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1611 option_type->count, lp_servicename(snum)));
1613 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1616 for(field_num=0; field_num<option_type->count; field_num++) {
1617 field = option_type->fields[field_num];
1618 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1620 if (!search_notify(type, field, &j) )
1623 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1626 current_data=&info->data[info->count];
1628 construct_info_data(current_data, type, field, id);
1630 DEBUG(10,("construct_notify_printer_info: calling %s\n",
1631 notify_info_data_table[j].name ));
1633 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1638 free_a_printer(&printer, 2);
1642 /*******************************************************************
1644 * fill a notify_info struct with info asked
1646 ********************************************************************/
1647 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1653 SPOOL_NOTIFY_INFO_DATA *current_data;
1654 NT_PRINTER_INFO_LEVEL *printer = NULL;
1656 DEBUG(4,("construct_notify_jobs_info\n"));
1658 type = option_type->type;
1660 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1661 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1662 option_type->count));
1664 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1667 for(field_num=0; field_num<option_type->count; field_num++) {
1668 field = option_type->fields[field_num];
1670 if (!search_notify(type, field, &j) )
1673 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1677 current_data=&(info->data[info->count]);
1679 construct_info_data(current_data, type, field, id);
1680 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1684 free_a_printer(&printer, 2);
1689 * JFM: The enumeration is not that simple, it's even non obvious.
1691 * let's take an example: I want to monitor the PRINTER SERVER for
1692 * the printer's name and the number of jobs currently queued.
1693 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1694 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1696 * I have 3 printers on the back of my server.
1698 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1701 * 1 printer 1 name 1
1702 * 2 printer 1 cjob 1
1703 * 3 printer 2 name 2
1704 * 4 printer 2 cjob 2
1705 * 5 printer 3 name 3
1706 * 6 printer 3 name 3
1708 * that's the print server case, the printer case is even worse.
1713 /*******************************************************************
1715 * enumerate all printers on the printserver
1716 * fill a notify_info struct with info asked
1718 ********************************************************************/
1719 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1722 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1723 int n_services=lp_numservices();
1726 SPOOL_NOTIFY_OPTION *option;
1727 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1729 DEBUG(4,("printserver_notify_info\n"));
1731 option=Printer->notify.option;
1737 for (i=0; i<option->count; i++) {
1738 option_type=&(option->ctr.type[i]);
1740 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1743 for (snum=0; snum<n_services; snum++)
1744 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1745 if (construct_notify_printer_info(info, snum, option_type, id))
1750 * Debugging information, don't delete.
1753 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1754 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1755 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1757 for (i=0; i<info->count; i++) {
1758 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1759 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1760 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1764 return NT_STATUS_NO_PROBLEMO;
1767 /*******************************************************************
1769 * fill a notify_info struct with info asked
1771 ********************************************************************/
1772 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1775 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1778 SPOOL_NOTIFY_OPTION *option;
1779 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1781 print_queue_struct *queue=NULL;
1782 print_status_struct status;
1784 DEBUG(4,("printer_notify_info\n"));
1786 option=Printer->notify.option;
1792 get_printer_snum(hnd, &snum);
1794 for (i=0; i<option->count; i++) {
1795 option_type=&option->ctr.type[i];
1797 switch ( option_type->type ) {
1798 case PRINTER_NOTIFY_TYPE:
1799 if(construct_notify_printer_info(info, snum, option_type, id))
1803 case JOB_NOTIFY_TYPE:
1804 memset(&status, 0, sizeof(status));
1805 count = print_queue_status(snum, &queue, &status);
1806 for (j=0; j<count; j++)
1807 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1814 * Debugging information, don't delete.
1817 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1818 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1819 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1821 for (i=0; i<info->count; i++) {
1822 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1823 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1824 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1827 return NT_STATUS_NO_PROBLEMO;
1830 /********************************************************************
1832 ********************************************************************/
1833 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1834 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1836 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1838 if (!OPEN_HANDLE(Printer)) {
1839 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1840 return ERROR_INVALID_HANDLE;
1843 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1845 /* jfm: the change value isn't used right now.
1846 * we will honour it when
1847 * a) we'll be able to send notification to the client
1848 * b) we'll have a way to communicate between the spoolss process.
1850 * same thing for option->flags
1851 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1852 * I don't have a global notification system, I'm sending back all the
1853 * informations even when _NOTHING_ has changed.
1856 /* just discard the SPOOL_NOTIFY_OPTION */
1858 safe_free(option->ctr.type);
1860 switch (Printer->printer_type) {
1861 case PRINTER_HANDLE_IS_PRINTSERVER:
1862 return printserver_notify_info(handle, info);
1863 case PRINTER_HANDLE_IS_PRINTER:
1864 return printer_notify_info(handle, info);
1867 return ERROR_INVALID_HANDLE;
1870 /********************************************************************
1871 * construct_printer_info_0
1872 * fill a printer_info_0 struct
1873 ********************************************************************/
1874 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
1878 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1879 counter_printer_0 *session_counter;
1880 uint32 global_counter;
1884 print_queue_struct *queue=NULL;
1885 print_status_struct status;
1887 memset(&status, 0, sizeof(status));
1889 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1892 count = print_queue_status(snum, &queue, &status);
1894 /* check if we already have a counter for this printer */
1895 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1897 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1898 if (session_counter->snum == snum)
1902 /* it's the first time, add it to the list */
1903 if (session_counter==NULL) {
1904 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1905 free_a_printer(&ntprinter, 2);
1908 ZERO_STRUCTP(session_counter);
1909 session_counter->snum=snum;
1910 session_counter->counter=0;
1911 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1915 session_counter->counter++;
1918 * the global_counter should be stored in a TDB as it's common to all the clients
1919 * and should be zeroed on samba startup
1921 global_counter=session_counter->counter;
1923 pstrcpy(chaine,ntprinter->info_2->printername);
1925 init_unistr(&printer->printername, chaine);
1927 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
1928 init_unistr(&printer->servername, chaine);
1930 printer->cjobs = count;
1931 printer->total_jobs = 0;
1932 printer->total_bytes = 0;
1934 setuptime = (time_t)ntprinter->info_2->setuptime;
1935 t=gmtime(&setuptime);
1937 printer->year = t->tm_year+1900;
1938 printer->month = t->tm_mon+1;
1939 printer->dayofweek = t->tm_wday;
1940 printer->day = t->tm_mday;
1941 printer->hour = t->tm_hour;
1942 printer->minute = t->tm_min;
1943 printer->second = t->tm_sec;
1944 printer->milliseconds = 0;
1946 printer->global_counter = global_counter;
1947 printer->total_pages = 0;
1948 printer->major_version = 0x0004; /* NT 4 */
1949 printer->build_version = 0x0565; /* build 1381 */
1950 printer->unknown7 = 0x1;
1951 printer->unknown8 = 0x0;
1952 printer->unknown9 = 0x0;
1953 printer->session_counter = session_counter->counter;
1954 printer->unknown11 = 0x0;
1955 printer->printer_errors = 0x0; /* number of print failure */
1956 printer->unknown13 = 0x0;
1957 printer->unknown14 = 0x1;
1958 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1959 printer->unknown16 = 0x0;
1960 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1961 printer->unknown18 = 0x0;
1962 printer->status = nt_printq_status(status.status);
1963 printer->unknown20 = 0x0;
1964 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1965 printer->unknown22 = 0x0;
1966 printer->unknown23 = 0x6; /* 6 ???*/
1967 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1968 printer->unknown25 = 0;
1969 printer->unknown26 = 0;
1970 printer->unknown27 = 0;
1971 printer->unknown28 = 0;
1972 printer->unknown29 = 0;
1975 free_a_printer(&ntprinter,2);
1979 /********************************************************************
1980 * construct_printer_info_1
1981 * fill a printer_info_1 struct
1982 ********************************************************************/
1983 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
1987 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1989 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1992 printer->flags=flags;
1994 if (*ntprinter->info_2->comment == '\0') {
1995 init_unistr(&printer->comment, lp_comment(snum));
1996 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
1997 ntprinter->info_2->drivername, lp_comment(snum));
2000 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2001 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2002 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2005 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2007 init_unistr(&printer->description, chaine);
2008 init_unistr(&printer->name, chaine2);
2010 free_a_printer(&ntprinter,2);
2015 /****************************************************************************
2016 Free a DEVMODE struct.
2017 ****************************************************************************/
2019 static void free_dev_mode(DEVICEMODE *dev)
2025 safe_free(dev->private);
2030 /****************************************************************************
2031 Create a DEVMODE struct. Returns malloced memory.
2032 ****************************************************************************/
2034 static DEVICEMODE *construct_dev_mode(int snum)
2038 NT_PRINTER_INFO_LEVEL *printer = NULL;
2039 NT_DEVICEMODE *ntdevmode = NULL;
2040 DEVICEMODE *devmode = NULL;
2042 DEBUG(7,("construct_dev_mode\n"));
2044 DEBUGADD(8,("getting printer characteristics\n"));
2046 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2047 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2051 ZERO_STRUCTP(devmode);
2053 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2056 if (printer->info_2->devmode)
2057 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2059 if (ntdevmode == NULL)
2062 DEBUGADD(8,("loading DEVICEMODE\n"));
2064 snprintf(adevice, sizeof(adevice), printer->info_2->printername);
2065 init_unistr(&devmode->devicename, adevice);
2067 snprintf(aform, sizeof(aform), ntdevmode->formname);
2068 init_unistr(&devmode->formname, aform);
2070 devmode->specversion = ntdevmode->specversion;
2071 devmode->driverversion = ntdevmode->driverversion;
2072 devmode->size = ntdevmode->size;
2073 devmode->driverextra = ntdevmode->driverextra;
2074 devmode->fields = ntdevmode->fields;
2076 devmode->orientation = ntdevmode->orientation;
2077 devmode->papersize = ntdevmode->papersize;
2078 devmode->paperlength = ntdevmode->paperlength;
2079 devmode->paperwidth = ntdevmode->paperwidth;
2080 devmode->scale = ntdevmode->scale;
2081 devmode->copies = ntdevmode->copies;
2082 devmode->defaultsource = ntdevmode->defaultsource;
2083 devmode->printquality = ntdevmode->printquality;
2084 devmode->color = ntdevmode->color;
2085 devmode->duplex = ntdevmode->duplex;
2086 devmode->yresolution = ntdevmode->yresolution;
2087 devmode->ttoption = ntdevmode->ttoption;
2088 devmode->collate = ntdevmode->collate;
2089 devmode->icmmethod = ntdevmode->icmmethod;
2090 devmode->icmintent = ntdevmode->icmintent;
2091 devmode->mediatype = ntdevmode->mediatype;
2092 devmode->dithertype = ntdevmode->dithertype;
2094 if (ntdevmode->private != NULL) {
2095 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2099 free_nt_devicemode(&ntdevmode);
2100 free_a_printer(&printer,2);
2107 free_nt_devicemode(&ntdevmode);
2109 free_a_printer(&printer,2);
2110 free_dev_mode(devmode);
2115 /********************************************************************
2116 * construct_printer_info_2
2117 * fill a printer_info_2 struct
2118 ********************************************************************/
2120 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2123 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2125 print_queue_struct *queue=NULL;
2126 print_status_struct status;
2127 memset(&status, 0, sizeof(status));
2129 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2132 memset(&status, 0, sizeof(status));
2133 count = print_queue_status(snum, &queue, &status);
2135 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2136 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2137 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2138 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2139 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2141 if (*ntprinter->info_2->comment == '\0')
2142 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2144 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2146 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2147 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2148 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2149 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2150 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2152 printer->attributes = ntprinter->info_2->attributes;
2154 printer->priority = ntprinter->info_2->priority; /* priority */
2155 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2156 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2157 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2158 printer->status = nt_printq_status(status.status); /* status */
2159 printer->cjobs = count; /* jobs */
2160 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2162 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2163 DEBUG(8, ("Returning NULL Devicemode!\n"));
2166 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2167 /* steal the printer info sec_desc structure. [badly done]. */
2168 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2169 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2170 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2171 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2174 printer->secdesc = NULL;
2177 free_a_printer(&ntprinter, 2);
2182 /********************************************************************
2183 * construct_printer_info_3
2184 * fill a printer_info_3 struct
2185 ********************************************************************/
2186 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2188 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2189 PRINTER_INFO_3 *printer = NULL;
2191 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2195 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2196 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2200 ZERO_STRUCTP(printer);
2202 printer->flags = 4; /* These are the components of the SD we are returning. */
2203 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2204 /* steal the printer info sec_desc structure. [badly done]. */
2205 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2209 * Set the flags for the components we are returning.
2212 if (printer->secdesc->owner_sid)
2213 printer->flags |= OWNER_SECURITY_INFORMATION;
2215 if (printer->secdesc->grp_sid)
2216 printer->flags |= GROUP_SECURITY_INFORMATION;
2218 if (printer->secdesc->dacl)
2219 printer->flags |= DACL_SECURITY_INFORMATION;
2221 if (printer->secdesc->sacl)
2222 printer->flags |= SACL_SECURITY_INFORMATION;
2225 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2226 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2227 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2230 free_a_printer(&ntprinter, 2);
2232 *pp_printer = printer;
2236 /********************************************************************
2237 Spoolss_enumprinters.
2238 ********************************************************************/
2239 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2243 int n_services=lp_numservices();
2244 PRINTER_INFO_1 *printers=NULL;
2245 PRINTER_INFO_1 current_prt;
2247 DEBUG(4,("enum_all_printers_info_1\n"));
2249 for (snum=0; snum<n_services; snum++) {
2250 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2251 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2253 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2254 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2256 return ERROR_NOT_ENOUGH_MEMORY;
2258 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2259 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2265 /* check the required size. */
2266 for (i=0; i<*returned; i++)
2267 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2269 if (!alloc_buffer_size(buffer, *needed))
2270 return ERROR_INSUFFICIENT_BUFFER;
2272 /* fill the buffer with the structures */
2273 for (i=0; i<*returned; i++)
2274 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2277 safe_free(printers);
2279 if (*needed > offered) {
2281 return ERROR_INSUFFICIENT_BUFFER;
2284 return NT_STATUS_NO_PROBLEMO;
2287 /********************************************************************
2288 enum_all_printers_info_1_local.
2289 *********************************************************************/
2290 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2292 DEBUG(4,("enum_all_printers_info_1_local\n"));
2294 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2297 /********************************************************************
2298 enum_all_printers_info_1_name.
2299 *********************************************************************/
2300 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2303 DEBUG(4,("enum_all_printers_info_1_name\n"));
2305 fstrcpy(temp, "\\\\");
2306 fstrcat(temp, global_myname);
2308 if (strequal(name, temp)) {
2309 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2312 return ERROR_INVALID_NAME;
2315 /********************************************************************
2316 enum_all_printers_info_1_remote.
2317 *********************************************************************/
2318 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2320 PRINTER_INFO_1 *printer;
2321 fstring printername;
2324 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2326 /* JFM: currently it's more a place holder than anything else.
2327 * In the spooler world there is a notion of server registration.
2328 * the print servers are registring (sp ?) on the PDC (in the same domain)
2330 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2333 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2334 return ERROR_NOT_ENOUGH_MEMORY;
2338 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2339 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2340 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2342 init_unistr(&printer->description, desc);
2343 init_unistr(&printer->name, printername);
2344 init_unistr(&printer->comment, comment);
2345 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2347 /* check the required size. */
2348 *needed += spoolss_size_printer_info_1(printer);
2350 if (!alloc_buffer_size(buffer, *needed)) {
2352 return ERROR_INSUFFICIENT_BUFFER;
2355 /* fill the buffer with the structures */
2356 new_smb_io_printer_info_1("", buffer, printer, 0);
2361 if (*needed > offered) {
2363 return ERROR_INSUFFICIENT_BUFFER;
2366 return NT_STATUS_NO_PROBLEMO;
2369 /********************************************************************
2370 enum_all_printers_info_1_network.
2371 *********************************************************************/
2372 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2374 DEBUG(4,("enum_all_printers_info_1_network\n"));
2376 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2379 /********************************************************************
2380 * api_spoolss_enumprinters
2382 * called from api_spoolss_enumprinters (see this to understand)
2383 ********************************************************************/
2384 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2388 int n_services=lp_numservices();
2389 PRINTER_INFO_2 *printers=NULL;
2390 PRINTER_INFO_2 current_prt;
2392 for (snum=0; snum<n_services; snum++) {
2393 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2394 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2396 if (construct_printer_info_2(¤t_prt, snum)) {
2397 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2398 return ERROR_NOT_ENOUGH_MEMORY;
2399 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2400 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2406 /* check the required size. */
2407 for (i=0; i<*returned; i++)
2408 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2410 if (!alloc_buffer_size(buffer, *needed)) {
2411 for (i=0; i<*returned; i++) {
2412 free_devmode(printers[i].devmode);
2413 free_sec_desc(&printers[i].secdesc);
2415 safe_free(printers);
2416 return ERROR_INSUFFICIENT_BUFFER;
2419 /* fill the buffer with the structures */
2420 for (i=0; i<*returned; i++)
2421 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2424 for (i=0; i<*returned; i++) {
2425 free_devmode(printers[i].devmode);
2426 free_sec_desc(&printers[i].secdesc);
2428 safe_free(printers);
2430 if (*needed > offered) {
2432 return ERROR_INSUFFICIENT_BUFFER;
2435 return NT_STATUS_NO_PROBLEMO;
2438 /********************************************************************
2439 * handle enumeration of printers at level 1
2440 ********************************************************************/
2441 static uint32 enumprinters_level1( uint32 flags, fstring name,
2442 NEW_BUFFER *buffer, uint32 offered,
2443 uint32 *needed, uint32 *returned)
2445 /* Not all the flags are equals */
2447 if (flags & PRINTER_ENUM_LOCAL)
2448 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2450 if (flags & PRINTER_ENUM_NAME)
2451 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2453 if (flags & PRINTER_ENUM_REMOTE)
2454 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2456 if (flags & PRINTER_ENUM_NETWORK)
2457 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2459 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2462 /********************************************************************
2463 * handle enumeration of printers at level 2
2464 ********************************************************************/
2465 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2466 NEW_BUFFER *buffer, uint32 offered,
2467 uint32 *needed, uint32 *returned)
2471 fstrcpy(temp, "\\\\");
2472 fstrcat(temp, global_myname);
2474 if (flags & PRINTER_ENUM_LOCAL) {
2475 if (strequal(servername, temp))
2476 return enum_all_printers_info_2(buffer, offered, needed, returned);
2478 return enum_all_printers_info_2(buffer, offered, needed, returned);
2481 if (flags & PRINTER_ENUM_NAME) {
2482 if (strequal(servername, temp))
2483 return enum_all_printers_info_2(buffer, offered, needed, returned);
2485 return ERROR_INVALID_NAME;
2488 if (flags & PRINTER_ENUM_REMOTE)
2489 return ERROR_INVALID_LEVEL;
2491 return NT_STATUS_NO_PROBLEMO;
2494 /********************************************************************
2495 * handle enumeration of printers at level 5
2496 ********************************************************************/
2497 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2498 NEW_BUFFER *buffer, uint32 offered,
2499 uint32 *needed, uint32 *returned)
2501 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2502 return NT_STATUS_NO_PROBLEMO;
2505 /********************************************************************
2506 * api_spoolss_enumprinters
2508 * called from api_spoolss_enumprinters (see this to understand)
2509 ********************************************************************/
2510 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2511 NEW_BUFFER *buffer, uint32 offered,
2512 uint32 *needed, uint32 *returned)
2516 DEBUG(4,("_spoolss_enumprinters\n"));
2523 * flags==PRINTER_ENUM_NAME
2524 * if name=="" then enumerates all printers
2525 * if name!="" then enumerate the printer
2526 * flags==PRINTER_ENUM_REMOTE
2527 * name is NULL, enumerate printers
2528 * Level 2: name!="" enumerates printers, name can't be NULL
2529 * Level 3: doesn't exist
2530 * Level 4: does a local registry lookup
2531 * Level 5: same as Level 2
2534 unistr2_to_ascii(name, servername, sizeof(name)-1);
2539 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2541 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2543 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2547 return ERROR_INVALID_LEVEL;
2551 /****************************************************************************
2552 ****************************************************************************/
2553 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2555 PRINTER_INFO_0 *printer=NULL;
2557 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2558 return ERROR_NOT_ENOUGH_MEMORY;
2560 construct_printer_info_0(printer, snum);
2562 /* check the required size. */
2563 *needed += spoolss_size_printer_info_0(printer);
2565 if (!alloc_buffer_size(buffer, *needed)) {
2567 return ERROR_INSUFFICIENT_BUFFER;
2570 /* fill the buffer with the structures */
2571 new_smb_io_printer_info_0("", buffer, printer, 0);
2576 if (*needed > offered) {
2577 return ERROR_INSUFFICIENT_BUFFER;
2580 return NT_STATUS_NO_PROBLEMO;
2583 /****************************************************************************
2584 ****************************************************************************/
2585 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2587 PRINTER_INFO_1 *printer=NULL;
2589 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2590 return ERROR_NOT_ENOUGH_MEMORY;
2592 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2594 /* check the required size. */
2595 *needed += spoolss_size_printer_info_1(printer);
2597 if (!alloc_buffer_size(buffer, *needed)) {
2599 return ERROR_INSUFFICIENT_BUFFER;
2602 /* fill the buffer with the structures */
2603 new_smb_io_printer_info_1("", buffer, printer, 0);
2608 if (*needed > offered) {
2609 return ERROR_INSUFFICIENT_BUFFER;
2612 return NT_STATUS_NO_PROBLEMO;
2615 /****************************************************************************
2616 ****************************************************************************/
2617 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2619 PRINTER_INFO_2 *printer=NULL;
2621 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2622 return ERROR_NOT_ENOUGH_MEMORY;
2624 construct_printer_info_2(printer, snum);
2626 /* check the required size. */
2627 *needed += spoolss_size_printer_info_2(printer);
2629 if (!alloc_buffer_size(buffer, *needed)) {
2630 free_printer_info_2(printer);
2631 return ERROR_INSUFFICIENT_BUFFER;
2634 /* fill the buffer with the structures */
2635 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2636 free_printer_info_2(printer);
2637 return ERROR_NOT_ENOUGH_MEMORY;
2641 free_printer_info_2(printer);
2643 if (*needed > offered) {
2644 return ERROR_INSUFFICIENT_BUFFER;
2647 return NT_STATUS_NO_PROBLEMO;
2650 /****************************************************************************
2651 ****************************************************************************/
2652 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2654 PRINTER_INFO_3 *printer=NULL;
2656 if (!construct_printer_info_3(&printer, snum))
2657 return ERROR_NOT_ENOUGH_MEMORY;
2659 /* check the required size. */
2660 *needed += spoolss_size_printer_info_3(printer);
2662 if (!alloc_buffer_size(buffer, *needed)) {
2663 free_printer_info_3(printer);
2664 return ERROR_INSUFFICIENT_BUFFER;
2667 /* fill the buffer with the structures */
2668 new_smb_io_printer_info_3("", buffer, printer, 0);
2671 free_printer_info_3(printer);
2673 if (*needed > offered) {
2674 return ERROR_INSUFFICIENT_BUFFER;
2677 return NT_STATUS_NO_PROBLEMO;
2680 /****************************************************************************
2681 ****************************************************************************/
2682 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2683 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2689 if (!get_printer_snum(handle, &snum))
2690 return ERROR_INVALID_HANDLE;
2694 return getprinter_level_0(snum, buffer, offered, needed);
2696 return getprinter_level_1(snum, buffer, offered, needed);
2698 return getprinter_level_2(snum, buffer, offered, needed);
2700 return getprinter_level_3(snum, buffer, offered, needed);
2702 return ERROR_INVALID_LEVEL;
2706 /********************************************************************
2707 * fill a DRIVER_INFO_1 struct
2708 ********************************************************************/
2709 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2711 init_unistr( &info->name, driver.info_3->name);
2714 /********************************************************************
2715 * construct_printer_driver_info_1
2716 ********************************************************************/
2717 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2719 NT_PRINTER_INFO_LEVEL *printer = NULL;
2720 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2722 ZERO_STRUCT(driver);
2724 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2725 return ERROR_INVALID_PRINTER_NAME;
2727 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2728 return ERROR_UNKNOWN_PRINTER_DRIVER;
2730 fill_printer_driver_info_1(info, driver, servername, architecture);
2732 free_a_printer(&printer,2);
2734 return NT_STATUS_NO_PROBLEMO;
2737 /********************************************************************
2738 * construct_printer_driver_info_2
2739 * fill a printer_info_2 struct
2740 ********************************************************************/
2741 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2743 pstring temp_driverpath;
2744 pstring temp_datafile;
2745 pstring temp_configfile;
2747 info->version=driver.info_3->cversion;
2749 init_unistr( &info->name, driver.info_3->name );
2750 init_unistr( &info->architecture, driver.info_3->environment );
2752 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2753 init_unistr( &info->driverpath, temp_driverpath );
2755 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2756 init_unistr( &info->datafile, temp_datafile );
2758 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2759 init_unistr( &info->configfile, temp_configfile );
2762 /********************************************************************
2763 * construct_printer_driver_info_2
2764 * fill a printer_info_2 struct
2765 ********************************************************************/
2766 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2768 NT_PRINTER_INFO_LEVEL *printer = NULL;
2769 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2771 ZERO_STRUCT(printer);
2772 ZERO_STRUCT(driver);
2774 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2775 return ERROR_INVALID_PRINTER_NAME;
2777 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2778 return ERROR_UNKNOWN_PRINTER_DRIVER;
2780 fill_printer_driver_info_2(info, driver, servername);
2782 free_a_printer(&printer,2);
2784 return NT_STATUS_NO_PROBLEMO;
2787 /********************************************************************
2788 * copy a strings array and convert to UNICODE
2790 * convert an array of ascii string to a UNICODE string
2791 ********************************************************************/
2792 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2799 DEBUG(6,("init_unistr_array\n"));
2803 if (char_array == NULL)
2807 if (!v) v = ""; /* hack to handle null lists */
2809 if (strlen(v) == 0) break;
2810 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2811 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2812 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2813 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2816 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2821 (*uni_array)[j]=0x0000;
2824 DEBUGADD(6,("last one:done\n"));
2827 /********************************************************************
2828 * construct_printer_info_3
2829 * fill a printer_info_3 struct
2830 ********************************************************************/
2831 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2833 pstring temp_driverpath;
2834 pstring temp_datafile;
2835 pstring temp_configfile;
2836 pstring temp_helpfile;
2840 info->version=driver.info_3->cversion;
2842 init_unistr( &info->name, driver.info_3->name );
2843 init_unistr( &info->architecture, driver.info_3->environment );
2845 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2846 init_unistr( &info->driverpath, temp_driverpath );
2848 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2849 init_unistr( &info->datafile, temp_datafile );
2851 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2852 init_unistr( &info->configfile, temp_configfile );
2854 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2855 init_unistr( &info->helpfile, temp_helpfile );
2857 init_unistr( &info->monitorname, driver.info_3->monitorname );
2858 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2860 info->dependentfiles=NULL;
2861 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2864 /********************************************************************
2865 * construct_printer_info_3
2866 * fill a printer_info_3 struct
2867 ********************************************************************/
2868 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2870 NT_PRINTER_INFO_LEVEL *printer = NULL;
2871 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2873 ZERO_STRUCT(driver);
2875 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2876 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2878 return ERROR_INVALID_PRINTER_NAME;
2880 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2881 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2883 free_a_printer(&printer,2);
2884 return ERROR_UNKNOWN_PRINTER_DRIVER;
2887 fill_printer_driver_info_3(info, driver, servername);
2889 free_a_printer(&printer,2);
2891 return NT_STATUS_NO_PROBLEMO;
2894 /********************************************************************
2895 * construct_printer_info_6
2896 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2897 ********************************************************************/
2899 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2901 pstring temp_driverpath;
2902 pstring temp_datafile;
2903 pstring temp_configfile;
2904 pstring temp_helpfile;
2908 memset(&nullstr, '\0', sizeof(fstring));
2910 info->version=driver.info_3->cversion;
2912 init_unistr( &info->name, driver.info_3->name );
2913 init_unistr( &info->architecture, driver.info_3->environment );
2915 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2916 init_unistr( &info->driverpath, temp_driverpath );
2918 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2919 init_unistr( &info->datafile, temp_datafile );
2921 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2922 init_unistr( &info->configfile, temp_configfile );
2924 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2925 init_unistr( &info->helpfile, temp_helpfile );
2927 init_unistr( &info->monitorname, driver.info_3->monitorname );
2928 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2930 info->dependentfiles=NULL;
2931 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2933 info->previousdrivernames=NULL;
2934 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2936 info->driver_date.low=0;
2937 info->driver_date.high=0;
2940 info->driver_version_low=0;
2941 info->driver_version_high=0;
2943 init_unistr( &info->mfgname, "");
2944 init_unistr( &info->oem_url, "");
2945 init_unistr( &info->hardware_id, "");
2946 init_unistr( &info->provider, "");
2949 /********************************************************************
2950 * construct_printer_info_6
2951 * fill a printer_info_6 struct
2952 ********************************************************************/
2953 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2955 NT_PRINTER_INFO_LEVEL *printer = NULL;
2956 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2958 ZERO_STRUCT(driver);
2960 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2961 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2963 return ERROR_INVALID_PRINTER_NAME;
2965 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2966 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2969 * Is this a W2k client ?
2973 free_a_printer(&printer,2);
2974 return ERROR_UNKNOWN_PRINTER_DRIVER;
2977 /* Yes - try again with a WinNT driver. */
2979 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2980 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2982 free_a_printer(&printer,2);
2983 return ERROR_UNKNOWN_PRINTER_DRIVER;
2987 fill_printer_driver_info_6(info, driver, servername);
2989 free_a_printer(&printer,2);
2991 return NT_STATUS_NO_PROBLEMO;
2994 /****************************************************************************
2995 ****************************************************************************/
2997 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2999 safe_free(info->dependentfiles);
3002 /****************************************************************************
3003 ****************************************************************************/
3005 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3007 safe_free(info->dependentfiles);
3011 /****************************************************************************
3012 ****************************************************************************/
3013 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3015 DRIVER_INFO_1 *info=NULL;
3018 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3019 return ERROR_NOT_ENOUGH_MEMORY;
3021 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3022 if (status != NT_STATUS_NO_PROBLEMO) {
3027 /* check the required size. */
3028 *needed += spoolss_size_printer_driver_info_1(info);
3030 if (!alloc_buffer_size(buffer, *needed)) {
3032 return ERROR_INSUFFICIENT_BUFFER;
3035 /* fill the buffer with the structures */
3036 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3041 if (*needed > offered)
3042 return ERROR_INSUFFICIENT_BUFFER;
3044 return NT_STATUS_NO_PROBLEMO;
3047 /****************************************************************************
3048 ****************************************************************************/
3049 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3051 DRIVER_INFO_2 *info=NULL;
3054 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3055 return ERROR_NOT_ENOUGH_MEMORY;
3057 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3058 if (status != NT_STATUS_NO_PROBLEMO) {
3063 /* check the required size. */
3064 *needed += spoolss_size_printer_driver_info_2(info);
3066 if (!alloc_buffer_size(buffer, *needed)) {
3068 return ERROR_INSUFFICIENT_BUFFER;
3071 /* fill the buffer with the structures */
3072 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3077 if (*needed > offered)
3078 return ERROR_INSUFFICIENT_BUFFER;
3080 return NT_STATUS_NO_PROBLEMO;
3083 /****************************************************************************
3084 ****************************************************************************/
3085 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3092 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3093 if (status != NT_STATUS_NO_PROBLEMO) {
3097 /* check the required size. */
3098 *needed += spoolss_size_printer_driver_info_3(&info);
3100 if (!alloc_buffer_size(buffer, *needed)) {
3101 free_printer_driver_info_3(&info);
3102 return ERROR_INSUFFICIENT_BUFFER;
3105 /* fill the buffer with the structures */
3106 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3108 free_printer_driver_info_3(&info);
3110 if (*needed > offered)
3111 return ERROR_INSUFFICIENT_BUFFER;
3113 return NT_STATUS_NO_PROBLEMO;
3116 /****************************************************************************
3117 ****************************************************************************/
3118 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3125 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3126 if (status != NT_STATUS_NO_PROBLEMO) {
3130 /* check the required size. */
3131 *needed += spoolss_size_printer_driver_info_6(&info);
3133 if (!alloc_buffer_size(buffer, *needed)) {
3134 free_printer_driver_info_6(&info);
3135 return ERROR_INSUFFICIENT_BUFFER;
3138 /* fill the buffer with the structures */
3139 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3141 free_printer_driver_info_6(&info);
3143 if (*needed > offered)
3144 return ERROR_INSUFFICIENT_BUFFER;
3146 return NT_STATUS_NO_PROBLEMO;
3149 /****************************************************************************
3150 ****************************************************************************/
3151 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3152 uint32 clientmajorversion, uint32 clientminorversion,
3153 NEW_BUFFER *buffer, uint32 offered,
3154 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3157 fstring architecture;
3160 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3163 *servermajorversion=0;
3164 *serverminorversion=0;
3166 pstrcpy(servername, global_myname);
3167 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3169 if (!get_printer_snum(handle, &snum))
3170 return ERROR_INVALID_HANDLE;
3174 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3176 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3178 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3180 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3182 return ERROR_INVALID_LEVEL;
3186 /****************************************************************************
3187 ****************************************************************************/
3188 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3190 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3192 if (OPEN_HANDLE(Printer)) {
3193 Printer->page_started=True;
3197 DEBUG(3,("Error in startpageprinter printer handle\n"));
3198 return ERROR_INVALID_HANDLE;
3201 /****************************************************************************
3202 ****************************************************************************/
3203 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3205 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3207 if (!OPEN_HANDLE(Printer)) {
3208 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3209 return ERROR_INVALID_HANDLE;
3212 Printer->page_started=False;
3214 return NT_STATUS_NO_PROBLEMO;
3217 /****************************************************************************
3218 Return a user struct for a pipe user.
3219 ****************************************************************************/
3221 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3223 if (p->ntlmssp_auth_validated) {
3224 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3226 extern struct current_user current_user;
3227 memcpy(user, ¤t_user, sizeof(struct current_user));
3233 /********************************************************************
3234 * api_spoolss_getprinter
3235 * called from the spoolss dispatcher
3237 ********************************************************************/
3238 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3239 pipes_struct *p, DOC_INFO *docinfo,
3242 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3246 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3247 struct current_user user;
3249 if (!OPEN_HANDLE(Printer)) {
3250 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3251 return ERROR_INVALID_HANDLE;
3254 get_current_user(&user, p);
3257 * a nice thing with NT is it doesn't listen to what you tell it.
3258 * when asked to send _only_ RAW datas, it tries to send datas
3261 * So I add checks like in NT Server ...
3263 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3264 * there's a bug in NT client-side code, so we'll fix it in the
3265 * server-side code. *nnnnnggggh!*
3268 if (info_1->p_datatype != 0) {
3269 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3270 if (strcmp(datatype, "RAW") != 0) {
3272 return ERROR_INVALID_DATATYPE;
3276 /* get the share number of the printer */
3277 if (!get_printer_snum(handle, &snum)) {
3278 return ERROR_INVALID_HANDLE;
3281 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3283 Printer->jobid = print_job_start(&user, snum, jobname);
3285 /* An error occured in print_job_start() so return an appropriate
3288 if (Printer->jobid == -1) {
3289 return map_nt_error_from_unix(errno);
3292 Printer->document_started=True;
3293 (*jobid) = Printer->jobid;
3295 srv_spoolss_sendnotify(handle);
3299 /********************************************************************
3300 * api_spoolss_getprinter
3301 * called from the spoolss dispatcher
3303 ********************************************************************/
3304 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3306 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3308 if (!OPEN_HANDLE(Printer)) {
3309 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3310 return ERROR_INVALID_HANDLE;
3313 Printer->document_started=False;
3314 print_job_end(Printer->jobid);
3315 /* error codes unhandled so far ... */
3317 srv_spoolss_sendnotify(handle);
3322 /****************************************************************************
3323 ****************************************************************************/
3324 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3327 uint32 *buffer_written)
3329 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3331 if (!OPEN_HANDLE(Printer)) {
3332 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3333 return ERROR_INVALID_HANDLE;
3336 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3342 /********************************************************************
3343 * api_spoolss_getprinter
3344 * called from the spoolss dispatcher
3346 ********************************************************************/
3347 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3350 struct current_user user;
3351 int snum, errcode = ERROR_INVALID_FUNCTION;
3352 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3354 get_current_user(&user, p);
3356 if (!OPEN_HANDLE(Printer)) {
3357 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3358 return ERROR_INVALID_HANDLE;
3361 if (!get_printer_snum(handle, &snum))
3362 return ERROR_INVALID_HANDLE;
3365 case PRINTER_CONTROL_PAUSE:
3366 if (print_queue_pause(&user, snum, &errcode)) {
3370 case PRINTER_CONTROL_RESUME:
3371 case PRINTER_CONTROL_UNPAUSE:
3372 if (print_queue_resume(&user, snum, &errcode)) {
3376 case PRINTER_CONTROL_PURGE:
3377 if (print_queue_purge(&user, snum, &errcode)) {
3382 return ERROR_INVALID_LEVEL;
3388 /********************************************************************
3389 * api_spoolss_abortprinter
3390 ********************************************************************/
3392 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3394 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3397 /********************************************************************
3398 * called by spoolss_api_setprinter
3399 * when updating a printer description
3400 ********************************************************************/
3401 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3402 const SPOOL_PRINTER_INFO_LEVEL *info,
3403 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3405 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3406 struct current_user user;
3410 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3412 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3413 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3414 OUR_HANDLE(handle)));
3416 result = ERROR_INVALID_HANDLE;
3420 /* NT seems to like setting the security descriptor even though
3421 nothing may have actually changed. This causes annoying
3422 dialog boxes when the user doesn't have permission to change
3423 the security descriptor. */
3425 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3427 if (DEBUGLEVEL >= 10) {
3431 acl = old_secdesc_ctr->sec->dacl;
3432 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3433 PRINTERNAME(snum), acl->num_aces));
3435 for (i = 0; i < acl->num_aces; i++) {
3438 sid_to_string(sid_str, &acl->ace[i].sid);
3440 DEBUG(10, ("%s 0x%08x\n", sid_str,
3441 acl->ace[i].info.mask));
3444 acl = secdesc_ctr->sec->dacl;
3447 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3448 PRINTERNAME(snum), acl->num_aces));
3450 for (i = 0; i < acl->num_aces; i++) {
3453 sid_to_string(sid_str, &acl->ace[i].sid);
3455 DEBUG(10, ("%s 0x%08x\n", sid_str,
3456 acl->ace[i].info.mask));
3459 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3463 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3465 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3466 result = NT_STATUS_NO_PROBLEMO;
3470 /* Work out which user is performing the operation */
3472 get_current_user(&user, p);
3474 /* Check the user has permissions to change the security
3475 descriptor. By experimentation with two NT machines, the user
3476 requires Full Access to the printer to change security
3479 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3480 result = ERROR_ACCESS_DENIED;
3484 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3487 free_sec_desc_buf(&new_secdesc_ctr);
3488 free_sec_desc_buf(&old_secdesc_ctr);
3493 /********************************************************************
3494 Do Samba sanity checks on a printer info struct.
3495 this has changed purpose: it now "canonicalises" printer
3496 info from a client rather than just checking it is correct
3497 ********************************************************************/
3499 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3501 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3502 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3504 /* we force some elements to "correct" values */
3505 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3506 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3507 global_myname, lp_servicename(snum));
3508 fstrcpy(info->sharename, lp_servicename(snum));
3509 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3510 | PRINTER_ATTRIBUTE_LOCAL \
3511 | PRINTER_ATTRIBUTE_RAW_ONLY \
3512 | PRINTER_ATTRIBUTE_QUEUED ;
3517 /****************************************************************************
3518 ****************************************************************************/
3519 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3521 pid_t local_pid = sys_getpid();
3522 char *cmd = lp_addprinter_cmd();
3527 pstring driverlocation;
3531 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3532 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3536 /* build driver path... only 9X architecture is needed for legacy reasons */
3537 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3539 /* change \ to \\ for the shell */
3540 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3542 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3543 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3544 cmd, printer->info_2->printername, printer->info_2->sharename,
3545 printer->info_2->portname, printer->info_2->drivername,
3546 printer->info_2->location, driverlocation);
3549 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3550 ret = smbrun(command, tmp_file, False);
3551 DEBUGADD(10,("returned [%d]\n", ret));
3559 qlines = file_lines_load(tmp_file, &numlines, True);
3560 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3561 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3565 /* Set the portname to what the script says the portname should be. */
3566 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3567 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3569 /* Send SIGHUP to process group... is there a better way? */
3574 file_lines_free(qlines);
3578 /* Return true if two devicemodes are equal */
3580 #define DEVMODE_CHECK_INT(field) \
3581 if (d1->field != d2->field) { \
3582 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3583 d1->field, d2->field)); \
3587 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3589 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
3592 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3593 return False; /* if either is exclusively NULL are not equal */
3596 if (!strequal(d1->devicename, d2->devicename) ||
3597 !strequal(d1->formname, d2->formname)) {
3598 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3602 DEVMODE_CHECK_INT(specversion);
3603 DEVMODE_CHECK_INT(driverversion);
3604 DEVMODE_CHECK_INT(driverextra);
3605 DEVMODE_CHECK_INT(orientation);
3606 DEVMODE_CHECK_INT(papersize);
3607 DEVMODE_CHECK_INT(paperlength);
3608 DEVMODE_CHECK_INT(paperwidth);
3609 DEVMODE_CHECK_INT(scale);
3610 DEVMODE_CHECK_INT(copies);
3611 DEVMODE_CHECK_INT(defaultsource);
3612 DEVMODE_CHECK_INT(printquality);
3613 DEVMODE_CHECK_INT(color);
3614 DEVMODE_CHECK_INT(duplex);
3615 DEVMODE_CHECK_INT(yresolution);
3616 DEVMODE_CHECK_INT(ttoption);
3617 DEVMODE_CHECK_INT(collate);
3618 DEVMODE_CHECK_INT(logpixels);
3620 DEVMODE_CHECK_INT(fields);
3621 DEVMODE_CHECK_INT(bitsperpel);
3622 DEVMODE_CHECK_INT(pelswidth);
3623 DEVMODE_CHECK_INT(pelsheight);
3624 DEVMODE_CHECK_INT(displayflags);
3625 DEVMODE_CHECK_INT(displayfrequency);
3626 DEVMODE_CHECK_INT(icmmethod);
3627 DEVMODE_CHECK_INT(icmintent);
3628 DEVMODE_CHECK_INT(mediatype);
3629 DEVMODE_CHECK_INT(dithertype);
3630 DEVMODE_CHECK_INT(reserved1);
3631 DEVMODE_CHECK_INT(reserved2);
3632 DEVMODE_CHECK_INT(panningwidth);
3633 DEVMODE_CHECK_INT(panningheight);
3635 /* compare the private data if it exists */
3636 if (!d1->driverextra && !d2->driverextra) goto equal;
3639 DEVMODE_CHECK_INT(driverextra);
3641 if (memcmp(d1->private, d2->private, d1->driverextra)) {
3642 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
3647 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
3651 /* Return true if two NT_PRINTER_PARAM structures are equal */
3653 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3654 NT_PRINTER_PARAM *p2)
3656 if (!p1 && !p2) goto equal;
3658 if ((!p1 && p2) || (p1 && !p2)) {
3659 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
3663 /* Compare lists of printer parameters */
3667 NT_PRINTER_PARAM *q = p1;
3669 /* Find the parameter in the second structure */
3673 if (strequal(p1->value, q->value)) {
3675 if (p1->type != q->type) {
3676 DEBUG(10, ("nt_printer_param_equal():"
3677 "types for %s differ (%d != %d)\n",
3678 p1->value, p1->type,
3683 if (p1->data_len != q->data_len) {
3684 DEBUG(10, ("nt_printer_param_equal():"
3685 "len for %s differs (%d != %d)\n",
3686 p1->value, p1->data_len,
3691 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
3694 DEBUG(10, ("nt_printer_param_equal():"
3695 "data for %s differs\n", p1->value));
3705 DEBUG(10, ("nt_printer_param_equal(): param %s "
3706 "does not exist\n", p1->value));
3715 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
3719 /********************************************************************
3720 * Called by update_printer when trying to work out whether to
3721 * actually update printer info.
3722 ********************************************************************/
3724 #define PI_CHECK_INT(field) \
3725 if (pi1->field != pi2->field) { \
3726 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
3727 pi1->field, pi2->field)); \
3731 #define PI_CHECK_STR(field) \
3732 if (!strequal(pi1->field, pi2->field)) { \
3733 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
3734 pi1->field, pi2->field)); \
3738 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3739 NT_PRINTER_INFO_LEVEL *p2)
3741 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3743 /* Trivial conditions */
3745 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3749 if ((!p1 && p2) || (p1 && !p2) ||
3750 (!p1->info_2 && p2->info_2) ||
3751 (p1->info_2 && !p2->info_2)) {
3752 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
3757 /* Compare two nt_printer_info_level structures. Don't compare
3758 status or cjobs as they seem to have something to do with the
3764 PI_CHECK_INT(attributes);
3765 PI_CHECK_INT(priority);
3766 PI_CHECK_INT(default_priority);
3767 PI_CHECK_INT(starttime);
3768 PI_CHECK_INT(untiltime);
3769 PI_CHECK_INT(averageppm);
3771 /* Yuck - don't check the printername or servername as the
3772 add_a_printer() code plays games with them. You can't
3773 change the printername or the sharename through this interface
3776 PI_CHECK_STR(sharename);
3777 PI_CHECK_STR(portname);
3778 PI_CHECK_STR(drivername);
3779 PI_CHECK_STR(comment);
3780 PI_CHECK_STR(location);
3782 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3786 PI_CHECK_STR(sepfile);
3787 PI_CHECK_STR(printprocessor);
3788 PI_CHECK_STR(datatype);
3789 PI_CHECK_STR(parameters);
3791 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3795 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3799 PI_CHECK_INT(changeid);
3800 PI_CHECK_INT(c_setprinter);
3801 PI_CHECK_INT(setuptime);
3804 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
3808 /********************************************************************
3809 * called by spoolss_api_setprinter
3810 * when updating a printer description
3811 ********************************************************************/
3813 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3814 const SPOOL_PRINTER_INFO_LEVEL *info,
3815 DEVICEMODE *devmode)
3818 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3819 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3822 DEBUG(8,("update_printer\n"));
3824 result = NT_STATUS_NO_PROBLEMO;
3827 DEBUG(0,("Send a mail to samba@samba.org\n"));
3828 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3829 result = ERROR_INVALID_LEVEL;
3833 if (!OPEN_HANDLE(Printer)) {
3834 result = ERROR_INVALID_HANDLE;
3838 if (!get_printer_snum(handle, &snum)) {
3839 result = ERROR_INVALID_HANDLE;
3843 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3844 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3845 result = ERROR_INVALID_HANDLE;
3849 DEBUGADD(8,("Converting info_2 struct\n"));
3852 * convert_printer_info converts the incoming
3853 * info from the client and overwrites the info
3854 * just read from the tdb in the pointer 'printer'.
3857 convert_printer_info(info, printer, level);
3859 if (info->info_2->devmode_ptr != 0) {
3860 /* we have a valid devmode
3861 convert it and link it*/
3864 * Ensure printer->info_2->devmode is a valid pointer
3865 * as we will be overwriting it in convert_devicemode().
3868 if (printer->info_2->devmode == NULL)
3869 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3871 DEBUGADD(8,("Converting the devicemode struct\n"));
3872 convert_devicemode(devmode, printer->info_2->devmode);
3875 if (printer->info_2->devmode != NULL)
3876 free_nt_devicemode(&printer->info_2->devmode);
3877 printer->info_2->devmode=NULL;
3880 /* Do sanity check on the requested changes for Samba */
3882 if (!check_printer_ok(printer->info_2, snum)) {
3883 result = ERROR_INVALID_PARAMETER;
3887 /* NT likes to call this function even though nothing has actually
3888 changed. Check this so the user doesn't end up with an
3889 annoying permission denied dialog box. */
3891 if (nt_printer_info_level_equal(printer, old_printer)) {
3892 DEBUG(3, ("printer info has not changed\n"));
3893 result = NT_STATUS_NO_PROBLEMO;
3897 /* Check calling user has permission to update printer description */
3899 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3900 DEBUG(3, ("printer property change denied by security "
3902 result = ERROR_ACCESS_DENIED;
3906 /* Call addprinter hook */
3908 if (*lp_addprinter_cmd() )
3909 if ( !add_printer_hook(printer) ) {
3910 result = ERROR_ACCESS_DENIED;
3914 /* Update printer info */
3916 if (add_a_printer(*printer, 2)!=0) {
3917 /* I don't really know what to return here !!! */
3918 result = ERROR_ACCESS_DENIED;
3923 free_a_printer(&printer, 2);
3924 free_a_printer(&old_printer, 2);
3926 srv_spoolss_sendnotify(handle);
3931 /****************************************************************************
3932 ****************************************************************************/
3933 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3934 const SPOOL_PRINTER_INFO_LEVEL *info,
3935 DEVMODE_CTR devmode_ctr,
3936 SEC_DESC_BUF *secdesc_ctr,
3937 uint32 command, pipes_struct *p)
3939 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3941 if (!OPEN_HANDLE(Printer)) {
3942 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3943 return ERROR_INVALID_HANDLE;
3946 /* check the level */
3949 return control_printer(handle, command, p);
3951 return update_printer(handle, level, info, devmode_ctr.devmode);
3953 return update_printer_sec(handle, level, info, p,
3956 return ERROR_INVALID_LEVEL;
3960 /****************************************************************************
3961 ****************************************************************************/
3962 uint32 _spoolss_fcpn(POLICY_HND *handle)
3964 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3966 if (!OPEN_HANDLE(Printer)) {
3967 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3968 return ERROR_INVALID_HANDLE;
3971 if (Printer->notify.client_connected==True)
3972 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3973 return ERROR_INVALID_HANDLE;
3975 Printer->notify.flags=0;
3976 Printer->notify.options=0;
3977 Printer->notify.localmachine[0]='\0';
3978 Printer->notify.printerlocal=0;
3979 if (Printer->notify.option)
3980 safe_free(Printer->notify.option->ctr.type);
3981 safe_free(Printer->notify.option);
3982 Printer->notify.option=NULL;
3983 Printer->notify.client_connected=False;
3985 return NT_STATUS_NO_PROBLEMO;
3988 /****************************************************************************
3989 ****************************************************************************/
3990 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3991 NEW_BUFFER *buffer, uint32 offered,
3995 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3996 returns for AddJob. AddJob
3997 must fail on non-local
4001 /****************************************************************************
4002 ****************************************************************************/
4003 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4004 int position, int snum)
4010 t=gmtime(&queue->time);
4011 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4013 job_info->jobid=queue->job;
4014 init_unistr(&job_info->printername, lp_servicename(snum));
4015 init_unistr(&job_info->machinename, temp_name);
4016 init_unistr(&job_info->username, queue->user);
4017 init_unistr(&job_info->document, queue->file);
4018 init_unistr(&job_info->datatype, "RAW");
4019 init_unistr(&job_info->text_status, "");
4020 job_info->status=nt_printj_status(queue->status);
4021 job_info->priority=queue->priority;
4022 job_info->position=position;
4023 job_info->totalpages=0;
4024 job_info->pagesprinted=0;
4026 make_systemtime(&job_info->submitted, t);
4029 /****************************************************************************
4030 ****************************************************************************/
4031 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4032 int position, int snum)
4035 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4039 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
4042 t=gmtime(&queue->time);
4043 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4045 job_info->jobid=queue->job;
4047 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4049 init_unistr(&job_info->printername, chaine);
4051 init_unistr(&job_info->machinename, temp_name);
4052 init_unistr(&job_info->username, queue->user);
4053 init_unistr(&job_info->document, queue->file);
4054 init_unistr(&job_info->notifyname, queue->user);
4055 init_unistr(&job_info->datatype, "RAW");
4056 init_unistr(&job_info->printprocessor, "winprint");
4057 init_unistr(&job_info->parameters, "");
4058 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4059 init_unistr(&job_info->text_status, "");
4061 /* and here the security descriptor */
4063 job_info->status=nt_printj_status(queue->status);
4064 job_info->priority=queue->priority;
4065 job_info->position=position;
4066 job_info->starttime=0;
4067 job_info->untiltime=0;
4068 job_info->totalpages=0;
4069 job_info->size=queue->size;
4070 make_systemtime(&(job_info->submitted), t);
4071 job_info->timeelapsed=0;
4072 job_info->pagesprinted=0;
4074 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4075 free_a_printer(&ntprinter, 2);
4079 free_a_printer(&ntprinter, 2);
4083 /****************************************************************************
4084 Enumjobs at level 1.
4085 ****************************************************************************/
4086 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4087 NEW_BUFFER *buffer, uint32 offered,
4088 uint32 *needed, uint32 *returned)
4093 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4097 return ERROR_NOT_ENOUGH_MEMORY;
4100 for (i=0; i<*returned; i++)
4101 fill_job_info_1(&info[i], &queue[i], i, snum);
4105 /* check the required size. */
4106 for (i=0; i<*returned; i++)
4107 (*needed) += spoolss_size_job_info_1(&info[i]);
4109 if (!alloc_buffer_size(buffer, *needed)) {
4111 return ERROR_INSUFFICIENT_BUFFER;
4114 /* fill the buffer with the structures */
4115 for (i=0; i<*returned; i++)
4116 new_smb_io_job_info_1("", buffer, &info[i], 0);
4121 if (*needed > offered) {
4123 return ERROR_INSUFFICIENT_BUFFER;
4126 return NT_STATUS_NO_PROBLEMO;
4129 /****************************************************************************
4130 Enumjobs at level 2.
4131 ****************************************************************************/
4132 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4133 NEW_BUFFER *buffer, uint32 offered,
4134 uint32 *needed, uint32 *returned)
4139 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4143 return ERROR_NOT_ENOUGH_MEMORY;
4146 for (i=0; i<*returned; i++)
4147 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4151 /* check the required size. */
4152 for (i=0; i<*returned; i++)
4153 (*needed) += spoolss_size_job_info_2(&info[i]);
4155 if (!alloc_buffer_size(buffer, *needed)) {
4157 return ERROR_INSUFFICIENT_BUFFER;
4160 /* fill the buffer with the structures */
4161 for (i=0; i<*returned; i++)
4162 new_smb_io_job_info_2("", buffer, &info[i], 0);
4165 free_job_info_2(info);
4167 if (*needed > offered) {
4169 return ERROR_INSUFFICIENT_BUFFER;
4172 return NT_STATUS_NO_PROBLEMO;
4175 /****************************************************************************
4177 ****************************************************************************/
4178 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4179 NEW_BUFFER *buffer, uint32 offered,
4180 uint32 *needed, uint32 *returned)
4183 print_queue_struct *queue=NULL;
4184 print_status_struct prt_status;
4186 DEBUG(4,("_spoolss_enumjobs\n"));
4188 ZERO_STRUCT(prt_status);
4193 if (!get_printer_snum(handle, &snum))
4194 return ERROR_INVALID_HANDLE;
4196 *returned = print_queue_status(snum, &queue, &prt_status);
4197 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4199 if (*returned == 0) {
4201 return NT_STATUS_NO_PROBLEMO;
4206 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4208 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4212 return ERROR_INVALID_LEVEL;
4217 /****************************************************************************
4218 ****************************************************************************/
4219 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4224 /****************************************************************************
4225 ****************************************************************************/
4226 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4227 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4229 struct current_user user;
4230 print_status_struct prt_status;
4231 int snum, errcode = ERROR_INVALID_FUNCTION;
4233 memset(&prt_status, 0, sizeof(prt_status));
4235 if (!get_printer_snum(handle, &snum)) {
4236 return ERROR_INVALID_HANDLE;
4239 if (!print_job_exists(jobid)) {
4240 return ERROR_INVALID_PRINTER_NAME;
4243 get_current_user(&user, p);
4246 case JOB_CONTROL_CANCEL:
4247 case JOB_CONTROL_DELETE:
4248 if (print_job_delete(&user, jobid, &errcode)) {
4252 case JOB_CONTROL_PAUSE:
4253 if (print_job_pause(&user, jobid, &errcode)) {
4257 case JOB_CONTROL_RESTART:
4258 case JOB_CONTROL_RESUME:
4259 if (print_job_resume(&user, jobid, &errcode)) {
4264 return ERROR_INVALID_LEVEL;
4270 /****************************************************************************
4271 Enumerates all printer drivers at level 1.
4272 ****************************************************************************/
4273 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4278 fstring *list = NULL;
4280 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4281 DRIVER_INFO_1 *driver_info_1=NULL;
4285 #define MAX_VERSION 4
4287 for (version=0; version<MAX_VERSION; version++) {
4289 ndrivers=get_ntdrivers(&list, architecture, version);
4290 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4293 return ERROR_NOT_ENOUGH_MEMORY;
4296 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4298 return ERROR_NOT_ENOUGH_MEMORY;
4302 for (i=0; i<ndrivers; i++) {
4304 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4305 ZERO_STRUCT(driver);
4306 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4310 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4311 free_a_printer_driver(driver, 3);
4314 *returned+=ndrivers;
4318 /* check the required size. */
4319 for (i=0; i<*returned; i++) {
4320 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4321 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4324 if (!alloc_buffer_size(buffer, *needed)) {
4325 safe_free(driver_info_1);
4326 return ERROR_INSUFFICIENT_BUFFER;
4329 /* fill the buffer with the form structures */
4330 for (i=0; i<*returned; i++) {
4331 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4332 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4335 safe_free(driver_info_1);
4337 if (*needed > offered) {
4339 return ERROR_INSUFFICIENT_BUFFER;
4342 return NT_STATUS_NO_PROBLEMO;
4345 /****************************************************************************
4346 Enumerates all printer drivers at level 2.
4347 ****************************************************************************/
4348 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4353 fstring *list = NULL;
4355 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4356 DRIVER_INFO_2 *driver_info_2=NULL;
4360 #define MAX_VERSION 4
4362 for (version=0; version<MAX_VERSION; version++) {
4364 ndrivers=get_ntdrivers(&list, architecture, version);
4365 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4368 return ERROR_NOT_ENOUGH_MEMORY;
4371 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4373 return ERROR_NOT_ENOUGH_MEMORY;
4377 for (i=0; i<ndrivers; i++) {
4380 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4381 ZERO_STRUCT(driver);
4382 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4386 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4387 free_a_printer_driver(driver, 3);
4390 *returned+=ndrivers;
4394 /* check the required size. */
4395 for (i=0; i<*returned; i++) {
4396 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4397 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4400 if (!alloc_buffer_size(buffer, *needed)) {
4401 safe_free(driver_info_2);
4402 return ERROR_INSUFFICIENT_BUFFER;
4405 /* fill the buffer with the form structures */
4406 for (i=0; i<*returned; i++) {
4407 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4408 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4411 safe_free(driver_info_2);
4413 if (*needed > offered) {
4415 return ERROR_INSUFFICIENT_BUFFER;
4418 return NT_STATUS_NO_PROBLEMO;
4421 /****************************************************************************
4422 Enumerates all printer drivers at level 3.
4423 ****************************************************************************/
4424 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4429 fstring *list = NULL;
4431 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4432 DRIVER_INFO_3 *driver_info_3=NULL;
4436 #define MAX_VERSION 4
4438 for (version=0; version<MAX_VERSION; version++) {
4440 ndrivers=get_ntdrivers(&list, architecture, version);
4441 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4444 return ERROR_NOT_ENOUGH_MEMORY;
4447 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4449 return ERROR_NOT_ENOUGH_MEMORY;
4453 for (i=0; i<ndrivers; i++) {
4456 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4457 ZERO_STRUCT(driver);
4458 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4462 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4463 free_a_printer_driver(driver, 3);
4466 *returned+=ndrivers;
4470 /* check the required size. */
4471 for (i=0; i<*returned; i++) {
4472 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4473 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4476 if (!alloc_buffer_size(buffer, *needed)) {
4477 safe_free(driver_info_3);
4478 return ERROR_INSUFFICIENT_BUFFER;
4481 /* fill the buffer with the driver structures */
4482 for (i=0; i<*returned; i++) {
4483 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4484 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4487 for (i=0; i<*returned; i++)
4488 safe_free(driver_info_3[i].dependentfiles);
4490 safe_free(driver_info_3);
4492 if (*needed > offered) {
4494 return ERROR_INSUFFICIENT_BUFFER;
4497 return NT_STATUS_NO_PROBLEMO;
4500 /****************************************************************************
4501 Enumerates all printer drivers.
4502 ****************************************************************************/
4503 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4504 NEW_BUFFER *buffer, uint32 offered,
4505 uint32 *needed, uint32 *returned)
4507 fstring *list = NULL;
4509 fstring architecture;
4511 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4512 fstrcpy(servername, global_myname);
4516 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4520 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4522 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4524 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4528 return ERROR_INVALID_LEVEL;
4532 /****************************************************************************
4533 ****************************************************************************/
4534 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4536 form->flag=list->flag;
4537 init_unistr(&form->name, list->name);
4538 form->width=list->width;
4539 form->length=list->length;
4540 form->left=list->left;
4541 form->top=list->top;
4542 form->right=list->right;
4543 form->bottom=list->bottom;
4546 /****************************************************************************
4547 ****************************************************************************/
4548 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4549 NEW_BUFFER *buffer, uint32 offered,
4550 uint32 *needed, uint32 *numofforms)
4552 nt_forms_struct *list=NULL;
4557 DEBUG(4,("_new_spoolss_enumforms\n"));
4558 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4559 DEBUGADD(5,("Info level [%d]\n", level));
4561 *numofforms = get_ntforms(&list);
4562 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4564 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4568 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4570 return ERROR_NOT_ENOUGH_MEMORY;
4573 /* construct the list of form structures */
4574 for (i=0; i<*numofforms; i++) {
4575 DEBUGADD(6,("Filling form number [%d]\n",i));
4576 fill_form_1(&forms_1[i], &list[i]);
4581 /* check the required size. */
4582 for (i=0; i<*numofforms; i++) {
4583 DEBUGADD(6,("adding form [%d]'s size\n",i));
4584 buffer_size += spoolss_size_form_1(&forms_1[i]);
4587 *needed=buffer_size;
4589 if (!alloc_buffer_size(buffer, buffer_size)){
4591 return ERROR_INSUFFICIENT_BUFFER;
4594 /* fill the buffer with the form structures */
4595 for (i=0; i<*numofforms; i++) {
4596 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4597 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4602 if (*needed > offered) {
4604 return ERROR_INSUFFICIENT_BUFFER;
4607 return NT_STATUS_NO_PROBLEMO;
4611 return ERROR_INVALID_LEVEL;
4616 /****************************************************************************
4617 ****************************************************************************/
4618 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4620 nt_forms_struct *list=NULL;
4626 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4628 DEBUG(4,("_spoolss_getform\n"));
4629 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4630 DEBUGADD(5,("Info level [%d]\n", level));
4632 numofforms = get_ntforms(&list);
4633 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4635 if (numofforms == 0)
4636 return ERROR_NO_MORE_ITEMS;
4641 /* Check if the requested name is in the list of form structures */
4642 for (i=0; i<numofforms; i++) {
4644 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4646 if (strequal(form_name, list[i].name)) {
4647 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4648 fill_form_1(&form_1, &list[i]);
4655 /* check the required size. */
4657 *needed=spoolss_size_form_1(&form_1);
4659 if (!alloc_buffer_size(buffer, buffer_size)){
4660 return ERROR_INSUFFICIENT_BUFFER;
4663 if (*needed > offered) {
4664 return ERROR_INSUFFICIENT_BUFFER;
4667 /* fill the buffer with the form structures */
4668 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4669 new_smb_io_form_1("", buffer, &form_1, 0);
4671 return NT_STATUS_NO_PROBLEMO;
4675 return ERROR_INVALID_LEVEL;
4679 /****************************************************************************
4680 ****************************************************************************/
4681 static void fill_port_1(PORT_INFO_1 *port, char *name)
4683 init_unistr(&port->port_name, name);
4686 /****************************************************************************
4687 ****************************************************************************/
4688 static void fill_port_2(PORT_INFO_2 *port, char *name)
4690 init_unistr(&port->port_name, name);
4691 init_unistr(&port->monitor_name, "Local Monitor");
4692 init_unistr(&port->description, "Local Port");
4693 #define PORT_TYPE_WRITE 1
4694 port->port_type=PORT_TYPE_WRITE;
4698 /****************************************************************************
4700 ****************************************************************************/
4701 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4703 PORT_INFO_1 *ports=NULL;
4706 if (*lp_enumports_cmd()) {
4707 pid_t local_pid = sys_getpid();
4708 char *cmd = lp_enumports_cmd();
4716 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4717 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4721 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4722 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4725 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4726 ret = smbrun(command, tmp_file, False);
4727 DEBUG(10,("Returned [%d]\n", ret));
4730 /* Is this the best error to return here? */
4731 return ERROR_ACCESS_DENIED;
4735 qlines = file_lines_load(tmp_file, &numlines,True);
4736 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4737 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4741 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4742 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4743 file_lines_free(qlines);
4744 return ERROR_NOT_ENOUGH_MEMORY;
4747 for (i=0; i<numlines; i++) {
4748 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4749 fill_port_1(&ports[i], qlines[i]);
4752 file_lines_free(qlines);
4755 *returned = numlines;
4758 *returned = 1; /* Sole Samba port returned. */
4760 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4761 return ERROR_NOT_ENOUGH_MEMORY;
4763 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4765 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4768 /* check the required size. */
4769 for (i=0; i<*returned; i++) {
4770 DEBUGADD(6,("adding port [%d]'s size\n", i));
4771 *needed += spoolss_size_port_info_1(&ports[i]);
4774 if (!alloc_buffer_size(buffer, *needed)) {
4776 return ERROR_INSUFFICIENT_BUFFER;
4779 /* fill the buffer with the ports structures */
4780 for (i=0; i<*returned; i++) {
4781 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4782 new_smb_io_port_1("", buffer, &ports[i], 0);
4787 if (*needed > offered) {
4789 return ERROR_INSUFFICIENT_BUFFER;
4792 return NT_STATUS_NO_PROBLEMO;
4795 /****************************************************************************
4797 ****************************************************************************/
4799 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4801 PORT_INFO_2 *ports=NULL;
4804 if (*lp_enumports_cmd()) {
4805 pid_t local_pid = sys_getpid();
4806 char *cmd = lp_enumports_cmd();
4814 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4815 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4819 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4820 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4823 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4824 ret = smbrun(command, tmp_file, False);
4825 DEBUGADD(10,("returned [%d]\n", ret));
4828 /* Is this the best error to return here? */
4829 return ERROR_ACCESS_DENIED;
4833 qlines = file_lines_load(tmp_file, &numlines,True);
4834 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4835 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4839 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4840 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4841 file_lines_free(qlines);
4842 return ERROR_NOT_ENOUGH_MEMORY;
4845 for (i=0; i<numlines; i++) {
4846 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4847 fill_port_2(&(ports[i]), qlines[i]);
4850 file_lines_free(qlines);
4853 *returned = numlines;
4859 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4860 return ERROR_NOT_ENOUGH_MEMORY;
4862 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4864 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4867 /* check the required size. */
4868 for (i=0; i<*returned; i++) {
4869 DEBUGADD(6,("adding port [%d]'s size\n", i));
4870 *needed += spoolss_size_port_info_2(&ports[i]);
4873 if (!alloc_buffer_size(buffer, *needed)) {
4875 return ERROR_INSUFFICIENT_BUFFER;
4878 /* fill the buffer with the ports structures */
4879 for (i=0; i<*returned; i++) {
4880 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4881 new_smb_io_port_2("", buffer, &ports[i], 0);
4886 if (*needed > offered) {
4888 return ERROR_INSUFFICIENT_BUFFER;
4891 return NT_STATUS_NO_PROBLEMO;
4894 /****************************************************************************
4896 ****************************************************************************/
4897 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4898 NEW_BUFFER *buffer, uint32 offered,
4899 uint32 *needed, uint32 *returned)
4901 DEBUG(4,("_spoolss_enumports\n"));
4908 return enumports_level_1(buffer, offered, needed, returned);
4910 return enumports_level_2(buffer, offered, needed, returned);
4912 return ERROR_INVALID_LEVEL;
4916 /****************************************************************************
4917 ****************************************************************************/
4918 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4919 const SPOOL_PRINTER_INFO_LEVEL *info,
4920 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4921 uint32 user_switch, const SPOOL_USER_CTR *user,
4924 NT_PRINTER_INFO_LEVEL *printer = NULL;
4928 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4929 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4930 return ERROR_NOT_ENOUGH_MEMORY;
4933 ZERO_STRUCTP(printer);
4935 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4936 convert_printer_info(info, printer, 2);
4938 if (*lp_addprinter_cmd() )
4939 if ( !add_printer_hook(printer) ) {
4940 free_a_printer(&printer,2);
4941 return ERROR_ACCESS_DENIED;
4944 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4945 printer->info_2->sharename);
4947 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4948 free_a_printer(&printer,2);
4949 return ERROR_ACCESS_DENIED;
4952 /* you must be a printer admin to add a new printer */
4953 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4954 free_a_printer(&printer,2);
4955 return ERROR_ACCESS_DENIED;
4959 * Do sanity check on the requested changes for Samba.
4962 if (!check_printer_ok(printer->info_2, snum)) {
4963 free_a_printer(&printer,2);
4964 return ERROR_INVALID_PARAMETER;
4967 /* write the ASCII on disk */
4968 if (add_a_printer(*printer, 2) != 0) {
4969 free_a_printer(&printer,2);
4970 return ERROR_ACCESS_DENIED;
4973 if (!open_printer_hnd(handle, name)) {
4974 /* Handle open failed - remove addition. */
4975 del_a_printer(printer->info_2->sharename);
4976 free_a_printer(&printer,2);
4977 return ERROR_ACCESS_DENIED;
4980 free_a_printer(&printer,2);
4982 srv_spoolss_sendnotify(handle);
4984 return NT_STATUS_NO_PROBLEMO;
4987 /****************************************************************************
4988 ****************************************************************************/
4989 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4990 const SPOOL_PRINTER_INFO_LEVEL *info,
4991 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4992 uint32 user_switch, const SPOOL_USER_CTR *user,
4997 /* we don't handle yet */
4998 /* but I know what to do ... */
4999 return ERROR_INVALID_LEVEL;
5001 return spoolss_addprinterex_level_2(uni_srv_name, info,
5002 unk0, unk1, unk2, unk3,
5003 user_switch, user, handle);
5005 return ERROR_INVALID_LEVEL;
5009 /****************************************************************************
5010 ****************************************************************************/
5011 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5012 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5014 uint32 err = NT_STATUS_NO_PROBLEMO;
5015 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5016 struct current_user user;
5018 ZERO_STRUCT(driver);
5020 get_current_user(&user, p);
5022 convert_printer_driver_info(info, &driver, level);
5024 DEBUG(5,("Cleaning driver's information\n"));
5025 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5028 DEBUG(5,("Moving driver to final destination\n"));
5029 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5031 err = ERROR_ACCESS_DENIED;
5035 if (add_a_printer_driver(driver, level)!=0) {
5036 err = ERROR_ACCESS_DENIED;
5041 free_a_printer_driver(driver, level);
5045 /****************************************************************************
5046 ****************************************************************************/
5047 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5049 init_unistr(&info->name, name);
5052 /****************************************************************************
5053 ****************************************************************************/
5054 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5058 pstring short_archi;
5059 DRIVER_DIRECTORY_1 *info=NULL;
5061 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5063 if (get_short_archi(short_archi, long_archi)==FALSE)
5064 return ERROR_INVALID_ENVIRONMENT;
5066 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5067 return ERROR_NOT_ENOUGH_MEMORY;
5069 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5071 DEBUG(4,("printer driver directory: [%s]\n", path));
5073 fill_driverdir_1(info, path);
5075 *needed += spoolss_size_driverdir_info_1(info);
5077 if (!alloc_buffer_size(buffer, *needed)) {
5079 return ERROR_INSUFFICIENT_BUFFER;
5082 new_smb_io_driverdir_1("", buffer, info, 0);
5086 if (*needed > offered)
5087 return ERROR_INSUFFICIENT_BUFFER;
5089 return NT_STATUS_NO_PROBLEMO;
5092 /****************************************************************************
5093 ****************************************************************************/
5094 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5095 NEW_BUFFER *buffer, uint32 offered,
5098 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5104 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5106 return ERROR_INVALID_LEVEL;
5110 /****************************************************************************
5111 ****************************************************************************/
5112 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5113 uint32 in_value_len, uint32 in_data_len,
5114 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5116 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5118 NT_PRINTER_INFO_LEVEL *printer = NULL;
5123 uint32 biggest_valuesize;
5124 uint32 biggest_datasize;
5126 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5131 ZERO_STRUCT(printer);
5133 *out_max_value_len=0;
5139 *out_max_data_len=0;
5143 DEBUG(5,("spoolss_enumprinterdata\n"));
5145 if (!OPEN_HANDLE(Printer)) {
5146 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5147 return ERROR_INVALID_HANDLE;
5150 if (!get_printer_snum(handle, &snum))
5151 return ERROR_INVALID_HANDLE;
5153 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5154 return ERROR_INVALID_HANDLE;
5157 * The NT machine wants to know the biggest size of value and data
5159 * cf: MSDN EnumPrinterData remark section
5161 if ( (in_value_len==0) && (in_data_len==0) ) {
5162 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5166 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5167 * if this parameter size doesn't exist.
5168 * Ok - my opinion here is that the client is not asking for the greatest
5169 * possible size of all the parameters, but is asking specifically for the size needed
5170 * for this specific parameter. In that case we can remove the loop below and
5171 * simplify this lookup code considerably. JF - comments welcome. JRA.
5174 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5176 free_a_printer(&printer, 2);
5177 return ERROR_NO_MORE_ITEMS;
5185 biggest_valuesize=0;
5188 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5189 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5190 if (data_len > biggest_datasize) biggest_datasize=data_len;
5192 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5200 * I think this is correct, it doesn't break APW and
5201 * allows Gerald's Win32 test programs to work correctly,
5202 * but may need altering.... JRA.
5205 if (param_index == 0) {
5206 /* No parameters found. */
5207 free_a_printer(&printer, 2);
5208 return ERROR_NO_MORE_ITEMS;
5211 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5212 *out_value_len=2*(1+biggest_valuesize);
5213 *out_data_len=biggest_datasize;
5215 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5217 free_a_printer(&printer, 2);
5218 return NT_STATUS_NO_PROBLEMO;
5222 * the value len is wrong in NT sp3
5223 * that's the number of bytes not the number of unicode chars
5226 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5228 free_a_printer(&printer, 2);
5229 return ERROR_NO_MORE_ITEMS;
5232 free_a_printer(&printer, 2);
5236 * - counted in bytes in the request
5237 * - counted in UNICODE chars in the max reply
5238 * - counted in bytes in the real size
5240 * take a pause *before* coding not *during* coding
5243 *out_max_value_len=(in_value_len/sizeof(uint16));
5244 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5246 return ERROR_NOT_ENOUGH_MEMORY;
5249 ZERO_STRUCTP(*out_value);
5250 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5254 /* the data is counted in bytes */
5255 *out_max_data_len=in_data_len;
5256 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5258 return ERROR_NOT_ENOUGH_MEMORY;
5261 memset(*data_out,'\0',in_data_len);
5262 memcpy(*data_out, data, (size_t)data_len);
5263 *out_data_len=data_len;
5267 return NT_STATUS_NO_PROBLEMO;
5270 /****************************************************************************
5271 ****************************************************************************/
5272 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5273 const UNISTR2 *value,
5278 uint32 numeric_data)
5280 NT_PRINTER_INFO_LEVEL *printer = NULL;
5281 NT_PRINTER_PARAM *param = NULL, old_param;
5283 uint32 status = 0x0;
5284 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5286 DEBUG(5,("spoolss_setprinterdata\n"));
5288 if (!OPEN_HANDLE(Printer)) {
5289 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5290 return ERROR_INVALID_HANDLE;
5293 if (!get_printer_snum(handle, &snum))
5294 return ERROR_INVALID_HANDLE;
5296 status = get_a_printer(&printer, 2, lp_servicename(snum));
5298 return ERROR_INVALID_NAME;
5300 convert_specific_param(¶m, value , type, data, real_len);
5302 /* Check if we are making any changes or not. Return true if
5303 nothing is actually changing. */
5305 ZERO_STRUCT(old_param);
5307 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5308 &old_param.type, (unsigned int *)&old_param.data_len)) {
5310 if (param->type == old_param.type &&
5311 param->data_len == old_param.data_len &&
5312 memcmp(param->data, old_param.data,
5313 old_param.data_len) == 0) {
5315 DEBUG(3, ("setprinterdata hasn't changed\n"));
5316 status = NT_STATUS_NO_PROBLEMO;
5323 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5324 DEBUG(3, ("security descriptor change denied by existing "
5325 "security descriptor\n"));
5326 status = ERROR_ACCESS_DENIED;
5330 unlink_specific_param_if_exist(printer->info_2, param);
5332 add_a_specific_param(printer->info_2, ¶m);
5333 status = mod_a_printer(*printer, 2);
5336 free_a_printer(&printer, 2);
5338 free_nt_printer_param(¶m);
5339 safe_free(old_param.data);
5344 /****************************************************************************
5345 ****************************************************************************/
5346 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5348 NT_PRINTER_INFO_LEVEL *printer = NULL;
5349 NT_PRINTER_PARAM param;
5351 uint32 status = 0x0;
5352 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5354 DEBUG(5,("spoolss_deleteprinterdata\n"));
5356 if (!OPEN_HANDLE(Printer)) {
5357 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5358 return ERROR_INVALID_HANDLE;
5361 if (!get_printer_snum(handle, &snum))
5362 return ERROR_INVALID_HANDLE;
5364 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5365 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5366 "security descriptor\n"));
5367 return ERROR_ACCESS_DENIED;
5370 status = get_a_printer(&printer, 2, lp_servicename(snum));
5372 return ERROR_INVALID_NAME;
5374 ZERO_STRUCTP(¶m);
5375 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5377 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5378 status = ERROR_INVALID_PARAMETER;
5380 status = mod_a_printer(*printer, 2);
5382 free_a_printer(&printer, 2);
5386 /****************************************************************************
5387 ****************************************************************************/
5388 uint32 _spoolss_addform( POLICY_HND *handle,
5393 nt_forms_struct *list=NULL;
5394 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5396 DEBUG(5,("spoolss_addform\n"));
5398 if (!OPEN_HANDLE(Printer)) {
5399 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5400 return ERROR_INVALID_HANDLE;
5403 count=get_ntforms(&list);
5404 if(!add_a_form(&list, form, &count))
5405 return ERROR_NOT_ENOUGH_MEMORY;
5406 write_ntforms(&list, count);
5413 /****************************************************************************
5414 ****************************************************************************/
5415 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5419 nt_forms_struct *list=NULL;
5420 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5422 DEBUG(5,("spoolss_deleteform\n"));
5424 if (!OPEN_HANDLE(Printer)) {
5425 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5426 return ERROR_INVALID_HANDLE;
5429 count = get_ntforms(&list);
5430 if(!delete_a_form(&list, form_name, &count, &ret))
5431 return ERROR_INVALID_PARAMETER;
5438 /****************************************************************************
5439 ****************************************************************************/
5440 uint32 _spoolss_setform( POLICY_HND *handle,
5441 const UNISTR2 *uni_name,
5446 nt_forms_struct *list=NULL;
5447 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5449 DEBUG(5,("spoolss_setform\n"));
5451 if (!OPEN_HANDLE(Printer)) {
5452 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5453 return ERROR_INVALID_HANDLE;
5455 count=get_ntforms(&list);
5456 update_a_form(&list, form, count);
5457 write_ntforms(&list, count);
5464 /****************************************************************************
5465 enumprintprocessors level 1.
5466 ****************************************************************************/
5467 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5469 PRINTPROCESSOR_1 *info_1=NULL;
5471 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5472 return ERROR_NOT_ENOUGH_MEMORY;
5476 init_unistr(&info_1->name, "winprint");
5478 *needed += spoolss_size_printprocessor_info_1(info_1);
5480 if (!alloc_buffer_size(buffer, *needed))
5481 return ERROR_INSUFFICIENT_BUFFER;
5483 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5487 if (*needed > offered) {
5489 return ERROR_INSUFFICIENT_BUFFER;
5492 return NT_STATUS_NO_PROBLEMO;
5495 /****************************************************************************
5496 ****************************************************************************/
5497 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5498 NEW_BUFFER *buffer, uint32 offered,
5499 uint32 *needed, uint32 *returned)
5501 DEBUG(5,("spoolss_enumprintprocessors\n"));
5504 * Enumerate the print processors ...
5506 * Just reply with "winprint", to keep NT happy
5507 * and I can use my nice printer checker.
5515 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5517 return ERROR_INVALID_LEVEL;
5521 /****************************************************************************
5522 enumprintprocdatatypes level 1.
5523 ****************************************************************************/
5524 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5526 PRINTPROCDATATYPE_1 *info_1=NULL;
5528 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5529 return ERROR_NOT_ENOUGH_MEMORY;
5533 init_unistr(&info_1->name, "RAW");
5535 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5537 if (!alloc_buffer_size(buffer, *needed))
5538 return ERROR_INSUFFICIENT_BUFFER;
5540 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5544 if (*needed > offered) {
5546 return ERROR_INSUFFICIENT_BUFFER;
5549 return NT_STATUS_NO_PROBLEMO;
5552 /****************************************************************************
5553 ****************************************************************************/
5554 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5555 NEW_BUFFER *buffer, uint32 offered,
5556 uint32 *needed, uint32 *returned)
5558 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5565 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5567 return ERROR_INVALID_LEVEL;
5571 /****************************************************************************
5572 enumprintmonitors level 1.
5573 ****************************************************************************/
5574 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5576 PRINTMONITOR_1 *info_1=NULL;
5578 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5579 return ERROR_NOT_ENOUGH_MEMORY;
5583 init_unistr(&info_1->name, "Local Port");
5585 *needed += spoolss_size_printmonitor_info_1(info_1);
5587 if (!alloc_buffer_size(buffer, *needed))
5588 return ERROR_INSUFFICIENT_BUFFER;
5590 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5594 if (*needed > offered) {
5596 return ERROR_INSUFFICIENT_BUFFER;
5599 return NT_STATUS_NO_PROBLEMO;
5602 /****************************************************************************
5603 enumprintmonitors level 2.
5604 ****************************************************************************/
5605 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5607 PRINTMONITOR_2 *info_2=NULL;
5609 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5610 return ERROR_NOT_ENOUGH_MEMORY;
5614 init_unistr(&info_2->name, "Local Port");
5615 init_unistr(&info_2->environment, "Windows NT X86");
5616 init_unistr(&info_2->dll_name, "localmon.dll");
5618 *needed += spoolss_size_printmonitor_info_2(info_2);
5620 if (!alloc_buffer_size(buffer, *needed))
5621 return ERROR_INSUFFICIENT_BUFFER;
5623 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5627 if (*needed > offered) {
5629 return ERROR_INSUFFICIENT_BUFFER;
5632 return NT_STATUS_NO_PROBLEMO;
5635 /****************************************************************************
5636 ****************************************************************************/
5637 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5638 NEW_BUFFER *buffer, uint32 offered,
5639 uint32 *needed, uint32 *returned)
5641 DEBUG(5,("spoolss_enumprintmonitors\n"));
5644 * Enumerate the print monitors ...
5646 * Just reply with "Local Port", to keep NT happy
5647 * and I can use my nice printer checker.
5655 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5657 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5659 return ERROR_INVALID_LEVEL;
5663 /****************************************************************************
5664 ****************************************************************************/
5665 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5669 JOB_INFO_1 *info_1=NULL;
5671 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5673 if (info_1 == NULL) {
5675 return ERROR_NOT_ENOUGH_MEMORY;
5678 for (i=0; i<count && found==False; i++) {
5679 if (queue[i].job==(int)jobid)
5686 /* I shoud reply something else ... I can't find the good one */
5687 return NT_STATUS_NO_PROBLEMO;
5690 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5694 *needed += spoolss_size_job_info_1(info_1);
5696 if (!alloc_buffer_size(buffer, *needed)) {
5698 return ERROR_INSUFFICIENT_BUFFER;
5701 new_smb_io_job_info_1("", buffer, info_1, 0);
5705 if (*needed > offered)
5706 return ERROR_INSUFFICIENT_BUFFER;
5708 return NT_STATUS_NO_PROBLEMO;
5712 /****************************************************************************
5713 ****************************************************************************/
5714 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5719 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5721 ZERO_STRUCTP(info_2);
5723 if (info_2 == NULL) {
5725 return ERROR_NOT_ENOUGH_MEMORY;
5728 for (i=0; i<count && found==False; i++) {
5729 if (queue[i].job==(int)jobid)
5736 /* I shoud reply something else ... I can't find the good one */
5737 return NT_STATUS_NO_PROBLEMO;
5740 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5744 *needed += spoolss_size_job_info_2(info_2);
5746 if (!alloc_buffer_size(buffer, *needed)) {
5748 return ERROR_INSUFFICIENT_BUFFER;
5751 new_smb_io_job_info_2("", buffer, info_2, 0);
5753 free_job_info_2(info_2);
5755 if (*needed > offered)
5756 return ERROR_INSUFFICIENT_BUFFER;
5758 return NT_STATUS_NO_PROBLEMO;
5761 /****************************************************************************
5762 ****************************************************************************/
5763 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5764 NEW_BUFFER *buffer, uint32 offered,
5769 print_queue_struct *queue=NULL;
5770 print_status_struct prt_status;
5772 DEBUG(5,("spoolss_getjob\n"));
5774 memset(&prt_status, 0, sizeof(prt_status));
5778 if (!get_printer_snum(handle, &snum))
5779 return ERROR_INVALID_HANDLE;
5781 count = print_queue_status(snum, &queue, &prt_status);
5783 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5784 count, prt_status.status, prt_status.message));
5788 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5790 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5793 return ERROR_INVALID_LEVEL;