merge from appliance head
[Samba/gbeck.git] / source / rpc_server / srv_spoolss_nt.c
blobcd67a3b88a1f19f5fb260d8447a3c72bd053fec2
1 #define OLD_NTDOMAIN 1
2 /*
3 * Unix SMB/Netbios implementation.
4 * Version 1.9.
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.
25 #include "includes.h"
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
32 #endif
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{
42 ubi_dlNode Next;
43 ubi_dlNode Prev;
45 BOOL open;
46 BOOL document_started;
47 BOOL page_started;
48 int jobid; /* jobid in printing backend */
49 POLICY_HND printer_hnd;
50 BOOL printer_type;
51 union {
52 fstring handlename;
53 fstring printerservername;
54 } dev;
55 uint32 type;
56 uint32 access;
57 struct {
58 uint32 flags;
59 uint32 options;
60 fstring localmachine;
61 uint32 printerlocal;
62 SPOOL_NOTIFY_OPTION *option;
63 POLICY_HND client_hnd;
64 uint32 client_connected;
65 } notify;
66 struct {
67 fstring machine;
68 fstring user;
69 } client;
70 } Printer_entry;
72 typedef struct _counter_printer_0 {
73 ubi_dlNode Next;
74 ubi_dlNode Prev;
76 int snum;
77 uint32 counter;
78 } 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)
92 switch (v) {
93 case LPQ_PAUSED:
94 return PRINTER_STATUS_PAUSED;
95 case LPQ_QUEUED:
96 case LPQ_SPOOLING:
97 case LPQ_PRINTING:
98 return 0;
100 return 0;
103 static int nt_printq_status(int v)
105 switch (v) {
106 case LPQ_PAUSED:
107 return PRINTER_STATUS_PAUSED;
108 case LPQ_QUEUED:
109 case LPQ_SPOOLING:
110 case LPQ_PRINTING:
111 return 0;
113 return 0;
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... */
136 prt_hnd_low++;
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));*/
160 return find_printer;
164 DEBUG(3,("Whoops, Printer handle not found: "));
165 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
166 return NULL;
169 /****************************************************************************
170 clear an handle
171 ****************************************************************************/
172 static void clear_handle(POLICY_HND *hnd)
174 ZERO_STRUCTP(hnd);
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
180 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
182 uint32 status;
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"));
187 return False;
190 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
191 return False;
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
195 if(!spoolss_disconnect_from_client(&cli))
196 return False;
198 message_deregister(MSG_PRINTER_NOTIFY);
201 smb_connections--;
203 return True;
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)));
215 return False;
218 if (Printer->notify.client_connected==True)
219 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
220 return ERROR_INVALID_HANDLE;
222 Printer->open=False;
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;
231 clear_handle(hnd);
233 ubi_dlRemThis(&Printer_list, Printer);
235 safe_free(Printer);
237 return True;
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)));
249 return False;
252 if (del_a_printer(Printer->dev.handlename) != 0) {
253 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
254 return False;
257 if (*lp_deleteprinter_cmd()) {
259 pid_t local_pid = sys_getpid();
260 char *cmd = lp_deleteprinter_cmd();
261 char *path;
262 pstring tmp_file;
263 pstring command;
264 int ret;
265 int i;
267 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
268 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
269 else
270 path = tmpdir();
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);
277 unlink(tmp_file);
278 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
279 ret = smbrun(command, tmp_file, False);
280 if (ret != 0) {
281 unlink(tmp_file);
282 return False;
284 DEBUGADD(10,("returned [%d]\n", ret));
285 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
286 unlink(tmp_file);
288 /* Send SIGHUP to process group... is there a better way? */
289 kill(0, SIGHUP);
291 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
292 lp_remove_service( i );
293 lp_killservice( i );
294 return True;
295 } else
296 return False;
299 return True;
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)));
311 return False;
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:
320 return False;
321 default:
322 return False;
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)));
335 return False;
338 DEBUG(4,("Setting printer access=%x\n", access_required));
339 Printer->access = access_required;
340 return True;
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));
354 return False;
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;
362 /* it's a printer */
363 else {
364 DEBUGADD(4,("Printer is a printer\n"));
365 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
368 return True;
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;
378 int snum;
379 int n_services=lp_numservices();
380 char *aprinter;
381 BOOL found=False;
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));
388 return True;
391 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
392 return False;
394 aprinter=strchr(handlename+2, '\\');
395 aprinter++;
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++) {
408 char *printername;
410 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
411 continue;
413 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
415 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
416 continue;
418 printername=strchr(printer->info_2->printername+2, '\\');
419 printername++;
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);
426 continue;
429 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
430 free_a_printer(&printer, 2);
431 continue;
434 found=True;
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
440 * \\server\share
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
448 if (found==False) {
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) ) )
454 continue;
456 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
458 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
459 continue;
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);
466 continue;
469 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
470 free_a_printer(&printer, 2);
471 continue;
474 found=True;
478 if (found==False) {
479 DEBUGADD(4,("Printer not found\n"));
480 return False;
483 snum--;
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);
492 return True;
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));
504 clear_handle(hnd);
505 create_printer_hnd(hnd);
507 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
508 return False;
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);
521 return False;
524 if (!set_printer_hnd_name(new_printer, name)) {
525 close_printer_handle(hnd);
526 return False;
529 return True;
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))
540 return False;
542 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
543 return False;
545 return True;
548 /****************************************************************************
549 allocate more memory for a BUFFER.
550 ****************************************************************************/
551 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
553 prs_struct *ps;
554 uint32 extra_space;
555 uint32 old_offset;
557 ps= &buffer->prs;
559 /* damn, I'm doing the reverse operation of prs_grow() :) */
560 if (buffer_size < prs_data_size(ps))
561 extra_space=0;
562 else
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))
573 return False;
575 prs_set_offset(ps, old_offset);
577 buffer->string_at_end=prs_data_size(ps);
579 return True;
582 /***************************************************************************
583 receive the notify message
584 ****************************************************************************/
585 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
587 fstring printer;
588 uint32 status;
589 Printer_entry *find_printer;
591 *printer = '\0';
592 fstrcpy(printer,buf);
594 if (len == 0) {
595 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
596 return;
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))
613 continue;
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 /***************************************************************************
622 send a notify event
623 ****************************************************************************/
624 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
626 fstring printer;
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)));
632 return False;
635 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
636 fstrcpy(printer, Printer->dev.handlename);
637 else
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... */
645 return True;
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,
656 POLICY_HND *handle)
658 fstring name;
660 if (printername == NULL)
661 return ERROR_INVALID_PRINTER_NAME;
663 /* some sanity check because you can open a printer or a print server */
664 /* aka: \\server\printer or \\server */
665 unistr2_to_ascii(name, printername, sizeof(name)-1);
667 DEBUGADD(3,("checking name: %s\n",name));
669 if (!open_printer_hnd(handle, name))
670 return ERROR_INVALID_PRINTER_NAME;
673 if (printer_default->datatype_ptr != NULL)
675 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
676 set_printer_hnd_datatype(handle, datatype);
678 else
679 set_printer_hnd_datatype(handle, "");
682 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
683 close_printer_handle(handle);
684 return ERROR_ACCESS_DENIED;
687 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
688 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
689 Then both Win2k and WinNT clients try an OpenPrinterEx with
690 SERVER_ALL_ACCESS, which we force to fail. Then they try
691 OpenPrinterEx with SERVER_READ which we allow. This lets the
692 client view printer folder, but does not show the MSAPW.
694 Note: this test needs code to check access rights here too. Jeremy
695 could you look at this? */
697 if (handle_is_printserver(handle) &&
698 !lp_ms_add_printer_wizard()) {
699 if (printer_default->access_required == 0)
700 return NT_STATUS_NO_PROBLEMO;
701 else if (printer_default->access_required != (SERVER_READ))
702 return ERROR_ACCESS_DENIED;
705 return NT_STATUS_NO_PROBLEMO;
708 /****************************************************************************
709 ****************************************************************************/
710 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
711 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
713 switch (level) {
714 case 2:
715 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
716 break;
717 default:
718 break;
721 return True;
724 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
725 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
727 switch (level) {
728 case 3:
729 printer->info_3=NULL;
730 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
731 break;
732 case 6:
733 printer->info_6=NULL;
734 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
735 break;
736 default:
737 break;
740 return True;
743 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
745 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
746 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
748 nt_devmode->specversion=devmode->specversion;
749 nt_devmode->driverversion=devmode->driverversion;
750 nt_devmode->size=devmode->size;
751 nt_devmode->driverextra=devmode->driverextra;
752 nt_devmode->fields=devmode->fields;
753 nt_devmode->orientation=devmode->orientation;
754 nt_devmode->papersize=devmode->papersize;
755 nt_devmode->paperlength=devmode->paperlength;
756 nt_devmode->paperwidth=devmode->paperwidth;
757 nt_devmode->scale=devmode->scale;
758 nt_devmode->copies=devmode->copies;
759 nt_devmode->defaultsource=devmode->defaultsource;
760 nt_devmode->printquality=devmode->printquality;
761 nt_devmode->color=devmode->color;
762 nt_devmode->duplex=devmode->duplex;
763 nt_devmode->yresolution=devmode->yresolution;
764 nt_devmode->ttoption=devmode->ttoption;
765 nt_devmode->collate=devmode->collate;
767 nt_devmode->logpixels=devmode->logpixels;
768 nt_devmode->bitsperpel=devmode->bitsperpel;
769 nt_devmode->pelswidth=devmode->pelswidth;
770 nt_devmode->pelsheight=devmode->pelsheight;
771 nt_devmode->displayflags=devmode->displayflags;
772 nt_devmode->displayfrequency=devmode->displayfrequency;
773 nt_devmode->icmmethod=devmode->icmmethod;
774 nt_devmode->icmintent=devmode->icmintent;
775 nt_devmode->mediatype=devmode->mediatype;
776 nt_devmode->dithertype=devmode->dithertype;
777 nt_devmode->reserved1=devmode->reserved1;
778 nt_devmode->reserved2=devmode->reserved2;
779 nt_devmode->panningwidth=devmode->panningwidth;
780 nt_devmode->panningheight=devmode->panningheight;
782 safe_free(nt_devmode->private);
783 if (nt_devmode->driverextra != 0) {
784 /* if we had a previous private delete it and make a new one */
785 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
786 return False;
787 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
789 else {
790 nt_devmode->private = NULL;
793 return True;
796 /********************************************************************
797 * api_spoolss_closeprinter
798 ********************************************************************/
799 uint32 _spoolss_closeprinter(POLICY_HND *handle)
801 Printer_entry *Printer=find_printer_index_by_hnd(handle);
803 if (Printer && Printer->document_started)
804 _spoolss_enddocprinter(handle); /* print job was not closed */
806 if (!close_printer_handle(handle))
807 return ERROR_INVALID_HANDLE;
809 return NT_STATUS_NO_PROBLEMO;
812 /********************************************************************
813 * api_spoolss_deleteprinter
814 ********************************************************************/
815 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
817 Printer_entry *Printer=find_printer_index_by_hnd(handle);
819 if (Printer && Printer->document_started)
820 _spoolss_enddocprinter(handle); /* print job was not closed */
822 if (!delete_printer_handle(handle))
823 return ERROR_INVALID_HANDLE;
825 srv_spoolss_sendnotify(handle);
827 return NT_STATUS_NO_PROBLEMO;
830 /********************************************************************
831 GetPrinterData on a printer server Handle.
832 ********************************************************************/
833 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
835 int i;
837 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
839 if (!strcmp(value, "BeepEnabled")) {
840 *type = 0x4;
841 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
842 return False;
843 SIVAL(*data, 0, 0x01);
844 *needed = 0x4;
845 return True;
848 if (!strcmp(value, "EventLog")) {
849 *type = 0x4;
850 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
851 return False;
852 SIVAL(*data, 0, 0x1B);
853 *needed = 0x4;
854 return True;
857 if (!strcmp(value, "NetPopup")) {
858 *type = 0x4;
859 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
860 return False;
861 SIVAL(*data, 0, 0x01);
862 *needed = 0x4;
863 return True;
866 if (!strcmp(value, "MajorVersion")) {
867 *type = 0x4;
868 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
869 return False;
870 SIVAL(*data, 0, 0x02);
871 *needed = 0x4;
872 return True;
875 if (!strcmp(value, "DefaultSpoolDirectory")) {
876 pstring string="You are using a Samba server";
877 *type = 0x1;
878 *needed = 2*(strlen(string)+1);
879 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
880 return False;
881 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
883 /* it's done by hand ready to go on the wire */
884 for (i=0; i<strlen(string); i++) {
885 (*data)[2*i]=string[i];
886 (*data)[2*i+1]='\0';
888 return True;
891 if (!strcmp(value, "Architecture")) {
892 pstring string="Windows NT x86";
893 *type = 0x1;
894 *needed = 2*(strlen(string)+1);
895 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
896 return False;
897 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
898 for (i=0; i<strlen(string); i++) {
899 (*data)[2*i]=string[i];
900 (*data)[2*i+1]='\0';
902 return True;
905 return False;
908 /********************************************************************
909 GetPrinterData on a printer Handle.
910 ********************************************************************/
911 static BOOL getprinterdata_printer(POLICY_HND *handle,
912 fstring value, uint32 *type,
913 uint8 **data, uint32 *needed, uint32 in_size )
915 NT_PRINTER_INFO_LEVEL *printer = NULL;
916 int snum=0;
917 uint8 *idata=NULL;
918 uint32 len;
919 Printer_entry *Printer = find_printer_index_by_hnd(handle);
921 DEBUG(5,("getprinterdata_printer\n"));
923 if (!OPEN_HANDLE(Printer)) {
924 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
925 return False;
928 if(!get_printer_snum(handle, &snum))
929 return False;
931 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
932 return False;
934 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
935 free_a_printer(&printer, 2);
936 return False;
939 free_a_printer(&printer, 2);
941 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
943 if (in_size) {
944 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
945 return False;
948 memset(*data, 0, in_size *sizeof(uint8));
949 /* copy the min(in_size, len) */
950 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
951 } else {
952 *data = NULL;
955 *needed = len;
957 DEBUG(5,("getprinterdata_printer:copy done\n"));
959 safe_free(idata);
961 return True;
964 /********************************************************************
965 * spoolss_getprinterdata
966 ********************************************************************/
967 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
968 uint32 in_size,
969 uint32 *type,
970 uint32 *out_size,
971 uint8 **data,
972 uint32 *needed)
974 fstring value;
975 BOOL found=False;
976 Printer_entry *Printer = find_printer_index_by_hnd(handle);
979 * Reminder: when it's a string, the length is in BYTES
980 * even if UNICODE is negociated.
982 * JFM, 4/19/1999
985 *out_size=in_size;
987 /* in case of problem, return some default values */
988 *needed=0;
989 *type=0;
991 DEBUG(4,("_spoolss_getprinterdata\n"));
993 if (!OPEN_HANDLE(Printer)) {
994 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
995 return ERROR_NOT_ENOUGH_MEMORY;
996 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
997 return ERROR_INVALID_HANDLE;
1000 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1002 if (handle_is_printserver(handle))
1003 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1004 else
1005 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
1007 if (found==False) {
1008 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1009 /* reply this param doesn't exist */
1010 if (*out_size) {
1011 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1012 return ERROR_NOT_ENOUGH_MEMORY;
1013 memset(*data, '\0', *out_size*sizeof(uint8));
1014 } else {
1015 *data = NULL;
1018 return ERROR_INVALID_PARAMETER;
1021 if (*needed > *out_size)
1022 return ERROR_MORE_DATA;
1023 else
1024 return NT_STATUS_NO_PROBLEMO;
1027 /***************************************************************************
1028 connect to the client
1029 ****************************************************************************/
1030 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1032 uint32 status;
1035 * If it's the first connection, contact the client
1036 * and connect to the IPC$ share anonumously
1038 if (smb_connections==0) {
1039 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1040 return False;
1041 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1045 smb_connections++;
1047 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1048 return False;
1050 return True;
1053 /********************************************************************
1054 * _spoolss_rffpcnex
1055 * ReplyFindFirstPrinterChangeNotifyEx
1057 * jfmxxxx: before replying OK: status=0
1058 * should do a rpc call to the workstation asking ReplyOpenPrinter
1059 * have to code it, later.
1061 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1062 * called from api_spoolss_rffpcnex
1063 ********************************************************************/
1064 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1065 const UNISTR2 *localmachine, uint32 printerlocal,
1066 SPOOL_NOTIFY_OPTION *option)
1068 /* store the notify value in the printer struct */
1070 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1072 if (!OPEN_HANDLE(Printer)) {
1073 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1074 return ERROR_INVALID_HANDLE;
1077 Printer->notify.flags=flags;
1078 Printer->notify.options=options;
1079 Printer->notify.printerlocal=printerlocal;
1080 Printer->notify.option=option;
1081 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1083 /* connect to the client machine and send a ReplyOpenPrinter */
1084 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1085 Printer->notify.printerlocal, 1,
1086 &Printer->notify.client_hnd))
1087 Printer->notify.client_connected=True;
1089 return NT_STATUS_NO_PROBLEMO;
1092 /*******************************************************************
1093 * fill a notify_info_data with the servername
1094 ********************************************************************/
1095 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1096 NT_PRINTER_INFO_LEVEL *printer)
1098 pstring temp_name;
1100 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1102 data->notify_data.data.length= (uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1103 temp_name, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1106 /*******************************************************************
1107 * fill a notify_info_data with the printername (not including the servername).
1108 ********************************************************************/
1109 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
1110 NT_PRINTER_INFO_LEVEL *printer)
1112 /* the notify name should not contain the \\server\ part */
1113 char *p = strrchr(printer->info_2->printername, '\\');
1114 if (!p) {
1115 p = printer->info_2->printername;
1116 } else {
1117 p++;
1120 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1121 p, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1124 /*******************************************************************
1125 * fill a notify_info_data with the servicename
1126 ********************************************************************/
1127 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1129 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1130 lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
1133 /*******************************************************************
1134 * fill a notify_info_data with the port name
1135 ********************************************************************/
1136 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1138 /* even if it's strange, that's consistant in all the code */
1140 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1141 printer->info_2->portname, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
1144 /*******************************************************************
1145 * fill a notify_info_data with the printername
1146 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1147 * but it doesn't exist, have to see what to do
1148 ********************************************************************/
1149 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1151 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1152 printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1155 /*******************************************************************
1156 * fill a notify_info_data with the comment
1157 ********************************************************************/
1158 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1160 if (*printer->info_2->comment == '\0')
1161 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1162 lp_comment(snum), sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1163 else
1164 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1165 printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1168 /*******************************************************************
1169 * fill a notify_info_data with the comment
1170 * jfm:xxxx incorrect, have to create a new smb.conf option
1171 * location = "Room 1, floor 2, building 3"
1172 ********************************************************************/
1173 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1175 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1176 printer->info_2->location, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1179 /*******************************************************************
1180 * fill a notify_info_data with the device mode
1181 * jfm:xxxx don't to it for know but that's a real problem !!!
1182 ********************************************************************/
1183 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1187 /*******************************************************************
1188 * fill a notify_info_data with the separator file name
1189 * jfm:xxxx just return no file could add an option to smb.conf
1190 * separator file = "separator.txt"
1191 ********************************************************************/
1192 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1194 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1195 printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True) - sizeof(uint16))/sizeof(uint16));
1198 /*******************************************************************
1199 * fill a notify_info_data with the print processor
1200 * jfm:xxxx return always winprint to indicate we don't do anything to it
1201 ********************************************************************/
1202 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1204 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1205 printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1208 /*******************************************************************
1209 * fill a notify_info_data with the print processor options
1210 * jfm:xxxx send an empty string
1211 ********************************************************************/
1212 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1214 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1215 printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1218 /*******************************************************************
1219 * fill a notify_info_data with the data type
1220 * jfm:xxxx always send RAW as data type
1221 ********************************************************************/
1222 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1224 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1225 printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1228 /*******************************************************************
1229 * fill a notify_info_data with the security descriptor
1230 * jfm:xxxx send an null pointer to say no security desc
1231 * have to implement security before !
1232 ********************************************************************/
1233 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1235 data->notify_data.data.length=0;
1236 data->notify_data.data.string[0]=0x00;
1239 /*******************************************************************
1240 * fill a notify_info_data with the attributes
1241 * jfm:xxxx a samba printer is always shared
1242 ********************************************************************/
1243 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1245 data->notify_data.value[0] = printer->info_2->attributes;
1248 /*******************************************************************
1249 * fill a notify_info_data with the priority
1250 ********************************************************************/
1251 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1253 data->notify_data.value[0] = printer->info_2->priority;
1256 /*******************************************************************
1257 * fill a notify_info_data with the default priority
1258 ********************************************************************/
1259 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1261 data->notify_data.value[0] = printer->info_2->default_priority;
1264 /*******************************************************************
1265 * fill a notify_info_data with the start time
1266 ********************************************************************/
1267 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1269 data->notify_data.value[0] = printer->info_2->starttime;
1272 /*******************************************************************
1273 * fill a notify_info_data with the until time
1274 ********************************************************************/
1275 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1277 data->notify_data.value[0] = printer->info_2->untiltime;
1280 /*******************************************************************
1281 * fill a notify_info_data with the status
1282 ********************************************************************/
1283 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1285 int count;
1286 print_queue_struct *q=NULL;
1287 print_status_struct status;
1289 memset(&status, 0, sizeof(status));
1290 count = print_queue_status(snum, &q, &status);
1291 data->notify_data.value[0]=(uint32) status.status;
1292 safe_free(q);
1295 /*******************************************************************
1296 * fill a notify_info_data with the number of jobs queued
1297 ********************************************************************/
1298 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1300 print_queue_struct *q=NULL;
1301 print_status_struct status;
1303 memset(&status, 0, sizeof(status));
1304 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1305 safe_free(q);
1308 /*******************************************************************
1309 * fill a notify_info_data with the average ppm
1310 ********************************************************************/
1311 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1313 /* always respond 8 pages per minutes */
1314 /* a little hard ! */
1315 data->notify_data.value[0] = printer->info_2->averageppm;
1318 /*******************************************************************
1319 * fill a notify_info_data with username
1320 ********************************************************************/
1321 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1323 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1324 queue->user, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1327 /*******************************************************************
1328 * fill a notify_info_data with job status
1329 ********************************************************************/
1330 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1332 data->notify_data.value[0]=nt_printj_status(queue->status);
1335 /*******************************************************************
1336 * fill a notify_info_data with job name
1337 ********************************************************************/
1338 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1340 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1341 queue->file, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1344 /*******************************************************************
1345 * fill a notify_info_data with job status
1346 ********************************************************************/
1347 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1349 char *p = "unknown";
1351 switch (queue->status) {
1352 case LPQ_QUEUED:
1353 p = "Queued";
1354 break;
1355 case LPQ_PAUSED:
1356 p = ""; /* NT provides the paused string */
1357 break;
1358 case LPQ_SPOOLING:
1359 p = "Spooling";
1360 break;
1361 case LPQ_PRINTING:
1362 p = "Printing";
1363 break;
1365 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1366 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1369 /*******************************************************************
1370 * fill a notify_info_data with job time
1371 ********************************************************************/
1372 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1374 data->notify_data.value[0]=0x0;
1377 /*******************************************************************
1378 * fill a notify_info_data with job size
1379 ********************************************************************/
1380 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1382 data->notify_data.value[0]=queue->size;
1385 /*******************************************************************
1386 * fill a notify_info_data with job position
1387 ********************************************************************/
1388 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1390 data->notify_data.value[0]=queue->job;
1393 /*******************************************************************
1394 * fill a notify_info_data with submitted time
1395 ********************************************************************/
1396 static void spoolss_notify_submitted_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1398 struct tm *t;
1400 t=gmtime(&queue->time);
1402 data->notify_data.data.length = sizeof(SYSTEMTIME);
1403 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1406 #define END 65535
1408 struct s_notify_info_data_table
1410 uint16 type;
1411 uint16 field;
1412 char *name;
1413 uint32 size;
1414 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1415 print_queue_struct *queue,
1416 NT_PRINTER_INFO_LEVEL *printer);
1419 struct s_notify_info_data_table notify_info_data_table[] =
1421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1471 { END, END, "", END, NULL }
1474 /*******************************************************************
1475 return the size of info_data structure
1476 ********************************************************************/
1477 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1479 int i=0;
1481 while (notify_info_data_table[i].type != END)
1483 if ( (notify_info_data_table[i].type == type ) &&
1484 (notify_info_data_table[i].field == field ) )
1486 return (notify_info_data_table[i].size);
1488 i++;
1490 return (65535);
1493 /*******************************************************************
1494 return the type of notify_info_data
1495 ********************************************************************/
1496 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1498 int i=0;
1500 while (notify_info_data_table[i].type != END)
1502 if ( (notify_info_data_table[i].type == type ) &&
1503 (notify_info_data_table[i].field == field ) )
1505 if (notify_info_data_table[i].size == POINTER)
1507 return (False);
1509 else
1511 return (True);
1514 i++;
1516 return (False);
1519 /****************************************************************************
1520 ****************************************************************************/
1521 static int search_notify(uint16 type, uint16 field, int *value)
1523 int j;
1524 BOOL found;
1526 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1528 if ( (notify_info_data_table[j].type == type ) &&
1529 (notify_info_data_table[j].field == field ) )
1530 found=True;
1532 *value=--j;
1534 if ( found && (notify_info_data_table[j].fn != NULL) )
1535 return True;
1536 else
1537 return False;
1540 /****************************************************************************
1541 ****************************************************************************/
1542 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1544 info_data->type = type;
1545 info_data->field = field;
1546 info_data->reserved = 0;
1547 info_data->id = id;
1548 info_data->size = size_of_notify_info_data(type, field);
1549 info_data->enc_type = type_of_notify_info_data(type, field);
1553 /*******************************************************************
1555 * fill a notify_info struct with info asked
1557 ********************************************************************/
1558 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1560 int field_num,j;
1561 uint16 type;
1562 uint16 field;
1564 SPOOL_NOTIFY_INFO_DATA *current_data;
1565 NT_PRINTER_INFO_LEVEL *printer = NULL;
1566 print_queue_struct *queue=NULL;
1568 DEBUG(4,("construct_notify_printer_info\n"));
1570 type=option_type->type;
1572 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1573 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1574 option_type->count, lp_servicename(snum)));
1576 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1577 return False;
1579 for(field_num=0; field_num<option_type->count; field_num++) {
1580 field = option_type->fields[field_num];
1581 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1583 if (!search_notify(type, field, &j) )
1584 continue;
1586 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1587 return False;
1589 current_data=&info->data[info->count];
1591 construct_info_data(current_data, type, field, id);
1593 DEBUG(10,("construct_notify_printer_info: calling %s\n",
1594 notify_info_data_table[j].name ));
1596 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1598 info->count++;
1601 free_a_printer(&printer, 2);
1602 return True;
1605 /*******************************************************************
1607 * fill a notify_info struct with info asked
1609 ********************************************************************/
1610 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1612 int field_num,j;
1613 uint16 type;
1614 uint16 field;
1616 SPOOL_NOTIFY_INFO_DATA *current_data;
1617 NT_PRINTER_INFO_LEVEL *printer = NULL;
1619 DEBUG(4,("construct_notify_jobs_info\n"));
1621 type = option_type->type;
1623 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1624 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1625 option_type->count));
1627 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1628 return False;
1630 for(field_num=0; field_num<option_type->count; field_num++) {
1631 field = option_type->fields[field_num];
1633 if (!search_notify(type, field, &j) )
1634 continue;
1636 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1637 return False;
1640 current_data=&(info->data[info->count]);
1642 construct_info_data(current_data, type, field, id);
1643 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1644 info->count++;
1647 free_a_printer(&printer, 2);
1648 return True;
1652 * JFM: The enumeration is not that simple, it's even non obvious.
1654 * let's take an example: I want to monitor the PRINTER SERVER for
1655 * the printer's name and the number of jobs currently queued.
1656 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1657 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1659 * I have 3 printers on the back of my server.
1661 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1662 * structures.
1663 * Number Data Id
1664 * 1 printer 1 name 1
1665 * 2 printer 1 cjob 1
1666 * 3 printer 2 name 2
1667 * 4 printer 2 cjob 2
1668 * 5 printer 3 name 3
1669 * 6 printer 3 name 3
1671 * that's the print server case, the printer case is even worse.
1676 /*******************************************************************
1678 * enumerate all printers on the printserver
1679 * fill a notify_info struct with info asked
1681 ********************************************************************/
1682 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1684 int snum;
1685 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1686 int n_services=lp_numservices();
1687 int i;
1688 uint32 id;
1689 SPOOL_NOTIFY_OPTION *option;
1690 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1692 DEBUG(4,("printserver_notify_info\n"));
1694 option=Printer->notify.option;
1695 id=1;
1696 info->version=2;
1697 info->data=NULL;
1698 info->count=0;
1700 for (i=0; i<option->count; i++) {
1701 option_type=&(option->ctr.type[i]);
1703 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1704 continue;
1706 for (snum=0; snum<n_services; snum++)
1707 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1708 if (construct_notify_printer_info(info, snum, option_type, id))
1709 id++;
1713 * Debugging information, don't delete.
1716 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1717 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1718 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1720 for (i=0; i<info->count; i++) {
1721 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1722 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1723 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1727 return NT_STATUS_NO_PROBLEMO;
1730 /*******************************************************************
1732 * fill a notify_info struct with info asked
1734 ********************************************************************/
1735 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1737 int snum;
1738 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1739 int i;
1740 uint32 id;
1741 SPOOL_NOTIFY_OPTION *option;
1742 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1743 int count,j;
1744 print_queue_struct *queue=NULL;
1745 print_status_struct status;
1747 DEBUG(4,("printer_notify_info\n"));
1749 option=Printer->notify.option;
1750 id=0xffffffff;
1751 info->version=2;
1752 info->data=NULL;
1753 info->count=0;
1755 get_printer_snum(hnd, &snum);
1757 for (i=0; i<option->count; i++) {
1758 option_type=&option->ctr.type[i];
1760 switch ( option_type->type ) {
1761 case PRINTER_NOTIFY_TYPE:
1762 if(construct_notify_printer_info(info, snum, option_type, id))
1763 id--;
1764 break;
1766 case JOB_NOTIFY_TYPE:
1767 memset(&status, 0, sizeof(status));
1768 count = print_queue_status(snum, &queue, &status);
1769 for (j=0; j<count; j++)
1770 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1771 safe_free(queue);
1772 break;
1777 * Debugging information, don't delete.
1780 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1781 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1782 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1784 for (i=0; i<info->count; i++) {
1785 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1786 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1787 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1790 return NT_STATUS_NO_PROBLEMO;
1793 /********************************************************************
1794 * spoolss_rfnpcnex
1795 ********************************************************************/
1796 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1797 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1799 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1801 if (!OPEN_HANDLE(Printer)) {
1802 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1803 return ERROR_INVALID_HANDLE;
1806 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1808 /* jfm: the change value isn't used right now.
1809 * we will honour it when
1810 * a) we'll be able to send notification to the client
1811 * b) we'll have a way to communicate between the spoolss process.
1813 * same thing for option->flags
1814 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1815 * I don't have a global notification system, I'm sending back all the
1816 * informations even when _NOTHING_ has changed.
1819 /* just discard the SPOOL_NOTIFY_OPTION */
1820 if (option!=NULL)
1821 safe_free(option->ctr.type);
1823 switch (Printer->printer_type) {
1824 case PRINTER_HANDLE_IS_PRINTSERVER:
1825 return printserver_notify_info(handle, info);
1826 case PRINTER_HANDLE_IS_PRINTER:
1827 return printer_notify_info(handle, info);
1830 return ERROR_INVALID_HANDLE;
1833 /********************************************************************
1834 * construct_printer_info_0
1835 * fill a printer_info_0 struct
1836 ********************************************************************/
1837 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
1839 pstring chaine;
1840 int count;
1841 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1842 counter_printer_0 *session_counter;
1843 uint32 global_counter;
1844 struct tm *t;
1845 time_t setuptime;
1847 print_queue_struct *queue=NULL;
1848 print_status_struct status;
1850 memset(&status, 0, sizeof(status));
1852 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1853 return False;
1855 count = print_queue_status(snum, &queue, &status);
1857 /* check if we already have a counter for this printer */
1858 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1860 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1861 if (session_counter->snum == snum)
1862 break;
1865 /* it's the first time, add it to the list */
1866 if (session_counter==NULL) {
1867 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1868 free_a_printer(&ntprinter, 2);
1869 return False;
1871 ZERO_STRUCTP(session_counter);
1872 session_counter->snum=snum;
1873 session_counter->counter=0;
1874 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1877 /* increment it */
1878 session_counter->counter++;
1880 /* JFM:
1881 * the global_counter should be stored in a TDB as it's common to all the clients
1882 * and should be zeroed on samba startup
1884 global_counter=session_counter->counter;
1886 pstrcpy(chaine,ntprinter->info_2->printername);
1888 init_unistr(&printer->printername, chaine);
1890 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
1891 init_unistr(&printer->servername, chaine);
1893 printer->cjobs = count;
1894 printer->total_jobs = 0;
1895 printer->total_bytes = 0;
1897 setuptime = (time_t)ntprinter->info_2->setuptime;
1898 t=gmtime(&setuptime);
1900 printer->year = t->tm_year+1900;
1901 printer->month = t->tm_mon+1;
1902 printer->dayofweek = t->tm_wday;
1903 printer->day = t->tm_mday;
1904 printer->hour = t->tm_hour;
1905 printer->minute = t->tm_min;
1906 printer->second = t->tm_sec;
1907 printer->milliseconds = 0;
1909 printer->global_counter = global_counter;
1910 printer->total_pages = 0;
1911 printer->major_version = 0x0004; /* NT 4 */
1912 printer->build_version = 0x0565; /* build 1381 */
1913 printer->unknown7 = 0x1;
1914 printer->unknown8 = 0x0;
1915 printer->unknown9 = 0x0;
1916 printer->session_counter = session_counter->counter;
1917 printer->unknown11 = 0x0;
1918 printer->printer_errors = 0x0; /* number of print failure */
1919 printer->unknown13 = 0x0;
1920 printer->unknown14 = 0x1;
1921 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1922 printer->unknown16 = 0x0;
1923 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1924 printer->unknown18 = 0x0;
1925 printer->status = nt_printq_status(status.status);
1926 printer->unknown20 = 0x0;
1927 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1928 printer->unknown22 = 0x0;
1929 printer->unknown23 = 0x6; /* 6 ???*/
1930 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1931 printer->unknown25 = 0;
1932 printer->unknown26 = 0;
1933 printer->unknown27 = 0;
1934 printer->unknown28 = 0;
1935 printer->unknown29 = 0;
1937 safe_free(queue);
1938 free_a_printer(&ntprinter,2);
1939 return (True);
1942 /********************************************************************
1943 * construct_printer_info_1
1944 * fill a printer_info_1 struct
1945 ********************************************************************/
1946 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
1948 pstring chaine;
1949 pstring chaine2;
1950 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1952 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1953 return False;
1955 printer->flags=flags;
1957 if (*ntprinter->info_2->comment == '\0') {
1958 init_unistr(&printer->comment, lp_comment(snum));
1959 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
1960 ntprinter->info_2->drivername, lp_comment(snum));
1962 else {
1963 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1964 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
1965 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1968 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
1970 init_unistr(&printer->description, chaine);
1971 init_unistr(&printer->name, chaine2);
1973 free_a_printer(&ntprinter,2);
1975 return True;
1978 /****************************************************************************
1979 Free a DEVMODE struct.
1980 ****************************************************************************/
1982 static void free_dev_mode(DEVICEMODE *dev)
1984 if (dev == NULL)
1985 return;
1987 if (dev->private)
1988 safe_free(dev->private);
1990 safe_free(dev);
1993 /****************************************************************************
1994 Create a DEVMODE struct. Returns malloced memory.
1995 ****************************************************************************/
1997 static DEVICEMODE *construct_dev_mode(int snum)
1999 char adevice[32];
2000 char aform[32];
2001 NT_PRINTER_INFO_LEVEL *printer = NULL;
2002 NT_DEVICEMODE *ntdevmode = NULL;
2003 DEVICEMODE *devmode = NULL;
2005 DEBUG(7,("construct_dev_mode\n"));
2007 DEBUGADD(8,("getting printer characteristics\n"));
2009 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2010 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2011 return NULL;
2014 ZERO_STRUCTP(devmode);
2016 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2017 goto fail;
2019 if (printer->info_2->devmode)
2020 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2022 if (ntdevmode == NULL)
2023 goto fail;
2025 DEBUGADD(8,("loading DEVICEMODE\n"));
2027 snprintf(adevice, sizeof(adevice), printer->info_2->printername);
2028 init_unistr(&devmode->devicename, adevice);
2030 snprintf(aform, sizeof(aform), ntdevmode->formname);
2031 init_unistr(&devmode->formname, aform);
2033 devmode->specversion = ntdevmode->specversion;
2034 devmode->driverversion = ntdevmode->driverversion;
2035 devmode->size = ntdevmode->size;
2036 devmode->driverextra = ntdevmode->driverextra;
2037 devmode->fields = ntdevmode->fields;
2039 devmode->orientation = ntdevmode->orientation;
2040 devmode->papersize = ntdevmode->papersize;
2041 devmode->paperlength = ntdevmode->paperlength;
2042 devmode->paperwidth = ntdevmode->paperwidth;
2043 devmode->scale = ntdevmode->scale;
2044 devmode->copies = ntdevmode->copies;
2045 devmode->defaultsource = ntdevmode->defaultsource;
2046 devmode->printquality = ntdevmode->printquality;
2047 devmode->color = ntdevmode->color;
2048 devmode->duplex = ntdevmode->duplex;
2049 devmode->yresolution = ntdevmode->yresolution;
2050 devmode->ttoption = ntdevmode->ttoption;
2051 devmode->collate = ntdevmode->collate;
2052 devmode->icmmethod = ntdevmode->icmmethod;
2053 devmode->icmintent = ntdevmode->icmintent;
2054 devmode->mediatype = ntdevmode->mediatype;
2055 devmode->dithertype = ntdevmode->dithertype;
2057 if (ntdevmode->private != NULL) {
2058 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2059 goto fail;
2062 free_nt_devicemode(&ntdevmode);
2063 free_a_printer(&printer,2);
2065 return devmode;
2067 fail:
2069 if (ntdevmode)
2070 free_nt_devicemode(&ntdevmode);
2071 if (printer)
2072 free_a_printer(&printer,2);
2073 free_dev_mode(devmode);
2075 return NULL;
2078 /********************************************************************
2079 * construct_printer_info_2
2080 * fill a printer_info_2 struct
2081 ********************************************************************/
2083 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2085 int count;
2086 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2088 print_queue_struct *queue=NULL;
2089 print_status_struct status;
2090 memset(&status, 0, sizeof(status));
2092 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2093 return False;
2095 memset(&status, 0, sizeof(status));
2096 count = print_queue_status(snum, &queue, &status);
2098 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2099 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2100 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2101 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2102 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2104 if (*ntprinter->info_2->comment == '\0')
2105 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2106 else
2107 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2109 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2110 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2111 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2112 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2113 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2115 printer->attributes = ntprinter->info_2->attributes;
2117 printer->priority = ntprinter->info_2->priority; /* priority */
2118 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2119 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2120 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2121 printer->status = nt_printq_status(status.status); /* status */
2122 printer->cjobs = count; /* jobs */
2123 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2125 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2126 DEBUG(8, ("Returning NULL Devicemode!\n"));
2129 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2130 /* steal the printer info sec_desc structure. [badly done]. */
2131 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2132 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2133 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2134 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2136 else {
2137 printer->secdesc = NULL;
2140 free_a_printer(&ntprinter, 2);
2141 safe_free(queue);
2142 return True;
2145 /********************************************************************
2146 * construct_printer_info_3
2147 * fill a printer_info_3 struct
2148 ********************************************************************/
2149 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2151 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2152 PRINTER_INFO_3 *printer = NULL;
2154 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2155 return False;
2157 *pp_printer = NULL;
2158 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2159 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2160 return False;
2163 ZERO_STRUCTP(printer);
2165 printer->flags = 4; /* These are the components of the SD we are returning. */
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;
2170 #if 0
2172 * Set the flags for the components we are returning.
2175 if (printer->secdesc->owner_sid)
2176 printer->flags |= OWNER_SECURITY_INFORMATION;
2178 if (printer->secdesc->grp_sid)
2179 printer->flags |= GROUP_SECURITY_INFORMATION;
2181 if (printer->secdesc->dacl)
2182 printer->flags |= DACL_SECURITY_INFORMATION;
2184 if (printer->secdesc->sacl)
2185 printer->flags |= SACL_SECURITY_INFORMATION;
2186 #endif
2188 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2189 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2190 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2193 free_a_printer(&ntprinter, 2);
2195 *pp_printer = printer;
2196 return True;
2199 /********************************************************************
2200 Spoolss_enumprinters.
2201 ********************************************************************/
2202 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2204 int snum;
2205 int i;
2206 int n_services=lp_numservices();
2207 PRINTER_INFO_1 *printers=NULL;
2208 PRINTER_INFO_1 current_prt;
2210 DEBUG(4,("enum_all_printers_info_1\n"));
2212 for (snum=0; snum<n_services; snum++) {
2213 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2214 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2216 if (construct_printer_info_1(flags, &current_prt, snum)) {
2217 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2218 *returned=0;
2219 return ERROR_NOT_ENOUGH_MEMORY;
2221 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2222 memcpy(&(printers[*returned]), &current_prt, sizeof(PRINTER_INFO_1));
2223 (*returned)++;
2228 /* check the required size. */
2229 for (i=0; i<*returned; i++)
2230 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2232 if (!alloc_buffer_size(buffer, *needed))
2233 return ERROR_INSUFFICIENT_BUFFER;
2235 /* fill the buffer with the structures */
2236 for (i=0; i<*returned; i++)
2237 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2239 /* clear memory */
2240 safe_free(printers);
2242 if (*needed > offered) {
2243 *returned=0;
2244 return ERROR_INSUFFICIENT_BUFFER;
2246 else
2247 return NT_STATUS_NO_PROBLEMO;
2250 /********************************************************************
2251 enum_all_printers_info_1_local.
2252 *********************************************************************/
2253 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2255 DEBUG(4,("enum_all_printers_info_1_local\n"));
2257 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2260 /********************************************************************
2261 enum_all_printers_info_1_name.
2262 *********************************************************************/
2263 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2265 fstring temp;
2266 DEBUG(4,("enum_all_printers_info_1_name\n"));
2268 fstrcpy(temp, "\\\\");
2269 fstrcat(temp, global_myname);
2271 if (strequal(name, temp)) {
2272 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2274 else
2275 return ERROR_INVALID_NAME;
2278 /********************************************************************
2279 enum_all_printers_info_1_remote.
2280 *********************************************************************/
2281 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2283 PRINTER_INFO_1 *printer;
2284 fstring printername;
2285 fstring desc;
2286 fstring comment;
2287 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2289 /* JFM: currently it's more a place holder than anything else.
2290 * In the spooler world there is a notion of server registration.
2291 * the print servers are registring (sp ?) on the PDC (in the same domain)
2293 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2296 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2297 return ERROR_NOT_ENOUGH_MEMORY;
2299 *returned=1;
2301 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2302 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2303 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2305 init_unistr(&printer->description, desc);
2306 init_unistr(&printer->name, printername);
2307 init_unistr(&printer->comment, comment);
2308 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2310 /* check the required size. */
2311 *needed += spoolss_size_printer_info_1(printer);
2313 if (!alloc_buffer_size(buffer, *needed)) {
2314 safe_free(printer);
2315 return ERROR_INSUFFICIENT_BUFFER;
2318 /* fill the buffer with the structures */
2319 new_smb_io_printer_info_1("", buffer, printer, 0);
2321 /* clear memory */
2322 safe_free(printer);
2324 if (*needed > offered) {
2325 *returned=0;
2326 return ERROR_INSUFFICIENT_BUFFER;
2328 else
2329 return NT_STATUS_NO_PROBLEMO;
2332 /********************************************************************
2333 enum_all_printers_info_1_network.
2334 *********************************************************************/
2335 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2337 DEBUG(4,("enum_all_printers_info_1_network\n"));
2339 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2342 /********************************************************************
2343 * api_spoolss_enumprinters
2345 * called from api_spoolss_enumprinters (see this to understand)
2346 ********************************************************************/
2347 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2349 int snum;
2350 int i;
2351 int n_services=lp_numservices();
2352 PRINTER_INFO_2 *printers=NULL;
2353 PRINTER_INFO_2 current_prt;
2355 for (snum=0; snum<n_services; snum++) {
2356 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2357 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2359 if (construct_printer_info_2(&current_prt, snum)) {
2360 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2361 return ERROR_NOT_ENOUGH_MEMORY;
2362 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2363 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
2364 (*returned)++;
2369 /* check the required size. */
2370 for (i=0; i<*returned; i++)
2371 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2373 if (!alloc_buffer_size(buffer, *needed)) {
2374 for (i=0; i<*returned; i++) {
2375 free_devmode(printers[i].devmode);
2376 free_sec_desc(&printers[i].secdesc);
2378 safe_free(printers);
2379 return ERROR_INSUFFICIENT_BUFFER;
2382 /* fill the buffer with the structures */
2383 for (i=0; i<*returned; i++)
2384 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2386 /* clear memory */
2387 for (i=0; i<*returned; i++) {
2388 free_devmode(printers[i].devmode);
2389 free_sec_desc(&printers[i].secdesc);
2391 safe_free(printers);
2393 if (*needed > offered) {
2394 *returned=0;
2395 return ERROR_INSUFFICIENT_BUFFER;
2397 else
2398 return NT_STATUS_NO_PROBLEMO;
2401 /********************************************************************
2402 * handle enumeration of printers at level 1
2403 ********************************************************************/
2404 static uint32 enumprinters_level1( uint32 flags, fstring name,
2405 NEW_BUFFER *buffer, uint32 offered,
2406 uint32 *needed, uint32 *returned)
2408 /* Not all the flags are equals */
2410 if (flags & PRINTER_ENUM_LOCAL)
2411 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2413 if (flags & PRINTER_ENUM_NAME)
2414 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2416 if (flags & PRINTER_ENUM_REMOTE)
2417 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2419 if (flags & PRINTER_ENUM_NETWORK)
2420 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2422 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2425 /********************************************************************
2426 * handle enumeration of printers at level 2
2427 ********************************************************************/
2428 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2429 NEW_BUFFER *buffer, uint32 offered,
2430 uint32 *needed, uint32 *returned)
2432 fstring temp;
2434 fstrcpy(temp, "\\\\");
2435 fstrcat(temp, global_myname);
2437 if (flags & PRINTER_ENUM_LOCAL) {
2438 if (strequal(servername, temp))
2439 return enum_all_printers_info_2(buffer, offered, needed, returned);
2440 else
2441 return enum_all_printers_info_2(buffer, offered, needed, returned);
2444 if (flags & PRINTER_ENUM_NAME) {
2445 if (strequal(servername, temp))
2446 return enum_all_printers_info_2(buffer, offered, needed, returned);
2447 else
2448 return ERROR_INVALID_NAME;
2451 if (flags & PRINTER_ENUM_REMOTE)
2452 return ERROR_INVALID_LEVEL;
2454 return NT_STATUS_NO_PROBLEMO;
2457 /********************************************************************
2458 * handle enumeration of printers at level 5
2459 ********************************************************************/
2460 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2461 NEW_BUFFER *buffer, uint32 offered,
2462 uint32 *needed, uint32 *returned)
2464 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2465 return NT_STATUS_NO_PROBLEMO;
2468 /********************************************************************
2469 * api_spoolss_enumprinters
2471 * called from api_spoolss_enumprinters (see this to understand)
2472 ********************************************************************/
2473 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2474 NEW_BUFFER *buffer, uint32 offered,
2475 uint32 *needed, uint32 *returned)
2477 fstring name;
2479 DEBUG(4,("_spoolss_enumprinters\n"));
2481 *needed=0;
2482 *returned=0;
2485 * Level 1:
2486 * flags==PRINTER_ENUM_NAME
2487 * if name=="" then enumerates all printers
2488 * if name!="" then enumerate the printer
2489 * flags==PRINTER_ENUM_REMOTE
2490 * name is NULL, enumerate printers
2491 * Level 2: name!="" enumerates printers, name can't be NULL
2492 * Level 3: doesn't exist
2493 * Level 4: does a local registry lookup
2494 * Level 5: same as Level 2
2497 unistr2_to_ascii(name, servername, sizeof(name)-1);
2498 strupper(name);
2500 switch (level) {
2501 case 1:
2502 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2503 case 2:
2504 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2505 case 5:
2506 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2507 case 3:
2508 case 4:
2509 default:
2510 return ERROR_INVALID_LEVEL;
2514 /****************************************************************************
2515 ****************************************************************************/
2516 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2518 PRINTER_INFO_0 *printer=NULL;
2520 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2521 return ERROR_NOT_ENOUGH_MEMORY;
2523 construct_printer_info_0(printer, snum);
2525 /* check the required size. */
2526 *needed += spoolss_size_printer_info_0(printer);
2528 if (!alloc_buffer_size(buffer, *needed)) {
2529 safe_free(printer);
2530 return ERROR_INSUFFICIENT_BUFFER;
2533 /* fill the buffer with the structures */
2534 new_smb_io_printer_info_0("", buffer, printer, 0);
2536 /* clear memory */
2537 safe_free(printer);
2539 if (*needed > offered) {
2540 return ERROR_INSUFFICIENT_BUFFER;
2542 else
2543 return NT_STATUS_NO_PROBLEMO;
2546 /****************************************************************************
2547 ****************************************************************************/
2548 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2550 PRINTER_INFO_1 *printer=NULL;
2552 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2553 return ERROR_NOT_ENOUGH_MEMORY;
2555 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2557 /* check the required size. */
2558 *needed += spoolss_size_printer_info_1(printer);
2560 if (!alloc_buffer_size(buffer, *needed)) {
2561 safe_free(printer);
2562 return ERROR_INSUFFICIENT_BUFFER;
2565 /* fill the buffer with the structures */
2566 new_smb_io_printer_info_1("", buffer, printer, 0);
2568 /* clear memory */
2569 safe_free(printer);
2571 if (*needed > offered) {
2572 return ERROR_INSUFFICIENT_BUFFER;
2574 else
2575 return NT_STATUS_NO_PROBLEMO;
2578 /****************************************************************************
2579 ****************************************************************************/
2580 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2582 PRINTER_INFO_2 *printer=NULL;
2584 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2585 return ERROR_NOT_ENOUGH_MEMORY;
2587 construct_printer_info_2(printer, snum);
2589 /* check the required size. */
2590 *needed += spoolss_size_printer_info_2(printer);
2592 if (!alloc_buffer_size(buffer, *needed)) {
2593 free_printer_info_2(printer);
2594 return ERROR_INSUFFICIENT_BUFFER;
2597 /* fill the buffer with the structures */
2598 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2599 free_printer_info_2(printer);
2600 return ERROR_NOT_ENOUGH_MEMORY;
2603 /* clear memory */
2604 free_printer_info_2(printer);
2606 if (*needed > offered) {
2607 return ERROR_INSUFFICIENT_BUFFER;
2609 else
2610 return NT_STATUS_NO_PROBLEMO;
2613 /****************************************************************************
2614 ****************************************************************************/
2615 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2617 PRINTER_INFO_3 *printer=NULL;
2619 if (!construct_printer_info_3(&printer, snum))
2620 return ERROR_NOT_ENOUGH_MEMORY;
2622 /* check the required size. */
2623 *needed += spoolss_size_printer_info_3(printer);
2625 if (!alloc_buffer_size(buffer, *needed)) {
2626 free_printer_info_3(printer);
2627 return ERROR_INSUFFICIENT_BUFFER;
2630 /* fill the buffer with the structures */
2631 new_smb_io_printer_info_3("", buffer, printer, 0);
2633 /* clear memory */
2634 free_printer_info_3(printer);
2636 if (*needed > offered) {
2637 return ERROR_INSUFFICIENT_BUFFER;
2639 else
2640 return NT_STATUS_NO_PROBLEMO;
2643 /****************************************************************************
2644 ****************************************************************************/
2645 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2646 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2648 int snum;
2650 *needed=0;
2652 if (!get_printer_snum(handle, &snum))
2653 return ERROR_INVALID_HANDLE;
2655 switch (level) {
2656 case 0:
2657 return getprinter_level_0(snum, buffer, offered, needed);
2658 case 1:
2659 return getprinter_level_1(snum, buffer, offered, needed);
2660 case 2:
2661 return getprinter_level_2(snum, buffer, offered, needed);
2662 case 3:
2663 return getprinter_level_3(snum, buffer, offered, needed);
2664 default:
2665 return ERROR_INVALID_LEVEL;
2669 /********************************************************************
2670 * fill a DRIVER_INFO_1 struct
2671 ********************************************************************/
2672 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2674 init_unistr( &info->name, driver.info_3->name);
2677 /********************************************************************
2678 * construct_printer_driver_info_1
2679 ********************************************************************/
2680 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2682 NT_PRINTER_INFO_LEVEL *printer = NULL;
2683 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2685 ZERO_STRUCT(driver);
2687 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2688 return ERROR_INVALID_PRINTER_NAME;
2690 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2691 return ERROR_UNKNOWN_PRINTER_DRIVER;
2693 fill_printer_driver_info_1(info, driver, servername, architecture);
2695 free_a_printer(&printer,2);
2697 return NT_STATUS_NO_PROBLEMO;
2700 /********************************************************************
2701 * construct_printer_driver_info_2
2702 * fill a printer_info_2 struct
2703 ********************************************************************/
2704 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2706 pstring temp_driverpath;
2707 pstring temp_datafile;
2708 pstring temp_configfile;
2710 info->version=driver.info_3->cversion;
2712 init_unistr( &info->name, driver.info_3->name );
2713 init_unistr( &info->architecture, driver.info_3->environment );
2715 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2716 init_unistr( &info->driverpath, temp_driverpath );
2718 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2719 init_unistr( &info->datafile, temp_datafile );
2721 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2722 init_unistr( &info->configfile, temp_configfile );
2725 /********************************************************************
2726 * construct_printer_driver_info_2
2727 * fill a printer_info_2 struct
2728 ********************************************************************/
2729 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2731 NT_PRINTER_INFO_LEVEL *printer = NULL;
2732 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2734 ZERO_STRUCT(printer);
2735 ZERO_STRUCT(driver);
2737 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2738 return ERROR_INVALID_PRINTER_NAME;
2740 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2741 return ERROR_UNKNOWN_PRINTER_DRIVER;
2743 fill_printer_driver_info_2(info, driver, servername);
2745 free_a_printer(&printer,2);
2747 return NT_STATUS_NO_PROBLEMO;
2750 /********************************************************************
2751 * copy a strings array and convert to UNICODE
2753 * convert an array of ascii string to a UNICODE string
2754 ********************************************************************/
2755 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2757 int i=0;
2758 int j=0;
2759 char *v;
2760 pstring line;
2762 DEBUG(6,("init_unistr_array\n"));
2763 *uni_array=NULL;
2765 while (1) {
2766 if (char_array == NULL)
2767 v = "";
2768 else {
2769 v = char_array[i];
2770 if (!v) v = ""; /* hack to handle null lists */
2772 if (strlen(v) == 0) break;
2773 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2774 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2775 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2776 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2777 return;
2779 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2780 i++;
2783 if (*uni_array) {
2784 (*uni_array)[j]=0x0000;
2787 DEBUGADD(6,("last one:done\n"));
2790 /********************************************************************
2791 * construct_printer_info_3
2792 * fill a printer_info_3 struct
2793 ********************************************************************/
2794 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2796 pstring temp_driverpath;
2797 pstring temp_datafile;
2798 pstring temp_configfile;
2799 pstring temp_helpfile;
2801 ZERO_STRUCTP(info);
2803 info->version=driver.info_3->cversion;
2805 init_unistr( &info->name, driver.info_3->name );
2806 init_unistr( &info->architecture, driver.info_3->environment );
2808 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2809 init_unistr( &info->driverpath, temp_driverpath );
2811 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2812 init_unistr( &info->datafile, temp_datafile );
2814 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2815 init_unistr( &info->configfile, temp_configfile );
2817 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2818 init_unistr( &info->helpfile, temp_helpfile );
2820 init_unistr( &info->monitorname, driver.info_3->monitorname );
2821 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2823 info->dependentfiles=NULL;
2824 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2827 /********************************************************************
2828 * construct_printer_info_3
2829 * fill a printer_info_3 struct
2830 ********************************************************************/
2831 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2833 NT_PRINTER_INFO_LEVEL *printer = NULL;
2834 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2835 uint32 status=0;
2836 ZERO_STRUCT(driver);
2838 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2839 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2840 if (status != 0)
2841 return ERROR_INVALID_PRINTER_NAME;
2843 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2844 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2845 if (status != 0) {
2846 free_a_printer(&printer,2);
2847 return ERROR_UNKNOWN_PRINTER_DRIVER;
2850 fill_printer_driver_info_3(info, driver, servername);
2852 free_a_printer(&printer,2);
2854 return NT_STATUS_NO_PROBLEMO;
2857 /********************************************************************
2858 * construct_printer_info_6
2859 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2860 ********************************************************************/
2862 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2864 pstring temp_driverpath;
2865 pstring temp_datafile;
2866 pstring temp_configfile;
2867 pstring temp_helpfile;
2868 fstring nullstr;
2870 ZERO_STRUCTP(info);
2871 memset(&nullstr, '\0', sizeof(fstring));
2873 info->version=driver.info_3->cversion;
2875 init_unistr( &info->name, driver.info_3->name );
2876 init_unistr( &info->architecture, driver.info_3->environment );
2878 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2879 init_unistr( &info->driverpath, temp_driverpath );
2881 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2882 init_unistr( &info->datafile, temp_datafile );
2884 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2885 init_unistr( &info->configfile, temp_configfile );
2887 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2888 init_unistr( &info->helpfile, temp_helpfile );
2890 init_unistr( &info->monitorname, driver.info_3->monitorname );
2891 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2893 info->dependentfiles=NULL;
2894 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2896 info->previousdrivernames=NULL;
2897 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
2899 info->driver_date.low=0;
2900 info->driver_date.high=0;
2902 info->padding=0;
2903 info->driver_version_low=0;
2904 info->driver_version_high=0;
2906 init_unistr( &info->mfgname, "");
2907 init_unistr( &info->oem_url, "");
2908 init_unistr( &info->hardware_id, "");
2909 init_unistr( &info->provider, "");
2912 /********************************************************************
2913 * construct_printer_info_6
2914 * fill a printer_info_6 struct
2915 ********************************************************************/
2916 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
2918 NT_PRINTER_INFO_LEVEL *printer = NULL;
2919 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2920 uint32 status=0;
2921 ZERO_STRUCT(driver);
2923 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2924 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2925 if (status != 0)
2926 return ERROR_INVALID_PRINTER_NAME;
2928 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2929 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2930 if (status != 0) {
2932 * Is this a W2k client ?
2935 if (version < 3) {
2936 free_a_printer(&printer,2);
2937 return ERROR_UNKNOWN_PRINTER_DRIVER;
2940 /* Yes - try again with a WinNT driver. */
2941 version = 2;
2942 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2943 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
2944 if (status != 0) {
2945 free_a_printer(&printer,2);
2946 return ERROR_UNKNOWN_PRINTER_DRIVER;
2950 fill_printer_driver_info_6(info, driver, servername);
2952 free_a_printer(&printer,2);
2954 return NT_STATUS_NO_PROBLEMO;
2957 /****************************************************************************
2958 ****************************************************************************/
2960 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2962 safe_free(info->dependentfiles);
2965 /****************************************************************************
2966 ****************************************************************************/
2968 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
2970 safe_free(info->dependentfiles);
2974 /****************************************************************************
2975 ****************************************************************************/
2976 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2978 DRIVER_INFO_1 *info=NULL;
2979 uint32 status;
2981 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2982 return ERROR_NOT_ENOUGH_MEMORY;
2984 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2985 if (status != NT_STATUS_NO_PROBLEMO) {
2986 safe_free(info);
2987 return status;
2990 /* check the required size. */
2991 *needed += spoolss_size_printer_driver_info_1(info);
2993 if (!alloc_buffer_size(buffer, *needed)) {
2994 safe_free(info);
2995 return ERROR_INSUFFICIENT_BUFFER;
2998 /* fill the buffer with the structures */
2999 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3001 /* clear memory */
3002 safe_free(info);
3004 if (*needed > offered)
3005 return ERROR_INSUFFICIENT_BUFFER;
3006 else
3007 return NT_STATUS_NO_PROBLEMO;
3010 /****************************************************************************
3011 ****************************************************************************/
3012 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3014 DRIVER_INFO_2 *info=NULL;
3015 uint32 status;
3017 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3018 return ERROR_NOT_ENOUGH_MEMORY;
3020 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3021 if (status != NT_STATUS_NO_PROBLEMO) {
3022 safe_free(info);
3023 return status;
3026 /* check the required size. */
3027 *needed += spoolss_size_printer_driver_info_2(info);
3029 if (!alloc_buffer_size(buffer, *needed)) {
3030 safe_free(info);
3031 return ERROR_INSUFFICIENT_BUFFER;
3034 /* fill the buffer with the structures */
3035 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3037 /* clear memory */
3038 safe_free(info);
3040 if (*needed > offered)
3041 return ERROR_INSUFFICIENT_BUFFER;
3042 else
3043 return NT_STATUS_NO_PROBLEMO;
3046 /****************************************************************************
3047 ****************************************************************************/
3048 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3050 DRIVER_INFO_3 info;
3051 uint32 status;
3053 ZERO_STRUCT(info);
3055 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3056 if (status != NT_STATUS_NO_PROBLEMO) {
3057 return status;
3060 /* check the required size. */
3061 *needed += spoolss_size_printer_driver_info_3(&info);
3063 if (!alloc_buffer_size(buffer, *needed)) {
3064 free_printer_driver_info_3(&info);
3065 return ERROR_INSUFFICIENT_BUFFER;
3068 /* fill the buffer with the structures */
3069 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3071 free_printer_driver_info_3(&info);
3073 if (*needed > offered)
3074 return ERROR_INSUFFICIENT_BUFFER;
3075 else
3076 return NT_STATUS_NO_PROBLEMO;
3079 /****************************************************************************
3080 ****************************************************************************/
3081 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3083 DRIVER_INFO_6 info;
3084 uint32 status;
3086 ZERO_STRUCT(info);
3088 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3089 if (status != NT_STATUS_NO_PROBLEMO) {
3090 return status;
3093 /* check the required size. */
3094 *needed += spoolss_size_printer_driver_info_6(&info);
3096 if (!alloc_buffer_size(buffer, *needed)) {
3097 free_printer_driver_info_6(&info);
3098 return ERROR_INSUFFICIENT_BUFFER;
3101 /* fill the buffer with the structures */
3102 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3104 free_printer_driver_info_6(&info);
3106 if (*needed > offered)
3107 return ERROR_INSUFFICIENT_BUFFER;
3108 else
3109 return NT_STATUS_NO_PROBLEMO;
3112 /****************************************************************************
3113 ****************************************************************************/
3114 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3115 uint32 clientmajorversion, uint32 clientminorversion,
3116 NEW_BUFFER *buffer, uint32 offered,
3117 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3119 fstring servername;
3120 fstring architecture;
3121 int snum;
3123 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3125 *needed=0;
3126 *servermajorversion=0;
3127 *serverminorversion=0;
3129 pstrcpy(servername, global_myname);
3130 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3132 if (!get_printer_snum(handle, &snum))
3133 return ERROR_INVALID_HANDLE;
3135 switch (level) {
3136 case 1:
3137 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3138 case 2:
3139 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3140 case 3:
3141 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3142 case 6:
3143 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3144 default:
3145 return ERROR_INVALID_LEVEL;
3149 /****************************************************************************
3150 ****************************************************************************/
3151 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3153 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3155 if (OPEN_HANDLE(Printer)) {
3156 Printer->page_started=True;
3157 return 0x0;
3160 DEBUG(3,("Error in startpageprinter printer handle\n"));
3161 return ERROR_INVALID_HANDLE;
3164 /****************************************************************************
3165 ****************************************************************************/
3166 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3168 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3170 if (!OPEN_HANDLE(Printer)) {
3171 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3172 return ERROR_INVALID_HANDLE;
3175 Printer->page_started=False;
3177 return NT_STATUS_NO_PROBLEMO;
3180 /****************************************************************************
3181 Return a user struct for a pipe user.
3182 ****************************************************************************/
3184 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3186 if (p->ntlmssp_auth_validated) {
3187 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3188 } else {
3189 extern struct current_user current_user;
3190 memcpy(user, &current_user, sizeof(struct current_user));
3193 return user;
3196 /********************************************************************
3197 * api_spoolss_getprinter
3198 * called from the spoolss dispatcher
3200 ********************************************************************/
3201 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3202 pipes_struct *p, DOC_INFO *docinfo,
3203 uint32 *jobid)
3205 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3206 int snum;
3207 pstring jobname;
3208 fstring datatype;
3209 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3210 struct current_user user;
3212 if (!OPEN_HANDLE(Printer)) {
3213 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3214 return ERROR_INVALID_HANDLE;
3217 get_current_user(&user, p);
3220 * a nice thing with NT is it doesn't listen to what you tell it.
3221 * when asked to send _only_ RAW datas, it tries to send datas
3222 * in EMF format.
3224 * So I add checks like in NT Server ...
3226 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3227 * there's a bug in NT client-side code, so we'll fix it in the
3228 * server-side code. *nnnnnggggh!*
3231 if (info_1->p_datatype != 0) {
3232 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3233 if (strcmp(datatype, "RAW") != 0) {
3234 (*jobid)=0;
3235 return ERROR_INVALID_DATATYPE;
3239 /* get the share number of the printer */
3240 if (!get_printer_snum(handle, &snum)) {
3241 return ERROR_INVALID_HANDLE;
3244 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3246 Printer->jobid = print_job_start(&user, snum, jobname);
3248 /* An error occured in print_job_start() so return an appropriate
3249 NT error code. */
3251 if (Printer->jobid == -1) {
3252 return map_nt_error_from_unix(errno);
3255 Printer->document_started=True;
3256 (*jobid) = Printer->jobid;
3258 srv_spoolss_sendnotify(handle);
3259 return 0x0;
3262 /********************************************************************
3263 * api_spoolss_getprinter
3264 * called from the spoolss dispatcher
3266 ********************************************************************/
3267 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3269 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3271 if (!OPEN_HANDLE(Printer)) {
3272 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3273 return ERROR_INVALID_HANDLE;
3276 Printer->document_started=False;
3277 print_job_end(Printer->jobid);
3278 /* error codes unhandled so far ... */
3280 srv_spoolss_sendnotify(handle);
3282 return 0x0;
3285 /****************************************************************************
3286 ****************************************************************************/
3287 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3288 uint32 buffer_size,
3289 uint8 *buffer,
3290 uint32 *buffer_written)
3292 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3294 if (!OPEN_HANDLE(Printer)) {
3295 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3296 return ERROR_INVALID_HANDLE;
3299 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3300 buffer_size);
3302 return 0x0;
3305 /********************************************************************
3306 * api_spoolss_getprinter
3307 * called from the spoolss dispatcher
3309 ********************************************************************/
3310 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3311 pipes_struct *p)
3313 struct current_user user;
3314 int snum, errcode = ERROR_INVALID_FUNCTION;
3315 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3317 get_current_user(&user, p);
3319 if (!OPEN_HANDLE(Printer)) {
3320 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3321 return ERROR_INVALID_HANDLE;
3324 if (!get_printer_snum(handle, &snum))
3325 return ERROR_INVALID_HANDLE;
3327 switch (command) {
3328 case PRINTER_CONTROL_PAUSE:
3329 if (print_queue_pause(&user, snum, &errcode)) {
3330 errcode = 0;
3332 break;
3333 case PRINTER_CONTROL_RESUME:
3334 case PRINTER_CONTROL_UNPAUSE:
3335 if (print_queue_resume(&user, snum, &errcode)) {
3336 errcode = 0;
3338 break;
3339 case PRINTER_CONTROL_PURGE:
3340 if (print_queue_purge(&user, snum, &errcode)) {
3341 errcode = 0;
3343 break;
3344 default:
3345 return ERROR_INVALID_LEVEL;
3348 return errcode;
3351 /********************************************************************
3352 * api_spoolss_abortprinter
3353 ********************************************************************/
3355 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3357 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3360 /********************************************************************
3361 * called by spoolss_api_setprinter
3362 * when updating a printer description
3363 ********************************************************************/
3364 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3365 const SPOOL_PRINTER_INFO_LEVEL *info,
3366 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3368 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3369 struct current_user user;
3370 uint32 result;
3371 int snum;
3373 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3375 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3376 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3377 OUR_HANDLE(handle)));
3379 result = ERROR_INVALID_HANDLE;
3380 goto done;
3383 /* NT seems to like setting the security descriptor even though
3384 nothing may have actually changed. This causes annoying
3385 dialog boxes when the user doesn't have permission to change
3386 the security descriptor. */
3388 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3390 if (DEBUGLEVEL >= 10) {
3391 SEC_ACL *acl;
3392 int i;
3394 acl = old_secdesc_ctr->sec->dacl;
3395 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3396 PRINTERNAME(snum), acl->num_aces));
3398 for (i = 0; i < acl->num_aces; i++) {
3399 fstring sid_str;
3401 sid_to_string(sid_str, &acl->ace[i].sid);
3403 DEBUG(10, ("%s 0x%08x\n", sid_str,
3404 acl->ace[i].info.mask));
3407 acl = secdesc_ctr->sec->dacl;
3409 if (acl) {
3410 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3411 PRINTERNAME(snum), acl->num_aces));
3413 for (i = 0; i < acl->num_aces; i++) {
3414 fstring sid_str;
3416 sid_to_string(sid_str, &acl->ace[i].sid);
3418 DEBUG(10, ("%s 0x%08x\n", sid_str,
3419 acl->ace[i].info.mask));
3421 } else {
3422 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3426 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3428 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3429 result = NT_STATUS_NO_PROBLEMO;
3430 goto done;
3433 /* Work out which user is performing the operation */
3435 get_current_user(&user, p);
3437 /* Check the user has permissions to change the security
3438 descriptor. By experimentation with two NT machines, the user
3439 requires Full Access to the printer to change security
3440 information. */
3442 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3443 result = ERROR_ACCESS_DENIED;
3444 goto done;
3447 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3449 done:
3450 free_sec_desc_buf(&new_secdesc_ctr);
3451 free_sec_desc_buf(&old_secdesc_ctr);
3453 return result;
3456 /********************************************************************
3457 Do Samba sanity checks on a printer info struct.
3458 this has changed purpose: it now "canonicalises" printer
3459 info from a client rather than just checking it is correct
3460 ********************************************************************/
3462 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3464 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3465 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3467 /* we force some elements to "correct" values */
3468 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3469 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3470 global_myname, lp_servicename(snum));
3471 fstrcpy(info->sharename, lp_servicename(snum));
3472 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3473 | PRINTER_ATTRIBUTE_LOCAL \
3474 | PRINTER_ATTRIBUTE_RAW_ONLY \
3475 | PRINTER_ATTRIBUTE_QUEUED ;
3477 return True;
3480 /****************************************************************************
3481 ****************************************************************************/
3482 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3484 pid_t local_pid = sys_getpid();
3485 char *cmd = lp_addprinter_cmd();
3486 char *path;
3487 char **qlines;
3488 pstring tmp_file;
3489 pstring command;
3490 pstring driverlocation;
3491 int numlines;
3492 int ret;
3494 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3495 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3496 else
3497 path = tmpdir();
3499 /* build driver path... only 9X architecture is needed for legacy reasons */
3500 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3501 global_myname);
3502 /* change \ to \\ for the shell */
3503 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3505 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3506 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3507 cmd, printer->info_2->printername, printer->info_2->sharename,
3508 printer->info_2->portname, printer->info_2->drivername,
3509 printer->info_2->location, driverlocation);
3511 unlink(tmp_file);
3512 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3513 ret = smbrun(command, tmp_file, False);
3514 DEBUGADD(10,("returned [%d]\n", ret));
3516 if ( ret != 0 ) {
3517 unlink(tmp_file);
3518 return False;
3521 numlines = 0;
3522 qlines = file_lines_load(tmp_file, &numlines, True);
3523 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3524 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3525 unlink(tmp_file);
3527 if(numlines) {
3528 /* Set the portname to what the script says the portname should be. */
3529 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3530 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3532 /* Send SIGHUP to process group... is there a better way? */
3533 kill(0, SIGHUP);
3534 add_all_printers();
3537 file_lines_free(qlines);
3538 return True;
3541 /* Return true if two devicemodes are equal */
3543 #define DEVMODE_CHECK_INT(field) \
3544 if (d1->field != d2->field) { \
3545 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3546 d1->field, d2->field)); \
3547 return False; \
3550 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3552 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
3554 if (!d1 ^ !d2) {
3555 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3556 return False; /* if either is exclusively NULL are not equal */
3559 if (!strequal(d1->devicename, d2->devicename) ||
3560 !strequal(d1->formname, d2->formname)) {
3561 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3562 return False;
3565 DEVMODE_CHECK_INT(specversion);
3566 DEVMODE_CHECK_INT(driverversion);
3567 DEVMODE_CHECK_INT(driverextra);
3568 DEVMODE_CHECK_INT(orientation);
3569 DEVMODE_CHECK_INT(papersize);
3570 DEVMODE_CHECK_INT(paperlength);
3571 DEVMODE_CHECK_INT(paperwidth);
3572 DEVMODE_CHECK_INT(scale);
3573 DEVMODE_CHECK_INT(copies);
3574 DEVMODE_CHECK_INT(defaultsource);
3575 DEVMODE_CHECK_INT(printquality);
3576 DEVMODE_CHECK_INT(color);
3577 DEVMODE_CHECK_INT(duplex);
3578 DEVMODE_CHECK_INT(yresolution);
3579 DEVMODE_CHECK_INT(ttoption);
3580 DEVMODE_CHECK_INT(collate);
3581 DEVMODE_CHECK_INT(logpixels);
3583 DEVMODE_CHECK_INT(fields);
3584 DEVMODE_CHECK_INT(bitsperpel);
3585 DEVMODE_CHECK_INT(pelswidth);
3586 DEVMODE_CHECK_INT(pelsheight);
3587 DEVMODE_CHECK_INT(displayflags);
3588 DEVMODE_CHECK_INT(displayfrequency);
3589 DEVMODE_CHECK_INT(icmmethod);
3590 DEVMODE_CHECK_INT(icmintent);
3591 DEVMODE_CHECK_INT(mediatype);
3592 DEVMODE_CHECK_INT(dithertype);
3593 DEVMODE_CHECK_INT(reserved1);
3594 DEVMODE_CHECK_INT(reserved2);
3595 DEVMODE_CHECK_INT(panningwidth);
3596 DEVMODE_CHECK_INT(panningheight);
3598 /* compare the private data if it exists */
3599 if (!d1->driverextra && !d2->driverextra) goto equal;
3602 DEVMODE_CHECK_INT(driverextra);
3604 if (memcmp(d1->private, d2->private, d1->driverextra)) {
3605 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
3606 return False;
3609 equal:
3610 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
3611 return True;
3614 /* Return true if two NT_PRINTER_PARAM structures are equal */
3616 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
3617 NT_PRINTER_PARAM *p2)
3619 if (!p1 && !p2) goto equal;
3621 if ((!p1 && p2) || (p1 && !p2)) {
3622 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
3623 return False;
3626 /* Compare lists of printer parameters */
3628 while (p1) {
3629 BOOL found = False;
3630 NT_PRINTER_PARAM *q = p1;
3632 /* Find the parameter in the second structure */
3634 while(q) {
3636 if (strequal(p1->value, q->value)) {
3638 if (p1->type != q->type) {
3639 DEBUG(10, ("nt_printer_param_equal():"
3640 "types for %s differ (%d != %d)\n",
3641 p1->value, p1->type,
3642 q->type));
3643 break;
3646 if (p1->data_len != q->data_len) {
3647 DEBUG(10, ("nt_printer_param_equal():"
3648 "len for %s differs (%d != %d)\n",
3649 p1->value, p1->data_len,
3650 q->data_len));
3651 break;
3654 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
3655 found = True;
3656 } else {
3657 DEBUG(10, ("nt_printer_param_equal():"
3658 "data for %s differs\n", p1->value));
3661 break;
3664 q = q->next;
3667 if (!found) {
3668 DEBUG(10, ("nt_printer_param_equal(): param %s "
3669 "does not exist\n", p1->value));
3670 return False;
3673 p1 = p1->next;
3676 equal:
3678 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
3679 return True;
3682 /********************************************************************
3683 * Called by update_printer when trying to work out whether to
3684 * actually update printer info.
3685 ********************************************************************/
3687 #define PI_CHECK_INT(field) \
3688 if (pi1->field != pi2->field) { \
3689 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
3690 pi1->field, pi2->field)); \
3691 return False; \
3694 #define PI_CHECK_STR(field) \
3695 if (!strequal(pi1->field, pi2->field)) { \
3696 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
3697 pi1->field, pi2->field)); \
3698 return False; \
3701 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
3702 NT_PRINTER_INFO_LEVEL *p2)
3704 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
3706 /* Trivial conditions */
3708 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
3709 goto equal;
3712 if ((!p1 && p2) || (p1 && !p2) ||
3713 (!p1->info_2 && p2->info_2) ||
3714 (p1->info_2 && !p2->info_2)) {
3715 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
3716 "differ\n"));
3717 return False;
3720 /* Compare two nt_printer_info_level structures. Don't compare
3721 status or cjobs as they seem to have something to do with the
3722 printer queue. */
3724 pi1 = p1->info_2;
3725 pi2 = p2->info_2;
3727 PI_CHECK_INT(attributes);
3728 PI_CHECK_INT(priority);
3729 PI_CHECK_INT(default_priority);
3730 PI_CHECK_INT(starttime);
3731 PI_CHECK_INT(untiltime);
3732 PI_CHECK_INT(averageppm);
3734 /* Yuck - don't check the printername or servername as the
3735 add_a_printer() code plays games with them. You can't
3736 change the printername or the sharename through this interface
3737 in Samba. */
3739 PI_CHECK_STR(sharename);
3740 PI_CHECK_STR(portname);
3741 PI_CHECK_STR(drivername);
3742 PI_CHECK_STR(comment);
3743 PI_CHECK_STR(location);
3745 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
3746 return False;
3749 PI_CHECK_STR(sepfile);
3750 PI_CHECK_STR(printprocessor);
3751 PI_CHECK_STR(datatype);
3752 PI_CHECK_STR(parameters);
3754 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
3755 return False;
3758 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
3759 return False;
3762 PI_CHECK_INT(changeid);
3763 PI_CHECK_INT(c_setprinter);
3764 PI_CHECK_INT(setuptime);
3766 equal:
3767 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
3768 return True;
3771 /********************************************************************
3772 * called by spoolss_api_setprinter
3773 * when updating a printer description
3774 ********************************************************************/
3776 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3777 const SPOOL_PRINTER_INFO_LEVEL *info,
3778 DEVICEMODE *devmode)
3780 int snum;
3781 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
3782 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3783 uint32 result;
3785 DEBUG(8,("update_printer\n"));
3787 result = NT_STATUS_NO_PROBLEMO;
3789 if (level!=2) {
3790 DEBUG(0,("Send a mail to samba@samba.org\n"));
3791 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3792 result = ERROR_INVALID_LEVEL;
3793 goto done;
3796 if (!OPEN_HANDLE(Printer)) {
3797 result = ERROR_INVALID_HANDLE;
3798 goto done;
3801 if (!get_printer_snum(handle, &snum)) {
3802 result = ERROR_INVALID_HANDLE;
3803 goto done;
3806 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
3807 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
3808 result = ERROR_INVALID_HANDLE;
3809 goto done;
3812 DEBUGADD(8,("Converting info_2 struct\n"));
3815 * convert_printer_info converts the incoming
3816 * info from the client and overwrites the info
3817 * just read from the tdb in the pointer 'printer'.
3820 convert_printer_info(info, printer, level);
3822 if (info->info_2->devmode_ptr != 0) {
3823 /* we have a valid devmode
3824 convert it and link it*/
3827 * Ensure printer->info_2->devmode is a valid pointer
3828 * as we will be overwriting it in convert_devicemode().
3831 if (printer->info_2->devmode == NULL)
3832 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3834 DEBUGADD(8,("Converting the devicemode struct\n"));
3835 convert_devicemode(devmode, printer->info_2->devmode);
3837 } else {
3838 if (printer->info_2->devmode != NULL)
3839 free_nt_devicemode(&printer->info_2->devmode);
3840 printer->info_2->devmode=NULL;
3843 /* Do sanity check on the requested changes for Samba */
3845 if (!check_printer_ok(printer->info_2, snum)) {
3846 result = ERROR_INVALID_PARAMETER;
3847 goto done;
3850 /* NT likes to call this function even though nothing has actually
3851 changed. Check this so the user doesn't end up with an
3852 annoying permission denied dialog box. */
3854 if (nt_printer_info_level_equal(printer, old_printer)) {
3855 DEBUG(3, ("printer info has not changed\n"));
3856 result = NT_STATUS_NO_PROBLEMO;
3857 goto done;
3860 /* Check calling user has permission to update printer description */
3862 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3863 DEBUG(3, ("printer property change denied by security "
3864 "descriptor\n"));
3865 result = ERROR_ACCESS_DENIED;
3866 goto done;
3869 /* Call addprinter hook */
3871 if (*lp_addprinter_cmd() )
3872 if ( !add_printer_hook(printer) ) {
3873 result = ERROR_ACCESS_DENIED;
3874 goto done;
3877 /* Update printer info */
3879 if (add_a_printer(*printer, 2)!=0) {
3880 /* I don't really know what to return here !!! */
3881 result = ERROR_ACCESS_DENIED;
3882 goto done;
3885 done:
3886 free_a_printer(&printer, 2);
3887 free_a_printer(&old_printer, 2);
3889 srv_spoolss_sendnotify(handle);
3891 return result;
3894 /****************************************************************************
3895 ****************************************************************************/
3896 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3897 const SPOOL_PRINTER_INFO_LEVEL *info,
3898 DEVMODE_CTR devmode_ctr,
3899 SEC_DESC_BUF *secdesc_ctr,
3900 uint32 command, pipes_struct *p)
3902 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3904 if (!OPEN_HANDLE(Printer)) {
3905 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3906 return ERROR_INVALID_HANDLE;
3909 /* check the level */
3910 switch (level) {
3911 case 0:
3912 return control_printer(handle, command, p);
3913 case 2:
3914 return update_printer(handle, level, info, devmode_ctr.devmode);
3915 case 3:
3916 return update_printer_sec(handle, level, info, p,
3917 secdesc_ctr);
3918 default:
3919 return ERROR_INVALID_LEVEL;
3923 /****************************************************************************
3924 ****************************************************************************/
3925 uint32 _spoolss_fcpn(POLICY_HND *handle)
3927 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3929 if (!OPEN_HANDLE(Printer)) {
3930 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3931 return ERROR_INVALID_HANDLE;
3934 if (Printer->notify.client_connected==True)
3935 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
3936 return ERROR_INVALID_HANDLE;
3938 Printer->notify.flags=0;
3939 Printer->notify.options=0;
3940 Printer->notify.localmachine[0]='\0';
3941 Printer->notify.printerlocal=0;
3942 if (Printer->notify.option)
3943 safe_free(Printer->notify.option->ctr.type);
3944 safe_free(Printer->notify.option);
3945 Printer->notify.option=NULL;
3946 Printer->notify.client_connected=False;
3948 return NT_STATUS_NO_PROBLEMO;
3951 /****************************************************************************
3952 ****************************************************************************/
3953 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3954 NEW_BUFFER *buffer, uint32 offered,
3955 uint32 *needed)
3957 *needed = 0;
3958 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3959 returns for AddJob. AddJob
3960 must fail on non-local
3961 printers */
3964 /****************************************************************************
3965 ****************************************************************************/
3966 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3967 int position, int snum)
3969 pstring temp_name;
3971 struct tm *t;
3973 t=gmtime(&queue->time);
3974 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3976 job_info->jobid=queue->job;
3977 init_unistr(&job_info->printername, lp_servicename(snum));
3978 init_unistr(&job_info->machinename, temp_name);
3979 init_unistr(&job_info->username, queue->user);
3980 init_unistr(&job_info->document, queue->file);
3981 init_unistr(&job_info->datatype, "RAW");
3982 init_unistr(&job_info->text_status, "");
3983 job_info->status=nt_printj_status(queue->status);
3984 job_info->priority=queue->priority;
3985 job_info->position=position;
3986 job_info->totalpages=0;
3987 job_info->pagesprinted=0;
3989 make_systemtime(&job_info->submitted, t);
3992 /****************************************************************************
3993 ****************************************************************************/
3994 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3995 int position, int snum)
3997 pstring temp_name;
3998 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3999 pstring chaine;
4000 struct tm *t;
4002 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
4003 return False;
4005 t=gmtime(&queue->time);
4006 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4008 job_info->jobid=queue->job;
4010 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4012 init_unistr(&job_info->printername, chaine);
4014 init_unistr(&job_info->machinename, temp_name);
4015 init_unistr(&job_info->username, queue->user);
4016 init_unistr(&job_info->document, queue->file);
4017 init_unistr(&job_info->notifyname, queue->user);
4018 init_unistr(&job_info->datatype, "RAW");
4019 init_unistr(&job_info->printprocessor, "winprint");
4020 init_unistr(&job_info->parameters, "");
4021 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4022 init_unistr(&job_info->text_status, "");
4024 /* and here the security descriptor */
4026 job_info->status=nt_printj_status(queue->status);
4027 job_info->priority=queue->priority;
4028 job_info->position=position;
4029 job_info->starttime=0;
4030 job_info->untiltime=0;
4031 job_info->totalpages=0;
4032 job_info->size=queue->size;
4033 make_systemtime(&(job_info->submitted), t);
4034 job_info->timeelapsed=0;
4035 job_info->pagesprinted=0;
4037 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4038 free_a_printer(&ntprinter, 2);
4039 return False;
4042 free_a_printer(&ntprinter, 2);
4043 return (True);
4046 /****************************************************************************
4047 Enumjobs at level 1.
4048 ****************************************************************************/
4049 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4050 NEW_BUFFER *buffer, uint32 offered,
4051 uint32 *needed, uint32 *returned)
4053 JOB_INFO_1 *info;
4054 int i;
4056 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4057 if (info==NULL) {
4058 safe_free(queue);
4059 *returned=0;
4060 return ERROR_NOT_ENOUGH_MEMORY;
4063 for (i=0; i<*returned; i++)
4064 fill_job_info_1(&info[i], &queue[i], i, snum);
4066 safe_free(queue);
4068 /* check the required size. */
4069 for (i=0; i<*returned; i++)
4070 (*needed) += spoolss_size_job_info_1(&info[i]);
4072 if (!alloc_buffer_size(buffer, *needed)) {
4073 safe_free(info);
4074 return ERROR_INSUFFICIENT_BUFFER;
4077 /* fill the buffer with the structures */
4078 for (i=0; i<*returned; i++)
4079 new_smb_io_job_info_1("", buffer, &info[i], 0);
4081 /* clear memory */
4082 safe_free(info);
4084 if (*needed > offered) {
4085 *returned=0;
4086 return ERROR_INSUFFICIENT_BUFFER;
4088 else
4089 return NT_STATUS_NO_PROBLEMO;
4092 /****************************************************************************
4093 Enumjobs at level 2.
4094 ****************************************************************************/
4095 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4096 NEW_BUFFER *buffer, uint32 offered,
4097 uint32 *needed, uint32 *returned)
4099 JOB_INFO_2 *info;
4100 int i;
4102 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4103 if (info==NULL) {
4104 safe_free(queue);
4105 *returned=0;
4106 return ERROR_NOT_ENOUGH_MEMORY;
4109 for (i=0; i<*returned; i++)
4110 fill_job_info_2(&(info[i]), &queue[i], i, snum);
4112 safe_free(queue);
4114 /* check the required size. */
4115 for (i=0; i<*returned; i++)
4116 (*needed) += spoolss_size_job_info_2(&info[i]);
4118 if (!alloc_buffer_size(buffer, *needed)) {
4119 safe_free(info);
4120 return ERROR_INSUFFICIENT_BUFFER;
4123 /* fill the buffer with the structures */
4124 for (i=0; i<*returned; i++)
4125 new_smb_io_job_info_2("", buffer, &info[i], 0);
4127 /* clear memory */
4128 free_job_info_2(info);
4130 if (*needed > offered) {
4131 *returned=0;
4132 return ERROR_INSUFFICIENT_BUFFER;
4134 else
4135 return NT_STATUS_NO_PROBLEMO;
4138 /****************************************************************************
4139 Enumjobs.
4140 ****************************************************************************/
4141 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4142 NEW_BUFFER *buffer, uint32 offered,
4143 uint32 *needed, uint32 *returned)
4145 int snum;
4146 print_queue_struct *queue=NULL;
4147 print_status_struct prt_status;
4149 DEBUG(4,("_spoolss_enumjobs\n"));
4151 ZERO_STRUCT(prt_status);
4153 *needed=0;
4154 *returned=0;
4156 if (!get_printer_snum(handle, &snum))
4157 return ERROR_INVALID_HANDLE;
4159 *returned = print_queue_status(snum, &queue, &prt_status);
4160 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4162 if (*returned == 0) {
4163 safe_free(queue);
4164 return NT_STATUS_NO_PROBLEMO;
4167 switch (level) {
4168 case 1:
4169 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4170 case 2:
4171 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4172 default:
4173 safe_free(queue);
4174 *returned=0;
4175 return ERROR_INVALID_LEVEL;
4180 /****************************************************************************
4181 ****************************************************************************/
4182 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4184 return 0x0;
4187 /****************************************************************************
4188 ****************************************************************************/
4189 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4190 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4192 struct current_user user;
4193 print_status_struct prt_status;
4194 int snum, errcode = ERROR_INVALID_FUNCTION;
4196 memset(&prt_status, 0, sizeof(prt_status));
4198 if (!get_printer_snum(handle, &snum)) {
4199 return ERROR_INVALID_HANDLE;
4202 if (!print_job_exists(jobid)) {
4203 return ERROR_INVALID_PRINTER_NAME;
4206 get_current_user(&user, p);
4208 switch (command) {
4209 case JOB_CONTROL_CANCEL:
4210 case JOB_CONTROL_DELETE:
4211 if (print_job_delete(&user, jobid, &errcode)) {
4212 errcode = 0;
4214 break;
4215 case JOB_CONTROL_PAUSE:
4216 if (print_job_pause(&user, jobid, &errcode)) {
4217 errcode = 0;
4219 break;
4220 case JOB_CONTROL_RESTART:
4221 case JOB_CONTROL_RESUME:
4222 if (print_job_resume(&user, jobid, &errcode)) {
4223 errcode = 0;
4225 break;
4226 default:
4227 return ERROR_INVALID_LEVEL;
4230 return errcode;
4233 /****************************************************************************
4234 Enumerates all printer drivers at level 1.
4235 ****************************************************************************/
4236 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4238 int i;
4239 int ndrivers;
4240 uint32 version;
4241 fstring *list = NULL;
4243 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4244 DRIVER_INFO_1 *driver_info_1=NULL;
4246 *returned=0;
4248 #define MAX_VERSION 4
4250 for (version=0; version<MAX_VERSION; version++) {
4251 list=NULL;
4252 ndrivers=get_ntdrivers(&list, architecture, version);
4253 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4255 if(ndrivers == -1)
4256 return ERROR_NOT_ENOUGH_MEMORY;
4258 if(ndrivers != 0) {
4259 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4260 safe_free(list);
4261 return ERROR_NOT_ENOUGH_MEMORY;
4265 for (i=0; i<ndrivers; i++) {
4266 uint32 status;
4267 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4268 ZERO_STRUCT(driver);
4269 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4270 safe_free(list);
4271 return status;
4273 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4274 free_a_printer_driver(driver, 3);
4277 *returned+=ndrivers;
4278 safe_free(list);
4281 /* check the required size. */
4282 for (i=0; i<*returned; i++) {
4283 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4284 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4287 if (!alloc_buffer_size(buffer, *needed)) {
4288 safe_free(driver_info_1);
4289 return ERROR_INSUFFICIENT_BUFFER;
4292 /* fill the buffer with the form structures */
4293 for (i=0; i<*returned; i++) {
4294 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4295 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4298 safe_free(driver_info_1);
4300 if (*needed > offered) {
4301 *returned=0;
4302 return ERROR_INSUFFICIENT_BUFFER;
4304 else
4305 return NT_STATUS_NO_PROBLEMO;
4308 /****************************************************************************
4309 Enumerates all printer drivers at level 2.
4310 ****************************************************************************/
4311 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4313 int i;
4314 int ndrivers;
4315 uint32 version;
4316 fstring *list = NULL;
4318 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4319 DRIVER_INFO_2 *driver_info_2=NULL;
4321 *returned=0;
4323 #define MAX_VERSION 4
4325 for (version=0; version<MAX_VERSION; version++) {
4326 list=NULL;
4327 ndrivers=get_ntdrivers(&list, architecture, version);
4328 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4330 if(ndrivers == -1)
4331 return ERROR_NOT_ENOUGH_MEMORY;
4333 if(ndrivers != 0) {
4334 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4335 safe_free(list);
4336 return ERROR_NOT_ENOUGH_MEMORY;
4340 for (i=0; i<ndrivers; i++) {
4341 uint32 status;
4343 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4344 ZERO_STRUCT(driver);
4345 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4346 safe_free(list);
4347 return status;
4349 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4350 free_a_printer_driver(driver, 3);
4353 *returned+=ndrivers;
4354 safe_free(list);
4357 /* check the required size. */
4358 for (i=0; i<*returned; i++) {
4359 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4360 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4363 if (!alloc_buffer_size(buffer, *needed)) {
4364 safe_free(driver_info_2);
4365 return ERROR_INSUFFICIENT_BUFFER;
4368 /* fill the buffer with the form structures */
4369 for (i=0; i<*returned; i++) {
4370 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4371 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4374 safe_free(driver_info_2);
4376 if (*needed > offered) {
4377 *returned=0;
4378 return ERROR_INSUFFICIENT_BUFFER;
4380 else
4381 return NT_STATUS_NO_PROBLEMO;
4384 /****************************************************************************
4385 Enumerates all printer drivers at level 3.
4386 ****************************************************************************/
4387 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4389 int i;
4390 int ndrivers;
4391 uint32 version;
4392 fstring *list = NULL;
4394 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4395 DRIVER_INFO_3 *driver_info_3=NULL;
4397 *returned=0;
4399 #define MAX_VERSION 4
4401 for (version=0; version<MAX_VERSION; version++) {
4402 list=NULL;
4403 ndrivers=get_ntdrivers(&list, architecture, version);
4404 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4406 if(ndrivers == -1)
4407 return ERROR_NOT_ENOUGH_MEMORY;
4409 if(ndrivers != 0) {
4410 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4411 safe_free(list);
4412 return ERROR_NOT_ENOUGH_MEMORY;
4416 for (i=0; i<ndrivers; i++) {
4417 uint32 status;
4419 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4420 ZERO_STRUCT(driver);
4421 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4422 safe_free(list);
4423 return status;
4425 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4426 free_a_printer_driver(driver, 3);
4429 *returned+=ndrivers;
4430 safe_free(list);
4433 /* check the required size. */
4434 for (i=0; i<*returned; i++) {
4435 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4436 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4439 if (!alloc_buffer_size(buffer, *needed)) {
4440 safe_free(driver_info_3);
4441 return ERROR_INSUFFICIENT_BUFFER;
4444 /* fill the buffer with the driver structures */
4445 for (i=0; i<*returned; i++) {
4446 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4447 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4450 for (i=0; i<*returned; i++)
4451 safe_free(driver_info_3[i].dependentfiles);
4453 safe_free(driver_info_3);
4455 if (*needed > offered) {
4456 *returned=0;
4457 return ERROR_INSUFFICIENT_BUFFER;
4459 else
4460 return NT_STATUS_NO_PROBLEMO;
4463 /****************************************************************************
4464 Enumerates all printer drivers.
4465 ****************************************************************************/
4466 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4467 NEW_BUFFER *buffer, uint32 offered,
4468 uint32 *needed, uint32 *returned)
4470 fstring *list = NULL;
4471 fstring servername;
4472 fstring architecture;
4474 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4475 fstrcpy(servername, global_myname);
4476 *needed=0;
4477 *returned=0;
4479 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4481 switch (level) {
4482 case 1:
4483 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4484 case 2:
4485 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4486 case 3:
4487 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4488 default:
4489 *returned=0;
4490 safe_free(list);
4491 return ERROR_INVALID_LEVEL;
4495 /****************************************************************************
4496 ****************************************************************************/
4497 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4499 form->flag=list->flag;
4500 init_unistr(&form->name, list->name);
4501 form->width=list->width;
4502 form->length=list->length;
4503 form->left=list->left;
4504 form->top=list->top;
4505 form->right=list->right;
4506 form->bottom=list->bottom;
4509 /****************************************************************************
4510 ****************************************************************************/
4511 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4512 NEW_BUFFER *buffer, uint32 offered,
4513 uint32 *needed, uint32 *numofforms)
4515 nt_forms_struct *list=NULL;
4516 FORM_1 *forms_1;
4517 int buffer_size=0;
4518 int i;
4520 DEBUG(4,("_new_spoolss_enumforms\n"));
4521 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4522 DEBUGADD(5,("Info level [%d]\n", level));
4524 *numofforms = get_ntforms(&list);
4525 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4527 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4529 switch (level) {
4530 case 1:
4531 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4532 *numofforms=0;
4533 return ERROR_NOT_ENOUGH_MEMORY;
4536 /* construct the list of form structures */
4537 for (i=0; i<*numofforms; i++) {
4538 DEBUGADD(6,("Filling form number [%d]\n",i));
4539 fill_form_1(&forms_1[i], &list[i]);
4542 safe_free(list);
4544 /* check the required size. */
4545 for (i=0; i<*numofforms; i++) {
4546 DEBUGADD(6,("adding form [%d]'s size\n",i));
4547 buffer_size += spoolss_size_form_1(&forms_1[i]);
4550 *needed=buffer_size;
4552 if (!alloc_buffer_size(buffer, buffer_size)){
4553 safe_free(forms_1);
4554 return ERROR_INSUFFICIENT_BUFFER;
4557 /* fill the buffer with the form structures */
4558 for (i=0; i<*numofforms; i++) {
4559 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4560 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4563 safe_free(forms_1);
4565 if (*needed > offered) {
4566 *numofforms=0;
4567 return ERROR_INSUFFICIENT_BUFFER;
4569 else
4570 return NT_STATUS_NO_PROBLEMO;
4572 default:
4573 safe_free(list);
4574 return ERROR_INVALID_LEVEL;
4579 /****************************************************************************
4580 ****************************************************************************/
4581 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4583 nt_forms_struct *list=NULL;
4584 FORM_1 form_1;
4585 fstring form_name;
4586 int buffer_size=0;
4587 int numofforms, i;
4589 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4591 DEBUG(4,("_spoolss_getform\n"));
4592 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4593 DEBUGADD(5,("Info level [%d]\n", level));
4595 numofforms = get_ntforms(&list);
4596 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
4598 if (numofforms == 0)
4599 return ERROR_NO_MORE_ITEMS;
4601 switch (level) {
4602 case 1:
4604 /* Check if the requested name is in the list of form structures */
4605 for (i=0; i<numofforms; i++) {
4607 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
4609 if (strequal(form_name, list[i].name)) {
4610 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
4611 fill_form_1(&form_1, &list[i]);
4612 break;
4616 safe_free(list);
4618 /* check the required size. */
4620 *needed=spoolss_size_form_1(&form_1);
4622 if (!alloc_buffer_size(buffer, buffer_size)){
4623 return ERROR_INSUFFICIENT_BUFFER;
4626 if (*needed > offered) {
4627 return ERROR_INSUFFICIENT_BUFFER;
4630 /* fill the buffer with the form structures */
4631 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
4632 new_smb_io_form_1("", buffer, &form_1, 0);
4634 return NT_STATUS_NO_PROBLEMO;
4636 default:
4637 safe_free(list);
4638 return ERROR_INVALID_LEVEL;
4642 /****************************************************************************
4643 ****************************************************************************/
4644 static void fill_port_1(PORT_INFO_1 *port, char *name)
4646 init_unistr(&port->port_name, name);
4649 /****************************************************************************
4650 ****************************************************************************/
4651 static void fill_port_2(PORT_INFO_2 *port, char *name)
4653 init_unistr(&port->port_name, name);
4654 init_unistr(&port->monitor_name, "Local Monitor");
4655 init_unistr(&port->description, "Local Port");
4656 #define PORT_TYPE_WRITE 1
4657 port->port_type=PORT_TYPE_WRITE;
4658 port->reserved=0x0;
4661 /****************************************************************************
4662 enumports level 1.
4663 ****************************************************************************/
4664 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4666 PORT_INFO_1 *ports=NULL;
4667 int i=0;
4669 if (*lp_enumports_cmd()) {
4670 pid_t local_pid = sys_getpid();
4671 char *cmd = lp_enumports_cmd();
4672 char *path;
4673 char **qlines;
4674 pstring tmp_file;
4675 pstring command;
4676 int numlines;
4677 int ret;
4679 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4680 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4681 else
4682 path = tmpdir();
4684 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4685 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4687 unlink(tmp_file);
4688 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4689 ret = smbrun(command, tmp_file, False);
4690 DEBUG(10,("Returned [%d]\n", ret));
4691 if (ret != 0) {
4692 unlink(tmp_file);
4693 /* Is this the best error to return here? */
4694 return ERROR_ACCESS_DENIED;
4697 numlines = 0;
4698 qlines = file_lines_load(tmp_file, &numlines,True);
4699 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4700 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4701 unlink(tmp_file);
4703 if(numlines) {
4704 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4705 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4706 file_lines_free(qlines);
4707 return ERROR_NOT_ENOUGH_MEMORY;
4710 for (i=0; i<numlines; i++) {
4711 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4712 fill_port_1(&ports[i], qlines[i]);
4715 file_lines_free(qlines);
4718 *returned = numlines;
4720 } else {
4721 *returned = 1; /* Sole Samba port returned. */
4723 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4724 return ERROR_NOT_ENOUGH_MEMORY;
4726 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4728 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4731 /* check the required size. */
4732 for (i=0; i<*returned; i++) {
4733 DEBUGADD(6,("adding port [%d]'s size\n", i));
4734 *needed += spoolss_size_port_info_1(&ports[i]);
4737 if (!alloc_buffer_size(buffer, *needed)) {
4738 safe_free(ports);
4739 return ERROR_INSUFFICIENT_BUFFER;
4742 /* fill the buffer with the ports structures */
4743 for (i=0; i<*returned; i++) {
4744 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4745 new_smb_io_port_1("", buffer, &ports[i], 0);
4748 safe_free(ports);
4750 if (*needed > offered) {
4751 *returned=0;
4752 return ERROR_INSUFFICIENT_BUFFER;
4754 else
4755 return NT_STATUS_NO_PROBLEMO;
4758 /****************************************************************************
4759 enumports level 2.
4760 ****************************************************************************/
4762 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4764 PORT_INFO_2 *ports=NULL;
4765 int i=0;
4767 if (*lp_enumports_cmd()) {
4768 pid_t local_pid = sys_getpid();
4769 char *cmd = lp_enumports_cmd();
4770 char *path;
4771 char **qlines;
4772 pstring tmp_file;
4773 pstring command;
4774 int numlines;
4775 int ret;
4777 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4778 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4779 else
4780 path = tmpdir();
4782 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4783 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4785 unlink(tmp_file);
4786 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4787 ret = smbrun(command, tmp_file, False);
4788 DEBUGADD(10,("returned [%d]\n", ret));
4789 if (ret != 0) {
4790 unlink(tmp_file);
4791 /* Is this the best error to return here? */
4792 return ERROR_ACCESS_DENIED;
4795 numlines = 0;
4796 qlines = file_lines_load(tmp_file, &numlines,True);
4797 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4798 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4799 unlink(tmp_file);
4801 if(numlines) {
4802 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4803 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4804 file_lines_free(qlines);
4805 return ERROR_NOT_ENOUGH_MEMORY;
4808 for (i=0; i<numlines; i++) {
4809 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4810 fill_port_2(&(ports[i]), qlines[i]);
4813 file_lines_free(qlines);
4816 *returned = numlines;
4818 } else {
4820 *returned = 1;
4822 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4823 return ERROR_NOT_ENOUGH_MEMORY;
4825 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4827 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4830 /* check the required size. */
4831 for (i=0; i<*returned; i++) {
4832 DEBUGADD(6,("adding port [%d]'s size\n", i));
4833 *needed += spoolss_size_port_info_2(&ports[i]);
4836 if (!alloc_buffer_size(buffer, *needed)) {
4837 safe_free(ports);
4838 return ERROR_INSUFFICIENT_BUFFER;
4841 /* fill the buffer with the ports structures */
4842 for (i=0; i<*returned; i++) {
4843 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4844 new_smb_io_port_2("", buffer, &ports[i], 0);
4847 safe_free(ports);
4849 if (*needed > offered) {
4850 *returned=0;
4851 return ERROR_INSUFFICIENT_BUFFER;
4853 else
4854 return NT_STATUS_NO_PROBLEMO;
4857 /****************************************************************************
4858 enumports.
4859 ****************************************************************************/
4860 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4861 NEW_BUFFER *buffer, uint32 offered,
4862 uint32 *needed, uint32 *returned)
4864 DEBUG(4,("_spoolss_enumports\n"));
4866 *returned=0;
4867 *needed=0;
4869 switch (level) {
4870 case 1:
4871 return enumports_level_1(buffer, offered, needed, returned);
4872 case 2:
4873 return enumports_level_2(buffer, offered, needed, returned);
4874 default:
4875 return ERROR_INVALID_LEVEL;
4879 /****************************************************************************
4880 ****************************************************************************/
4881 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4882 const SPOOL_PRINTER_INFO_LEVEL *info,
4883 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4884 uint32 user_switch, const SPOOL_USER_CTR *user,
4885 POLICY_HND *handle)
4887 NT_PRINTER_INFO_LEVEL *printer = NULL;
4888 fstring name;
4889 int snum;
4891 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4892 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4893 return ERROR_NOT_ENOUGH_MEMORY;
4896 ZERO_STRUCTP(printer);
4898 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4899 convert_printer_info(info, printer, 2);
4901 if (*lp_addprinter_cmd() )
4902 if ( !add_printer_hook(printer) ) {
4903 free_a_printer(&printer,2);
4904 return ERROR_ACCESS_DENIED;
4907 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4908 printer->info_2->sharename);
4910 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4911 free_a_printer(&printer,2);
4912 return ERROR_ACCESS_DENIED;
4915 /* you must be a printer admin to add a new printer */
4916 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4917 free_a_printer(&printer,2);
4918 return ERROR_ACCESS_DENIED;
4922 * Do sanity check on the requested changes for Samba.
4925 if (!check_printer_ok(printer->info_2, snum)) {
4926 free_a_printer(&printer,2);
4927 return ERROR_INVALID_PARAMETER;
4930 /* write the ASCII on disk */
4931 if (add_a_printer(*printer, 2) != 0) {
4932 free_a_printer(&printer,2);
4933 return ERROR_ACCESS_DENIED;
4936 if (!open_printer_hnd(handle, name)) {
4937 /* Handle open failed - remove addition. */
4938 del_a_printer(printer->info_2->sharename);
4939 free_a_printer(&printer,2);
4940 return ERROR_ACCESS_DENIED;
4943 free_a_printer(&printer,2);
4945 srv_spoolss_sendnotify(handle);
4947 return NT_STATUS_NO_PROBLEMO;
4950 /****************************************************************************
4951 ****************************************************************************/
4952 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4953 const SPOOL_PRINTER_INFO_LEVEL *info,
4954 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4955 uint32 user_switch, const SPOOL_USER_CTR *user,
4956 POLICY_HND *handle)
4958 switch (level) {
4959 case 1:
4960 /* we don't handle yet */
4961 /* but I know what to do ... */
4962 return ERROR_INVALID_LEVEL;
4963 case 2:
4964 return spoolss_addprinterex_level_2(uni_srv_name, info,
4965 unk0, unk1, unk2, unk3,
4966 user_switch, user, handle);
4967 default:
4968 return ERROR_INVALID_LEVEL;
4972 /****************************************************************************
4973 ****************************************************************************/
4974 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4975 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4977 uint32 err = NT_STATUS_NO_PROBLEMO;
4978 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4979 struct current_user user;
4981 ZERO_STRUCT(driver);
4983 get_current_user(&user, p);
4985 convert_printer_driver_info(info, &driver, level);
4987 DEBUG(5,("Cleaning driver's information\n"));
4988 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
4989 goto done;
4991 DEBUG(5,("Moving driver to final destination\n"));
4992 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4993 if (err == 0)
4994 err = ERROR_ACCESS_DENIED;
4995 goto done;
4998 if (add_a_printer_driver(driver, level)!=0) {
4999 err = ERROR_ACCESS_DENIED;
5000 goto done;
5003 done:
5004 free_a_printer_driver(driver, level);
5005 return err;
5008 /****************************************************************************
5009 ****************************************************************************/
5010 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5012 init_unistr(&info->name, name);
5015 /****************************************************************************
5016 ****************************************************************************/
5017 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5019 pstring path;
5020 pstring long_archi;
5021 pstring short_archi;
5022 DRIVER_DIRECTORY_1 *info=NULL;
5024 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5026 if (get_short_archi(short_archi, long_archi)==FALSE)
5027 return ERROR_INVALID_ENVIRONMENT;
5029 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5030 return ERROR_NOT_ENOUGH_MEMORY;
5032 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5034 DEBUG(4,("printer driver directory: [%s]\n", path));
5036 fill_driverdir_1(info, path);
5038 *needed += spoolss_size_driverdir_info_1(info);
5040 if (!alloc_buffer_size(buffer, *needed)) {
5041 safe_free(info);
5042 return ERROR_INSUFFICIENT_BUFFER;
5045 new_smb_io_driverdir_1("", buffer, info, 0);
5047 safe_free(info);
5049 if (*needed > offered)
5050 return ERROR_INSUFFICIENT_BUFFER;
5051 else
5052 return NT_STATUS_NO_PROBLEMO;
5055 /****************************************************************************
5056 ****************************************************************************/
5057 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5058 NEW_BUFFER *buffer, uint32 offered,
5059 uint32 *needed)
5061 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5063 *needed=0;
5065 switch(level) {
5066 case 1:
5067 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5068 default:
5069 return ERROR_INVALID_LEVEL;
5073 /****************************************************************************
5074 ****************************************************************************/
5075 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5076 uint32 in_value_len, uint32 in_data_len,
5077 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5078 uint32 *out_type,
5079 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5081 NT_PRINTER_INFO_LEVEL *printer = NULL;
5083 fstring value;
5085 uint32 param_index;
5086 uint32 biggest_valuesize;
5087 uint32 biggest_datasize;
5088 uint32 data_len;
5089 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5090 int snum;
5091 uint8 *data=NULL;
5092 uint32 type;
5094 ZERO_STRUCT(printer);
5096 *out_max_value_len=0;
5097 *out_value=NULL;
5098 *out_value_len=0;
5100 *out_type=0;
5102 *out_max_data_len=0;
5103 *data_out=NULL;
5104 *out_data_len=0;
5106 DEBUG(5,("spoolss_enumprinterdata\n"));
5108 if (!OPEN_HANDLE(Printer)) {
5109 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5110 return ERROR_INVALID_HANDLE;
5113 if (!get_printer_snum(handle, &snum))
5114 return ERROR_INVALID_HANDLE;
5116 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5117 return ERROR_INVALID_HANDLE;
5120 * The NT machine wants to know the biggest size of value and data
5122 * cf: MSDN EnumPrinterData remark section
5124 if ( (in_value_len==0) && (in_data_len==0) ) {
5125 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5127 #if 0
5129 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5130 * if this parameter size doesn't exist.
5131 * Ok - my opinion here is that the client is not asking for the greatest
5132 * possible size of all the parameters, but is asking specifically for the size needed
5133 * for this specific parameter. In that case we can remove the loop below and
5134 * simplify this lookup code considerably. JF - comments welcome. JRA.
5137 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5138 safe_free(data);
5139 free_a_printer(&printer, 2);
5140 return ERROR_NO_MORE_ITEMS;
5142 #endif
5144 safe_free(data);
5145 data = NULL;
5147 param_index=0;
5148 biggest_valuesize=0;
5149 biggest_datasize=0;
5151 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5152 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5153 if (data_len > biggest_datasize) biggest_datasize=data_len;
5155 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5157 safe_free(data);
5158 data = NULL;
5159 param_index++;
5163 * I think this is correct, it doesn't break APW and
5164 * allows Gerald's Win32 test programs to work correctly,
5165 * but may need altering.... JRA.
5168 if (param_index == 0) {
5169 /* No parameters found. */
5170 free_a_printer(&printer, 2);
5171 return ERROR_NO_MORE_ITEMS;
5174 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5175 *out_value_len=2*(1+biggest_valuesize);
5176 *out_data_len=biggest_datasize;
5178 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5180 free_a_printer(&printer, 2);
5181 return NT_STATUS_NO_PROBLEMO;
5185 * the value len is wrong in NT sp3
5186 * that's the number of bytes not the number of unicode chars
5189 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5190 safe_free(data);
5191 free_a_printer(&printer, 2);
5192 return ERROR_NO_MORE_ITEMS;
5195 free_a_printer(&printer, 2);
5198 * the value is:
5199 * - counted in bytes in the request
5200 * - counted in UNICODE chars in the max reply
5201 * - counted in bytes in the real size
5203 * take a pause *before* coding not *during* coding
5206 *out_max_value_len=(in_value_len/sizeof(uint16));
5207 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5208 safe_free(data);
5209 return ERROR_NOT_ENOUGH_MEMORY;
5212 ZERO_STRUCTP(*out_value);
5213 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5215 *out_type=type;
5217 /* the data is counted in bytes */
5218 *out_max_data_len=in_data_len;
5219 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5220 safe_free(data);
5221 return ERROR_NOT_ENOUGH_MEMORY;
5224 memset(*data_out,'\0',in_data_len);
5225 memcpy(*data_out, data, (size_t)data_len);
5226 *out_data_len=data_len;
5228 safe_free(data);
5230 return NT_STATUS_NO_PROBLEMO;
5233 /****************************************************************************
5234 ****************************************************************************/
5235 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5236 const UNISTR2 *value,
5237 uint32 type,
5238 uint32 max_len,
5239 const uint8 *data,
5240 uint32 real_len,
5241 uint32 numeric_data)
5243 NT_PRINTER_INFO_LEVEL *printer = NULL;
5244 NT_PRINTER_PARAM *param = NULL, old_param;
5245 int snum=0;
5246 uint32 status = 0x0;
5247 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5249 DEBUG(5,("spoolss_setprinterdata\n"));
5251 if (!OPEN_HANDLE(Printer)) {
5252 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5253 return ERROR_INVALID_HANDLE;
5256 if (!get_printer_snum(handle, &snum))
5257 return ERROR_INVALID_HANDLE;
5259 status = get_a_printer(&printer, 2, lp_servicename(snum));
5260 if (status != 0x0)
5261 return ERROR_INVALID_NAME;
5263 convert_specific_param(&param, value , type, data, real_len);
5265 /* Check if we are making any changes or not. Return true if
5266 nothing is actually changing. */
5268 ZERO_STRUCT(old_param);
5270 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5271 &old_param.type, (unsigned int *)&old_param.data_len)) {
5273 if (param->type == old_param.type &&
5274 param->data_len == old_param.data_len &&
5275 memcmp(param->data, old_param.data,
5276 old_param.data_len) == 0) {
5278 DEBUG(3, ("setprinterdata hasn't changed\n"));
5279 status = NT_STATUS_NO_PROBLEMO;
5280 goto done;
5284 /* Access check */
5286 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5287 DEBUG(3, ("security descriptor change denied by existing "
5288 "security descriptor\n"));
5289 status = ERROR_ACCESS_DENIED;
5290 goto done;
5293 unlink_specific_param_if_exist(printer->info_2, param);
5295 add_a_specific_param(printer->info_2, &param);
5296 status = mod_a_printer(*printer, 2);
5298 done:
5299 free_a_printer(&printer, 2);
5300 if (param)
5301 free_nt_printer_param(&param);
5302 safe_free(old_param.data);
5304 return status;
5307 /****************************************************************************
5308 ****************************************************************************/
5309 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5311 NT_PRINTER_INFO_LEVEL *printer = NULL;
5312 NT_PRINTER_PARAM param;
5313 int snum=0;
5314 uint32 status = 0x0;
5315 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5317 DEBUG(5,("spoolss_deleteprinterdata\n"));
5319 if (!OPEN_HANDLE(Printer)) {
5320 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5321 return ERROR_INVALID_HANDLE;
5324 if (!get_printer_snum(handle, &snum))
5325 return ERROR_INVALID_HANDLE;
5327 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5328 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5329 "security descriptor\n"));
5330 return ERROR_ACCESS_DENIED;
5333 status = get_a_printer(&printer, 2, lp_servicename(snum));
5334 if (status != 0x0)
5335 return ERROR_INVALID_NAME;
5337 ZERO_STRUCTP(&param);
5338 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5340 if(!unlink_specific_param_if_exist(printer->info_2, &param))
5341 status = ERROR_INVALID_PARAMETER;
5342 else
5343 status = mod_a_printer(*printer, 2);
5345 free_a_printer(&printer, 2);
5346 return status;
5349 /****************************************************************************
5350 ****************************************************************************/
5351 uint32 _spoolss_addform( POLICY_HND *handle,
5352 uint32 level,
5353 const FORM *form)
5355 int count=0;
5356 nt_forms_struct *list=NULL;
5357 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5359 DEBUG(5,("spoolss_addform\n"));
5361 if (!OPEN_HANDLE(Printer)) {
5362 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5363 return ERROR_INVALID_HANDLE;
5366 count=get_ntforms(&list);
5367 if(!add_a_form(&list, form, &count))
5368 return ERROR_NOT_ENOUGH_MEMORY;
5369 write_ntforms(&list, count);
5371 safe_free(list);
5373 return 0x0;
5376 /****************************************************************************
5377 ****************************************************************************/
5378 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5380 int count=0;
5381 uint32 ret = 0;
5382 nt_forms_struct *list=NULL;
5383 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5385 DEBUG(5,("spoolss_deleteform\n"));
5387 if (!OPEN_HANDLE(Printer)) {
5388 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5389 return ERROR_INVALID_HANDLE;
5392 count = get_ntforms(&list);
5393 if(!delete_a_form(&list, form_name, &count, &ret))
5394 return ERROR_INVALID_PARAMETER;
5396 safe_free(list);
5398 return ret;
5401 /****************************************************************************
5402 ****************************************************************************/
5403 uint32 _spoolss_setform( POLICY_HND *handle,
5404 const UNISTR2 *uni_name,
5405 uint32 level,
5406 const FORM *form)
5408 int count=0;
5409 nt_forms_struct *list=NULL;
5410 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5412 DEBUG(5,("spoolss_setform\n"));
5414 if (!OPEN_HANDLE(Printer)) {
5415 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5416 return ERROR_INVALID_HANDLE;
5418 count=get_ntforms(&list);
5419 update_a_form(&list, form, count);
5420 write_ntforms(&list, count);
5422 safe_free(list);
5424 return 0x0;
5427 /****************************************************************************
5428 enumprintprocessors level 1.
5429 ****************************************************************************/
5430 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5432 PRINTPROCESSOR_1 *info_1=NULL;
5434 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5435 return ERROR_NOT_ENOUGH_MEMORY;
5437 (*returned) = 0x1;
5439 init_unistr(&info_1->name, "winprint");
5441 *needed += spoolss_size_printprocessor_info_1(info_1);
5443 if (!alloc_buffer_size(buffer, *needed))
5444 return ERROR_INSUFFICIENT_BUFFER;
5446 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5448 safe_free(info_1);
5450 if (*needed > offered) {
5451 *returned=0;
5452 return ERROR_INSUFFICIENT_BUFFER;
5454 else
5455 return NT_STATUS_NO_PROBLEMO;
5458 /****************************************************************************
5459 ****************************************************************************/
5460 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5461 NEW_BUFFER *buffer, uint32 offered,
5462 uint32 *needed, uint32 *returned)
5464 DEBUG(5,("spoolss_enumprintprocessors\n"));
5467 * Enumerate the print processors ...
5469 * Just reply with "winprint", to keep NT happy
5470 * and I can use my nice printer checker.
5473 *returned=0;
5474 *needed=0;
5476 switch (level) {
5477 case 1:
5478 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5479 default:
5480 return ERROR_INVALID_LEVEL;
5484 /****************************************************************************
5485 enumprintprocdatatypes level 1.
5486 ****************************************************************************/
5487 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5489 PRINTPROCDATATYPE_1 *info_1=NULL;
5491 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5492 return ERROR_NOT_ENOUGH_MEMORY;
5494 (*returned) = 0x1;
5496 init_unistr(&info_1->name, "RAW");
5498 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5500 if (!alloc_buffer_size(buffer, *needed))
5501 return ERROR_INSUFFICIENT_BUFFER;
5503 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5505 safe_free(info_1);
5507 if (*needed > offered) {
5508 *returned=0;
5509 return ERROR_INSUFFICIENT_BUFFER;
5511 else
5512 return NT_STATUS_NO_PROBLEMO;
5515 /****************************************************************************
5516 ****************************************************************************/
5517 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5518 NEW_BUFFER *buffer, uint32 offered,
5519 uint32 *needed, uint32 *returned)
5521 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5523 *returned=0;
5524 *needed=0;
5526 switch (level) {
5527 case 1:
5528 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5529 default:
5530 return ERROR_INVALID_LEVEL;
5534 /****************************************************************************
5535 enumprintmonitors level 1.
5536 ****************************************************************************/
5537 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5539 PRINTMONITOR_1 *info_1=NULL;
5541 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5542 return ERROR_NOT_ENOUGH_MEMORY;
5544 (*returned) = 0x1;
5546 init_unistr(&info_1->name, "Local Port");
5548 *needed += spoolss_size_printmonitor_info_1(info_1);
5550 if (!alloc_buffer_size(buffer, *needed))
5551 return ERROR_INSUFFICIENT_BUFFER;
5553 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5555 safe_free(info_1);
5557 if (*needed > offered) {
5558 *returned=0;
5559 return ERROR_INSUFFICIENT_BUFFER;
5561 else
5562 return NT_STATUS_NO_PROBLEMO;
5565 /****************************************************************************
5566 enumprintmonitors level 2.
5567 ****************************************************************************/
5568 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5570 PRINTMONITOR_2 *info_2=NULL;
5572 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5573 return ERROR_NOT_ENOUGH_MEMORY;
5575 (*returned) = 0x1;
5577 init_unistr(&info_2->name, "Local Port");
5578 init_unistr(&info_2->environment, "Windows NT X86");
5579 init_unistr(&info_2->dll_name, "localmon.dll");
5581 *needed += spoolss_size_printmonitor_info_2(info_2);
5583 if (!alloc_buffer_size(buffer, *needed))
5584 return ERROR_INSUFFICIENT_BUFFER;
5586 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5588 safe_free(info_2);
5590 if (*needed > offered) {
5591 *returned=0;
5592 return ERROR_INSUFFICIENT_BUFFER;
5594 else
5595 return NT_STATUS_NO_PROBLEMO;
5598 /****************************************************************************
5599 ****************************************************************************/
5600 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
5601 NEW_BUFFER *buffer, uint32 offered,
5602 uint32 *needed, uint32 *returned)
5604 DEBUG(5,("spoolss_enumprintmonitors\n"));
5607 * Enumerate the print monitors ...
5609 * Just reply with "Local Port", to keep NT happy
5610 * and I can use my nice printer checker.
5613 *returned=0;
5614 *needed=0;
5616 switch (level) {
5617 case 1:
5618 return enumprintmonitors_level_1(buffer, offered, needed, returned);
5619 case 2:
5620 return enumprintmonitors_level_2(buffer, offered, needed, returned);
5621 default:
5622 return ERROR_INVALID_LEVEL;
5626 /****************************************************************************
5627 ****************************************************************************/
5628 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5630 int i=0;
5631 BOOL found=False;
5632 JOB_INFO_1 *info_1=NULL;
5634 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
5636 if (info_1 == NULL) {
5637 safe_free(queue);
5638 return ERROR_NOT_ENOUGH_MEMORY;
5641 for (i=0; i<count && found==False; i++) {
5642 if (queue[i].job==(int)jobid)
5643 found=True;
5646 if (found==False) {
5647 safe_free(queue);
5648 safe_free(info_1);
5649 /* I shoud reply something else ... I can't find the good one */
5650 return NT_STATUS_NO_PROBLEMO;
5653 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
5655 safe_free(queue);
5657 *needed += spoolss_size_job_info_1(info_1);
5659 if (!alloc_buffer_size(buffer, *needed)) {
5660 safe_free(info_1);
5661 return ERROR_INSUFFICIENT_BUFFER;
5664 new_smb_io_job_info_1("", buffer, info_1, 0);
5666 safe_free(info_1);
5668 if (*needed > offered)
5669 return ERROR_INSUFFICIENT_BUFFER;
5670 else
5671 return NT_STATUS_NO_PROBLEMO;
5675 /****************************************************************************
5676 ****************************************************************************/
5677 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5679 int i=0;
5680 BOOL found=False;
5681 JOB_INFO_2 *info_2;
5682 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
5684 ZERO_STRUCTP(info_2);
5686 if (info_2 == NULL) {
5687 safe_free(queue);
5688 return ERROR_NOT_ENOUGH_MEMORY;
5691 for (i=0; i<count && found==False; i++) {
5692 if (queue[i].job==(int)jobid)
5693 found=True;
5696 if (found==False) {
5697 safe_free(queue);
5698 safe_free(info_2);
5699 /* I shoud reply something else ... I can't find the good one */
5700 return NT_STATUS_NO_PROBLEMO;
5703 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
5705 safe_free(queue);
5707 *needed += spoolss_size_job_info_2(info_2);
5709 if (!alloc_buffer_size(buffer, *needed)) {
5710 safe_free(info_2);
5711 return ERROR_INSUFFICIENT_BUFFER;
5714 new_smb_io_job_info_2("", buffer, info_2, 0);
5716 free_job_info_2(info_2);
5718 if (*needed > offered)
5719 return ERROR_INSUFFICIENT_BUFFER;
5720 else
5721 return NT_STATUS_NO_PROBLEMO;
5724 /****************************************************************************
5725 ****************************************************************************/
5726 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
5727 NEW_BUFFER *buffer, uint32 offered,
5728 uint32 *needed)
5730 int snum;
5731 int count;
5732 print_queue_struct *queue=NULL;
5733 print_status_struct prt_status;
5735 DEBUG(5,("spoolss_getjob\n"));
5737 memset(&prt_status, 0, sizeof(prt_status));
5739 *needed=0;
5741 if (!get_printer_snum(handle, &snum))
5742 return ERROR_INVALID_HANDLE;
5744 count = print_queue_status(snum, &queue, &prt_status);
5746 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5747 count, prt_status.status, prt_status.message));
5749 switch (level) {
5750 case 1:
5751 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
5752 case 2:
5753 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
5754 default:
5755 safe_free(queue);
5756 return ERROR_INVALID_LEVEL;
5759 #undef OLD_NTDOMAIN