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)
2745 info->version=driver.info_3->cversion;
2747 init_unistr( &info->name, driver.info_3->name );
2748 init_unistr( &info->architecture, driver.info_3->environment );
2751 if (strlen(driver.info_3->driverpath)) {
2752 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2753 init_unistr( &info->driverpath, temp );
2755 init_unistr( &info->driverpath, "" );
2757 if (strlen(driver.info_3->datafile)) {
2758 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2759 init_unistr( &info->datafile, temp );
2761 init_unistr( &info->datafile, "" );
2763 if (strlen(driver.info_3->configfile)) {
2764 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2765 init_unistr( &info->configfile, temp );
2767 init_unistr( &info->configfile, "" );
2770 /********************************************************************
2771 * construct_printer_driver_info_2
2772 * fill a printer_info_2 struct
2773 ********************************************************************/
2774 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2776 NT_PRINTER_INFO_LEVEL *printer = NULL;
2777 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2779 ZERO_STRUCT(printer);
2780 ZERO_STRUCT(driver);
2782 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2783 return ERROR_INVALID_PRINTER_NAME;
2785 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2786 return ERROR_UNKNOWN_PRINTER_DRIVER;
2788 fill_printer_driver_info_2(info, driver, servername);
2790 free_a_printer(&printer,2);
2792 return NT_STATUS_NO_PROBLEMO;
2795 /********************************************************************
2796 * copy a strings array and convert to UNICODE
2798 * convert an array of ascii string to a UNICODE string
2799 ********************************************************************/
2800 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2807 DEBUG(6,("init_unistr_array\n"));
2811 if (char_array == NULL)
2815 if (!v) v = ""; /* hack to handle null lists */
2817 if (strlen(v) == 0) break;
2818 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2819 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2820 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2821 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2824 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2829 (*uni_array)[j]=0x0000;
2832 DEBUGADD(6,("last one:done\n"));
2835 /********************************************************************
2836 * construct_printer_info_3
2837 * fill a printer_info_3 struct
2838 ********************************************************************/
2839 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2845 info->version=driver.info_3->cversion;
2847 init_unistr( &info->name, driver.info_3->name );
2848 init_unistr( &info->architecture, driver.info_3->environment );
2850 if (strlen(driver.info_3->driverpath)) {
2851 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2852 init_unistr( &info->driverpath, temp );
2854 init_unistr( &info->driverpath, "" );
2856 if (strlen(driver.info_3->datafile)) {
2857 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2858 init_unistr( &info->datafile, temp );
2860 init_unistr( &info->datafile, "" );
2862 if (strlen(driver.info_3->configfile)) {
2863 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2864 init_unistr( &info->configfile, temp );
2866 init_unistr( &info->configfile, "" );
2868 if (strlen(driver.info_3->helpfile)) {
2869 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2870 init_unistr( &info->helpfile, temp );
2872 init_unistr( &info->helpfile, "" );
2874 init_unistr( &info->monitorname, driver.info_3->monitorname );
2875 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2877 info->dependentfiles=NULL;
2878 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2881 /********************************************************************
2882 * construct_printer_info_3
2883 * fill a printer_info_3 struct
2884 ********************************************************************/
2885 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2887 NT_PRINTER_INFO_LEVEL *printer = NULL;
2888 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2890 ZERO_STRUCT(driver);
2892 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2893 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2895 return ERROR_INVALID_PRINTER_NAME;
2897 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2898 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2900 free_a_printer(&printer,2);
2901 return ERROR_UNKNOWN_PRINTER_DRIVER;
2904 fill_printer_driver_info_3(info, driver, servername);
2906 free_a_printer(&printer,2);
2908 return NT_STATUS_NO_PROBLEMO;
2911 /********************************************************************
2912 * construct_printer_info_6
2913 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2914 ********************************************************************/
2916 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2922 memset(&nullstr, '\0', sizeof(fstring));
2924 info->version=driver.info_3->cversion;
2926 init_unistr( &info->name, driver.info_3->name );
2927 init_unistr( &info->architecture, driver.info_3->environment );
2929 if (strlen(driver.info_3->driverpath)) {
2930 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2931 init_unistr( &info->driverpath, temp );
2933 init_unistr( &info->driverpath, "" );
2935 if (strlen(driver.info_3->datafile)) {
2936 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2937 init_unistr( &info->datafile, temp );
2939 init_unistr( &info->datafile, "" );
2941 if (strlen(driver.info_3->configfile)) {
2942 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2943 init_unistr( &info->configfile, temp );
2945 init_unistr( &info->configfile, "" );
2947 if (strlen(driver.info_3->helpfile)) {
2948 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2949 init_unistr( &info->helpfile, temp );
2951 init_unistr( &info->helpfile, "" );
2953 init_unistr( &info->monitorname, driver.info_3->monitorname );
2954 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2956 info->dependentfiles=NULL;
2957 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2959 info->previousdrivernames=NULL;
2960 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2962 info->driver_date.low=0;
2963 info->driver_date.high=0;
2966 info->driver_version_low=0;
2967 info->driver_version_high=0;
2969 init_unistr( &info->mfgname, "");
2970 init_unistr( &info->oem_url, "");
2971 init_unistr( &info->hardware_id, "");
2972 init_unistr( &info->provider, "");
2975 /********************************************************************
2976 * construct_printer_info_6
2977 * fill a printer_info_6 struct
2978 ********************************************************************/
2979 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2981 NT_PRINTER_INFO_LEVEL *printer = NULL;
2982 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2984 ZERO_STRUCT(driver);
2986 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2987 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2989 return ERROR_INVALID_PRINTER_NAME;
2991 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2992 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2995 * Is this a W2k client ?
2999 free_a_printer(&printer,2);
3000 return ERROR_UNKNOWN_PRINTER_DRIVER;
3003 /* Yes - try again with a WinNT driver. */
3005 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3006 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3008 free_a_printer(&printer,2);
3009 return ERROR_UNKNOWN_PRINTER_DRIVER;
3013 fill_printer_driver_info_6(info, driver, servername);
3015 free_a_printer(&printer,2);
3017 return NT_STATUS_NO_PROBLEMO;
3020 /****************************************************************************
3021 ****************************************************************************/
3023 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3025 safe_free(info->dependentfiles);
3028 /****************************************************************************
3029 ****************************************************************************/
3031 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3033 safe_free(info->dependentfiles);
3037 /****************************************************************************
3038 ****************************************************************************/
3039 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3041 DRIVER_INFO_1 *info=NULL;
3044 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3045 return ERROR_NOT_ENOUGH_MEMORY;
3047 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3048 if (status != NT_STATUS_NO_PROBLEMO) {
3053 /* check the required size. */
3054 *needed += spoolss_size_printer_driver_info_1(info);
3056 if (!alloc_buffer_size(buffer, *needed)) {
3058 return ERROR_INSUFFICIENT_BUFFER;
3061 /* fill the buffer with the structures */
3062 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3067 if (*needed > offered)
3068 return ERROR_INSUFFICIENT_BUFFER;
3070 return NT_STATUS_NO_PROBLEMO;
3073 /****************************************************************************
3074 ****************************************************************************/
3075 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3077 DRIVER_INFO_2 *info=NULL;
3080 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3081 return ERROR_NOT_ENOUGH_MEMORY;
3083 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3084 if (status != NT_STATUS_NO_PROBLEMO) {
3089 /* check the required size. */
3090 *needed += spoolss_size_printer_driver_info_2(info);
3092 if (!alloc_buffer_size(buffer, *needed)) {
3094 return ERROR_INSUFFICIENT_BUFFER;
3097 /* fill the buffer with the structures */
3098 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3103 if (*needed > offered)
3104 return ERROR_INSUFFICIENT_BUFFER;
3106 return NT_STATUS_NO_PROBLEMO;
3109 /****************************************************************************
3110 ****************************************************************************/
3111 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3118 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3119 if (status != NT_STATUS_NO_PROBLEMO) {
3123 /* check the required size. */
3124 *needed += spoolss_size_printer_driver_info_3(&info);
3126 if (!alloc_buffer_size(buffer, *needed)) {
3127 free_printer_driver_info_3(&info);
3128 return ERROR_INSUFFICIENT_BUFFER;
3131 /* fill the buffer with the structures */
3132 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3134 free_printer_driver_info_3(&info);
3136 if (*needed > offered)
3137 return ERROR_INSUFFICIENT_BUFFER;
3139 return NT_STATUS_NO_PROBLEMO;
3142 /****************************************************************************
3143 ****************************************************************************/
3144 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3151 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3152 if (status != NT_STATUS_NO_PROBLEMO) {
3156 /* check the required size. */
3157 *needed += spoolss_size_printer_driver_info_6(&info);
3159 if (!alloc_buffer_size(buffer, *needed)) {
3160 free_printer_driver_info_6(&info);
3161 return ERROR_INSUFFICIENT_BUFFER;
3164 /* fill the buffer with the structures */
3165 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3167 free_printer_driver_info_6(&info);
3169 if (*needed > offered)
3170 return ERROR_INSUFFICIENT_BUFFER;
3172 return NT_STATUS_NO_PROBLEMO;
3175 /****************************************************************************
3176 ****************************************************************************/
3177 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3178 uint32 clientmajorversion, uint32 clientminorversion,
3179 NEW_BUFFER *buffer, uint32 offered,
3180 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3183 fstring architecture;
3186 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3189 *servermajorversion=0;
3190 *serverminorversion=0;
3192 pstrcpy(servername, global_myname);
3193 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3195 if (!get_printer_snum(handle, &snum))
3196 return ERROR_INVALID_HANDLE;
3200 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3202 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3204 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3206 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3208 return ERROR_INVALID_LEVEL;
3212 /****************************************************************************
3213 ****************************************************************************/
3214 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3216 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3218 if (OPEN_HANDLE(Printer)) {
3219 Printer->page_started=True;
3223 DEBUG(3,("Error in startpageprinter printer handle\n"));
3224 return ERROR_INVALID_HANDLE;
3227 /****************************************************************************
3228 ****************************************************************************/
3229 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3231 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3233 if (!OPEN_HANDLE(Printer)) {
3234 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3235 return ERROR_INVALID_HANDLE;
3238 Printer->page_started=False;
3240 return NT_STATUS_NO_PROBLEMO;
3243 /****************************************************************************
3244 Return a user struct for a pipe user.
3245 ****************************************************************************/
3247 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3249 if (p->ntlmssp_auth_validated) {
3250 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3252 extern struct current_user current_user;
3253 memcpy(user, ¤t_user, sizeof(struct current_user));
3259 /********************************************************************
3260 * api_spoolss_getprinter
3261 * called from the spoolss dispatcher
3263 ********************************************************************/
3264 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3265 pipes_struct *p, DOC_INFO *docinfo,
3268 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3272 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3273 struct current_user user;
3275 if (!OPEN_HANDLE(Printer)) {
3276 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3277 return ERROR_INVALID_HANDLE;
3280 get_current_user(&user, p);
3283 * a nice thing with NT is it doesn't listen to what you tell it.
3284 * when asked to send _only_ RAW datas, it tries to send datas
3287 * So I add checks like in NT Server ...
3289 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3290 * there's a bug in NT client-side code, so we'll fix it in the
3291 * server-side code. *nnnnnggggh!*
3294 if (info_1->p_datatype != 0) {
3295 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3296 if (strcmp(datatype, "RAW") != 0) {
3298 return ERROR_INVALID_DATATYPE;
3302 /* get the share number of the printer */
3303 if (!get_printer_snum(handle, &snum)) {
3304 return ERROR_INVALID_HANDLE;
3307 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3309 Printer->jobid = print_job_start(&user, snum, jobname);
3311 /* An error occured in print_job_start() so return an appropriate
3314 if (Printer->jobid == -1) {
3315 return map_nt_error_from_unix(errno);
3318 Printer->document_started=True;
3319 (*jobid) = Printer->jobid;
3321 srv_spoolss_sendnotify(handle);
3325 /********************************************************************
3326 * api_spoolss_getprinter
3327 * called from the spoolss dispatcher
3329 ********************************************************************/
3330 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3332 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3334 if (!OPEN_HANDLE(Printer)) {
3335 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3336 return ERROR_INVALID_HANDLE;
3339 Printer->document_started=False;
3340 print_job_end(Printer->jobid);
3341 /* error codes unhandled so far ... */
3343 srv_spoolss_sendnotify(handle);
3348 /****************************************************************************
3349 ****************************************************************************/
3350 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3353 uint32 *buffer_written)
3355 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3357 if (!OPEN_HANDLE(Printer)) {
3358 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3359 return ERROR_INVALID_HANDLE;
3362 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3368 /********************************************************************
3369 * api_spoolss_getprinter
3370 * called from the spoolss dispatcher
3372 ********************************************************************/
3373 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3376 struct current_user user;
3377 int snum, errcode = ERROR_INVALID_FUNCTION;
3378 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3380 get_current_user(&user, p);
3382 if (!OPEN_HANDLE(Printer)) {
3383 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3384 return ERROR_INVALID_HANDLE;
3387 if (!get_printer_snum(handle, &snum))
3388 return ERROR_INVALID_HANDLE;
3391 case PRINTER_CONTROL_PAUSE:
3392 if (print_queue_pause(&user, snum, &errcode)) {
3396 case PRINTER_CONTROL_RESUME:
3397 case PRINTER_CONTROL_UNPAUSE:
3398 if (print_queue_resume(&user, snum, &errcode)) {
3402 case PRINTER_CONTROL_PURGE:
3403 if (print_queue_purge(&user, snum, &errcode)) {
3408 return ERROR_INVALID_LEVEL;
3414 /********************************************************************
3415 * api_spoolss_abortprinter
3416 ********************************************************************/
3418 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3420 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3423 /********************************************************************
3424 * called by spoolss_api_setprinter
3425 * when updating a printer description
3426 ********************************************************************/
3427 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3428 const SPOOL_PRINTER_INFO_LEVEL *info,
3429 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3431 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3432 struct current_user user;
3436 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3438 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3439 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3440 OUR_HANDLE(handle)));
3442 result = ERROR_INVALID_HANDLE;
3446 /* NT seems to like setting the security descriptor even though
3447 nothing may have actually changed. This causes annoying
3448 dialog boxes when the user doesn't have permission to change
3449 the security descriptor. */
3451 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3453 if (DEBUGLEVEL >= 10) {
3457 acl = old_secdesc_ctr->sec->dacl;
3458 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3459 PRINTERNAME(snum), acl->num_aces));
3461 for (i = 0; i < acl->num_aces; i++) {
3464 sid_to_string(sid_str, &acl->ace[i].sid);
3466 DEBUG(10, ("%s 0x%08x\n", sid_str,
3467 acl->ace[i].info.mask));
3470 acl = secdesc_ctr->sec->dacl;
3473 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3474 PRINTERNAME(snum), acl->num_aces));
3476 for (i = 0; i < acl->num_aces; i++) {
3479 sid_to_string(sid_str, &acl->ace[i].sid);
3481 DEBUG(10, ("%s 0x%08x\n", sid_str,
3482 acl->ace[i].info.mask));
3485 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3489 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3491 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3492 result = NT_STATUS_NO_PROBLEMO;
3496 /* Work out which user is performing the operation */
3498 get_current_user(&user, p);
3500 /* Check the user has permissions to change the security
3501 descriptor. By experimentation with two NT machines, the user
3502 requires Full Access to the printer to change security
3505 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3506 result = ERROR_ACCESS_DENIED;
3510 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3513 free_sec_desc_buf(&new_secdesc_ctr);
3514 free_sec_desc_buf(&old_secdesc_ctr);
3519 /********************************************************************
3520 Do Samba sanity checks on a printer info struct.
3521 this has changed purpose: it now "canonicalises" printer
3522 info from a client rather than just checking it is correct
3523 ********************************************************************/
3525 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3527 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3528 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3530 /* we force some elements to "correct" values */
3531 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3532 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3533 global_myname, lp_servicename(snum));
3534 fstrcpy(info->sharename, lp_servicename(snum));
3535 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3536 | PRINTER_ATTRIBUTE_LOCAL \
3537 | PRINTER_ATTRIBUTE_RAW_ONLY \
3538 | PRINTER_ATTRIBUTE_QUEUED ;
3543 /****************************************************************************
3544 ****************************************************************************/
3545 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3547 pid_t local_pid = sys_getpid();
3548 char *cmd = lp_addprinter_cmd();
3553 pstring driverlocation;
3557 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3558 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3562 /* build driver path... only 9X architecture is needed for legacy reasons */
3563 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3565 /* change \ to \\ for the shell */
3566 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3568 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3569 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3570 cmd, printer->info_2->printername, printer->info_2->sharename,
3571 printer->info_2->portname, printer->info_2->drivername,
3572 printer->info_2->location, driverlocation);
3576 /* Convert script args to unix-codepage */
3577 dos_to_unix(command, True);
3578 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3579 ret = smbrun(command, tmp_file, False);
3580 DEBUGADD(10,("returned [%d]\n", ret));
3588 /* Get lines and convert them back to dos-codepage */
3589 qlines = file_lines_load(tmp_file, &numlines, True);
3590 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3591 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3595 /* Set the portname to what the script says the portname should be. */
3596 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3597 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3599 /* Send SIGHUP to process group... is there a better way? */
3604 file_lines_free(qlines);
3608 /* Return true if two devicemodes are equal */
3610 #define DEVMODE_CHECK_INT(field) \
3611 if (d1->field != d2->field) { \
3612 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3613 d1->field, d2->field)); \
3617 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3619 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
3622 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3623 return False; /* if either is exclusively NULL are not equal */
3626 if (!strequal(d1->devicename, d2->devicename) ||
3627 !strequal(d1->formname, d2->formname)) {
3628 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3632 DEVMODE_CHECK_INT(specversion);
3633 DEVMODE_CHECK_INT(driverversion);
3634 DEVMODE_CHECK_INT(driverextra);
3635 DEVMODE_CHECK_INT(orientation);
3636 DEVMODE_CHECK_INT(papersize);
3637 DEVMODE_CHECK_INT(paperlength);
3638 DEVMODE_CHECK_INT(paperwidth);
3639 DEVMODE_CHECK_INT(scale);
3640 DEVMODE_CHECK_INT(copies);
3641 DEVMODE_CHECK_INT(defaultsource);
3642 DEVMODE_CHECK_INT(printquality);
3643 DEVMODE_CHECK_INT(color);
3644 DEVMODE_CHECK_INT(duplex);
3645 DEVMODE_CHECK_INT(yresolution);
3646 DEVMODE_CHECK_INT(ttoption);
3647 DEVMODE_CHECK_INT(collate);
3648 DEVMODE_CHECK_INT(logpixels);
3650 DEVMODE_CHECK_INT(fields);
3651 DEVMODE_CHECK_INT(bitsperpel);
3652 DEVMODE_CHECK_INT(pelswidth);
3653 DEVMODE_CHECK_INT(pelsheight);
3654 DEVMODE_CHECK_INT(displayflags);
3655 DEVMODE_CHECK_INT(displayfrequency);
3656 DEVMODE_CHECK_INT(icmmethod);
3657 DEVMODE_CHECK_INT(icmintent);
3658 DEVMODE_CHECK_INT(mediatype);
3659 DEVMODE_CHECK_INT(dithertype);
3660 DEVMODE_CHECK_INT(reserved1);
3661 DEVMODE_CHECK_INT(reserved2);
3662 DEVMODE_CHECK_INT(panningwidth);
3663 DEVMODE_CHECK_INT(panningheight);
3665 /* compare the private data if it exists */
3666 if (!d1->driverextra && !d2->driverextra) goto equal;
3669 DEVMODE_CHECK_INT(driverextra);
3671 if (memcmp(d1->private, d2->private, d1->driverextra)) {
3672 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
3677 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
3681 /* Return true if two NT_PRINTER_PARAM structures are equal */
3683 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3684 NT_PRINTER_PARAM *p2)
3686 if (!p1 && !p2) goto equal;
3688 if ((!p1 && p2) || (p1 && !p2)) {
3689 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
3693 /* Compare lists of printer parameters */
3697 NT_PRINTER_PARAM *q = p1;
3699 /* Find the parameter in the second structure */
3703 if (strequal(p1->value, q->value)) {
3705 if (p1->type != q->type) {
3706 DEBUG(10, ("nt_printer_param_equal():"
3707 "types for %s differ (%d != %d)\n",
3708 p1->value, p1->type,
3713 if (p1->data_len != q->data_len) {
3714 DEBUG(10, ("nt_printer_param_equal():"
3715 "len for %s differs (%d != %d)\n",
3716 p1->value, p1->data_len,
3721 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
3724 DEBUG(10, ("nt_printer_param_equal():"
3725 "data for %s differs\n", p1->value));
3735 DEBUG(10, ("nt_printer_param_equal(): param %s "
3736 "does not exist\n", p1->value));
3745 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
3749 /********************************************************************
3750 * Called by update_printer when trying to work out whether to
3751 * actually update printer info.
3752 ********************************************************************/
3754 #define PI_CHECK_INT(field) \
3755 if (pi1->field != pi2->field) { \
3756 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
3757 pi1->field, pi2->field)); \
3761 #define PI_CHECK_STR(field) \
3762 if (!strequal(pi1->field, pi2->field)) { \
3763 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
3764 pi1->field, pi2->field)); \
3768 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3769 NT_PRINTER_INFO_LEVEL *p2)
3771 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3773 /* Trivial conditions */
3775 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3779 if ((!p1 && p2) || (p1 && !p2) ||
3780 (!p1->info_2 && p2->info_2) ||
3781 (p1->info_2 && !p2->info_2)) {
3782 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
3787 /* Compare two nt_printer_info_level structures. Don't compare
3788 status or cjobs as they seem to have something to do with the
3794 PI_CHECK_INT(attributes);
3795 PI_CHECK_INT(priority);
3796 PI_CHECK_INT(default_priority);
3797 PI_CHECK_INT(starttime);
3798 PI_CHECK_INT(untiltime);
3799 PI_CHECK_INT(averageppm);
3801 /* Yuck - don't check the printername or servername as the
3802 add_a_printer() code plays games with them. You can't
3803 change the printername or the sharename through this interface
3806 PI_CHECK_STR(sharename);
3807 PI_CHECK_STR(portname);
3808 PI_CHECK_STR(drivername);
3809 PI_CHECK_STR(comment);
3810 PI_CHECK_STR(location);
3812 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3816 PI_CHECK_STR(sepfile);
3817 PI_CHECK_STR(printprocessor);
3818 PI_CHECK_STR(datatype);
3819 PI_CHECK_STR(parameters);
3821 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3825 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3829 PI_CHECK_INT(changeid);
3830 PI_CHECK_INT(c_setprinter);
3831 PI_CHECK_INT(setuptime);
3834 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
3838 /********************************************************************
3839 * called by spoolss_api_setprinter
3840 * when updating a printer description
3841 ********************************************************************/
3843 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3844 const SPOOL_PRINTER_INFO_LEVEL *info,
3845 DEVICEMODE *devmode)
3848 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3849 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3852 DEBUG(8,("update_printer\n"));
3854 result = NT_STATUS_NO_PROBLEMO;
3857 DEBUG(0,("Send a mail to samba@samba.org\n"));
3858 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3859 result = ERROR_INVALID_LEVEL;
3863 if (!OPEN_HANDLE(Printer)) {
3864 result = ERROR_INVALID_HANDLE;
3868 if (!get_printer_snum(handle, &snum)) {
3869 result = ERROR_INVALID_HANDLE;
3873 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3874 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3875 result = ERROR_INVALID_HANDLE;
3879 DEBUGADD(8,("Converting info_2 struct\n"));
3882 * convert_printer_info converts the incoming
3883 * info from the client and overwrites the info
3884 * just read from the tdb in the pointer 'printer'.
3887 convert_printer_info(info, printer, level);
3889 if (info->info_2->devmode_ptr != 0) {
3890 /* we have a valid devmode
3891 convert it and link it*/
3894 * Ensure printer->info_2->devmode is a valid pointer
3895 * as we will be overwriting it in convert_devicemode().
3898 if (printer->info_2->devmode == NULL)
3899 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3901 DEBUGADD(8,("Converting the devicemode struct\n"));
3902 convert_devicemode(devmode, printer->info_2->devmode);
3905 if (printer->info_2->devmode != NULL)
3906 free_nt_devicemode(&printer->info_2->devmode);
3907 printer->info_2->devmode=NULL;
3910 /* Do sanity check on the requested changes for Samba */
3912 if (!check_printer_ok(printer->info_2, snum)) {
3913 result = ERROR_INVALID_PARAMETER;
3917 /* NT likes to call this function even though nothing has actually
3918 changed. Check this so the user doesn't end up with an
3919 annoying permission denied dialog box. */
3921 if (nt_printer_info_level_equal(printer, old_printer)) {
3922 DEBUG(3, ("printer info has not changed\n"));
3923 result = NT_STATUS_NO_PROBLEMO;
3927 /* Check calling user has permission to update printer description */
3929 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3930 DEBUG(3, ("printer property change denied by security "
3932 result = ERROR_ACCESS_DENIED;
3936 /* Call addprinter hook */
3938 if (*lp_addprinter_cmd() )
3939 if ( !add_printer_hook(printer) ) {
3940 result = ERROR_ACCESS_DENIED;
3944 /* Update printer info */
3946 if (add_a_printer(*printer, 2)!=0) {
3947 /* I don't really know what to return here !!! */
3948 result = ERROR_ACCESS_DENIED;
3953 free_a_printer(&printer, 2);
3954 free_a_printer(&old_printer, 2);
3956 srv_spoolss_sendnotify(handle);
3961 /****************************************************************************
3962 ****************************************************************************/
3963 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3964 const SPOOL_PRINTER_INFO_LEVEL *info,
3965 DEVMODE_CTR devmode_ctr,
3966 SEC_DESC_BUF *secdesc_ctr,
3967 uint32 command, pipes_struct *p)
3969 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3971 if (!OPEN_HANDLE(Printer)) {
3972 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3973 return ERROR_INVALID_HANDLE;
3976 /* check the level */
3979 return control_printer(handle, command, p);
3981 return update_printer(handle, level, info, devmode_ctr.devmode);
3983 return update_printer_sec(handle, level, info, p,
3986 return ERROR_INVALID_LEVEL;
3990 /****************************************************************************
3991 ****************************************************************************/
3992 uint32 _spoolss_fcpn(POLICY_HND *handle)
3994 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3996 if (!OPEN_HANDLE(Printer)) {
3997 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3998 return ERROR_INVALID_HANDLE;
4001 if (Printer->notify.client_connected==True)
4002 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4003 return ERROR_INVALID_HANDLE;
4005 Printer->notify.flags=0;
4006 Printer->notify.options=0;
4007 Printer->notify.localmachine[0]='\0';
4008 Printer->notify.printerlocal=0;
4009 if (Printer->notify.option)
4010 safe_free(Printer->notify.option->ctr.type);
4011 safe_free(Printer->notify.option);
4012 Printer->notify.option=NULL;
4013 Printer->notify.client_connected=False;
4015 return NT_STATUS_NO_PROBLEMO;
4018 /****************************************************************************
4019 ****************************************************************************/
4020 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4021 NEW_BUFFER *buffer, uint32 offered,
4025 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4026 returns for AddJob. AddJob
4027 must fail on non-local
4031 /****************************************************************************
4032 ****************************************************************************/
4033 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4034 int position, int snum)
4040 t=gmtime(&queue->time);
4041 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4043 job_info->jobid=queue->job;
4044 init_unistr(&job_info->printername, lp_servicename(snum));
4045 init_unistr(&job_info->machinename, temp_name);
4046 init_unistr(&job_info->username, queue->user);
4047 init_unistr(&job_info->document, queue->file);
4048 init_unistr(&job_info->datatype, "RAW");
4049 init_unistr(&job_info->text_status, "");
4050 job_info->status=nt_printj_status(queue->status);
4051 job_info->priority=queue->priority;
4052 job_info->position=position;
4053 job_info->totalpages=0;
4054 job_info->pagesprinted=0;
4056 make_systemtime(&job_info->submitted, t);
4059 /****************************************************************************
4060 ****************************************************************************/
4061 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4062 int position, int snum)
4065 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4069 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
4072 t=gmtime(&queue->time);
4073 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4075 job_info->jobid=queue->job;
4077 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4079 init_unistr(&job_info->printername, chaine);
4081 init_unistr(&job_info->machinename, temp_name);
4082 init_unistr(&job_info->username, queue->user);
4083 init_unistr(&job_info->document, queue->file);
4084 init_unistr(&job_info->notifyname, queue->user);
4085 init_unistr(&job_info->datatype, "RAW");
4086 init_unistr(&job_info->printprocessor, "winprint");
4087 init_unistr(&job_info->parameters, "");
4088 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4089 init_unistr(&job_info->text_status, "");
4091 /* and here the security descriptor */
4093 job_info->status=nt_printj_status(queue->status);
4094 job_info->priority=queue->priority;
4095 job_info->position=position;
4096 job_info->starttime=0;
4097 job_info->untiltime=0;
4098 job_info->totalpages=0;
4099 job_info->size=queue->size;
4100 make_systemtime(&(job_info->submitted), t);
4101 job_info->timeelapsed=0;
4102 job_info->pagesprinted=0;
4104 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4105 free_a_printer(&ntprinter, 2);
4109 free_a_printer(&ntprinter, 2);
4113 /****************************************************************************
4114 Enumjobs at level 1.
4115 ****************************************************************************/
4116 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4117 NEW_BUFFER *buffer, uint32 offered,
4118 uint32 *needed, uint32 *returned)
4123 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4127 return ERROR_NOT_ENOUGH_MEMORY;
4130 for (i=0; i<*returned; i++)
4131 fill_job_info_1(&info[i], &queue[i], i, snum);
4135 /* check the required size. */
4136 for (i=0; i<*returned; i++)
4137 (*needed) += spoolss_size_job_info_1(&info[i]);
4139 if (!alloc_buffer_size(buffer, *needed)) {
4141 return ERROR_INSUFFICIENT_BUFFER;
4144 /* fill the buffer with the structures */
4145 for (i=0; i<*returned; i++)
4146 new_smb_io_job_info_1("", buffer, &info[i], 0);
4151 if (*needed > offered) {
4153 return ERROR_INSUFFICIENT_BUFFER;
4156 return NT_STATUS_NO_PROBLEMO;
4159 /****************************************************************************
4160 Enumjobs at level 2.
4161 ****************************************************************************/
4162 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4163 NEW_BUFFER *buffer, uint32 offered,
4164 uint32 *needed, uint32 *returned)
4169 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4173 return ERROR_NOT_ENOUGH_MEMORY;
4176 for (i=0; i<*returned; i++)
4177 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4181 /* check the required size. */
4182 for (i=0; i<*returned; i++)
4183 (*needed) += spoolss_size_job_info_2(&info[i]);
4185 if (!alloc_buffer_size(buffer, *needed)) {
4187 return ERROR_INSUFFICIENT_BUFFER;
4190 /* fill the buffer with the structures */
4191 for (i=0; i<*returned; i++)
4192 new_smb_io_job_info_2("", buffer, &info[i], 0);
4195 free_job_info_2(info);
4197 if (*needed > offered) {
4199 return ERROR_INSUFFICIENT_BUFFER;
4202 return NT_STATUS_NO_PROBLEMO;
4205 /****************************************************************************
4207 ****************************************************************************/
4208 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4209 NEW_BUFFER *buffer, uint32 offered,
4210 uint32 *needed, uint32 *returned)
4213 print_queue_struct *queue=NULL;
4214 print_status_struct prt_status;
4216 DEBUG(4,("_spoolss_enumjobs\n"));
4218 ZERO_STRUCT(prt_status);
4223 if (!get_printer_snum(handle, &snum))
4224 return ERROR_INVALID_HANDLE;
4226 *returned = print_queue_status(snum, &queue, &prt_status);
4227 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4229 if (*returned == 0) {
4231 return NT_STATUS_NO_PROBLEMO;
4236 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4238 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4242 return ERROR_INVALID_LEVEL;
4247 /****************************************************************************
4248 ****************************************************************************/
4249 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4254 /****************************************************************************
4255 ****************************************************************************/
4256 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4257 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4259 struct current_user user;
4260 print_status_struct prt_status;
4261 int snum, errcode = ERROR_INVALID_FUNCTION;
4263 memset(&prt_status, 0, sizeof(prt_status));
4265 if (!get_printer_snum(handle, &snum)) {
4266 return ERROR_INVALID_HANDLE;
4269 if (!print_job_exists(jobid)) {
4270 return ERROR_INVALID_PRINTER_NAME;
4273 get_current_user(&user, p);
4276 case JOB_CONTROL_CANCEL:
4277 case JOB_CONTROL_DELETE:
4278 if (print_job_delete(&user, jobid, &errcode)) {
4282 case JOB_CONTROL_PAUSE:
4283 if (print_job_pause(&user, jobid, &errcode)) {
4287 case JOB_CONTROL_RESTART:
4288 case JOB_CONTROL_RESUME:
4289 if (print_job_resume(&user, jobid, &errcode)) {
4294 return ERROR_INVALID_LEVEL;
4300 /****************************************************************************
4301 Enumerates all printer drivers at level 1.
4302 ****************************************************************************/
4303 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4308 fstring *list = NULL;
4310 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4311 DRIVER_INFO_1 *driver_info_1=NULL;
4315 #define MAX_VERSION 4
4317 for (version=0; version<MAX_VERSION; version++) {
4319 ndrivers=get_ntdrivers(&list, architecture, version);
4320 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4323 return ERROR_NOT_ENOUGH_MEMORY;
4326 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4328 return ERROR_NOT_ENOUGH_MEMORY;
4332 for (i=0; i<ndrivers; i++) {
4334 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4335 ZERO_STRUCT(driver);
4336 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4340 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4341 free_a_printer_driver(driver, 3);
4344 *returned+=ndrivers;
4348 /* check the required size. */
4349 for (i=0; i<*returned; i++) {
4350 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4351 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4354 if (!alloc_buffer_size(buffer, *needed)) {
4355 safe_free(driver_info_1);
4356 return ERROR_INSUFFICIENT_BUFFER;
4359 /* fill the buffer with the form structures */
4360 for (i=0; i<*returned; i++) {
4361 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4362 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4365 safe_free(driver_info_1);
4367 if (*needed > offered) {
4369 return ERROR_INSUFFICIENT_BUFFER;
4372 return NT_STATUS_NO_PROBLEMO;
4375 /****************************************************************************
4376 Enumerates all printer drivers at level 2.
4377 ****************************************************************************/
4378 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4383 fstring *list = NULL;
4385 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4386 DRIVER_INFO_2 *driver_info_2=NULL;
4390 #define MAX_VERSION 4
4392 for (version=0; version<MAX_VERSION; version++) {
4394 ndrivers=get_ntdrivers(&list, architecture, version);
4395 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4398 return ERROR_NOT_ENOUGH_MEMORY;
4401 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4403 return ERROR_NOT_ENOUGH_MEMORY;
4407 for (i=0; i<ndrivers; i++) {
4410 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4411 ZERO_STRUCT(driver);
4412 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4416 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4417 free_a_printer_driver(driver, 3);
4420 *returned+=ndrivers;
4424 /* check the required size. */
4425 for (i=0; i<*returned; i++) {
4426 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4427 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4430 if (!alloc_buffer_size(buffer, *needed)) {
4431 safe_free(driver_info_2);
4432 return ERROR_INSUFFICIENT_BUFFER;
4435 /* fill the buffer with the form structures */
4436 for (i=0; i<*returned; i++) {
4437 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4438 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4441 safe_free(driver_info_2);
4443 if (*needed > offered) {
4445 return ERROR_INSUFFICIENT_BUFFER;
4448 return NT_STATUS_NO_PROBLEMO;
4451 /****************************************************************************
4452 Enumerates all printer drivers at level 3.
4453 ****************************************************************************/
4454 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4459 fstring *list = NULL;
4461 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4462 DRIVER_INFO_3 *driver_info_3=NULL;
4466 #define MAX_VERSION 4
4468 for (version=0; version<MAX_VERSION; version++) {
4470 ndrivers=get_ntdrivers(&list, architecture, version);
4471 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4474 return ERROR_NOT_ENOUGH_MEMORY;
4477 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4479 return ERROR_NOT_ENOUGH_MEMORY;
4483 for (i=0; i<ndrivers; i++) {
4486 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4487 ZERO_STRUCT(driver);
4488 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4492 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4493 free_a_printer_driver(driver, 3);
4496 *returned+=ndrivers;
4500 /* check the required size. */
4501 for (i=0; i<*returned; i++) {
4502 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4503 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4506 if (!alloc_buffer_size(buffer, *needed)) {
4507 safe_free(driver_info_3);
4508 return ERROR_INSUFFICIENT_BUFFER;
4511 /* fill the buffer with the driver structures */
4512 for (i=0; i<*returned; i++) {
4513 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4514 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4517 for (i=0; i<*returned; i++)
4518 safe_free(driver_info_3[i].dependentfiles);
4520 safe_free(driver_info_3);
4522 if (*needed > offered) {
4524 return ERROR_INSUFFICIENT_BUFFER;
4527 return NT_STATUS_NO_PROBLEMO;
4530 /****************************************************************************
4531 Enumerates all printer drivers.
4532 ****************************************************************************/
4533 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4534 NEW_BUFFER *buffer, uint32 offered,
4535 uint32 *needed, uint32 *returned)
4537 fstring *list = NULL;
4539 fstring architecture;
4541 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4542 fstrcpy(servername, global_myname);
4546 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4550 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4552 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4554 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4558 return ERROR_INVALID_LEVEL;
4562 /****************************************************************************
4563 ****************************************************************************/
4564 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4566 form->flag=list->flag;
4567 init_unistr(&form->name, list->name);
4568 form->width=list->width;
4569 form->length=list->length;
4570 form->left=list->left;
4571 form->top=list->top;
4572 form->right=list->right;
4573 form->bottom=list->bottom;
4576 /****************************************************************************
4577 ****************************************************************************/
4578 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4579 NEW_BUFFER *buffer, uint32 offered,
4580 uint32 *needed, uint32 *numofforms)
4582 nt_forms_struct *list=NULL;
4587 DEBUG(4,("_new_spoolss_enumforms\n"));
4588 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4589 DEBUGADD(5,("Info level [%d]\n", level));
4591 *numofforms = get_ntforms(&list);
4592 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4594 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4598 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4600 return ERROR_NOT_ENOUGH_MEMORY;
4603 /* construct the list of form structures */
4604 for (i=0; i<*numofforms; i++) {
4605 DEBUGADD(6,("Filling form number [%d]\n",i));
4606 fill_form_1(&forms_1[i], &list[i]);
4611 /* check the required size. */
4612 for (i=0; i<*numofforms; i++) {
4613 DEBUGADD(6,("adding form [%d]'s size\n",i));
4614 buffer_size += spoolss_size_form_1(&forms_1[i]);
4617 *needed=buffer_size;
4619 if (!alloc_buffer_size(buffer, buffer_size)){
4621 return ERROR_INSUFFICIENT_BUFFER;
4624 /* fill the buffer with the form structures */
4625 for (i=0; i<*numofforms; i++) {
4626 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4627 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4632 if (*needed > offered) {
4634 return ERROR_INSUFFICIENT_BUFFER;
4637 return NT_STATUS_NO_PROBLEMO;
4641 return ERROR_INVALID_LEVEL;
4646 /****************************************************************************
4647 ****************************************************************************/
4648 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4650 nt_forms_struct *list=NULL;
4656 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4658 DEBUG(4,("_spoolss_getform\n"));
4659 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4660 DEBUGADD(5,("Info level [%d]\n", level));
4662 numofforms = get_ntforms(&list);
4663 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4665 if (numofforms == 0)
4666 return ERROR_NO_MORE_ITEMS;
4671 /* Check if the requested name is in the list of form structures */
4672 for (i=0; i<numofforms; i++) {
4674 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4676 if (strequal(form_name, list[i].name)) {
4677 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4678 fill_form_1(&form_1, &list[i]);
4685 /* check the required size. */
4687 *needed=spoolss_size_form_1(&form_1);
4689 if (!alloc_buffer_size(buffer, buffer_size)){
4690 return ERROR_INSUFFICIENT_BUFFER;
4693 if (*needed > offered) {
4694 return ERROR_INSUFFICIENT_BUFFER;
4697 /* fill the buffer with the form structures */
4698 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4699 new_smb_io_form_1("", buffer, &form_1, 0);
4701 return NT_STATUS_NO_PROBLEMO;
4705 return ERROR_INVALID_LEVEL;
4709 /****************************************************************************
4710 ****************************************************************************/
4711 static void fill_port_1(PORT_INFO_1 *port, char *name)
4713 init_unistr(&port->port_name, name);
4716 /****************************************************************************
4717 ****************************************************************************/
4718 static void fill_port_2(PORT_INFO_2 *port, char *name)
4720 init_unistr(&port->port_name, name);
4721 init_unistr(&port->monitor_name, "Local Monitor");
4722 init_unistr(&port->description, "Local Port");
4723 #define PORT_TYPE_WRITE 1
4724 port->port_type=PORT_TYPE_WRITE;
4728 /****************************************************************************
4730 ****************************************************************************/
4731 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4733 PORT_INFO_1 *ports=NULL;
4736 if (*lp_enumports_cmd()) {
4737 pid_t local_pid = sys_getpid();
4738 char *cmd = lp_enumports_cmd();
4746 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4747 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4751 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4752 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4755 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4756 ret = smbrun(command, tmp_file, False);
4757 DEBUG(10,("Returned [%d]\n", ret));
4760 /* Is this the best error to return here? */
4761 return ERROR_ACCESS_DENIED;
4765 qlines = file_lines_load(tmp_file, &numlines,True);
4766 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4767 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4771 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4772 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4773 file_lines_free(qlines);
4774 return ERROR_NOT_ENOUGH_MEMORY;
4777 for (i=0; i<numlines; i++) {
4778 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4779 fill_port_1(&ports[i], qlines[i]);
4782 file_lines_free(qlines);
4785 *returned = numlines;
4788 *returned = 1; /* Sole Samba port returned. */
4790 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4791 return ERROR_NOT_ENOUGH_MEMORY;
4793 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4795 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4798 /* check the required size. */
4799 for (i=0; i<*returned; i++) {
4800 DEBUGADD(6,("adding port [%d]'s size\n", i));
4801 *needed += spoolss_size_port_info_1(&ports[i]);
4804 if (!alloc_buffer_size(buffer, *needed)) {
4806 return ERROR_INSUFFICIENT_BUFFER;
4809 /* fill the buffer with the ports structures */
4810 for (i=0; i<*returned; i++) {
4811 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4812 new_smb_io_port_1("", buffer, &ports[i], 0);
4817 if (*needed > offered) {
4819 return ERROR_INSUFFICIENT_BUFFER;
4822 return NT_STATUS_NO_PROBLEMO;
4825 /****************************************************************************
4827 ****************************************************************************/
4829 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4831 PORT_INFO_2 *ports=NULL;
4834 if (*lp_enumports_cmd()) {
4835 pid_t local_pid = sys_getpid();
4836 char *cmd = lp_enumports_cmd();
4844 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4845 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4849 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4850 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4853 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4854 ret = smbrun(command, tmp_file, False);
4855 DEBUGADD(10,("returned [%d]\n", ret));
4858 /* Is this the best error to return here? */
4859 return ERROR_ACCESS_DENIED;
4863 qlines = file_lines_load(tmp_file, &numlines,True);
4864 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4865 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4869 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4870 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4871 file_lines_free(qlines);
4872 return ERROR_NOT_ENOUGH_MEMORY;
4875 for (i=0; i<numlines; i++) {
4876 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4877 fill_port_2(&(ports[i]), qlines[i]);
4880 file_lines_free(qlines);
4883 *returned = numlines;
4889 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4890 return ERROR_NOT_ENOUGH_MEMORY;
4892 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4894 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4897 /* check the required size. */
4898 for (i=0; i<*returned; i++) {
4899 DEBUGADD(6,("adding port [%d]'s size\n", i));
4900 *needed += spoolss_size_port_info_2(&ports[i]);
4903 if (!alloc_buffer_size(buffer, *needed)) {
4905 return ERROR_INSUFFICIENT_BUFFER;
4908 /* fill the buffer with the ports structures */
4909 for (i=0; i<*returned; i++) {
4910 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4911 new_smb_io_port_2("", buffer, &ports[i], 0);
4916 if (*needed > offered) {
4918 return ERROR_INSUFFICIENT_BUFFER;
4921 return NT_STATUS_NO_PROBLEMO;
4924 /****************************************************************************
4926 ****************************************************************************/
4927 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4928 NEW_BUFFER *buffer, uint32 offered,
4929 uint32 *needed, uint32 *returned)
4931 DEBUG(4,("_spoolss_enumports\n"));
4938 return enumports_level_1(buffer, offered, needed, returned);
4940 return enumports_level_2(buffer, offered, needed, returned);
4942 return ERROR_INVALID_LEVEL;
4946 /****************************************************************************
4947 ****************************************************************************/
4948 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4949 const SPOOL_PRINTER_INFO_LEVEL *info,
4950 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4951 uint32 user_switch, const SPOOL_USER_CTR *user,
4954 NT_PRINTER_INFO_LEVEL *printer = NULL;
4958 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4959 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4960 return ERROR_NOT_ENOUGH_MEMORY;
4963 ZERO_STRUCTP(printer);
4965 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4966 convert_printer_info(info, printer, 2);
4968 if (*lp_addprinter_cmd() )
4969 if ( !add_printer_hook(printer) ) {
4970 free_a_printer(&printer,2);
4971 return ERROR_ACCESS_DENIED;
4974 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4975 printer->info_2->sharename);
4977 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4978 free_a_printer(&printer,2);
4979 return ERROR_ACCESS_DENIED;
4982 /* you must be a printer admin to add a new printer */
4983 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4984 free_a_printer(&printer,2);
4985 return ERROR_ACCESS_DENIED;
4989 * Do sanity check on the requested changes for Samba.
4992 if (!check_printer_ok(printer->info_2, snum)) {
4993 free_a_printer(&printer,2);
4994 return ERROR_INVALID_PARAMETER;
4997 /* write the ASCII on disk */
4998 if (add_a_printer(*printer, 2) != 0) {
4999 free_a_printer(&printer,2);
5000 return ERROR_ACCESS_DENIED;
5003 if (!open_printer_hnd(handle, name)) {
5004 /* Handle open failed - remove addition. */
5005 del_a_printer(printer->info_2->sharename);
5006 free_a_printer(&printer,2);
5007 return ERROR_ACCESS_DENIED;
5010 free_a_printer(&printer,2);
5012 srv_spoolss_sendnotify(handle);
5014 return NT_STATUS_NO_PROBLEMO;
5017 /****************************************************************************
5018 ****************************************************************************/
5019 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5020 const SPOOL_PRINTER_INFO_LEVEL *info,
5021 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5022 uint32 user_switch, const SPOOL_USER_CTR *user,
5027 /* we don't handle yet */
5028 /* but I know what to do ... */
5029 return ERROR_INVALID_LEVEL;
5031 return spoolss_addprinterex_level_2(uni_srv_name, info,
5032 unk0, unk1, unk2, unk3,
5033 user_switch, user, handle);
5035 return ERROR_INVALID_LEVEL;
5039 /****************************************************************************
5040 ****************************************************************************/
5041 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5042 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5044 uint32 err = NT_STATUS_NO_PROBLEMO;
5045 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5046 struct current_user user;
5048 ZERO_STRUCT(driver);
5050 get_current_user(&user, p);
5052 convert_printer_driver_info(info, &driver, level);
5054 DEBUG(5,("Cleaning driver's information\n"));
5055 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5058 DEBUG(5,("Moving driver to final destination\n"));
5059 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5061 err = ERROR_ACCESS_DENIED;
5065 if (add_a_printer_driver(driver, level)!=0) {
5066 err = ERROR_ACCESS_DENIED;
5071 free_a_printer_driver(driver, level);
5075 /****************************************************************************
5076 ****************************************************************************/
5077 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5079 init_unistr(&info->name, name);
5082 /****************************************************************************
5083 ****************************************************************************/
5084 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5088 pstring short_archi;
5089 DRIVER_DIRECTORY_1 *info=NULL;
5091 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5093 if (get_short_archi(short_archi, long_archi)==FALSE)
5094 return ERROR_INVALID_ENVIRONMENT;
5096 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5097 return ERROR_NOT_ENOUGH_MEMORY;
5099 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5101 DEBUG(4,("printer driver directory: [%s]\n", path));
5103 fill_driverdir_1(info, path);
5105 *needed += spoolss_size_driverdir_info_1(info);
5107 if (!alloc_buffer_size(buffer, *needed)) {
5109 return ERROR_INSUFFICIENT_BUFFER;
5112 new_smb_io_driverdir_1("", buffer, info, 0);
5116 if (*needed > offered)
5117 return ERROR_INSUFFICIENT_BUFFER;
5119 return NT_STATUS_NO_PROBLEMO;
5122 /****************************************************************************
5123 ****************************************************************************/
5124 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5125 NEW_BUFFER *buffer, uint32 offered,
5128 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5134 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5136 return ERROR_INVALID_LEVEL;
5140 /****************************************************************************
5141 ****************************************************************************/
5142 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5143 uint32 in_value_len, uint32 in_data_len,
5144 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5146 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5148 NT_PRINTER_INFO_LEVEL *printer = NULL;
5153 uint32 biggest_valuesize;
5154 uint32 biggest_datasize;
5156 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5161 ZERO_STRUCT(printer);
5163 *out_max_value_len=0;
5169 *out_max_data_len=0;
5173 DEBUG(5,("spoolss_enumprinterdata\n"));
5175 if (!OPEN_HANDLE(Printer)) {
5176 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5177 return ERROR_INVALID_HANDLE;
5180 if (!get_printer_snum(handle, &snum))
5181 return ERROR_INVALID_HANDLE;
5183 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5184 return ERROR_INVALID_HANDLE;
5187 * The NT machine wants to know the biggest size of value and data
5189 * cf: MSDN EnumPrinterData remark section
5191 if ( (in_value_len==0) && (in_data_len==0) ) {
5192 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5196 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5197 * if this parameter size doesn't exist.
5198 * Ok - my opinion here is that the client is not asking for the greatest
5199 * possible size of all the parameters, but is asking specifically for the size needed
5200 * for this specific parameter. In that case we can remove the loop below and
5201 * simplify this lookup code considerably. JF - comments welcome. JRA.
5204 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5206 free_a_printer(&printer, 2);
5207 return ERROR_NO_MORE_ITEMS;
5215 biggest_valuesize=0;
5218 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5219 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5220 if (data_len > biggest_datasize) biggest_datasize=data_len;
5222 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5230 * I think this is correct, it doesn't break APW and
5231 * allows Gerald's Win32 test programs to work correctly,
5232 * but may need altering.... JRA.
5235 if (param_index == 0) {
5236 /* No parameters found. */
5237 free_a_printer(&printer, 2);
5238 return ERROR_NO_MORE_ITEMS;
5241 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5242 *out_value_len=2*(1+biggest_valuesize);
5243 *out_data_len=biggest_datasize;
5245 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5247 free_a_printer(&printer, 2);
5248 return NT_STATUS_NO_PROBLEMO;
5252 * the value len is wrong in NT sp3
5253 * that's the number of bytes not the number of unicode chars
5256 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5258 free_a_printer(&printer, 2);
5259 return ERROR_NO_MORE_ITEMS;
5262 free_a_printer(&printer, 2);
5266 * - counted in bytes in the request
5267 * - counted in UNICODE chars in the max reply
5268 * - counted in bytes in the real size
5270 * take a pause *before* coding not *during* coding
5273 *out_max_value_len=(in_value_len/sizeof(uint16));
5274 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5276 return ERROR_NOT_ENOUGH_MEMORY;
5279 ZERO_STRUCTP(*out_value);
5280 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5284 /* the data is counted in bytes */
5285 *out_max_data_len=in_data_len;
5286 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5288 return ERROR_NOT_ENOUGH_MEMORY;
5291 memset(*data_out,'\0',in_data_len);
5292 memcpy(*data_out, data, (size_t)data_len);
5293 *out_data_len=data_len;
5297 return NT_STATUS_NO_PROBLEMO;
5300 /****************************************************************************
5301 ****************************************************************************/
5302 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5303 const UNISTR2 *value,
5308 uint32 numeric_data)
5310 NT_PRINTER_INFO_LEVEL *printer = NULL;
5311 NT_PRINTER_PARAM *param = NULL, old_param;
5313 uint32 status = 0x0;
5314 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5316 DEBUG(5,("spoolss_setprinterdata\n"));
5318 if (!OPEN_HANDLE(Printer)) {
5319 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5320 return ERROR_INVALID_HANDLE;
5323 if (!get_printer_snum(handle, &snum))
5324 return ERROR_INVALID_HANDLE;
5326 status = get_a_printer(&printer, 2, lp_servicename(snum));
5328 return ERROR_INVALID_NAME;
5330 convert_specific_param(¶m, value , type, data, real_len);
5332 /* Check if we are making any changes or not. Return true if
5333 nothing is actually changing. */
5335 ZERO_STRUCT(old_param);
5337 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5338 &old_param.type, (unsigned int *)&old_param.data_len)) {
5340 if (param->type == old_param.type &&
5341 param->data_len == old_param.data_len &&
5342 memcmp(param->data, old_param.data,
5343 old_param.data_len) == 0) {
5345 DEBUG(3, ("setprinterdata hasn't changed\n"));
5346 status = NT_STATUS_NO_PROBLEMO;
5353 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5354 DEBUG(3, ("security descriptor change denied by existing "
5355 "security descriptor\n"));
5356 status = ERROR_ACCESS_DENIED;
5360 unlink_specific_param_if_exist(printer->info_2, param);
5362 add_a_specific_param(printer->info_2, ¶m);
5363 status = mod_a_printer(*printer, 2);
5366 free_a_printer(&printer, 2);
5368 free_nt_printer_param(¶m);
5369 safe_free(old_param.data);
5374 /****************************************************************************
5375 ****************************************************************************/
5376 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5378 NT_PRINTER_INFO_LEVEL *printer = NULL;
5379 NT_PRINTER_PARAM param;
5381 uint32 status = 0x0;
5382 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5384 DEBUG(5,("spoolss_deleteprinterdata\n"));
5386 if (!OPEN_HANDLE(Printer)) {
5387 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5388 return ERROR_INVALID_HANDLE;
5391 if (!get_printer_snum(handle, &snum))
5392 return ERROR_INVALID_HANDLE;
5394 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5395 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5396 "security descriptor\n"));
5397 return ERROR_ACCESS_DENIED;
5400 status = get_a_printer(&printer, 2, lp_servicename(snum));
5402 return ERROR_INVALID_NAME;
5404 ZERO_STRUCTP(¶m);
5405 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5407 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5408 status = ERROR_INVALID_PARAMETER;
5410 status = mod_a_printer(*printer, 2);
5412 free_a_printer(&printer, 2);
5416 /****************************************************************************
5417 ****************************************************************************/
5418 uint32 _spoolss_addform( POLICY_HND *handle,
5423 nt_forms_struct *list=NULL;
5424 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5426 DEBUG(5,("spoolss_addform\n"));
5428 if (!OPEN_HANDLE(Printer)) {
5429 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5430 return ERROR_INVALID_HANDLE;
5433 count=get_ntforms(&list);
5434 if(!add_a_form(&list, form, &count))
5435 return ERROR_NOT_ENOUGH_MEMORY;
5436 write_ntforms(&list, count);
5443 /****************************************************************************
5444 ****************************************************************************/
5445 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5449 nt_forms_struct *list=NULL;
5450 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5452 DEBUG(5,("spoolss_deleteform\n"));
5454 if (!OPEN_HANDLE(Printer)) {
5455 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5456 return ERROR_INVALID_HANDLE;
5459 count = get_ntforms(&list);
5460 if(!delete_a_form(&list, form_name, &count, &ret))
5461 return ERROR_INVALID_PARAMETER;
5468 /****************************************************************************
5469 ****************************************************************************/
5470 uint32 _spoolss_setform( POLICY_HND *handle,
5471 const UNISTR2 *uni_name,
5476 nt_forms_struct *list=NULL;
5477 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5479 DEBUG(5,("spoolss_setform\n"));
5481 if (!OPEN_HANDLE(Printer)) {
5482 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5483 return ERROR_INVALID_HANDLE;
5485 count=get_ntforms(&list);
5486 update_a_form(&list, form, count);
5487 write_ntforms(&list, count);
5494 /****************************************************************************
5495 enumprintprocessors level 1.
5496 ****************************************************************************/
5497 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5499 PRINTPROCESSOR_1 *info_1=NULL;
5501 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5502 return ERROR_NOT_ENOUGH_MEMORY;
5506 init_unistr(&info_1->name, "winprint");
5508 *needed += spoolss_size_printprocessor_info_1(info_1);
5510 if (!alloc_buffer_size(buffer, *needed))
5511 return ERROR_INSUFFICIENT_BUFFER;
5513 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5517 if (*needed > offered) {
5519 return ERROR_INSUFFICIENT_BUFFER;
5522 return NT_STATUS_NO_PROBLEMO;
5525 /****************************************************************************
5526 ****************************************************************************/
5527 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5528 NEW_BUFFER *buffer, uint32 offered,
5529 uint32 *needed, uint32 *returned)
5531 DEBUG(5,("spoolss_enumprintprocessors\n"));
5534 * Enumerate the print processors ...
5536 * Just reply with "winprint", to keep NT happy
5537 * and I can use my nice printer checker.
5545 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5547 return ERROR_INVALID_LEVEL;
5551 /****************************************************************************
5552 enumprintprocdatatypes level 1.
5553 ****************************************************************************/
5554 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5556 PRINTPROCDATATYPE_1 *info_1=NULL;
5558 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5559 return ERROR_NOT_ENOUGH_MEMORY;
5563 init_unistr(&info_1->name, "RAW");
5565 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5567 if (!alloc_buffer_size(buffer, *needed))
5568 return ERROR_INSUFFICIENT_BUFFER;
5570 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5574 if (*needed > offered) {
5576 return ERROR_INSUFFICIENT_BUFFER;
5579 return NT_STATUS_NO_PROBLEMO;
5582 /****************************************************************************
5583 ****************************************************************************/
5584 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5585 NEW_BUFFER *buffer, uint32 offered,
5586 uint32 *needed, uint32 *returned)
5588 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5595 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5597 return ERROR_INVALID_LEVEL;
5601 /****************************************************************************
5602 enumprintmonitors level 1.
5603 ****************************************************************************/
5604 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5606 PRINTMONITOR_1 *info_1=NULL;
5608 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5609 return ERROR_NOT_ENOUGH_MEMORY;
5613 init_unistr(&info_1->name, "Local Port");
5615 *needed += spoolss_size_printmonitor_info_1(info_1);
5617 if (!alloc_buffer_size(buffer, *needed))
5618 return ERROR_INSUFFICIENT_BUFFER;
5620 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5624 if (*needed > offered) {
5626 return ERROR_INSUFFICIENT_BUFFER;
5629 return NT_STATUS_NO_PROBLEMO;
5632 /****************************************************************************
5633 enumprintmonitors level 2.
5634 ****************************************************************************/
5635 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5637 PRINTMONITOR_2 *info_2=NULL;
5639 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5640 return ERROR_NOT_ENOUGH_MEMORY;
5644 init_unistr(&info_2->name, "Local Port");
5645 init_unistr(&info_2->environment, "Windows NT X86");
5646 init_unistr(&info_2->dll_name, "localmon.dll");
5648 *needed += spoolss_size_printmonitor_info_2(info_2);
5650 if (!alloc_buffer_size(buffer, *needed))
5651 return ERROR_INSUFFICIENT_BUFFER;
5653 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5657 if (*needed > offered) {
5659 return ERROR_INSUFFICIENT_BUFFER;
5662 return NT_STATUS_NO_PROBLEMO;
5665 /****************************************************************************
5666 ****************************************************************************/
5667 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5668 NEW_BUFFER *buffer, uint32 offered,
5669 uint32 *needed, uint32 *returned)
5671 DEBUG(5,("spoolss_enumprintmonitors\n"));
5674 * Enumerate the print monitors ...
5676 * Just reply with "Local Port", to keep NT happy
5677 * and I can use my nice printer checker.
5685 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5687 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5689 return ERROR_INVALID_LEVEL;
5693 /****************************************************************************
5694 ****************************************************************************/
5695 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5699 JOB_INFO_1 *info_1=NULL;
5701 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5703 if (info_1 == NULL) {
5705 return ERROR_NOT_ENOUGH_MEMORY;
5708 for (i=0; i<count && found==False; i++) {
5709 if (queue[i].job==(int)jobid)
5716 /* I shoud reply something else ... I can't find the good one */
5717 return NT_STATUS_NO_PROBLEMO;
5720 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5724 *needed += spoolss_size_job_info_1(info_1);
5726 if (!alloc_buffer_size(buffer, *needed)) {
5728 return ERROR_INSUFFICIENT_BUFFER;
5731 new_smb_io_job_info_1("", buffer, info_1, 0);
5735 if (*needed > offered)
5736 return ERROR_INSUFFICIENT_BUFFER;
5738 return NT_STATUS_NO_PROBLEMO;
5742 /****************************************************************************
5743 ****************************************************************************/
5744 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5749 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5751 ZERO_STRUCTP(info_2);
5753 if (info_2 == NULL) {
5755 return ERROR_NOT_ENOUGH_MEMORY;
5758 for (i=0; i<count && found==False; i++) {
5759 if (queue[i].job==(int)jobid)
5766 /* I shoud reply something else ... I can't find the good one */
5767 return NT_STATUS_NO_PROBLEMO;
5770 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5774 *needed += spoolss_size_job_info_2(info_2);
5776 if (!alloc_buffer_size(buffer, *needed)) {
5778 return ERROR_INSUFFICIENT_BUFFER;
5781 new_smb_io_job_info_2("", buffer, info_2, 0);
5783 free_job_info_2(info_2);
5785 if (*needed > offered)
5786 return ERROR_INSUFFICIENT_BUFFER;
5788 return NT_STATUS_NO_PROBLEMO;
5791 /****************************************************************************
5792 ****************************************************************************/
5793 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5794 NEW_BUFFER *buffer, uint32 offered,
5799 print_queue_struct *queue=NULL;
5800 print_status_struct prt_status;
5802 DEBUG(5,("spoolss_getjob\n"));
5804 memset(&prt_status, 0, sizeof(prt_status));
5808 if (!get_printer_snum(handle, &snum))
5809 return ERROR_INVALID_HANDLE;
5811 count = print_queue_status(snum, &queue, &prt_status);
5813 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5814 count, prt_status.status, prt_status.message));
5818 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5820 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5823 return ERROR_INVALID_LEVEL;