More converted to canonical format. Home now - do the rest tomorrow...
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob29fd549e35f0308f2c7167e0e4b1acc89a94513f
1 /*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000.
8 * Copyright (C) Jeremy Allison 2001.
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_QUEUED:
94 return 0;
95 case LPQ_PAUSED:
96 return JOB_STATUS_PAUSED;
97 case LPQ_SPOOLING:
98 return JOB_STATUS_SPOOLING;
99 case LPQ_PRINTING:
100 return JOB_STATUS_PRINTING;
101 case LPQ_ERROR:
102 return JOB_STATUS_ERROR;
103 case LPQ_DELETING:
104 return JOB_STATUS_DELETING;
105 case LPQ_OFFLINE:
106 return JOB_STATUS_OFFLINE;
107 case LPQ_PAPEROUT:
108 return JOB_STATUS_PAPEROUT;
109 case LPQ_PRINTED:
110 return JOB_STATUS_PRINTED;
111 case LPQ_DELETED:
112 return JOB_STATUS_DELETED;
113 case LPQ_BLOCKED:
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
118 return 0;
121 static int nt_printq_status(int v)
123 switch (v) {
124 case LPQ_PAUSED:
125 return PRINTER_STATUS_PAUSED;
126 case LPQ_QUEUED:
127 case LPQ_SPOOLING:
128 case LPQ_PRINTING:
129 return 0;
131 return 0;
134 /****************************************************************************
135 initialise printer handle states...
136 ****************************************************************************/
137 void init_printer_hnd(void)
139 ubi_dlInitList(&Printer_list);
140 ubi_dlInitList(&counter_list);
143 /****************************************************************************
144 Return a user struct for a pipe user.
145 ****************************************************************************/
147 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
149 if (p->ntlmssp_auth_validated) {
150 memcpy(user, &p->pipe_user, sizeof(struct current_user));
151 } else {
152 extern struct current_user current_user;
153 memcpy(user, &current_user, sizeof(struct current_user));
156 return user;
159 /****************************************************************************
160 create a unique printer handle
161 ****************************************************************************/
162 static void create_printer_hnd(POLICY_HND *hnd)
164 static uint32 prt_hnd_low = 0;
165 static uint32 prt_hnd_high = 0;
167 if (hnd == NULL) return;
169 /* i severely doubt that prt_hnd_high will ever be non-zero... */
170 prt_hnd_low++;
171 if (prt_hnd_low == 0) prt_hnd_high++;
173 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
174 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
175 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
176 SIVAL(hnd->data, 12, time(NULL)); /* something random */
177 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
180 /****************************************************************************
181 find printer index by handle
182 ****************************************************************************/
183 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
185 Printer_entry *find_printer;
187 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
189 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
191 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
192 DEBUG(4,("Found printer handle \n"));
193 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
194 return find_printer;
198 DEBUG(3,("Whoops, Printer handle not found: "));
199 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
200 return NULL;
203 /****************************************************************************
204 clear an handle
205 ****************************************************************************/
206 static void clear_handle(POLICY_HND *hnd)
208 ZERO_STRUCTP(hnd);
211 /***************************************************************************
212 Disconnect from the client
213 ****************************************************************************/
214 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
216 uint32 status;
218 /* weird if the test succeds !!! */
219 if (smb_connections==0) {
220 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
221 return False;
224 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
225 return False;
227 /* if it's the last connection, deconnect the IPC$ share */
228 if (smb_connections==1) {
229 if(!spoolss_disconnect_from_client(&cli))
230 return False;
232 message_deregister(MSG_PRINTER_NOTIFY);
235 smb_connections--;
237 return True;
240 /****************************************************************************
241 close printer index by handle
242 ****************************************************************************/
243 static BOOL close_printer_handle(POLICY_HND *hnd)
245 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
247 if (!OPEN_HANDLE(Printer)) {
248 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
249 return False;
252 if (Printer->notify.client_connected==True)
253 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
254 return ERROR_INVALID_HANDLE;
256 Printer->open=False;
257 Printer->notify.flags=0;
258 Printer->notify.options=0;
259 Printer->notify.localmachine[0]='\0';
260 Printer->notify.printerlocal=0;
261 safe_free(Printer->notify.option);
262 Printer->notify.option=NULL;
263 Printer->notify.client_connected=False;
265 clear_handle(hnd);
267 ubi_dlRemThis(&Printer_list, Printer);
269 safe_free(Printer);
271 return True;
274 /****************************************************************************
275 delete a printer given a handle
276 ****************************************************************************/
277 static uint32 delete_printer_handle(POLICY_HND *hnd)
279 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
281 if (!OPEN_HANDLE(Printer)) {
282 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
283 return ERROR_INVALID_HANDLE;
286 if (del_a_printer(Printer->dev.handlename) != 0) {
287 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
288 return ERROR_INVALID_HANDLE;
291 /* Check calling user has permission to delete printer. Note that
292 since we set the snum parameter to -1 only administrators can
293 delete the printer. This stops people with the Full Control
294 permission from deleting the printer. */
296 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
297 DEBUG(3, ("printer delete denied by security descriptor\n"));
298 return ERROR_ACCESS_DENIED;
301 if (*lp_deleteprinter_cmd()) {
303 pid_t local_pid = sys_getpid();
304 char *cmd = lp_deleteprinter_cmd();
305 char *path;
306 pstring tmp_file;
307 pstring command;
308 int ret;
309 int i;
311 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
312 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
313 else
314 path = tmpdir();
316 /* Printer->dev.handlename equals portname equals sharename */
317 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
318 Printer->dev.handlename);
319 dos_to_unix(command, True); /* Convert printername to unix-codepage */
320 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
322 unlink(tmp_file);
323 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
324 ret = smbrun(command, tmp_file, False);
325 if (ret != 0) {
326 unlink(tmp_file);
327 return ERROR_INVALID_HANDLE; /* What to return here? */
329 DEBUGADD(10,("returned [%d]\n", ret));
330 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
331 unlink(tmp_file);
333 /* Send SIGHUP to process group... is there a better way? */
334 kill(0, SIGHUP);
336 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
337 lp_killservice( i );
338 return ERROR_SUCCESS;
339 } else
340 return ERROR_ACCESS_DENIED;
343 return ERROR_SUCCESS;
346 /****************************************************************************
347 return the snum of a printer corresponding to an handle
348 ****************************************************************************/
349 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
351 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
353 if (!OPEN_HANDLE(Printer)) {
354 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
355 return False;
358 switch (Printer->printer_type) {
359 case PRINTER_HANDLE_IS_PRINTER:
360 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
361 *number = print_queue_snum(Printer->dev.handlename);
362 return (*number != -1);
363 case PRINTER_HANDLE_IS_PRINTSERVER:
364 return False;
365 default:
366 return False;
370 /****************************************************************************
371 set printer handle type.
372 ****************************************************************************/
373 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
375 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
377 if (!OPEN_HANDLE(Printer)) {
378 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
379 return False;
382 DEBUG(4,("Setting printer access=%x\n", access_required));
383 Printer->access = access_required;
384 return True;
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
398 return False;
401 /* it's a print server */
402 if (!strchr(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
406 /* it's a printer */
407 else {
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
412 return True;
415 /****************************************************************************
416 Set printer handle name.
417 ****************************************************************************/
419 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
421 NT_PRINTER_INFO_LEVEL *printer = NULL;
422 int snum;
423 int n_services=lp_numservices();
424 char *aprinter;
425 BOOL found=False;
427 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
429 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
430 ZERO_STRUCT(Printer->dev.printerservername);
431 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
432 return True;
435 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
436 return False;
438 aprinter=strchr(handlename+2, '\\');
439 aprinter++;
441 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
444 * store the Samba share name in it
445 * in back we have the long printer name
446 * need to iterate all the snum and do a
447 * get_a_printer each time to find the printer
448 * faster to do it here than later.
451 for (snum=0;snum<n_services && found==False;snum++) {
452 char *printername;
454 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
455 continue;
457 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
459 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
460 continue;
462 printername=strchr(printer->info_2->printername+2, '\\');
463 printername++;
465 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
466 printer->info_2->printername, aprinter ));
468 if ( strlen(printername) != strlen(aprinter) ) {
469 free_a_printer(&printer, 2);
470 continue;
473 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
474 free_a_printer(&printer, 2);
475 continue;
478 found=True;
482 * if we haven't found a printer with the given handlename
483 * then it can be a share name as you can open both \\server\printer and
484 * \\server\share
488 * we still check if the printer description file exists as NT won't be happy
489 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
492 if (found==False) {
493 DEBUGADD(5,("Printer not found, checking for share now\n"));
495 for (snum=0;snum<n_services && found==False;snum++) {
497 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
498 continue;
500 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
502 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
503 continue;
505 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
506 printer->info_2->printername, aprinter ));
508 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
509 free_a_printer(&printer, 2);
510 continue;
513 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
514 free_a_printer(&printer, 2);
515 continue;
518 found=True;
522 if (found==False) {
523 DEBUGADD(4,("Printer not found\n"));
524 return False;
527 snum--;
528 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
529 printer->info_2->printername, lp_servicename(snum),snum));
531 ZERO_STRUCT(Printer->dev.handlename);
532 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
534 free_a_printer(&printer, 2);
536 return True;
539 /****************************************************************************
540 find first available printer slot. creates a printer handle for you.
541 ****************************************************************************/
543 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
545 Printer_entry *new_printer;
547 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
548 clear_handle(hnd);
549 create_printer_hnd(hnd);
551 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
552 return False;
554 ZERO_STRUCTP(new_printer);
556 new_printer->open = True;
557 new_printer->notify.option=NULL;
559 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
561 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
563 if (!set_printer_hnd_printertype(new_printer, name)) {
564 close_printer_handle(hnd);
565 return False;
568 if (!set_printer_hnd_name(new_printer, name)) {
569 close_printer_handle(hnd);
570 return False;
573 DEBUG(5, ("%d printer handles active\n",
574 (int)ubi_dlCount(&Printer_list)));
576 return True;
579 /********************************************************************
580 Return True is the handle is a print server.
581 ********************************************************************/
582 static BOOL handle_is_printserver(const POLICY_HND *handle)
584 Printer_entry *Printer=find_printer_index_by_hnd(handle);
586 if (!OPEN_HANDLE(Printer))
587 return False;
589 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
590 return False;
592 return True;
595 /****************************************************************************
596 allocate more memory for a BUFFER.
597 ****************************************************************************/
598 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
600 prs_struct *ps;
601 uint32 extra_space;
602 uint32 old_offset;
604 ps= &buffer->prs;
606 /* damn, I'm doing the reverse operation of prs_grow() :) */
607 if (buffer_size < prs_data_size(ps))
608 extra_space=0;
609 else
610 extra_space = buffer_size - prs_data_size(ps);
613 * save the offset and move to the end of the buffer
614 * prs_grow() checks the extra_space against the offset
616 old_offset=prs_offset(ps);
617 prs_set_offset(ps, prs_data_size(ps));
619 if (!prs_grow(ps, extra_space))
620 return False;
622 prs_set_offset(ps, old_offset);
624 buffer->string_at_end=prs_data_size(ps);
626 return True;
629 /***************************************************************************
630 receive the notify message
631 ****************************************************************************/
632 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
634 fstring printer;
635 uint32 status;
636 Printer_entry *find_printer;
638 *printer = '\0';
639 fstrcpy(printer,buf);
641 if (len == 0) {
642 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
643 return;
646 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
648 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
650 /* Iterate the printer list. */
651 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
654 * if the entry is the given printer or if it's a printerserver
655 * we send the message
658 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
659 if (strcmp(find_printer->dev.handlename, printer))
660 continue;
662 if (find_printer->notify.client_connected==True)
663 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
668 /***************************************************************************
669 send a notify event
670 ****************************************************************************/
671 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
673 fstring printer;
675 Printer_entry *Printer=find_printer_index_by_hnd(handle);
677 if (!OPEN_HANDLE(Printer)) {
678 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
679 return False;
682 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
683 fstrcpy(printer, Printer->dev.handlename);
684 else
685 fstrcpy(printer, "");
687 /*srv_spoolss_receive_message(printer);*/
688 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
690 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
692 return True;
695 /********************************************************************
696 * spoolss_open_printer
698 * called from the spoolss dispatcher
699 ********************************************************************/
701 uint32 _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
703 #if 0
704 uint32 result = NT_STATUS_NO_PROBLEMO;
705 #endif
707 UNISTR2 *printername = NULL;
708 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
709 /* uint32 user_switch = q_u->user_switch; - notused */
710 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
711 POLICY_HND *handle = &r_u->handle;
713 fstring name;
714 int snum;
715 struct current_user user;
717 if (q_u->printername_ptr != 0)
718 printername = &q_u->printername;
720 if (printername == NULL)
721 return ERROR_INVALID_PRINTER_NAME;
723 /* some sanity check because you can open a printer or a print server */
724 /* aka: \\server\printer or \\server */
725 unistr2_to_ascii(name, printername, sizeof(name)-1);
727 DEBUGADD(3,("checking name: %s\n",name));
729 if (!open_printer_hnd(handle, name))
730 return ERROR_INVALID_PRINTER_NAME;
733 if (printer_default->datatype_ptr != NULL)
735 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
736 set_printer_hnd_datatype(handle, datatype);
738 else
739 set_printer_hnd_datatype(handle, "");
742 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
743 close_printer_handle(handle);
744 return ERROR_ACCESS_DENIED;
748 First case: the user is opening the print server:
750 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
751 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
753 Then both Win2k and WinNT clients try an OpenPrinterEx with
754 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
755 or if the user is listed in the smb.conf printer admin parameter.
757 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
758 client view printer folder, but does not show the MSAPW.
760 Note: this test needs code to check access rights here too. Jeremy
761 could you look at this?
764 Second case: the user is opening a printer:
765 NT doesn't let us connect to a printer if the connecting user
766 doesn't have print permission.
770 get_current_user(&user, p);
772 if (handle_is_printserver(handle)) {
773 if (printer_default->access_required == 0) {
774 return NT_STATUS_NO_PROBLEMO;
776 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
778 if (!lp_ms_add_printer_wizard()) {
779 close_printer_handle(handle);
780 return ERROR_ACCESS_DENIED;
782 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
783 return NT_STATUS_NO_PROBLEMO;
785 else {
786 close_printer_handle(handle);
787 return ERROR_ACCESS_DENIED;
791 else
793 /* NT doesn't let us connect to a printer if the connecting user
794 doesn't have print permission. */
796 if (!get_printer_snum(handle, &snum))
797 return ERROR_INVALID_HANDLE;
799 /* map an empty access mask to the minimum access mask */
800 if (printer_default->access_required == 0x0)
801 printer_default->access_required = PRINTER_ACCESS_USE;
803 if (!print_access_check(&user, snum, printer_default->access_required)) {
804 DEBUG(3, ("access DENIED for printer open\n"));
805 close_printer_handle(handle);
806 return ERROR_ACCESS_DENIED;
810 * If we have a default device pointer in the
811 * printer_default struct, then we need to get
812 * the printer info from the tdb and if there is
813 * no default devicemode there then we do a *SET*
814 * here ! This is insanity.... JRA.
818 * If the openprinterex rpc call contains a devmode,
819 * it's a per-user one. This per-user devmode is derivated
820 * from the global devmode. Openprinterex() contains a per-user
821 * devmode for when you do EMF printing and spooling.
822 * In the EMF case, the NT workstation is only doing half the job
823 * of rendering the page. The other half is done by running the printer
824 * driver on the server.
825 * The EMF file doesn't contain the page description (paper size, orientation, ...).
826 * The EMF file only contains what is to be printed on the page.
827 * So in order for the server to know how to print, the NT client sends
828 * a devicemode attached to the openprinterex call.
829 * But this devicemode is short lived, it's only valid for the current print job.
831 * If Samba would have supported EMF spooling, this devicemode would
832 * have been attached to the handle, to sent it to the driver to correctly
833 * rasterize the EMF file.
835 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
836 * we just act as a pass-thru between windows and the printer.
838 * In order to know that Samba supports only RAW spooling, NT has to call
839 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
840 * and until NT sends a RAW job, we refuse it.
842 * But to call getprinter() or startdoc(), you first need a valid handle,
843 * and to get an handle you have to call openprintex(). Hence why you have
844 * a devicemode in the openprinterex() call.
847 * Differences between NT4 and NT 2000.
848 * NT4:
849 * ---
850 * On NT4, you only have a global devicemode. This global devicemode can be changed
851 * by the administrator (or by a user with enough privs). Everytime a user
852 * wants to print, the devicemode is resetted to the default. In Word, everytime
853 * you print, the printer's characteristics are always reset to the global devicemode.
855 * NT 2000:
856 * -------
857 * In W2K, there is the notion of per-user devicemode. The first time you use
858 * a printer, a per-user devicemode is build from the global devicemode.
859 * If you change your per-user devicemode, it is saved in the registry, under the
860 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
861 * printer preferences available.
863 * To change the per-user devicemode: it's the "Printing Preferences ..." button
864 * on the General Tab of the printer properties windows.
866 * To change the global devicemode: it's the "Printing Defaults..." button
867 * on the Advanced Tab of the printer properties window.
869 * JFM.
874 #if 0
875 if (printer_default->devmode_cont.devmode != NULL) {
876 result = printer_write_default_dev( snum, printer_default);
877 if (result != 0) {
878 close_printer_handle(handle);
879 return result;
882 #endif
885 return NT_STATUS_NO_PROBLEMO;
888 /****************************************************************************
889 ****************************************************************************/
890 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
891 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
893 switch (level) {
894 case 2:
895 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
896 break;
897 default:
898 break;
901 return True;
904 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
905 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
907 switch (level) {
908 case 3:
909 printer->info_3=NULL;
910 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
911 break;
912 case 6:
913 printer->info_6=NULL;
914 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
915 break;
916 default:
917 break;
920 return True;
923 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
924 NT_DEVICEMODE **pp_nt_devmode)
926 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
929 * Ensure nt_devmode is a valid pointer
930 * as we will be overwriting it.
933 if (nt_devmode == NULL) {
934 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
935 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
936 return False;
939 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
940 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
942 nt_devmode->specversion=devmode->specversion;
943 nt_devmode->driverversion=devmode->driverversion;
944 nt_devmode->size=devmode->size;
945 nt_devmode->fields=devmode->fields;
946 nt_devmode->orientation=devmode->orientation;
947 nt_devmode->papersize=devmode->papersize;
948 nt_devmode->paperlength=devmode->paperlength;
949 nt_devmode->paperwidth=devmode->paperwidth;
950 nt_devmode->scale=devmode->scale;
951 nt_devmode->copies=devmode->copies;
952 nt_devmode->defaultsource=devmode->defaultsource;
953 nt_devmode->printquality=devmode->printquality;
954 nt_devmode->color=devmode->color;
955 nt_devmode->duplex=devmode->duplex;
956 nt_devmode->yresolution=devmode->yresolution;
957 nt_devmode->ttoption=devmode->ttoption;
958 nt_devmode->collate=devmode->collate;
960 nt_devmode->logpixels=devmode->logpixels;
961 nt_devmode->bitsperpel=devmode->bitsperpel;
962 nt_devmode->pelswidth=devmode->pelswidth;
963 nt_devmode->pelsheight=devmode->pelsheight;
964 nt_devmode->displayflags=devmode->displayflags;
965 nt_devmode->displayfrequency=devmode->displayfrequency;
966 nt_devmode->icmmethod=devmode->icmmethod;
967 nt_devmode->icmintent=devmode->icmintent;
968 nt_devmode->mediatype=devmode->mediatype;
969 nt_devmode->dithertype=devmode->dithertype;
970 nt_devmode->reserved1=devmode->reserved1;
971 nt_devmode->reserved2=devmode->reserved2;
972 nt_devmode->panningwidth=devmode->panningwidth;
973 nt_devmode->panningheight=devmode->panningheight;
976 * Only change private and driverextra if the incoming devmode
977 * has a new one. JRA.
980 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
981 safe_free(nt_devmode->private);
982 nt_devmode->driverextra=devmode->driverextra;
983 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
984 return False;
985 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
988 *pp_nt_devmode = nt_devmode;
990 return True;
993 /********************************************************************
994 * _spoolss_enddocprinter_internal.
995 ********************************************************************/
997 static uint32 _spoolss_enddocprinter_internal(POLICY_HND *handle)
999 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1001 if (!OPEN_HANDLE(Printer)) {
1002 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1003 return ERROR_INVALID_HANDLE;
1006 Printer->document_started=False;
1007 print_job_end(Printer->jobid,True);
1008 /* error codes unhandled so far ... */
1010 return 0x0;
1013 /********************************************************************
1014 * api_spoolss_closeprinter
1015 ********************************************************************/
1017 uint32 _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1019 POLICY_HND *handle = &q_u->handle;
1021 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1023 if (Printer && Printer->document_started)
1024 _spoolss_enddocprinter_internal(handle); /* print job was not closed */
1026 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1028 if (!close_printer_handle(handle))
1029 return ERROR_INVALID_HANDLE;
1031 return NT_STATUS_NO_PROBLEMO;
1034 /********************************************************************
1035 * api_spoolss_deleteprinter
1037 ********************************************************************/
1039 uint32 _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1041 POLICY_HND *handle = &q_u->handle;
1043 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1044 uint32 result;
1046 if (Printer && Printer->document_started)
1047 _spoolss_enddocprinter_internal(handle); /* print job was not closed */
1049 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1051 result = delete_printer_handle(handle);
1053 if (result == ERROR_SUCCESS) {
1054 srv_spoolss_sendnotify(handle);
1057 return result;
1060 /********************************************************************
1061 GetPrinterData on a printer server Handle.
1062 ********************************************************************/
1063 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1065 int i;
1067 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1069 if (!strcmp(value, "BeepEnabled")) {
1070 *type = 0x4;
1071 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1072 return False;
1073 SIVAL(*data, 0, 0x01);
1074 *needed = 0x4;
1075 return True;
1078 if (!strcmp(value, "EventLog")) {
1079 *type = 0x4;
1080 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1081 return False;
1082 SIVAL(*data, 0, 0x1B);
1083 *needed = 0x4;
1084 return True;
1087 if (!strcmp(value, "NetPopup")) {
1088 *type = 0x4;
1089 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1090 return False;
1091 SIVAL(*data, 0, 0x01);
1092 *needed = 0x4;
1093 return True;
1096 if (!strcmp(value, "MajorVersion")) {
1097 *type = 0x4;
1098 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1099 return False;
1100 SIVAL(*data, 0, 0x02);
1101 *needed = 0x4;
1102 return True;
1105 if (!strcmp(value, "DefaultSpoolDirectory")) {
1106 pstring string="You are using a Samba server";
1107 *type = 0x1;
1108 *needed = 2*(strlen(string)+1);
1109 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1110 return False;
1111 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1113 /* it's done by hand ready to go on the wire */
1114 for (i=0; i<strlen(string); i++) {
1115 (*data)[2*i]=string[i];
1116 (*data)[2*i+1]='\0';
1118 return True;
1121 if (!strcmp(value, "Architecture")) {
1122 pstring string="Windows NT x86";
1123 *type = 0x1;
1124 *needed = 2*(strlen(string)+1);
1125 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1126 return False;
1127 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1128 for (i=0; i<strlen(string); i++) {
1129 (*data)[2*i]=string[i];
1130 (*data)[2*i+1]='\0';
1132 return True;
1135 return False;
1138 /********************************************************************
1139 GetPrinterData on a printer Handle.
1140 ********************************************************************/
1141 static BOOL getprinterdata_printer(POLICY_HND *handle,
1142 fstring value, uint32 *type,
1143 uint8 **data, uint32 *needed, uint32 in_size )
1145 NT_PRINTER_INFO_LEVEL *printer = NULL;
1146 int snum=0;
1147 uint8 *idata=NULL;
1148 uint32 len;
1149 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1151 DEBUG(5,("getprinterdata_printer\n"));
1153 if (!OPEN_HANDLE(Printer)) {
1154 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1155 return False;
1158 if(!get_printer_snum(handle, &snum))
1159 return False;
1161 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1162 return False;
1164 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1165 free_a_printer(&printer, 2);
1166 return False;
1169 free_a_printer(&printer, 2);
1171 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1173 if (in_size) {
1174 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
1175 return False;
1178 memset(*data, 0, in_size *sizeof(uint8));
1179 /* copy the min(in_size, len) */
1180 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1181 } else {
1182 *data = NULL;
1185 *needed = len;
1187 DEBUG(5,("getprinterdata_printer:copy done\n"));
1189 safe_free(idata);
1191 return True;
1194 /********************************************************************
1195 * spoolss_getprinterdata
1196 ********************************************************************/
1198 uint32 _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1200 POLICY_HND *handle = &q_u->handle;
1201 UNISTR2 *valuename = &q_u->valuename;
1202 uint32 in_size = q_u->size;
1203 uint32 *type = &r_u->type;
1204 uint32 *out_size = &r_u->size;
1205 uint8 **data = &r_u->data;
1206 uint32 *needed = &r_u->needed;
1208 fstring value;
1209 BOOL found=False;
1210 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1213 * Reminder: when it's a string, the length is in BYTES
1214 * even if UNICODE is negociated.
1216 * JFM, 4/19/1999
1219 *out_size=in_size;
1221 /* in case of problem, return some default values */
1222 *needed=0;
1223 *type=0;
1225 DEBUG(4,("_spoolss_getprinterdata\n"));
1227 if (!OPEN_HANDLE(Printer)) {
1228 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1229 return ERROR_NOT_ENOUGH_MEMORY;
1230 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1231 return ERROR_INVALID_HANDLE;
1234 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1236 if (handle_is_printserver(handle))
1237 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1238 else
1239 found= getprinterdata_printer(handle, value, type, data, needed, *out_size);
1241 if (found==False) {
1242 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1243 /* reply this param doesn't exist */
1244 if (*out_size) {
1245 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1246 return ERROR_NOT_ENOUGH_MEMORY;
1247 } else {
1248 *data = NULL;
1251 return ERROR_INVALID_PARAMETER;
1254 if (*needed > *out_size)
1255 return ERROR_MORE_DATA;
1256 else {
1257 return NT_STATUS_NO_PROBLEMO;
1261 /***************************************************************************
1262 connect to the client
1263 ****************************************************************************/
1264 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1266 uint32 status;
1269 * If it's the first connection, contact the client
1270 * and connect to the IPC$ share anonumously
1272 if (smb_connections==0) {
1273 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1274 return False;
1275 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1279 smb_connections++;
1281 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1282 return False;
1284 return True;
1287 /********************************************************************
1288 * _spoolss_rffpcnex
1289 * ReplyFindFirstPrinterChangeNotifyEx
1291 * jfmxxxx: before replying OK: status=0
1292 * should do a rpc call to the workstation asking ReplyOpenPrinter
1293 * have to code it, later.
1295 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1296 * called from api_spoolss_rffpcnex
1297 ********************************************************************/
1299 uint32 _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1301 POLICY_HND *handle = &q_u->handle;
1302 uint32 flags = q_u->flags;
1303 uint32 options = q_u->options;
1304 UNISTR2 *localmachine = &q_u->localmachine;
1305 uint32 printerlocal = q_u->printerlocal;
1306 SPOOL_NOTIFY_OPTION *option = q_u->option;
1308 /* store the notify value in the printer struct */
1310 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1312 if (!OPEN_HANDLE(Printer)) {
1313 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1314 return ERROR_INVALID_HANDLE;
1317 Printer->notify.flags=flags;
1318 Printer->notify.options=options;
1319 Printer->notify.printerlocal=printerlocal;
1320 Printer->notify.option=option;
1321 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1323 /* connect to the client machine and send a ReplyOpenPrinter */
1324 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1325 Printer->notify.printerlocal, 1,
1326 &Printer->notify.client_hnd))
1327 Printer->notify.client_connected=True;
1329 return NT_STATUS_NO_PROBLEMO;
1332 /*******************************************************************
1333 * fill a notify_info_data with the servername
1334 ********************************************************************/
1336 static void spoolss_notify_server_name(int snum,
1337 SPOOL_NOTIFY_INFO_DATA *data,
1338 print_queue_struct *queue,
1339 NT_PRINTER_INFO_LEVEL *printer,
1340 TALLOC_CTX *mem_ctx)
1342 pstring temp_name, temp;
1343 uint32 len;
1345 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1347 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1349 data->notify_data.data.length = len / 2 - 1;
1350 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1352 if (!data->notify_data.data.string) {
1353 data->notify_data.data.length = 0;
1354 return;
1357 memcpy(data->notify_data.data.string, temp, len);
1360 /*******************************************************************
1361 * fill a notify_info_data with the printername (not including the servername).
1362 ********************************************************************/
1363 static void spoolss_notify_printer_name(int snum,
1364 SPOOL_NOTIFY_INFO_DATA *data,
1365 print_queue_struct *queue,
1366 NT_PRINTER_INFO_LEVEL *printer,
1367 TALLOC_CTX *mem_ctx)
1369 pstring temp;
1370 uint32 len;
1372 /* the notify name should not contain the \\server\ part */
1373 char *p = strrchr(printer->info_2->printername, '\\');
1375 if (!p) {
1376 p = printer->info_2->printername;
1377 } else {
1378 p++;
1381 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1383 data->notify_data.data.length = len / 2 - 1;
1384 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1386 if (!data->notify_data.data.string) {
1387 data->notify_data.data.length = 0;
1388 return;
1391 memcpy(data->notify_data.data.string, temp, len);
1394 /*******************************************************************
1395 * fill a notify_info_data with the servicename
1396 ********************************************************************/
1397 static void spoolss_notify_share_name(int snum,
1398 SPOOL_NOTIFY_INFO_DATA *data,
1399 print_queue_struct *queue,
1400 NT_PRINTER_INFO_LEVEL *printer,
1401 TALLOC_CTX *mem_ctx)
1403 pstring temp;
1404 uint32 len;
1406 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1407 sizeof(temp) - 2, True);
1409 data->notify_data.data.length = len / 2 - 1;
1410 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1412 if (!data->notify_data.data.string) {
1413 data->notify_data.data.length = 0;
1414 return;
1417 memcpy(data->notify_data.data.string, temp, len);
1420 /*******************************************************************
1421 * fill a notify_info_data with the port name
1422 ********************************************************************/
1423 static void spoolss_notify_port_name(int snum,
1424 SPOOL_NOTIFY_INFO_DATA *data,
1425 print_queue_struct *queue,
1426 NT_PRINTER_INFO_LEVEL *printer,
1427 TALLOC_CTX *mem_ctx)
1429 pstring temp;
1430 uint32 len;
1432 /* even if it's strange, that's consistant in all the code */
1434 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1435 sizeof(temp) - 2, True);
1437 data->notify_data.data.length = len / 2 - 1;
1438 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1440 if (!data->notify_data.data.string) {
1441 data->notify_data.data.length = 0;
1442 return;
1445 memcpy(data->notify_data.data.string, temp, len);
1448 /*******************************************************************
1449 * fill a notify_info_data with the printername
1450 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1451 * but it doesn't exist, have to see what to do
1452 ********************************************************************/
1453 static void spoolss_notify_driver_name(int snum,
1454 SPOOL_NOTIFY_INFO_DATA *data,
1455 print_queue_struct *queue,
1456 NT_PRINTER_INFO_LEVEL *printer,
1457 TALLOC_CTX *mem_ctx)
1459 pstring temp;
1460 uint32 len;
1462 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1463 sizeof(temp) - 2, True);
1465 data->notify_data.data.length = len / 2 - 1;
1466 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1468 if (!data->notify_data.data.string) {
1469 data->notify_data.data.length = 0;
1470 return;
1473 memcpy(data->notify_data.data.string, temp, len);
1476 /*******************************************************************
1477 * fill a notify_info_data with the comment
1478 ********************************************************************/
1479 static void spoolss_notify_comment(int snum,
1480 SPOOL_NOTIFY_INFO_DATA *data,
1481 print_queue_struct *queue,
1482 NT_PRINTER_INFO_LEVEL *printer,
1483 TALLOC_CTX *mem_ctx)
1485 pstring temp;
1486 uint32 len;
1488 if (*printer->info_2->comment == '\0')
1489 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1490 sizeof(temp) - 2, True);
1491 else
1492 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1493 sizeof(temp) - 2, True);
1495 data->notify_data.data.length = len / 2 - 1;
1496 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1498 if (!data->notify_data.data.string) {
1499 data->notify_data.data.length = 0;
1500 return;
1503 memcpy(data->notify_data.data.string, temp, len);
1506 /*******************************************************************
1507 * fill a notify_info_data with the comment
1508 * jfm:xxxx incorrect, have to create a new smb.conf option
1509 * location = "Room 1, floor 2, building 3"
1510 ********************************************************************/
1511 static void spoolss_notify_location(int snum,
1512 SPOOL_NOTIFY_INFO_DATA *data,
1513 print_queue_struct *queue,
1514 NT_PRINTER_INFO_LEVEL *printer,
1515 TALLOC_CTX *mem_ctx)
1517 pstring temp;
1518 uint32 len;
1520 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1521 sizeof(temp) - 2, True);
1523 data->notify_data.data.length = len / 2 - 1;
1524 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1526 if (!data->notify_data.data.string) {
1527 data->notify_data.data.length = 0;
1528 return;
1531 memcpy(data->notify_data.data.string, temp, len);
1534 /*******************************************************************
1535 * fill a notify_info_data with the device mode
1536 * jfm:xxxx don't to it for know but that's a real problem !!!
1537 ********************************************************************/
1538 static void spoolss_notify_devmode(int snum,
1539 SPOOL_NOTIFY_INFO_DATA *data,
1540 print_queue_struct *queue,
1541 NT_PRINTER_INFO_LEVEL *printer,
1542 TALLOC_CTX *mem_ctx)
1546 /*******************************************************************
1547 * fill a notify_info_data with the separator file name
1548 * jfm:xxxx just return no file could add an option to smb.conf
1549 * separator file = "separator.txt"
1550 ********************************************************************/
1551 static void spoolss_notify_sepfile(int snum,
1552 SPOOL_NOTIFY_INFO_DATA *data,
1553 print_queue_struct *queue,
1554 NT_PRINTER_INFO_LEVEL *printer,
1555 TALLOC_CTX *mem_ctx)
1557 pstring temp;
1558 uint32 len;
1560 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1561 sizeof(temp) - 2, True);
1563 data->notify_data.data.length = len / 2 - 1;
1564 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1566 if (!data->notify_data.data.string) {
1567 data->notify_data.data.length = 0;
1568 return;
1571 memcpy(data->notify_data.data.string, temp, len);
1574 /*******************************************************************
1575 * fill a notify_info_data with the print processor
1576 * jfm:xxxx return always winprint to indicate we don't do anything to it
1577 ********************************************************************/
1578 static void spoolss_notify_print_processor(int snum,
1579 SPOOL_NOTIFY_INFO_DATA *data,
1580 print_queue_struct *queue,
1581 NT_PRINTER_INFO_LEVEL *printer,
1582 TALLOC_CTX *mem_ctx)
1584 pstring temp;
1585 uint32 len;
1587 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1588 sizeof(temp) - 2, True);
1590 data->notify_data.data.length = len / 2 - 1;
1591 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1593 if (!data->notify_data.data.string) {
1594 data->notify_data.data.length = 0;
1595 return;
1598 memcpy(data->notify_data.data.string, temp, len);
1601 /*******************************************************************
1602 * fill a notify_info_data with the print processor options
1603 * jfm:xxxx send an empty string
1604 ********************************************************************/
1605 static void spoolss_notify_parameters(int snum,
1606 SPOOL_NOTIFY_INFO_DATA *data,
1607 print_queue_struct *queue,
1608 NT_PRINTER_INFO_LEVEL *printer,
1609 TALLOC_CTX *mem_ctx)
1611 pstring temp;
1612 uint32 len;
1614 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1615 sizeof(temp) - 2, True);
1617 data->notify_data.data.length = len / 2 - 1;
1618 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1620 if (!data->notify_data.data.string) {
1621 data->notify_data.data.length = 0;
1622 return;
1625 memcpy(data->notify_data.data.string, temp, len);
1628 /*******************************************************************
1629 * fill a notify_info_data with the data type
1630 * jfm:xxxx always send RAW as data type
1631 ********************************************************************/
1632 static void spoolss_notify_datatype(int snum,
1633 SPOOL_NOTIFY_INFO_DATA *data,
1634 print_queue_struct *queue,
1635 NT_PRINTER_INFO_LEVEL *printer,
1636 TALLOC_CTX *mem_ctx)
1638 pstring temp;
1639 uint32 len;
1641 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1642 sizeof(pstring) - 2, True);
1644 data->notify_data.data.length = len / 2 - 1;
1645 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1647 if (!data->notify_data.data.string) {
1648 data->notify_data.data.length = 0;
1649 return;
1652 memcpy(data->notify_data.data.string, temp, len);
1655 /*******************************************************************
1656 * fill a notify_info_data with the security descriptor
1657 * jfm:xxxx send an null pointer to say no security desc
1658 * have to implement security before !
1659 ********************************************************************/
1660 static void spoolss_notify_security_desc(int snum,
1661 SPOOL_NOTIFY_INFO_DATA *data,
1662 print_queue_struct *queue,
1663 NT_PRINTER_INFO_LEVEL *printer,
1664 TALLOC_CTX *mem_ctx)
1666 data->notify_data.data.length=0;
1667 data->notify_data.data.string = NULL;
1670 /*******************************************************************
1671 * fill a notify_info_data with the attributes
1672 * jfm:xxxx a samba printer is always shared
1673 ********************************************************************/
1674 static void spoolss_notify_attributes(int snum,
1675 SPOOL_NOTIFY_INFO_DATA *data,
1676 print_queue_struct *queue,
1677 NT_PRINTER_INFO_LEVEL *printer,
1678 TALLOC_CTX *mem_ctx)
1680 data->notify_data.value[0] = printer->info_2->attributes;
1683 /*******************************************************************
1684 * fill a notify_info_data with the priority
1685 ********************************************************************/
1686 static void spoolss_notify_priority(int snum,
1687 SPOOL_NOTIFY_INFO_DATA *data,
1688 print_queue_struct *queue,
1689 NT_PRINTER_INFO_LEVEL *printer,
1690 TALLOC_CTX *mem_ctx)
1692 data->notify_data.value[0] = printer->info_2->priority;
1695 /*******************************************************************
1696 * fill a notify_info_data with the default priority
1697 ********************************************************************/
1698 static void spoolss_notify_default_priority(int snum,
1699 SPOOL_NOTIFY_INFO_DATA *data,
1700 print_queue_struct *queue,
1701 NT_PRINTER_INFO_LEVEL *printer,
1702 TALLOC_CTX *mem_ctx)
1704 data->notify_data.value[0] = printer->info_2->default_priority;
1707 /*******************************************************************
1708 * fill a notify_info_data with the start time
1709 ********************************************************************/
1710 static void spoolss_notify_start_time(int snum,
1711 SPOOL_NOTIFY_INFO_DATA *data,
1712 print_queue_struct *queue,
1713 NT_PRINTER_INFO_LEVEL *printer,
1714 TALLOC_CTX *mem_ctx)
1716 data->notify_data.value[0] = printer->info_2->starttime;
1719 /*******************************************************************
1720 * fill a notify_info_data with the until time
1721 ********************************************************************/
1722 static void spoolss_notify_until_time(int snum,
1723 SPOOL_NOTIFY_INFO_DATA *data,
1724 print_queue_struct *queue,
1725 NT_PRINTER_INFO_LEVEL *printer,
1726 TALLOC_CTX *mem_ctx)
1728 data->notify_data.value[0] = printer->info_2->untiltime;
1731 /*******************************************************************
1732 * fill a notify_info_data with the status
1733 ********************************************************************/
1734 static void spoolss_notify_status(int snum,
1735 SPOOL_NOTIFY_INFO_DATA *data,
1736 print_queue_struct *queue,
1737 NT_PRINTER_INFO_LEVEL *printer,
1738 TALLOC_CTX *mem_ctx)
1740 int count;
1742 print_queue_struct *q=NULL;
1743 print_status_struct status;
1745 memset(&status, 0, sizeof(status));
1746 count = print_queue_status(snum, &q, &status);
1747 data->notify_data.value[0]=(uint32) status.status;
1748 safe_free(q);
1751 /*******************************************************************
1752 * fill a notify_info_data with the number of jobs queued
1753 ********************************************************************/
1754 static void spoolss_notify_cjobs(int snum,
1755 SPOOL_NOTIFY_INFO_DATA *data,
1756 print_queue_struct *queue,
1757 NT_PRINTER_INFO_LEVEL *printer,
1758 TALLOC_CTX *mem_ctx)
1760 print_queue_struct *q=NULL;
1761 print_status_struct status;
1763 memset(&status, 0, sizeof(status));
1764 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1765 safe_free(q);
1768 /*******************************************************************
1769 * fill a notify_info_data with the average ppm
1770 ********************************************************************/
1771 static void spoolss_notify_average_ppm(int snum,
1772 SPOOL_NOTIFY_INFO_DATA *data,
1773 print_queue_struct *queue,
1774 NT_PRINTER_INFO_LEVEL *printer,
1775 TALLOC_CTX *mem_ctx)
1777 /* always respond 8 pages per minutes */
1778 /* a little hard ! */
1779 data->notify_data.value[0] = printer->info_2->averageppm;
1782 /*******************************************************************
1783 * fill a notify_info_data with username
1784 ********************************************************************/
1785 static void spoolss_notify_username(int snum,
1786 SPOOL_NOTIFY_INFO_DATA *data,
1787 print_queue_struct *queue,
1788 NT_PRINTER_INFO_LEVEL *printer,
1789 TALLOC_CTX *mem_ctx)
1791 pstring temp;
1792 uint32 len;
1794 len = (uint32)dos_PutUniCode(temp, queue->user,
1795 sizeof(temp) - 2, True);
1797 data->notify_data.data.length = len / 2 - 1;
1798 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1800 if (!data->notify_data.data.string) {
1801 data->notify_data.data.length = 0;
1802 return;
1805 memcpy(data->notify_data.data.string, temp, len);
1808 /*******************************************************************
1809 * fill a notify_info_data with job status
1810 ********************************************************************/
1811 static void spoolss_notify_job_status(int snum,
1812 SPOOL_NOTIFY_INFO_DATA *data,
1813 print_queue_struct *queue,
1814 NT_PRINTER_INFO_LEVEL *printer,
1815 TALLOC_CTX *mem_ctx)
1817 data->notify_data.value[0]=nt_printj_status(queue->status);
1820 /*******************************************************************
1821 * fill a notify_info_data with job name
1822 ********************************************************************/
1823 static void spoolss_notify_job_name(int snum,
1824 SPOOL_NOTIFY_INFO_DATA *data,
1825 print_queue_struct *queue,
1826 NT_PRINTER_INFO_LEVEL *printer,
1827 TALLOC_CTX *mem_ctx)
1829 pstring temp;
1830 uint32 len;
1832 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1833 True);
1835 data->notify_data.data.length = len / 2 - 1;
1836 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1838 if (!data->notify_data.data.string) {
1839 data->notify_data.data.length = 0;
1840 return;
1843 memcpy(data->notify_data.data.string, temp, len);
1846 /*******************************************************************
1847 * fill a notify_info_data with job status
1848 ********************************************************************/
1849 static void spoolss_notify_job_status_string(int snum,
1850 SPOOL_NOTIFY_INFO_DATA *data,
1851 print_queue_struct *queue,
1852 NT_PRINTER_INFO_LEVEL *printer,
1853 TALLOC_CTX *mem_ctx)
1856 * Now we're returning job status codes we just return a "" here. JRA.
1859 char *p = "";
1860 pstring temp;
1861 uint32 len;
1863 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1864 p = "unknown";
1866 switch (queue->status) {
1867 case LPQ_QUEUED:
1868 p = "Queued";
1869 break;
1870 case LPQ_PAUSED:
1871 p = ""; /* NT provides the paused string */
1872 break;
1873 case LPQ_SPOOLING:
1874 p = "Spooling";
1875 break;
1876 case LPQ_PRINTING:
1877 p = "Printing";
1878 break;
1880 #endif /* NO LONGER NEEDED. */
1882 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1884 data->notify_data.data.length = len / 2 - 1;
1885 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1887 if (!data->notify_data.data.string) {
1888 data->notify_data.data.length = 0;
1889 return;
1892 memcpy(data->notify_data.data.string, temp, len);
1895 /*******************************************************************
1896 * fill a notify_info_data with job time
1897 ********************************************************************/
1898 static void spoolss_notify_job_time(int snum,
1899 SPOOL_NOTIFY_INFO_DATA *data,
1900 print_queue_struct *queue,
1901 NT_PRINTER_INFO_LEVEL *printer,
1902 TALLOC_CTX *mem_ctx)
1904 data->notify_data.value[0]=0x0;
1907 /*******************************************************************
1908 * fill a notify_info_data with job size
1909 ********************************************************************/
1910 static void spoolss_notify_job_size(int snum,
1911 SPOOL_NOTIFY_INFO_DATA *data,
1912 print_queue_struct *queue,
1913 NT_PRINTER_INFO_LEVEL *printer,
1914 TALLOC_CTX *mem_ctx)
1916 data->notify_data.value[0]=queue->size;
1919 /*******************************************************************
1920 * fill a notify_info_data with job position
1921 ********************************************************************/
1922 static void spoolss_notify_job_position(int snum,
1923 SPOOL_NOTIFY_INFO_DATA *data,
1924 print_queue_struct *queue,
1925 NT_PRINTER_INFO_LEVEL *printer,
1926 TALLOC_CTX *mem_ctx)
1928 data->notify_data.value[0]=queue->job;
1931 /*******************************************************************
1932 * fill a notify_info_data with submitted time
1933 ********************************************************************/
1934 static void spoolss_notify_submitted_time(int snum,
1935 SPOOL_NOTIFY_INFO_DATA *data,
1936 print_queue_struct *queue,
1937 NT_PRINTER_INFO_LEVEL *printer,
1938 TALLOC_CTX *mem_ctx)
1940 struct tm *t;
1941 uint32 len;
1943 t=gmtime(&queue->time);
1945 len = sizeof(SYSTEMTIME);
1947 data->notify_data.data.length = len;
1948 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1950 if (!data->notify_data.data.string) {
1951 data->notify_data.data.length = 0;
1952 return;
1955 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1958 #define END 65535
1960 struct s_notify_info_data_table
1962 uint16 type;
1963 uint16 field;
1964 char *name;
1965 uint32 size;
1966 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1967 print_queue_struct *queue,
1968 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1971 struct s_notify_info_data_table notify_info_data_table[] =
1973 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1974 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1975 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1976 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1977 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1978 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1979 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1980 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1981 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1982 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1983 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1984 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1985 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1986 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1987 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1988 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1999 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2000 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2001 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2002 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2003 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2004 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2005 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2006 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2007 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2008 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2009 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2010 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2011 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2012 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2013 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2014 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2015 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2016 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2017 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2018 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2019 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2020 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2021 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2022 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2023 { END, END, "", END, NULL }
2026 /*******************************************************************
2027 return the size of info_data structure
2028 ********************************************************************/
2029 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2031 int i=0;
2033 while (notify_info_data_table[i].type != END)
2035 if ( (notify_info_data_table[i].type == type ) &&
2036 (notify_info_data_table[i].field == field ) )
2038 return (notify_info_data_table[i].size);
2040 i++;
2042 return (65535);
2045 /*******************************************************************
2046 return the type of notify_info_data
2047 ********************************************************************/
2048 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2050 int i=0;
2052 while (notify_info_data_table[i].type != END)
2054 if ( (notify_info_data_table[i].type == type ) &&
2055 (notify_info_data_table[i].field == field ) )
2057 if (notify_info_data_table[i].size == POINTER)
2059 return (False);
2061 else
2063 return (True);
2066 i++;
2068 return (False);
2071 /****************************************************************************
2072 ****************************************************************************/
2073 static int search_notify(uint16 type, uint16 field, int *value)
2075 int j;
2076 BOOL found;
2078 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2080 if ( (notify_info_data_table[j].type == type ) &&
2081 (notify_info_data_table[j].field == field ) )
2082 found=True;
2084 *value=--j;
2086 if ( found && (notify_info_data_table[j].fn != NULL) )
2087 return True;
2088 else
2089 return False;
2092 /****************************************************************************
2093 ****************************************************************************/
2094 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2096 info_data->type = type;
2097 info_data->field = field;
2098 info_data->reserved = 0;
2099 info_data->id = id;
2100 info_data->size = size_of_notify_info_data(type, field);
2101 info_data->enc_type = type_of_notify_info_data(type, field);
2105 /*******************************************************************
2107 * fill a notify_info struct with info asked
2109 ********************************************************************/
2110 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2111 snum, SPOOL_NOTIFY_OPTION_TYPE
2112 *option_type, uint32 id,
2113 TALLOC_CTX *mem_ctx)
2115 int field_num,j;
2116 uint16 type;
2117 uint16 field;
2119 SPOOL_NOTIFY_INFO_DATA *current_data;
2120 NT_PRINTER_INFO_LEVEL *printer = NULL;
2121 print_queue_struct *queue=NULL;
2122 size_t realloc_size = 0;
2123 SPOOL_NOTIFY_INFO_DATA *info_data_ptr = NULL;
2125 type=option_type->type;
2127 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2128 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2129 option_type->count, lp_servicename(snum)));
2131 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2132 return False;
2134 for(field_num=0; field_num<option_type->count; field_num++) {
2135 field = option_type->fields[field_num];
2136 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2138 if (!search_notify(type, field, &j) )
2139 continue;
2141 realloc_size = (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA);
2142 if((info_data_ptr=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info_data_ptr, realloc_size)) == NULL) {
2143 return False;
2145 current_data=&info_data_ptr[info->count];
2147 construct_info_data(current_data, type, field, id);
2149 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2150 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2152 notify_info_data_table[j].fn(snum, current_data, queue,
2153 printer, mem_ctx);
2155 info->count++;
2158 if (realloc_size)
2159 info->data = talloc_memdup(mem_ctx, info_data_ptr, realloc_size);
2160 else
2161 info->data = NULL;
2163 safe_free(info_data_ptr);
2164 free_a_printer(&printer, 2);
2165 return True;
2168 /*******************************************************************
2170 * fill a notify_info struct with info asked
2172 ********************************************************************/
2173 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2174 SPOOL_NOTIFY_INFO *info,
2175 NT_PRINTER_INFO_LEVEL *printer,
2176 int snum, SPOOL_NOTIFY_OPTION_TYPE
2177 *option_type, uint32 id,
2178 TALLOC_CTX *mem_ctx)
2180 int field_num,j;
2181 uint16 type;
2182 uint16 field;
2184 SPOOL_NOTIFY_INFO_DATA *current_data;
2186 DEBUG(4,("construct_notify_jobs_info\n"));
2188 type = option_type->type;
2190 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2191 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2192 option_type->count));
2194 for(field_num=0; field_num<option_type->count; field_num++) {
2195 field = option_type->fields[field_num];
2197 if (!search_notify(type, field, &j) )
2198 continue;
2200 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2201 return False;
2204 current_data=&(info->data[info->count]);
2206 construct_info_data(current_data, type, field, id);
2207 notify_info_data_table[j].fn(snum, current_data, queue,
2208 printer, mem_ctx);
2209 info->count++;
2212 return True;
2216 * JFM: The enumeration is not that simple, it's even non obvious.
2218 * let's take an example: I want to monitor the PRINTER SERVER for
2219 * the printer's name and the number of jobs currently queued.
2220 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2221 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2223 * I have 3 printers on the back of my server.
2225 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2226 * structures.
2227 * Number Data Id
2228 * 1 printer 1 name 1
2229 * 2 printer 1 cjob 1
2230 * 3 printer 2 name 2
2231 * 4 printer 2 cjob 2
2232 * 5 printer 3 name 3
2233 * 6 printer 3 name 3
2235 * that's the print server case, the printer case is even worse.
2240 /*******************************************************************
2242 * enumerate all printers on the printserver
2243 * fill a notify_info struct with info asked
2245 ********************************************************************/
2246 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2247 SPOOL_NOTIFY_INFO *info,
2248 TALLOC_CTX *mem_ctx)
2250 int snum;
2251 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2252 int n_services=lp_numservices();
2253 int i;
2254 uint32 id;
2255 SPOOL_NOTIFY_OPTION *option;
2256 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2258 DEBUG(4,("printserver_notify_info\n"));
2260 option=Printer->notify.option;
2261 id=1;
2262 info->version=2;
2263 info->data=NULL;
2264 info->count=0;
2266 for (i=0; i<option->count; i++) {
2267 option_type=&(option->ctr.type[i]);
2269 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2270 continue;
2272 for (snum=0; snum<n_services; snum++)
2273 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2274 if (construct_notify_printer_info
2275 (info, snum, option_type, id, mem_ctx))
2276 id++;
2280 * Debugging information, don't delete.
2283 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2284 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2285 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2287 for (i=0; i<info->count; i++) {
2288 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2289 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2290 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2294 return NT_STATUS_NO_PROBLEMO;
2297 /*******************************************************************
2299 * fill a notify_info struct with info asked
2301 ********************************************************************/
2302 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2303 TALLOC_CTX *mem_ctx)
2305 int snum;
2306 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2307 int i;
2308 uint32 id;
2309 SPOOL_NOTIFY_OPTION *option;
2310 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2311 int count,j;
2312 print_queue_struct *queue=NULL;
2313 print_status_struct status;
2315 DEBUG(4,("printer_notify_info\n"));
2317 option=Printer->notify.option;
2318 id=0xffffffff;
2319 info->version=2;
2320 info->data=NULL;
2321 info->count=0;
2323 get_printer_snum(hnd, &snum);
2325 for (i=0; i<option->count; i++) {
2326 option_type=&option->ctr.type[i];
2328 switch ( option_type->type ) {
2329 case PRINTER_NOTIFY_TYPE:
2330 if(construct_notify_printer_info(info, snum,
2331 option_type, id,
2332 mem_ctx))
2333 id--;
2334 break;
2336 case JOB_NOTIFY_TYPE: {
2337 NT_PRINTER_INFO_LEVEL *printer = NULL;
2339 memset(&status, 0, sizeof(status));
2340 count = print_queue_status(snum, &queue, &status);
2342 if (get_a_printer(&printer, 2,
2343 lp_servicename(snum)) != 0)
2344 goto done;
2346 for (j=0; j<count; j++) {
2347 construct_notify_jobs_info(&queue[j], info,
2348 printer, snum,
2349 option_type,
2350 queue[j].job,
2351 mem_ctx);
2354 free_a_printer(&printer, 2);
2356 done:
2357 safe_free(queue);
2358 break;
2364 * Debugging information, don't delete.
2367 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2368 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2369 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2371 for (i=0; i<info->count; i++) {
2372 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2373 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2374 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2377 return NT_STATUS_NO_PROBLEMO;
2380 /********************************************************************
2381 * spoolss_rfnpcnex
2382 ********************************************************************/
2384 uint32 _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2386 POLICY_HND *handle = &q_u->handle;
2387 /* uint32 change = q_u->change; - notused. */
2388 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2389 SPOOL_NOTIFY_INFO *info = &r_u->info;
2391 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2392 uint32 result = ERROR_INVALID_HANDLE;
2394 /* we always have a NOTIFY_INFO struct */
2395 r_u->info_ptr=0x1;
2397 if (!OPEN_HANDLE(Printer)) {
2398 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2399 OUR_HANDLE(handle)));
2400 goto done;
2403 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2405 /* jfm: the change value isn't used right now.
2406 * we will honour it when
2407 * a) we'll be able to send notification to the client
2408 * b) we'll have a way to communicate between the spoolss process.
2410 * same thing for option->flags
2411 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2412 * I don't have a global notification system, I'm sending back all the
2413 * informations even when _NOTHING_ has changed.
2416 /* just ignore the SPOOL_NOTIFY_OPTION */
2418 switch (Printer->printer_type) {
2419 case PRINTER_HANDLE_IS_PRINTSERVER:
2420 result = printserver_notify_info(handle, info,
2421 p->mem_ctx);
2422 break;
2424 case PRINTER_HANDLE_IS_PRINTER:
2425 result = printer_notify_info(handle, info, p->mem_ctx);
2426 break;
2429 done:
2430 return result;
2433 /********************************************************************
2434 * construct_printer_info_0
2435 * fill a printer_info_0 struct
2436 ********************************************************************/
2437 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2439 pstring chaine;
2440 int count;
2441 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2442 counter_printer_0 *session_counter;
2443 uint32 global_counter;
2444 struct tm *t;
2445 time_t setuptime;
2447 print_queue_struct *queue=NULL;
2448 print_status_struct status;
2450 memset(&status, 0, sizeof(status));
2452 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2453 return False;
2455 count = print_queue_status(snum, &queue, &status);
2457 /* check if we already have a counter for this printer */
2458 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2460 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2461 if (session_counter->snum == snum)
2462 break;
2465 /* it's the first time, add it to the list */
2466 if (session_counter==NULL) {
2467 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2468 free_a_printer(&ntprinter, 2);
2469 return False;
2471 ZERO_STRUCTP(session_counter);
2472 session_counter->snum=snum;
2473 session_counter->counter=0;
2474 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2477 /* increment it */
2478 session_counter->counter++;
2480 /* JFM:
2481 * the global_counter should be stored in a TDB as it's common to all the clients
2482 * and should be zeroed on samba startup
2484 global_counter=session_counter->counter;
2486 pstrcpy(chaine,ntprinter->info_2->printername);
2488 init_unistr(&printer->printername, chaine);
2490 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2491 init_unistr(&printer->servername, chaine);
2493 printer->cjobs = count;
2494 printer->total_jobs = 0;
2495 printer->total_bytes = 0;
2497 setuptime = (time_t)ntprinter->info_2->setuptime;
2498 t=gmtime(&setuptime);
2500 printer->year = t->tm_year+1900;
2501 printer->month = t->tm_mon+1;
2502 printer->dayofweek = t->tm_wday;
2503 printer->day = t->tm_mday;
2504 printer->hour = t->tm_hour;
2505 printer->minute = t->tm_min;
2506 printer->second = t->tm_sec;
2507 printer->milliseconds = 0;
2509 printer->global_counter = global_counter;
2510 printer->total_pages = 0;
2511 printer->major_version = 0x0004; /* NT 4 */
2512 printer->build_version = 0x0565; /* build 1381 */
2513 printer->unknown7 = 0x1;
2514 printer->unknown8 = 0x0;
2515 printer->unknown9 = 0x0;
2516 printer->session_counter = session_counter->counter;
2517 printer->unknown11 = 0x0;
2518 printer->printer_errors = 0x0; /* number of print failure */
2519 printer->unknown13 = 0x0;
2520 printer->unknown14 = 0x1;
2521 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2522 printer->unknown16 = 0x0;
2523 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2524 printer->unknown18 = 0x0;
2525 printer->status = nt_printq_status(status.status);
2526 printer->unknown20 = 0x0;
2527 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2528 printer->unknown22 = 0x0;
2529 printer->unknown23 = 0x6; /* 6 ???*/
2530 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2531 printer->unknown25 = 0;
2532 printer->unknown26 = 0;
2533 printer->unknown27 = 0;
2534 printer->unknown28 = 0;
2535 printer->unknown29 = 0;
2537 safe_free(queue);
2538 free_a_printer(&ntprinter,2);
2539 return (True);
2542 /********************************************************************
2543 * construct_printer_info_1
2544 * fill a printer_info_1 struct
2545 ********************************************************************/
2546 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2548 pstring chaine;
2549 pstring chaine2;
2550 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2552 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2553 return False;
2555 printer->flags=flags;
2557 if (*ntprinter->info_2->comment == '\0') {
2558 init_unistr(&printer->comment, lp_comment(snum));
2559 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2560 ntprinter->info_2->drivername, lp_comment(snum));
2562 else {
2563 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2564 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2565 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2568 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2570 init_unistr(&printer->description, chaine);
2571 init_unistr(&printer->name, chaine2);
2573 free_a_printer(&ntprinter,2);
2575 return True;
2578 /****************************************************************************
2579 Free a DEVMODE struct.
2580 ****************************************************************************/
2582 static void free_dev_mode(DEVICEMODE *dev)
2584 if (dev == NULL)
2585 return;
2587 if (dev->private)
2588 safe_free(dev->private);
2590 safe_free(dev);
2593 /****************************************************************************
2594 Create a DEVMODE struct. Returns malloced memory.
2595 ****************************************************************************/
2597 static DEVICEMODE *construct_dev_mode(int snum)
2599 char adevice[32];
2600 char aform[32];
2601 NT_PRINTER_INFO_LEVEL *printer = NULL;
2602 NT_DEVICEMODE *ntdevmode = NULL;
2603 DEVICEMODE *devmode = NULL;
2605 DEBUG(7,("construct_dev_mode\n"));
2607 DEBUGADD(8,("getting printer characteristics\n"));
2609 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2610 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2611 return NULL;
2614 ZERO_STRUCTP(devmode);
2616 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2617 goto fail;
2619 if (printer->info_2->devmode)
2620 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2622 if (ntdevmode == NULL)
2623 goto fail;
2625 DEBUGADD(8,("loading DEVICEMODE\n"));
2627 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2628 init_unistr(&devmode->devicename, adevice);
2630 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2631 init_unistr(&devmode->formname, aform);
2633 devmode->specversion = ntdevmode->specversion;
2634 devmode->driverversion = ntdevmode->driverversion;
2635 devmode->size = ntdevmode->size;
2636 devmode->driverextra = ntdevmode->driverextra;
2637 devmode->fields = ntdevmode->fields;
2639 devmode->orientation = ntdevmode->orientation;
2640 devmode->papersize = ntdevmode->papersize;
2641 devmode->paperlength = ntdevmode->paperlength;
2642 devmode->paperwidth = ntdevmode->paperwidth;
2643 devmode->scale = ntdevmode->scale;
2644 devmode->copies = ntdevmode->copies;
2645 devmode->defaultsource = ntdevmode->defaultsource;
2646 devmode->printquality = ntdevmode->printquality;
2647 devmode->color = ntdevmode->color;
2648 devmode->duplex = ntdevmode->duplex;
2649 devmode->yresolution = ntdevmode->yresolution;
2650 devmode->ttoption = ntdevmode->ttoption;
2651 devmode->collate = ntdevmode->collate;
2652 devmode->icmmethod = ntdevmode->icmmethod;
2653 devmode->icmintent = ntdevmode->icmintent;
2654 devmode->mediatype = ntdevmode->mediatype;
2655 devmode->dithertype = ntdevmode->dithertype;
2657 if (ntdevmode->private != NULL) {
2658 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2659 goto fail;
2662 free_nt_devicemode(&ntdevmode);
2663 free_a_printer(&printer,2);
2665 return devmode;
2667 fail:
2669 if (ntdevmode)
2670 free_nt_devicemode(&ntdevmode);
2671 if (printer)
2672 free_a_printer(&printer,2);
2673 free_dev_mode(devmode);
2675 return NULL;
2678 /********************************************************************
2679 * construct_printer_info_2
2680 * fill a printer_info_2 struct
2681 ********************************************************************/
2683 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2685 int count;
2686 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2688 print_queue_struct *queue=NULL;
2689 print_status_struct status;
2690 memset(&status, 0, sizeof(status));
2692 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2693 return False;
2695 memset(&status, 0, sizeof(status));
2696 count = print_queue_status(snum, &queue, &status);
2698 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2699 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2700 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2701 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2702 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2704 if (*ntprinter->info_2->comment == '\0')
2705 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2706 else
2707 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2709 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2710 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2711 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2712 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2713 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2715 printer->attributes = ntprinter->info_2->attributes;
2717 printer->priority = ntprinter->info_2->priority; /* priority */
2718 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2719 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2720 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2721 printer->status = nt_printq_status(status.status); /* status */
2722 printer->cjobs = count; /* jobs */
2723 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2725 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2726 DEBUG(8, ("Returning NULL Devicemode!\n"));
2729 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2730 /* steal the printer info sec_desc structure. [badly done]. */
2731 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2732 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2733 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2734 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2736 else {
2737 printer->secdesc = NULL;
2740 free_a_printer(&ntprinter, 2);
2741 safe_free(queue);
2742 return True;
2745 /********************************************************************
2746 * construct_printer_info_3
2747 * fill a printer_info_3 struct
2748 ********************************************************************/
2749 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2751 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2752 PRINTER_INFO_3 *printer = NULL;
2754 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2755 return False;
2757 *pp_printer = NULL;
2758 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2759 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2760 return False;
2763 ZERO_STRUCTP(printer);
2765 printer->flags = 4; /* These are the components of the SD we are returning. */
2766 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2767 /* steal the printer info sec_desc structure. [badly done]. */
2768 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2770 #if 0
2772 * Set the flags for the components we are returning.
2775 if (printer->secdesc->owner_sid)
2776 printer->flags |= OWNER_SECURITY_INFORMATION;
2778 if (printer->secdesc->grp_sid)
2779 printer->flags |= GROUP_SECURITY_INFORMATION;
2781 if (printer->secdesc->dacl)
2782 printer->flags |= DACL_SECURITY_INFORMATION;
2784 if (printer->secdesc->sacl)
2785 printer->flags |= SACL_SECURITY_INFORMATION;
2786 #endif
2788 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2789 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2790 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2793 free_a_printer(&ntprinter, 2);
2795 *pp_printer = printer;
2796 return True;
2799 /********************************************************************
2800 Spoolss_enumprinters.
2801 ********************************************************************/
2802 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2804 int snum;
2805 int i;
2806 int n_services=lp_numservices();
2807 PRINTER_INFO_1 *printers=NULL;
2808 PRINTER_INFO_1 current_prt;
2810 DEBUG(4,("enum_all_printers_info_1\n"));
2812 for (snum=0; snum<n_services; snum++) {
2813 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2814 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2816 if (construct_printer_info_1(flags, &current_prt, snum)) {
2817 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2818 *returned=0;
2819 return ERROR_NOT_ENOUGH_MEMORY;
2821 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2822 memcpy(&(printers[*returned]), &current_prt, sizeof(PRINTER_INFO_1));
2823 (*returned)++;
2828 /* check the required size. */
2829 for (i=0; i<*returned; i++)
2830 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2832 if (!alloc_buffer_size(buffer, *needed))
2833 return ERROR_INSUFFICIENT_BUFFER;
2835 /* fill the buffer with the structures */
2836 for (i=0; i<*returned; i++)
2837 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2839 /* clear memory */
2840 safe_free(printers);
2842 if (*needed > offered) {
2843 *returned=0;
2844 return ERROR_INSUFFICIENT_BUFFER;
2846 else
2847 return NT_STATUS_NO_PROBLEMO;
2850 /********************************************************************
2851 enum_all_printers_info_1_local.
2852 *********************************************************************/
2853 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2855 DEBUG(4,("enum_all_printers_info_1_local\n"));
2857 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2860 /********************************************************************
2861 enum_all_printers_info_1_name.
2862 *********************************************************************/
2863 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2865 fstring temp;
2866 DEBUG(4,("enum_all_printers_info_1_name\n"));
2868 fstrcpy(temp, "\\\\");
2869 fstrcat(temp, global_myname);
2871 if (strequal(name, temp)) {
2872 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2874 else
2875 return ERROR_INVALID_NAME;
2878 /********************************************************************
2879 enum_all_printers_info_1_remote.
2880 *********************************************************************/
2881 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2883 PRINTER_INFO_1 *printer;
2884 fstring printername;
2885 fstring desc;
2886 fstring comment;
2887 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2889 /* JFM: currently it's more a place holder than anything else.
2890 * In the spooler world there is a notion of server registration.
2891 * the print servers are registring (sp ?) on the PDC (in the same domain)
2893 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2896 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2897 return ERROR_NOT_ENOUGH_MEMORY;
2899 *returned=1;
2901 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2902 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2903 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2905 init_unistr(&printer->description, desc);
2906 init_unistr(&printer->name, printername);
2907 init_unistr(&printer->comment, comment);
2908 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2910 /* check the required size. */
2911 *needed += spoolss_size_printer_info_1(printer);
2913 if (!alloc_buffer_size(buffer, *needed)) {
2914 safe_free(printer);
2915 return ERROR_INSUFFICIENT_BUFFER;
2918 /* fill the buffer with the structures */
2919 new_smb_io_printer_info_1("", buffer, printer, 0);
2921 /* clear memory */
2922 safe_free(printer);
2924 if (*needed > offered) {
2925 *returned=0;
2926 return ERROR_INSUFFICIENT_BUFFER;
2928 else
2929 return NT_STATUS_NO_PROBLEMO;
2932 /********************************************************************
2933 enum_all_printers_info_1_network.
2934 *********************************************************************/
2936 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2938 DEBUG(4,("enum_all_printers_info_1_network\n"));
2940 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2943 /********************************************************************
2944 * api_spoolss_enumprinters
2946 * called from api_spoolss_enumprinters (see this to understand)
2947 ********************************************************************/
2949 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2951 int snum;
2952 int i;
2953 int n_services=lp_numservices();
2954 PRINTER_INFO_2 *printers=NULL;
2955 PRINTER_INFO_2 current_prt;
2957 for (snum=0; snum<n_services; snum++) {
2958 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2959 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2961 if (construct_printer_info_2(&current_prt, snum)) {
2962 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2963 return ERROR_NOT_ENOUGH_MEMORY;
2964 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2965 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
2966 (*returned)++;
2971 /* check the required size. */
2972 for (i=0; i<*returned; i++)
2973 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2975 if (!alloc_buffer_size(buffer, *needed)) {
2976 for (i=0; i<*returned; i++) {
2977 free_devmode(printers[i].devmode);
2979 safe_free(printers);
2980 return ERROR_INSUFFICIENT_BUFFER;
2983 /* fill the buffer with the structures */
2984 for (i=0; i<*returned; i++)
2985 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2987 /* clear memory */
2988 for (i=0; i<*returned; i++) {
2989 free_devmode(printers[i].devmode);
2991 safe_free(printers);
2993 if (*needed > offered) {
2994 *returned=0;
2995 return ERROR_INSUFFICIENT_BUFFER;
2997 else
2998 return NT_STATUS_NO_PROBLEMO;
3001 /********************************************************************
3002 * handle enumeration of printers at level 1
3003 ********************************************************************/
3004 static uint32 enumprinters_level1( uint32 flags, fstring name,
3005 NEW_BUFFER *buffer, uint32 offered,
3006 uint32 *needed, uint32 *returned)
3008 /* Not all the flags are equals */
3010 if (flags & PRINTER_ENUM_LOCAL)
3011 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3013 if (flags & PRINTER_ENUM_NAME)
3014 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3016 if (flags & PRINTER_ENUM_REMOTE)
3017 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3019 if (flags & PRINTER_ENUM_NETWORK)
3020 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3022 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
3025 /********************************************************************
3026 * handle enumeration of printers at level 2
3027 ********************************************************************/
3028 static uint32 enumprinters_level2( uint32 flags, fstring servername,
3029 NEW_BUFFER *buffer, uint32 offered,
3030 uint32 *needed, uint32 *returned)
3032 fstring temp;
3034 fstrcpy(temp, "\\\\");
3035 fstrcat(temp, global_myname);
3037 if (flags & PRINTER_ENUM_LOCAL) {
3038 if (strequal(servername, temp))
3039 return enum_all_printers_info_2(buffer, offered, needed, returned);
3040 else
3041 return enum_all_printers_info_2(buffer, offered, needed, returned);
3044 if (flags & PRINTER_ENUM_NAME) {
3045 if (strequal(servername, temp))
3046 return enum_all_printers_info_2(buffer, offered, needed, returned);
3047 else
3048 return ERROR_INVALID_NAME;
3051 if (flags & PRINTER_ENUM_REMOTE)
3052 return ERROR_INVALID_LEVEL;
3054 return NT_STATUS_NO_PROBLEMO;
3057 /********************************************************************
3058 * handle enumeration of printers at level 5
3059 ********************************************************************/
3060 static uint32 enumprinters_level5( uint32 flags, fstring servername,
3061 NEW_BUFFER *buffer, uint32 offered,
3062 uint32 *needed, uint32 *returned)
3064 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3065 return NT_STATUS_NO_PROBLEMO;
3068 /********************************************************************
3069 * api_spoolss_enumprinters
3071 * called from api_spoolss_enumprinters (see this to understand)
3072 ********************************************************************/
3074 uint32 _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3076 uint32 flags = q_u->flags;
3077 UNISTR2 *servername = &q_u->servername;
3078 uint32 level = q_u->level;
3079 NEW_BUFFER *buffer = NULL;
3080 uint32 offered = q_u->offered;
3081 uint32 *needed = &r_u->needed;
3082 uint32 *returned = &r_u->returned;
3084 fstring name;
3086 /* that's an [in out] buffer */
3087 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3088 buffer = r_u->buffer;
3090 DEBUG(4,("_spoolss_enumprinters\n"));
3092 *needed=0;
3093 *returned=0;
3096 * Level 1:
3097 * flags==PRINTER_ENUM_NAME
3098 * if name=="" then enumerates all printers
3099 * if name!="" then enumerate the printer
3100 * flags==PRINTER_ENUM_REMOTE
3101 * name is NULL, enumerate printers
3102 * Level 2: name!="" enumerates printers, name can't be NULL
3103 * Level 3: doesn't exist
3104 * Level 4: does a local registry lookup
3105 * Level 5: same as Level 2
3108 unistr2_to_ascii(name, servername, sizeof(name)-1);
3109 strupper(name);
3111 switch (level) {
3112 case 1:
3113 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3114 case 2:
3115 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3116 case 5:
3117 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3118 case 3:
3119 case 4:
3120 default:
3121 return ERROR_INVALID_LEVEL;
3125 /****************************************************************************
3126 ****************************************************************************/
3127 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3129 PRINTER_INFO_0 *printer=NULL;
3131 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3132 return ERROR_NOT_ENOUGH_MEMORY;
3134 construct_printer_info_0(printer, snum);
3136 /* check the required size. */
3137 *needed += spoolss_size_printer_info_0(printer);
3139 if (!alloc_buffer_size(buffer, *needed)) {
3140 safe_free(printer);
3141 return ERROR_INSUFFICIENT_BUFFER;
3144 /* fill the buffer with the structures */
3145 new_smb_io_printer_info_0("", buffer, printer, 0);
3147 /* clear memory */
3148 safe_free(printer);
3150 if (*needed > offered) {
3151 return ERROR_INSUFFICIENT_BUFFER;
3153 else
3154 return NT_STATUS_NO_PROBLEMO;
3157 /****************************************************************************
3158 ****************************************************************************/
3159 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3161 PRINTER_INFO_1 *printer=NULL;
3163 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3164 return ERROR_NOT_ENOUGH_MEMORY;
3166 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3168 /* check the required size. */
3169 *needed += spoolss_size_printer_info_1(printer);
3171 if (!alloc_buffer_size(buffer, *needed)) {
3172 safe_free(printer);
3173 return ERROR_INSUFFICIENT_BUFFER;
3176 /* fill the buffer with the structures */
3177 new_smb_io_printer_info_1("", buffer, printer, 0);
3179 /* clear memory */
3180 safe_free(printer);
3182 if (*needed > offered) {
3183 return ERROR_INSUFFICIENT_BUFFER;
3185 else
3186 return NT_STATUS_NO_PROBLEMO;
3189 /****************************************************************************
3190 ****************************************************************************/
3191 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3193 PRINTER_INFO_2 *printer=NULL;
3195 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3196 return ERROR_NOT_ENOUGH_MEMORY;
3198 construct_printer_info_2(printer, snum);
3200 /* check the required size. */
3201 *needed += spoolss_size_printer_info_2(printer);
3203 if (!alloc_buffer_size(buffer, *needed)) {
3204 free_printer_info_2(printer);
3205 return ERROR_INSUFFICIENT_BUFFER;
3208 /* fill the buffer with the structures */
3209 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
3210 free_printer_info_2(printer);
3211 return ERROR_NOT_ENOUGH_MEMORY;
3214 /* clear memory */
3215 free_printer_info_2(printer);
3217 if (*needed > offered) {
3218 return ERROR_INSUFFICIENT_BUFFER;
3220 else
3221 return NT_STATUS_NO_PROBLEMO;
3224 /****************************************************************************
3225 ****************************************************************************/
3226 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3228 PRINTER_INFO_3 *printer=NULL;
3230 if (!construct_printer_info_3(&printer, snum))
3231 return ERROR_NOT_ENOUGH_MEMORY;
3233 /* check the required size. */
3234 *needed += spoolss_size_printer_info_3(printer);
3236 if (!alloc_buffer_size(buffer, *needed)) {
3237 free_printer_info_3(printer);
3238 return ERROR_INSUFFICIENT_BUFFER;
3241 /* fill the buffer with the structures */
3242 new_smb_io_printer_info_3("", buffer, printer, 0);
3244 /* clear memory */
3245 free_printer_info_3(printer);
3247 if (*needed > offered) {
3248 return ERROR_INSUFFICIENT_BUFFER;
3250 else
3251 return NT_STATUS_NO_PROBLEMO;
3254 /****************************************************************************
3255 ****************************************************************************/
3257 uint32 _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3259 POLICY_HND *handle = &q_u->handle;
3260 uint32 level = q_u->level;
3261 NEW_BUFFER *buffer = NULL;
3262 uint32 offered = q_u->offered;
3263 uint32 *needed = &r_u->needed;
3265 int snum;
3267 /* that's an [in out] buffer */
3268 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3269 buffer = r_u->buffer;
3271 *needed=0;
3273 if (!get_printer_snum(handle, &snum))
3274 return ERROR_INVALID_HANDLE;
3276 switch (level) {
3277 case 0:
3278 return getprinter_level_0(snum, buffer, offered, needed);
3279 case 1:
3280 return getprinter_level_1(snum, buffer, offered, needed);
3281 case 2:
3282 return getprinter_level_2(snum, buffer, offered, needed);
3283 case 3:
3284 return getprinter_level_3(snum, buffer, offered, needed);
3285 default:
3286 return ERROR_INVALID_LEVEL;
3290 /********************************************************************
3291 * fill a DRIVER_INFO_1 struct
3292 ********************************************************************/
3293 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3295 init_unistr( &info->name, driver.info_3->name);
3298 /********************************************************************
3299 * construct_printer_driver_info_1
3300 ********************************************************************/
3301 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3303 NT_PRINTER_INFO_LEVEL *printer = NULL;
3304 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3306 ZERO_STRUCT(driver);
3308 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3309 return ERROR_INVALID_PRINTER_NAME;
3311 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3312 return ERROR_UNKNOWN_PRINTER_DRIVER;
3314 fill_printer_driver_info_1(info, driver, servername, architecture);
3316 free_a_printer(&printer,2);
3318 return NT_STATUS_NO_PROBLEMO;
3321 /********************************************************************
3322 * construct_printer_driver_info_2
3323 * fill a printer_info_2 struct
3324 ********************************************************************/
3325 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3327 pstring temp;
3329 info->version=driver.info_3->cversion;
3331 init_unistr( &info->name, driver.info_3->name );
3332 init_unistr( &info->architecture, driver.info_3->environment );
3335 if (strlen(driver.info_3->driverpath)) {
3336 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3337 init_unistr( &info->driverpath, temp );
3338 } else
3339 init_unistr( &info->driverpath, "" );
3341 if (strlen(driver.info_3->datafile)) {
3342 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3343 init_unistr( &info->datafile, temp );
3344 } else
3345 init_unistr( &info->datafile, "" );
3347 if (strlen(driver.info_3->configfile)) {
3348 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3349 init_unistr( &info->configfile, temp );
3350 } else
3351 init_unistr( &info->configfile, "" );
3354 /********************************************************************
3355 * construct_printer_driver_info_2
3356 * fill a printer_info_2 struct
3357 ********************************************************************/
3358 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3360 NT_PRINTER_INFO_LEVEL *printer = NULL;
3361 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3363 ZERO_STRUCT(printer);
3364 ZERO_STRUCT(driver);
3366 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3367 return ERROR_INVALID_PRINTER_NAME;
3369 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3370 return ERROR_UNKNOWN_PRINTER_DRIVER;
3372 fill_printer_driver_info_2(info, driver, servername);
3374 free_a_printer(&printer,2);
3376 return NT_STATUS_NO_PROBLEMO;
3379 /********************************************************************
3380 * copy a strings array and convert to UNICODE
3382 * convert an array of ascii string to a UNICODE string
3383 ********************************************************************/
3384 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3386 int i=0;
3387 int j=0;
3388 char *v;
3389 pstring line;
3391 DEBUG(6,("init_unistr_array\n"));
3392 *uni_array=NULL;
3394 while (1) {
3395 if (char_array == NULL)
3396 v = "";
3397 else {
3398 v = char_array[i];
3399 if (!v) v = ""; /* hack to handle null lists */
3401 if (strlen(v) == 0) break;
3402 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3403 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3404 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3405 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3406 return;
3408 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3409 i++;
3412 if (*uni_array) {
3413 (*uni_array)[j]=0x0000;
3416 DEBUGADD(6,("last one:done\n"));
3419 /********************************************************************
3420 * construct_printer_info_3
3421 * fill a printer_info_3 struct
3422 ********************************************************************/
3423 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3425 pstring temp;
3427 ZERO_STRUCTP(info);
3429 info->version=driver.info_3->cversion;
3431 init_unistr( &info->name, driver.info_3->name );
3432 init_unistr( &info->architecture, driver.info_3->environment );
3434 if (strlen(driver.info_3->driverpath)) {
3435 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3436 init_unistr( &info->driverpath, temp );
3437 } else
3438 init_unistr( &info->driverpath, "" );
3440 if (strlen(driver.info_3->datafile)) {
3441 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3442 init_unistr( &info->datafile, temp );
3443 } else
3444 init_unistr( &info->datafile, "" );
3446 if (strlen(driver.info_3->configfile)) {
3447 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3448 init_unistr( &info->configfile, temp );
3449 } else
3450 init_unistr( &info->configfile, "" );
3452 if (strlen(driver.info_3->helpfile)) {
3453 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3454 init_unistr( &info->helpfile, temp );
3455 } else
3456 init_unistr( &info->helpfile, "" );
3458 init_unistr( &info->monitorname, driver.info_3->monitorname );
3459 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3461 info->dependentfiles=NULL;
3462 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3465 /********************************************************************
3466 * construct_printer_info_3
3467 * fill a printer_info_3 struct
3468 ********************************************************************/
3469 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3471 NT_PRINTER_INFO_LEVEL *printer = NULL;
3472 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3473 uint32 status=0;
3474 ZERO_STRUCT(driver);
3476 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3477 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3478 if (status != 0)
3479 return ERROR_INVALID_PRINTER_NAME;
3481 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3482 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3483 if (status != 0) {
3484 free_a_printer(&printer,2);
3485 return ERROR_UNKNOWN_PRINTER_DRIVER;
3488 fill_printer_driver_info_3(info, driver, servername);
3490 free_a_printer(&printer,2);
3492 return NT_STATUS_NO_PROBLEMO;
3495 /********************************************************************
3496 * construct_printer_info_6
3497 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3498 ********************************************************************/
3500 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3502 pstring temp;
3503 fstring nullstr;
3505 ZERO_STRUCTP(info);
3506 memset(&nullstr, '\0', sizeof(fstring));
3508 info->version=driver.info_3->cversion;
3510 init_unistr( &info->name, driver.info_3->name );
3511 init_unistr( &info->architecture, driver.info_3->environment );
3513 if (strlen(driver.info_3->driverpath)) {
3514 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3515 init_unistr( &info->driverpath, temp );
3516 } else
3517 init_unistr( &info->driverpath, "" );
3519 if (strlen(driver.info_3->datafile)) {
3520 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3521 init_unistr( &info->datafile, temp );
3522 } else
3523 init_unistr( &info->datafile, "" );
3525 if (strlen(driver.info_3->configfile)) {
3526 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3527 init_unistr( &info->configfile, temp );
3528 } else
3529 init_unistr( &info->configfile, "" );
3531 if (strlen(driver.info_3->helpfile)) {
3532 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3533 init_unistr( &info->helpfile, temp );
3534 } else
3535 init_unistr( &info->helpfile, "" );
3537 init_unistr( &info->monitorname, driver.info_3->monitorname );
3538 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3540 info->dependentfiles=NULL;
3541 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3543 info->previousdrivernames=NULL;
3544 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3546 info->driver_date.low=0;
3547 info->driver_date.high=0;
3549 info->padding=0;
3550 info->driver_version_low=0;
3551 info->driver_version_high=0;
3553 init_unistr( &info->mfgname, "");
3554 init_unistr( &info->oem_url, "");
3555 init_unistr( &info->hardware_id, "");
3556 init_unistr( &info->provider, "");
3559 /********************************************************************
3560 * construct_printer_info_6
3561 * fill a printer_info_6 struct
3562 ********************************************************************/
3563 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3565 NT_PRINTER_INFO_LEVEL *printer = NULL;
3566 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3567 uint32 status=0;
3568 ZERO_STRUCT(driver);
3570 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3571 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3572 if (status != 0)
3573 return ERROR_INVALID_PRINTER_NAME;
3575 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3576 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3577 if (status != 0) {
3579 * Is this a W2k client ?
3582 if (version < 3) {
3583 free_a_printer(&printer,2);
3584 return ERROR_UNKNOWN_PRINTER_DRIVER;
3587 /* Yes - try again with a WinNT driver. */
3588 version = 2;
3589 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3590 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3591 if (status != 0) {
3592 free_a_printer(&printer,2);
3593 return ERROR_UNKNOWN_PRINTER_DRIVER;
3597 fill_printer_driver_info_6(info, driver, servername);
3599 free_a_printer(&printer,2);
3601 return NT_STATUS_NO_PROBLEMO;
3604 /****************************************************************************
3605 ****************************************************************************/
3607 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3609 safe_free(info->dependentfiles);
3612 /****************************************************************************
3613 ****************************************************************************/
3615 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3617 safe_free(info->dependentfiles);
3621 /****************************************************************************
3622 ****************************************************************************/
3623 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3625 DRIVER_INFO_1 *info=NULL;
3626 uint32 status;
3628 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3629 return ERROR_NOT_ENOUGH_MEMORY;
3631 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3632 if (status != NT_STATUS_NO_PROBLEMO) {
3633 safe_free(info);
3634 return status;
3637 /* check the required size. */
3638 *needed += spoolss_size_printer_driver_info_1(info);
3640 if (!alloc_buffer_size(buffer, *needed)) {
3641 safe_free(info);
3642 return ERROR_INSUFFICIENT_BUFFER;
3645 /* fill the buffer with the structures */
3646 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3648 /* clear memory */
3649 safe_free(info);
3651 if (*needed > offered)
3652 return ERROR_INSUFFICIENT_BUFFER;
3653 else
3654 return NT_STATUS_NO_PROBLEMO;
3657 /****************************************************************************
3658 ****************************************************************************/
3659 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3661 DRIVER_INFO_2 *info=NULL;
3662 uint32 status;
3664 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3665 return ERROR_NOT_ENOUGH_MEMORY;
3667 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3668 if (status != NT_STATUS_NO_PROBLEMO) {
3669 safe_free(info);
3670 return status;
3673 /* check the required size. */
3674 *needed += spoolss_size_printer_driver_info_2(info);
3676 if (!alloc_buffer_size(buffer, *needed)) {
3677 safe_free(info);
3678 return ERROR_INSUFFICIENT_BUFFER;
3681 /* fill the buffer with the structures */
3682 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3684 /* clear memory */
3685 safe_free(info);
3687 if (*needed > offered)
3688 return ERROR_INSUFFICIENT_BUFFER;
3689 else
3690 return NT_STATUS_NO_PROBLEMO;
3693 /****************************************************************************
3694 ****************************************************************************/
3695 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3697 DRIVER_INFO_3 info;
3698 uint32 status;
3700 ZERO_STRUCT(info);
3702 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3703 if (status != NT_STATUS_NO_PROBLEMO) {
3704 return status;
3707 /* check the required size. */
3708 *needed += spoolss_size_printer_driver_info_3(&info);
3710 if (!alloc_buffer_size(buffer, *needed)) {
3711 free_printer_driver_info_3(&info);
3712 return ERROR_INSUFFICIENT_BUFFER;
3715 /* fill the buffer with the structures */
3716 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3718 free_printer_driver_info_3(&info);
3720 if (*needed > offered)
3721 return ERROR_INSUFFICIENT_BUFFER;
3722 else
3723 return NT_STATUS_NO_PROBLEMO;
3726 /****************************************************************************
3727 ****************************************************************************/
3728 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3730 DRIVER_INFO_6 info;
3731 uint32 status;
3733 ZERO_STRUCT(info);
3735 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3736 if (status != NT_STATUS_NO_PROBLEMO) {
3737 return status;
3740 /* check the required size. */
3741 *needed += spoolss_size_printer_driver_info_6(&info);
3743 if (!alloc_buffer_size(buffer, *needed)) {
3744 free_printer_driver_info_6(&info);
3745 return ERROR_INSUFFICIENT_BUFFER;
3748 /* fill the buffer with the structures */
3749 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3751 free_printer_driver_info_6(&info);
3753 if (*needed > offered)
3754 return ERROR_INSUFFICIENT_BUFFER;
3755 else
3756 return NT_STATUS_NO_PROBLEMO;
3759 /****************************************************************************
3760 ****************************************************************************/
3762 uint32 _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3764 POLICY_HND *handle = &q_u->handle;
3765 UNISTR2 *uni_arch = &q_u->architecture;
3766 uint32 level = q_u->level;
3767 uint32 clientmajorversion = q_u->clientmajorversion;
3768 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3769 NEW_BUFFER *buffer = NULL;
3770 uint32 offered = q_u->offered;
3771 uint32 *needed = &r_u->needed;
3772 uint32 *servermajorversion = &r_u->servermajorversion;
3773 uint32 *serverminorversion = &r_u->serverminorversion;
3775 fstring servername;
3776 fstring architecture;
3777 int snum;
3779 /* that's an [in out] buffer */
3780 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3781 buffer = r_u->buffer;
3783 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3785 *needed=0;
3786 *servermajorversion=0;
3787 *serverminorversion=0;
3789 pstrcpy(servername, global_myname);
3790 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3792 if (!get_printer_snum(handle, &snum))
3793 return ERROR_INVALID_HANDLE;
3795 switch (level) {
3796 case 1:
3797 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3798 case 2:
3799 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3800 case 3:
3801 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3802 case 6:
3803 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3804 default:
3805 return ERROR_INVALID_LEVEL;
3809 /****************************************************************************
3810 ****************************************************************************/
3812 uint32 _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3814 POLICY_HND *handle = &q_u->handle;
3816 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3818 if (OPEN_HANDLE(Printer)) {
3819 Printer->page_started=True;
3820 return 0x0;
3823 DEBUG(3,("Error in startpageprinter printer handle\n"));
3824 return ERROR_INVALID_HANDLE;
3827 /****************************************************************************
3828 ****************************************************************************/
3830 uint32 _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3832 POLICY_HND *handle = &q_u->handle;
3834 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3836 if (!OPEN_HANDLE(Printer)) {
3837 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3838 return ERROR_INVALID_HANDLE;
3841 Printer->page_started=False;
3843 return NT_STATUS_NO_PROBLEMO;
3846 /********************************************************************
3847 * api_spoolss_getprinter
3848 * called from the spoolss dispatcher
3850 ********************************************************************/
3852 uint32 _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3854 POLICY_HND *handle = &q_u->handle;
3855 /* uint32 level = q_u->doc_info_container.level; - notused. */
3856 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3857 uint32 *jobid = &r_u->jobid;
3859 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3860 int snum;
3861 pstring jobname;
3862 fstring datatype;
3863 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3864 struct current_user user;
3866 if (!OPEN_HANDLE(Printer)) {
3867 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3868 return ERROR_INVALID_HANDLE;
3871 get_current_user(&user, p);
3874 * a nice thing with NT is it doesn't listen to what you tell it.
3875 * when asked to send _only_ RAW datas, it tries to send datas
3876 * in EMF format.
3878 * So I add checks like in NT Server ...
3880 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3881 * there's a bug in NT client-side code, so we'll fix it in the
3882 * server-side code. *nnnnnggggh!*
3885 if (info_1->p_datatype != 0) {
3886 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3887 if (strcmp(datatype, "RAW") != 0) {
3888 (*jobid)=0;
3889 return ERROR_INVALID_DATATYPE;
3893 /* get the share number of the printer */
3894 if (!get_printer_snum(handle, &snum)) {
3895 return ERROR_INVALID_HANDLE;
3898 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3900 Printer->jobid = print_job_start(&user, snum, jobname);
3902 /* An error occured in print_job_start() so return an appropriate
3903 NT error code. */
3905 if (Printer->jobid == -1) {
3906 return map_nt_error_from_unix(errno);
3909 Printer->document_started=True;
3910 (*jobid) = Printer->jobid;
3912 return 0x0;
3915 /********************************************************************
3916 * api_spoolss_getprinter
3917 * called from the spoolss dispatcher
3919 ********************************************************************/
3921 uint32 _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
3923 POLICY_HND *handle = &q_u->handle;
3925 return _spoolss_enddocprinter_internal(handle);
3928 /****************************************************************************
3929 ****************************************************************************/
3931 uint32 _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
3933 POLICY_HND *handle = &q_u->handle;
3934 uint32 buffer_size = q_u->buffer_size;
3935 uint8 *buffer = q_u->buffer;
3936 uint32 *buffer_written = &q_u->buffer_size2;
3938 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3940 if (!OPEN_HANDLE(Printer)) {
3941 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3942 r_u->buffer_written = q_u->buffer_size2;
3943 return ERROR_INVALID_HANDLE;
3946 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
3949 r_u->buffer_written = q_u->buffer_size2;
3951 return 0x0;
3954 /********************************************************************
3955 * api_spoolss_getprinter
3956 * called from the spoolss dispatcher
3958 ********************************************************************/
3959 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3960 pipes_struct *p)
3962 struct current_user user;
3963 int snum, errcode = ERROR_INVALID_FUNCTION;
3964 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3966 get_current_user(&user, p);
3968 if (!OPEN_HANDLE(Printer)) {
3969 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3970 return ERROR_INVALID_HANDLE;
3973 if (!get_printer_snum(handle, &snum))
3974 return ERROR_INVALID_HANDLE;
3976 switch (command) {
3977 case PRINTER_CONTROL_PAUSE:
3978 if (print_queue_pause(&user, snum, &errcode)) {
3979 errcode = 0;
3981 break;
3982 case PRINTER_CONTROL_RESUME:
3983 case PRINTER_CONTROL_UNPAUSE:
3984 if (print_queue_resume(&user, snum, &errcode)) {
3985 errcode = 0;
3987 break;
3988 case PRINTER_CONTROL_PURGE:
3989 if (print_queue_purge(&user, snum, &errcode)) {
3990 errcode = 0;
3992 break;
3993 default:
3994 return ERROR_INVALID_LEVEL;
3997 return errcode;
4000 /********************************************************************
4001 * api_spoolss_abortprinter
4002 ********************************************************************/
4004 uint32 _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4006 POLICY_HND *handle = &q_u->handle;
4008 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4011 /********************************************************************
4012 * called by spoolss_api_setprinter
4013 * when updating a printer description
4014 ********************************************************************/
4015 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
4016 const SPOOL_PRINTER_INFO_LEVEL *info,
4017 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4019 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4020 struct current_user user;
4021 uint32 result;
4022 int snum;
4024 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4026 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
4027 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4028 OUR_HANDLE(handle)));
4030 result = ERROR_INVALID_HANDLE;
4031 goto done;
4034 /* NT seems to like setting the security descriptor even though
4035 nothing may have actually changed. This causes annoying
4036 dialog boxes when the user doesn't have permission to change
4037 the security descriptor. */
4039 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4041 if (DEBUGLEVEL >= 10) {
4042 SEC_ACL *acl;
4043 int i;
4045 acl = old_secdesc_ctr->sec->dacl;
4046 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4047 PRINTERNAME(snum), acl->num_aces));
4049 for (i = 0; i < acl->num_aces; i++) {
4050 fstring sid_str;
4052 sid_to_string(sid_str, &acl->ace[i].sid);
4054 DEBUG(10, ("%s 0x%08x\n", sid_str,
4055 acl->ace[i].info.mask));
4058 acl = secdesc_ctr->sec->dacl;
4060 if (acl) {
4061 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4062 PRINTERNAME(snum), acl->num_aces));
4064 for (i = 0; i < acl->num_aces; i++) {
4065 fstring sid_str;
4067 sid_to_string(sid_str, &acl->ace[i].sid);
4069 DEBUG(10, ("%s 0x%08x\n", sid_str,
4070 acl->ace[i].info.mask));
4072 } else {
4073 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4077 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4079 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4080 result = NT_STATUS_NO_PROBLEMO;
4081 goto done;
4084 /* Work out which user is performing the operation */
4086 get_current_user(&user, p);
4088 /* Check the user has permissions to change the security
4089 descriptor. By experimentation with two NT machines, the user
4090 requires Full Access to the printer to change security
4091 information. */
4093 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4094 result = ERROR_ACCESS_DENIED;
4095 goto done;
4098 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4100 done:
4102 return result;
4105 /********************************************************************
4106 Do Samba sanity checks on a printer info struct.
4107 this has changed purpose: it now "canonicalises" printer
4108 info from a client rather than just checking it is correct
4109 ********************************************************************/
4111 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4113 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4114 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4116 /* we force some elements to "correct" values */
4117 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4118 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4119 global_myname, lp_servicename(snum));
4120 fstrcpy(info->sharename, lp_servicename(snum));
4121 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4122 | PRINTER_ATTRIBUTE_LOCAL \
4123 | PRINTER_ATTRIBUTE_RAW_ONLY \
4124 | PRINTER_ATTRIBUTE_QUEUED ;
4126 return True;
4129 /****************************************************************************
4130 ****************************************************************************/
4131 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4133 pid_t local_pid = sys_getpid();
4134 char *cmd = lp_addprinter_cmd();
4135 char *path;
4136 char **qlines;
4137 pstring tmp_file;
4138 pstring command;
4139 pstring driverlocation;
4140 int numlines;
4141 int ret;
4143 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4144 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4145 else
4146 path = tmpdir();
4148 /* build driver path... only 9X architecture is needed for legacy reasons */
4149 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4150 global_myname);
4151 /* change \ to \\ for the shell */
4152 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4154 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
4155 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4156 cmd, printer->info_2->printername, printer->info_2->sharename,
4157 printer->info_2->portname, printer->info_2->drivername,
4158 printer->info_2->location, driverlocation);
4160 unlink(tmp_file);
4162 /* Convert script args to unix-codepage */
4163 dos_to_unix(command, True);
4164 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4165 ret = smbrun(command, tmp_file, False);
4166 DEBUGADD(10,("returned [%d]\n", ret));
4168 if ( ret != 0 ) {
4169 unlink(tmp_file);
4170 return False;
4173 numlines = 0;
4174 /* Get lines and convert them back to dos-codepage */
4175 qlines = file_lines_load(tmp_file, &numlines, True);
4176 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4177 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
4178 unlink(tmp_file);
4180 if(numlines) {
4181 /* Set the portname to what the script says the portname should be. */
4182 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4183 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4185 /* Send SIGHUP to process group... is there a better way? */
4186 kill(0, SIGHUP);
4187 add_all_printers();
4190 file_lines_free(qlines);
4191 return True;
4194 /* Return true if two devicemodes are equal */
4196 #define DEVMODE_CHECK_INT(field) \
4197 if (d1->field != d2->field) { \
4198 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4199 d1->field, d2->field)); \
4200 return False; \
4203 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4205 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4207 if (!d1 ^ !d2) {
4208 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4209 return False; /* if either is exclusively NULL are not equal */
4212 if (!strequal(d1->devicename, d2->devicename)) {
4213 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4214 return False;
4217 if (!strequal(d1->formname, d2->formname)) {
4218 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4219 return False;
4222 DEVMODE_CHECK_INT(specversion);
4223 DEVMODE_CHECK_INT(driverversion);
4224 DEVMODE_CHECK_INT(driverextra);
4225 DEVMODE_CHECK_INT(orientation);
4226 DEVMODE_CHECK_INT(papersize);
4227 DEVMODE_CHECK_INT(paperlength);
4228 DEVMODE_CHECK_INT(paperwidth);
4229 DEVMODE_CHECK_INT(scale);
4230 DEVMODE_CHECK_INT(copies);
4231 DEVMODE_CHECK_INT(defaultsource);
4232 DEVMODE_CHECK_INT(printquality);
4233 DEVMODE_CHECK_INT(color);
4234 DEVMODE_CHECK_INT(duplex);
4235 DEVMODE_CHECK_INT(yresolution);
4236 DEVMODE_CHECK_INT(ttoption);
4237 DEVMODE_CHECK_INT(collate);
4238 DEVMODE_CHECK_INT(logpixels);
4240 DEVMODE_CHECK_INT(fields);
4241 DEVMODE_CHECK_INT(bitsperpel);
4242 DEVMODE_CHECK_INT(pelswidth);
4243 DEVMODE_CHECK_INT(pelsheight);
4244 DEVMODE_CHECK_INT(displayflags);
4245 DEVMODE_CHECK_INT(displayfrequency);
4246 DEVMODE_CHECK_INT(icmmethod);
4247 DEVMODE_CHECK_INT(icmintent);
4248 DEVMODE_CHECK_INT(mediatype);
4249 DEVMODE_CHECK_INT(dithertype);
4250 DEVMODE_CHECK_INT(reserved1);
4251 DEVMODE_CHECK_INT(reserved2);
4252 DEVMODE_CHECK_INT(panningwidth);
4253 DEVMODE_CHECK_INT(panningheight);
4255 /* compare the private data if it exists */
4256 if (!d1->driverextra && !d2->driverextra) goto equal;
4259 DEVMODE_CHECK_INT(driverextra);
4261 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4262 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4263 return False;
4266 equal:
4267 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4268 return True;
4271 /* Return true if two NT_PRINTER_PARAM structures are equal */
4273 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4274 NT_PRINTER_PARAM *p2)
4276 if (!p1 && !p2) goto equal;
4278 if ((!p1 && p2) || (p1 && !p2)) {
4279 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4280 return False;
4283 /* Compare lists of printer parameters */
4285 while (p1) {
4286 BOOL found = False;
4287 NT_PRINTER_PARAM *q = p1;
4289 /* Find the parameter in the second structure */
4291 while(q) {
4293 if (strequal(p1->value, q->value)) {
4295 if (p1->type != q->type) {
4296 DEBUG(10, ("nt_printer_param_equal():"
4297 "types for %s differ (%d != %d)\n",
4298 p1->value, p1->type,
4299 q->type));
4300 break;
4303 if (p1->data_len != q->data_len) {
4304 DEBUG(10, ("nt_printer_param_equal():"
4305 "len for %s differs (%d != %d)\n",
4306 p1->value, p1->data_len,
4307 q->data_len));
4308 break;
4311 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4312 found = True;
4313 } else {
4314 DEBUG(10, ("nt_printer_param_equal():"
4315 "data for %s differs\n", p1->value));
4318 break;
4321 q = q->next;
4324 if (!found) {
4325 DEBUG(10, ("nt_printer_param_equal(): param %s "
4326 "does not exist\n", p1->value));
4327 return False;
4330 p1 = p1->next;
4333 equal:
4335 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4336 return True;
4339 /********************************************************************
4340 * Called by update_printer when trying to work out whether to
4341 * actually update printer info.
4342 ********************************************************************/
4344 #define PI_CHECK_INT(field) \
4345 if (pi1->field != pi2->field) { \
4346 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4347 pi1->field, pi2->field)); \
4348 return False; \
4351 #define PI_CHECK_STR(field) \
4352 if (!strequal(pi1->field, pi2->field)) { \
4353 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4354 pi1->field, pi2->field)); \
4355 return False; \
4358 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4359 NT_PRINTER_INFO_LEVEL *p2)
4361 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4363 /* Trivial conditions */
4365 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4366 goto equal;
4369 if ((!p1 && p2) || (p1 && !p2) ||
4370 (!p1->info_2 && p2->info_2) ||
4371 (p1->info_2 && !p2->info_2)) {
4372 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4373 "differ\n"));
4374 return False;
4377 /* Compare two nt_printer_info_level structures. Don't compare
4378 status or cjobs as they seem to have something to do with the
4379 printer queue. */
4381 pi1 = p1->info_2;
4382 pi2 = p2->info_2;
4384 /* Don't check the attributes as we stomp on the value in
4385 check_printer_ok() anyway. */
4387 #if 0
4388 PI_CHECK_INT(attributes);
4389 #endif
4391 PI_CHECK_INT(priority);
4392 PI_CHECK_INT(default_priority);
4393 PI_CHECK_INT(starttime);
4394 PI_CHECK_INT(untiltime);
4395 PI_CHECK_INT(averageppm);
4397 /* Yuck - don't check the printername or servername as the
4398 add_a_printer() code plays games with them. You can't
4399 change the printername or the sharename through this interface
4400 in Samba. */
4402 PI_CHECK_STR(sharename);
4403 PI_CHECK_STR(portname);
4404 PI_CHECK_STR(drivername);
4405 PI_CHECK_STR(comment);
4406 PI_CHECK_STR(location);
4408 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4409 return False;
4412 PI_CHECK_STR(sepfile);
4413 PI_CHECK_STR(printprocessor);
4414 PI_CHECK_STR(datatype);
4415 PI_CHECK_STR(parameters);
4417 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4418 return False;
4421 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4422 return False;
4425 PI_CHECK_INT(changeid);
4426 PI_CHECK_INT(c_setprinter);
4427 PI_CHECK_INT(setuptime);
4429 equal:
4430 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4431 return True;
4434 /********************************************************************
4435 * called by spoolss_api_setprinter
4436 * when updating a printer description
4437 ********************************************************************/
4439 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4440 const SPOOL_PRINTER_INFO_LEVEL *info,
4441 DEVICEMODE *devmode)
4443 int snum;
4444 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4445 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4446 uint32 result;
4448 DEBUG(8,("update_printer\n"));
4450 result = NT_STATUS_NO_PROBLEMO;
4452 if (level!=2) {
4453 DEBUG(0,("Send a mail to samba@samba.org\n"));
4454 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4455 result = ERROR_INVALID_LEVEL;
4456 goto done;
4459 if (!OPEN_HANDLE(Printer)) {
4460 result = ERROR_INVALID_HANDLE;
4461 goto done;
4464 if (!get_printer_snum(handle, &snum)) {
4465 result = ERROR_INVALID_HANDLE;
4466 goto done;
4469 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4470 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4471 result = ERROR_INVALID_HANDLE;
4472 goto done;
4475 DEBUGADD(8,("Converting info_2 struct\n"));
4478 * convert_printer_info converts the incoming
4479 * info from the client and overwrites the info
4480 * just read from the tdb in the pointer 'printer'.
4483 convert_printer_info(info, printer, level);
4485 if (info->info_2->devmode_ptr != 0) {
4486 /* we have a valid devmode
4487 convert it and link it*/
4489 DEBUGADD(8,("Converting the devicemode struct\n"));
4490 if (!convert_devicemode(printer->info_2->printername, devmode,
4491 &printer->info_2->devmode)) {
4492 result = ERROR_NOT_ENOUGH_MEMORY;
4493 goto done;
4497 /* Do sanity check on the requested changes for Samba */
4499 if (!check_printer_ok(printer->info_2, snum)) {
4500 result = ERROR_INVALID_PARAMETER;
4501 goto done;
4504 /* NT likes to call this function even though nothing has actually
4505 changed. Check this so the user doesn't end up with an
4506 annoying permission denied dialog box. */
4508 if (nt_printer_info_level_equal(printer, old_printer)) {
4509 DEBUG(3, ("printer info has not changed\n"));
4510 result = NT_STATUS_NO_PROBLEMO;
4511 goto done;
4514 /* Check calling user has permission to update printer description */
4516 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4517 DEBUG(3, ("printer property change denied by security "
4518 "descriptor\n"));
4519 result = ERROR_ACCESS_DENIED;
4520 goto done;
4523 /* Call addprinter hook */
4525 if (*lp_addprinter_cmd() )
4526 if ( !add_printer_hook(printer) ) {
4527 result = ERROR_ACCESS_DENIED;
4528 goto done;
4531 /* Update printer info */
4533 if (add_a_printer(*printer, 2)!=0) {
4534 /* I don't really know what to return here !!! */
4535 result = ERROR_ACCESS_DENIED;
4536 goto done;
4539 done:
4540 free_a_printer(&printer, 2);
4541 free_a_printer(&old_printer, 2);
4543 srv_spoolss_sendnotify(handle);
4545 return result;
4548 /****************************************************************************
4549 ****************************************************************************/
4551 uint32 _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4553 POLICY_HND *handle = &q_u->handle;
4554 uint32 level = q_u->level;
4555 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4556 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4557 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4558 uint32 command = q_u->command;
4560 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4562 if (!OPEN_HANDLE(Printer)) {
4563 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4564 return ERROR_INVALID_HANDLE;
4567 /* check the level */
4568 switch (level) {
4569 case 0:
4570 return control_printer(handle, command, p);
4571 case 2:
4572 return update_printer(handle, level, info, devmode_ctr.devmode);
4573 case 3:
4574 return update_printer_sec(handle, level, info, p,
4575 secdesc_ctr);
4576 default:
4577 return ERROR_INVALID_LEVEL;
4581 /****************************************************************************
4582 ****************************************************************************/
4584 uint32 _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4586 POLICY_HND *handle = &q_u->handle;
4588 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4590 if (!OPEN_HANDLE(Printer)) {
4591 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4592 return ERROR_INVALID_HANDLE;
4595 if (Printer->notify.client_connected==True)
4596 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4597 return ERROR_INVALID_HANDLE;
4599 Printer->notify.flags=0;
4600 Printer->notify.options=0;
4601 Printer->notify.localmachine[0]='\0';
4602 Printer->notify.printerlocal=0;
4603 if (Printer->notify.option)
4604 safe_free(Printer->notify.option->ctr.type);
4605 safe_free(Printer->notify.option);
4606 Printer->notify.option=NULL;
4607 Printer->notify.client_connected=False;
4609 return NT_STATUS_NO_PROBLEMO;
4612 /****************************************************************************
4613 ****************************************************************************/
4615 uint32 _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4617 /* that's an [in out] buffer (despite appearences to the contrary) */
4618 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4620 r_u->needed = 0;
4621 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4622 returns for AddJob. AddJob
4623 must fail on non-local
4624 printers */
4627 /****************************************************************************
4628 ****************************************************************************/
4629 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4630 int position, int snum)
4632 pstring temp_name;
4634 struct tm *t;
4636 t=gmtime(&queue->time);
4637 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4639 job_info->jobid=queue->job;
4640 init_unistr(&job_info->printername, lp_servicename(snum));
4641 init_unistr(&job_info->machinename, temp_name);
4642 init_unistr(&job_info->username, queue->user);
4643 init_unistr(&job_info->document, queue->file);
4644 init_unistr(&job_info->datatype, "RAW");
4645 init_unistr(&job_info->text_status, "");
4646 job_info->status=nt_printj_status(queue->status);
4647 job_info->priority=queue->priority;
4648 job_info->position=position;
4649 job_info->totalpages=0;
4650 job_info->pagesprinted=0;
4652 make_systemtime(&job_info->submitted, t);
4655 /****************************************************************************
4656 ****************************************************************************/
4657 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4658 int position, int snum,
4659 NT_PRINTER_INFO_LEVEL *ntprinter)
4661 pstring temp_name;
4662 pstring chaine;
4663 struct tm *t;
4665 t=gmtime(&queue->time);
4666 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4668 job_info->jobid=queue->job;
4670 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4672 init_unistr(&job_info->printername, chaine);
4674 init_unistr(&job_info->machinename, temp_name);
4675 init_unistr(&job_info->username, queue->user);
4676 init_unistr(&job_info->document, queue->file);
4677 init_unistr(&job_info->notifyname, queue->user);
4678 init_unistr(&job_info->datatype, "RAW");
4679 init_unistr(&job_info->printprocessor, "winprint");
4680 init_unistr(&job_info->parameters, "");
4681 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4682 init_unistr(&job_info->text_status, "");
4684 /* and here the security descriptor */
4686 job_info->status=nt_printj_status(queue->status);
4687 job_info->priority=queue->priority;
4688 job_info->position=position;
4689 job_info->starttime=0;
4690 job_info->untiltime=0;
4691 job_info->totalpages=0;
4692 job_info->size=queue->size;
4693 make_systemtime(&(job_info->submitted), t);
4694 job_info->timeelapsed=0;
4695 job_info->pagesprinted=0;
4697 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4698 return False;
4701 return (True);
4704 /****************************************************************************
4705 Enumjobs at level 1.
4706 ****************************************************************************/
4707 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4708 NEW_BUFFER *buffer, uint32 offered,
4709 uint32 *needed, uint32 *returned)
4711 JOB_INFO_1 *info;
4712 int i;
4714 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4715 if (info==NULL) {
4716 safe_free(queue);
4717 *returned=0;
4718 return ERROR_NOT_ENOUGH_MEMORY;
4721 for (i=0; i<*returned; i++)
4722 fill_job_info_1(&info[i], &queue[i], i, snum);
4724 safe_free(queue);
4726 /* check the required size. */
4727 for (i=0; i<*returned; i++)
4728 (*needed) += spoolss_size_job_info_1(&info[i]);
4730 if (!alloc_buffer_size(buffer, *needed)) {
4731 safe_free(info);
4732 return ERROR_INSUFFICIENT_BUFFER;
4735 /* fill the buffer with the structures */
4736 for (i=0; i<*returned; i++)
4737 new_smb_io_job_info_1("", buffer, &info[i], 0);
4739 /* clear memory */
4740 safe_free(info);
4742 if (*needed > offered) {
4743 *returned=0;
4744 return ERROR_INSUFFICIENT_BUFFER;
4746 else
4747 return NT_STATUS_NO_PROBLEMO;
4750 /****************************************************************************
4751 Enumjobs at level 2.
4752 ****************************************************************************/
4753 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4754 NEW_BUFFER *buffer, uint32 offered,
4755 uint32 *needed, uint32 *returned)
4757 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4758 JOB_INFO_2 *info;
4759 int i;
4761 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4762 if (info==NULL) {
4763 *returned=0;
4764 return ERROR_NOT_ENOUGH_MEMORY;
4767 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4768 *returned = 0;
4769 return ERROR_NOT_ENOUGH_MEMORY;
4772 for (i=0; i<*returned; i++)
4773 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4775 free_a_printer(&ntprinter, 2);
4776 safe_free(queue);
4778 /* check the required size. */
4779 for (i=0; i<*returned; i++)
4780 (*needed) += spoolss_size_job_info_2(&info[i]);
4782 if (!alloc_buffer_size(buffer, *needed)) {
4783 safe_free(info);
4784 return ERROR_INSUFFICIENT_BUFFER;
4787 /* fill the buffer with the structures */
4788 for (i=0; i<*returned; i++)
4789 new_smb_io_job_info_2("", buffer, &info[i], 0);
4791 /* clear memory */
4792 for (i = 0; i < *returned; i++)
4793 free_job_info_2(&info[i]);
4795 free(info);
4797 if (*needed > offered) {
4798 *returned=0;
4799 return ERROR_INSUFFICIENT_BUFFER;
4801 else
4802 return NT_STATUS_NO_PROBLEMO;
4805 /****************************************************************************
4806 Enumjobs.
4807 ****************************************************************************/
4809 uint32 _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4811 POLICY_HND *handle = &q_u->handle;
4812 /* uint32 firstjob = q_u->firstjob; - notused. */
4813 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4814 uint32 level = q_u->level;
4815 NEW_BUFFER *buffer = NULL;
4816 uint32 offered = q_u->offered;
4817 uint32 *needed = &r_u->needed;
4818 uint32 *returned = &r_u->returned;
4820 int snum;
4821 print_queue_struct *queue=NULL;
4822 print_status_struct prt_status;
4824 /* that's an [in out] buffer */
4825 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4826 buffer = r_u->buffer;
4828 DEBUG(4,("_spoolss_enumjobs\n"));
4830 ZERO_STRUCT(prt_status);
4832 *needed=0;
4833 *returned=0;
4835 if (!get_printer_snum(handle, &snum))
4836 return ERROR_INVALID_HANDLE;
4838 *returned = print_queue_status(snum, &queue, &prt_status);
4839 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4841 if (*returned == 0) {
4842 safe_free(queue);
4843 return NT_STATUS_NO_PROBLEMO;
4846 switch (level) {
4847 case 1:
4848 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4849 case 2:
4850 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4851 default:
4852 safe_free(queue);
4853 *returned=0;
4854 return ERROR_INVALID_LEVEL;
4858 /****************************************************************************
4859 ****************************************************************************/
4861 uint32 _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4863 return 0x0;
4866 /****************************************************************************
4867 ****************************************************************************/
4869 uint32 _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4871 POLICY_HND *handle = &q_u->handle;
4872 uint32 jobid = q_u->jobid;
4873 /* uint32 level = q_u->level; - notused. */
4874 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4875 uint32 command = q_u->command;
4877 struct current_user user;
4878 print_status_struct prt_status;
4879 int snum, errcode = ERROR_INVALID_FUNCTION;
4881 memset(&prt_status, 0, sizeof(prt_status));
4883 if (!get_printer_snum(handle, &snum)) {
4884 return ERROR_INVALID_HANDLE;
4887 if (!print_job_exists(jobid)) {
4888 return ERROR_INVALID_PRINTER_NAME;
4891 get_current_user(&user, p);
4893 switch (command) {
4894 case JOB_CONTROL_CANCEL:
4895 case JOB_CONTROL_DELETE:
4896 if (print_job_delete(&user, jobid, &errcode)) {
4897 errcode = 0;
4899 break;
4900 case JOB_CONTROL_PAUSE:
4901 if (print_job_pause(&user, jobid, &errcode)) {
4902 errcode = 0;
4904 break;
4905 case JOB_CONTROL_RESTART:
4906 case JOB_CONTROL_RESUME:
4907 if (print_job_resume(&user, jobid, &errcode)) {
4908 errcode = 0;
4910 break;
4911 default:
4912 return ERROR_INVALID_LEVEL;
4915 return errcode;
4918 /****************************************************************************
4919 Enumerates all printer drivers at level 1.
4920 ****************************************************************************/
4921 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4923 int i;
4924 int ndrivers;
4925 uint32 version;
4926 fstring *list = NULL;
4928 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4929 DRIVER_INFO_1 *driver_info_1=NULL;
4931 *returned=0;
4933 #define MAX_VERSION 4
4935 for (version=0; version<MAX_VERSION; version++) {
4936 list=NULL;
4937 ndrivers=get_ntdrivers(&list, architecture, version);
4938 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4940 if(ndrivers == -1)
4941 return ERROR_NOT_ENOUGH_MEMORY;
4943 if(ndrivers != 0) {
4944 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4945 safe_free(list);
4946 return ERROR_NOT_ENOUGH_MEMORY;
4950 for (i=0; i<ndrivers; i++) {
4951 uint32 status;
4952 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4953 ZERO_STRUCT(driver);
4954 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4955 safe_free(list);
4956 return status;
4958 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4959 free_a_printer_driver(driver, 3);
4962 *returned+=ndrivers;
4963 safe_free(list);
4966 /* check the required size. */
4967 for (i=0; i<*returned; i++) {
4968 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4969 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4972 if (!alloc_buffer_size(buffer, *needed)) {
4973 safe_free(driver_info_1);
4974 return ERROR_INSUFFICIENT_BUFFER;
4977 /* fill the buffer with the form structures */
4978 for (i=0; i<*returned; i++) {
4979 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4980 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4983 safe_free(driver_info_1);
4985 if (*needed > offered) {
4986 *returned=0;
4987 return ERROR_INSUFFICIENT_BUFFER;
4989 else
4990 return NT_STATUS_NO_PROBLEMO;
4993 /****************************************************************************
4994 Enumerates all printer drivers at level 2.
4995 ****************************************************************************/
4996 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4998 int i;
4999 int ndrivers;
5000 uint32 version;
5001 fstring *list = NULL;
5003 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5004 DRIVER_INFO_2 *driver_info_2=NULL;
5006 *returned=0;
5008 #define MAX_VERSION 4
5010 for (version=0; version<MAX_VERSION; version++) {
5011 list=NULL;
5012 ndrivers=get_ntdrivers(&list, architecture, version);
5013 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5015 if(ndrivers == -1)
5016 return ERROR_NOT_ENOUGH_MEMORY;
5018 if(ndrivers != 0) {
5019 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5020 safe_free(list);
5021 return ERROR_NOT_ENOUGH_MEMORY;
5025 for (i=0; i<ndrivers; i++) {
5026 uint32 status;
5028 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5029 ZERO_STRUCT(driver);
5030 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5031 safe_free(list);
5032 return status;
5034 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5035 free_a_printer_driver(driver, 3);
5038 *returned+=ndrivers;
5039 safe_free(list);
5042 /* check the required size. */
5043 for (i=0; i<*returned; i++) {
5044 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5045 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5048 if (!alloc_buffer_size(buffer, *needed)) {
5049 safe_free(driver_info_2);
5050 return ERROR_INSUFFICIENT_BUFFER;
5053 /* fill the buffer with the form structures */
5054 for (i=0; i<*returned; i++) {
5055 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5056 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5059 safe_free(driver_info_2);
5061 if (*needed > offered) {
5062 *returned=0;
5063 return ERROR_INSUFFICIENT_BUFFER;
5065 else
5066 return NT_STATUS_NO_PROBLEMO;
5069 /****************************************************************************
5070 Enumerates all printer drivers at level 3.
5071 ****************************************************************************/
5072 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5074 int i;
5075 int ndrivers;
5076 uint32 version;
5077 fstring *list = NULL;
5079 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5080 DRIVER_INFO_3 *driver_info_3=NULL;
5082 *returned=0;
5084 #define MAX_VERSION 4
5086 for (version=0; version<MAX_VERSION; version++) {
5087 list=NULL;
5088 ndrivers=get_ntdrivers(&list, architecture, version);
5089 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5091 if(ndrivers == -1)
5092 return ERROR_NOT_ENOUGH_MEMORY;
5094 if(ndrivers != 0) {
5095 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5096 safe_free(list);
5097 return ERROR_NOT_ENOUGH_MEMORY;
5101 for (i=0; i<ndrivers; i++) {
5102 uint32 status;
5104 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5105 ZERO_STRUCT(driver);
5106 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5107 safe_free(list);
5108 return status;
5110 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5111 free_a_printer_driver(driver, 3);
5114 *returned+=ndrivers;
5115 safe_free(list);
5118 /* check the required size. */
5119 for (i=0; i<*returned; i++) {
5120 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5121 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5124 if (!alloc_buffer_size(buffer, *needed)) {
5125 safe_free(driver_info_3);
5126 return ERROR_INSUFFICIENT_BUFFER;
5129 /* fill the buffer with the driver structures */
5130 for (i=0; i<*returned; i++) {
5131 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5132 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5135 for (i=0; i<*returned; i++)
5136 safe_free(driver_info_3[i].dependentfiles);
5138 safe_free(driver_info_3);
5140 if (*needed > offered) {
5141 *returned=0;
5142 return ERROR_INSUFFICIENT_BUFFER;
5144 else
5145 return NT_STATUS_NO_PROBLEMO;
5148 /****************************************************************************
5149 Enumerates all printer drivers.
5150 ****************************************************************************/
5152 uint32 _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5154 /* UNISTR2 *name = &q_u->name; - notused. */
5155 UNISTR2 *environment = &q_u->environment;
5156 uint32 level = q_u->level;
5157 NEW_BUFFER *buffer = NULL;
5158 uint32 offered = q_u->offered;
5159 uint32 *needed = &r_u->needed;
5160 uint32 *returned = &r_u->returned;
5162 fstring *list = NULL;
5163 fstring servername;
5164 fstring architecture;
5166 /* that's an [in out] buffer */
5167 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5168 buffer = r_u->buffer;
5170 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5171 fstrcpy(servername, global_myname);
5172 *needed=0;
5173 *returned=0;
5175 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5177 switch (level) {
5178 case 1:
5179 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5180 case 2:
5181 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5182 case 3:
5183 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5184 default:
5185 *returned=0;
5186 safe_free(list);
5187 return ERROR_INVALID_LEVEL;
5191 /****************************************************************************
5192 ****************************************************************************/
5193 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5195 form->flag=list->flag;
5196 init_unistr(&form->name, list->name);
5197 form->width=list->width;
5198 form->length=list->length;
5199 form->left=list->left;
5200 form->top=list->top;
5201 form->right=list->right;
5202 form->bottom=list->bottom;
5205 /****************************************************************************
5206 ****************************************************************************/
5207 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
5208 NEW_BUFFER *buffer, uint32 offered,
5209 uint32 *needed, uint32 *numofforms)
5211 nt_forms_struct *list=NULL;
5212 FORM_1 *forms_1;
5213 int buffer_size=0;
5214 int i;
5216 DEBUG(4,("_new_spoolss_enumforms\n"));
5217 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5218 DEBUGADD(5,("Info level [%d]\n", level));
5220 *numofforms = get_ntforms(&list);
5221 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
5223 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5225 switch (level) {
5226 case 1:
5227 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5228 *numofforms=0;
5229 return ERROR_NOT_ENOUGH_MEMORY;
5232 /* construct the list of form structures */
5233 for (i=0; i<*numofforms; i++) {
5234 DEBUGADD(6,("Filling form number [%d]\n",i));
5235 fill_form_1(&forms_1[i], &list[i]);
5238 safe_free(list);
5240 /* check the required size. */
5241 for (i=0; i<*numofforms; i++) {
5242 DEBUGADD(6,("adding form [%d]'s size\n",i));
5243 buffer_size += spoolss_size_form_1(&forms_1[i]);
5246 *needed=buffer_size;
5248 if (!alloc_buffer_size(buffer, buffer_size)){
5249 safe_free(forms_1);
5250 return ERROR_INSUFFICIENT_BUFFER;
5253 /* fill the buffer with the form structures */
5254 for (i=0; i<*numofforms; i++) {
5255 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5256 new_smb_io_form_1("", buffer, &forms_1[i], 0);
5259 safe_free(forms_1);
5261 if (*needed > offered) {
5262 *numofforms=0;
5263 return ERROR_INSUFFICIENT_BUFFER;
5265 else
5266 return NT_STATUS_NO_PROBLEMO;
5268 default:
5269 safe_free(list);
5270 return ERROR_INVALID_LEVEL;
5275 /****************************************************************************
5276 ****************************************************************************/
5277 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5279 nt_forms_struct *list=NULL;
5280 FORM_1 form_1;
5281 fstring form_name;
5282 int buffer_size=0;
5283 int numofforms, i;
5285 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5287 DEBUG(4,("_spoolss_getform\n"));
5288 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5289 DEBUGADD(5,("Info level [%d]\n", level));
5291 numofforms = get_ntforms(&list);
5292 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5294 if (numofforms == 0)
5295 return ERROR_NO_MORE_ITEMS;
5297 switch (level) {
5298 case 1:
5300 /* Check if the requested name is in the list of form structures */
5301 for (i=0; i<numofforms; i++) {
5303 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5305 if (strequal(form_name, list[i].name)) {
5306 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5307 fill_form_1(&form_1, &list[i]);
5308 break;
5312 safe_free(list);
5314 /* check the required size. */
5316 *needed=spoolss_size_form_1(&form_1);
5318 if (!alloc_buffer_size(buffer, buffer_size)){
5319 return ERROR_INSUFFICIENT_BUFFER;
5322 if (*needed > offered) {
5323 return ERROR_INSUFFICIENT_BUFFER;
5326 /* fill the buffer with the form structures */
5327 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5328 new_smb_io_form_1("", buffer, &form_1, 0);
5330 return NT_STATUS_NO_PROBLEMO;
5332 default:
5333 safe_free(list);
5334 return ERROR_INVALID_LEVEL;
5338 /****************************************************************************
5339 ****************************************************************************/
5340 static void fill_port_1(PORT_INFO_1 *port, char *name)
5342 init_unistr(&port->port_name, name);
5345 /****************************************************************************
5346 ****************************************************************************/
5347 static void fill_port_2(PORT_INFO_2 *port, char *name)
5349 init_unistr(&port->port_name, name);
5350 init_unistr(&port->monitor_name, "Local Monitor");
5351 init_unistr(&port->description, "Local Port");
5352 #define PORT_TYPE_WRITE 1
5353 port->port_type=PORT_TYPE_WRITE;
5354 port->reserved=0x0;
5357 /****************************************************************************
5358 enumports level 1.
5359 ****************************************************************************/
5360 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5362 PORT_INFO_1 *ports=NULL;
5363 int i=0;
5365 if (*lp_enumports_cmd()) {
5366 pid_t local_pid = sys_getpid();
5367 char *cmd = lp_enumports_cmd();
5368 char *path;
5369 char **qlines;
5370 pstring tmp_file;
5371 pstring command;
5372 int numlines;
5373 int ret;
5375 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5376 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5377 else
5378 path = tmpdir();
5380 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5381 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5383 unlink(tmp_file);
5384 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5385 ret = smbrun(command, tmp_file, False);
5386 DEBUG(10,("Returned [%d]\n", ret));
5387 if (ret != 0) {
5388 unlink(tmp_file);
5389 /* Is this the best error to return here? */
5390 return ERROR_ACCESS_DENIED;
5393 numlines = 0;
5394 qlines = file_lines_load(tmp_file, &numlines,True);
5395 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5396 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5397 unlink(tmp_file);
5399 if(numlines) {
5400 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5401 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5402 file_lines_free(qlines);
5403 return ERROR_NOT_ENOUGH_MEMORY;
5406 for (i=0; i<numlines; i++) {
5407 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5408 fill_port_1(&ports[i], qlines[i]);
5411 file_lines_free(qlines);
5414 *returned = numlines;
5416 } else {
5417 *returned = 1; /* Sole Samba port returned. */
5419 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5420 return ERROR_NOT_ENOUGH_MEMORY;
5422 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5424 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5427 /* check the required size. */
5428 for (i=0; i<*returned; i++) {
5429 DEBUGADD(6,("adding port [%d]'s size\n", i));
5430 *needed += spoolss_size_port_info_1(&ports[i]);
5433 if (!alloc_buffer_size(buffer, *needed)) {
5434 safe_free(ports);
5435 return ERROR_INSUFFICIENT_BUFFER;
5438 /* fill the buffer with the ports structures */
5439 for (i=0; i<*returned; i++) {
5440 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5441 new_smb_io_port_1("", buffer, &ports[i], 0);
5444 safe_free(ports);
5446 if (*needed > offered) {
5447 *returned=0;
5448 return ERROR_INSUFFICIENT_BUFFER;
5450 else
5451 return NT_STATUS_NO_PROBLEMO;
5454 /****************************************************************************
5455 enumports level 2.
5456 ****************************************************************************/
5458 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5460 PORT_INFO_2 *ports=NULL;
5461 int i=0;
5463 if (*lp_enumports_cmd()) {
5464 pid_t local_pid = sys_getpid();
5465 char *cmd = lp_enumports_cmd();
5466 char *path;
5467 char **qlines;
5468 pstring tmp_file;
5469 pstring command;
5470 int numlines;
5471 int ret;
5473 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5474 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5475 else
5476 path = tmpdir();
5478 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5479 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5481 unlink(tmp_file);
5482 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5483 ret = smbrun(command, tmp_file, False);
5484 DEBUGADD(10,("returned [%d]\n", ret));
5485 if (ret != 0) {
5486 unlink(tmp_file);
5487 /* Is this the best error to return here? */
5488 return ERROR_ACCESS_DENIED;
5491 numlines = 0;
5492 qlines = file_lines_load(tmp_file, &numlines,True);
5493 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5494 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5495 unlink(tmp_file);
5497 if(numlines) {
5498 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5499 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5500 file_lines_free(qlines);
5501 return ERROR_NOT_ENOUGH_MEMORY;
5504 for (i=0; i<numlines; i++) {
5505 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5506 fill_port_2(&(ports[i]), qlines[i]);
5509 file_lines_free(qlines);
5512 *returned = numlines;
5514 } else {
5516 *returned = 1;
5518 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5519 return ERROR_NOT_ENOUGH_MEMORY;
5521 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5523 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5526 /* check the required size. */
5527 for (i=0; i<*returned; i++) {
5528 DEBUGADD(6,("adding port [%d]'s size\n", i));
5529 *needed += spoolss_size_port_info_2(&ports[i]);
5532 if (!alloc_buffer_size(buffer, *needed)) {
5533 safe_free(ports);
5534 return ERROR_INSUFFICIENT_BUFFER;
5537 /* fill the buffer with the ports structures */
5538 for (i=0; i<*returned; i++) {
5539 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5540 new_smb_io_port_2("", buffer, &ports[i], 0);
5543 safe_free(ports);
5545 if (*needed > offered) {
5546 *returned=0;
5547 return ERROR_INSUFFICIENT_BUFFER;
5549 else
5550 return NT_STATUS_NO_PROBLEMO;
5553 /****************************************************************************
5554 enumports.
5555 ****************************************************************************/
5556 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5557 NEW_BUFFER *buffer, uint32 offered,
5558 uint32 *needed, uint32 *returned)
5560 DEBUG(4,("_spoolss_enumports\n"));
5562 *returned=0;
5563 *needed=0;
5565 switch (level) {
5566 case 1:
5567 return enumports_level_1(buffer, offered, needed, returned);
5568 case 2:
5569 return enumports_level_2(buffer, offered, needed, returned);
5570 default:
5571 return ERROR_INVALID_LEVEL;
5575 /****************************************************************************
5576 ****************************************************************************/
5577 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5578 const SPOOL_PRINTER_INFO_LEVEL *info,
5579 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5580 uint32 user_switch, const SPOOL_USER_CTR *user,
5581 POLICY_HND *handle)
5583 NT_PRINTER_INFO_LEVEL *printer = NULL;
5584 fstring name;
5585 int snum;
5587 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5588 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5589 return ERROR_NOT_ENOUGH_MEMORY;
5592 ZERO_STRUCTP(printer);
5594 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5595 convert_printer_info(info, printer, 2);
5597 if (*lp_addprinter_cmd() )
5598 if ( !add_printer_hook(printer) ) {
5599 free_a_printer(&printer,2);
5600 return ERROR_ACCESS_DENIED;
5603 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5604 printer->info_2->sharename);
5606 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5607 free_a_printer(&printer,2);
5608 return ERROR_ACCESS_DENIED;
5611 /* you must be a printer admin to add a new printer */
5612 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5613 free_a_printer(&printer,2);
5614 return ERROR_ACCESS_DENIED;
5618 * Do sanity check on the requested changes for Samba.
5621 if (!check_printer_ok(printer->info_2, snum)) {
5622 free_a_printer(&printer,2);
5623 return ERROR_INVALID_PARAMETER;
5626 /* write the ASCII on disk */
5627 if (add_a_printer(*printer, 2) != 0) {
5628 free_a_printer(&printer,2);
5629 return ERROR_ACCESS_DENIED;
5632 if (!open_printer_hnd(handle, name)) {
5633 /* Handle open failed - remove addition. */
5634 del_a_printer(printer->info_2->sharename);
5635 free_a_printer(&printer,2);
5636 return ERROR_ACCESS_DENIED;
5639 free_a_printer(&printer,2);
5641 srv_spoolss_sendnotify(handle);
5643 return NT_STATUS_NO_PROBLEMO;
5646 /****************************************************************************
5647 ****************************************************************************/
5648 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5649 const SPOOL_PRINTER_INFO_LEVEL *info,
5650 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5651 uint32 user_switch, const SPOOL_USER_CTR *user,
5652 POLICY_HND *handle)
5654 switch (level) {
5655 case 1:
5656 /* we don't handle yet */
5657 /* but I know what to do ... */
5658 return ERROR_INVALID_LEVEL;
5659 case 2:
5660 return spoolss_addprinterex_level_2(uni_srv_name, info,
5661 unk0, unk1, unk2, unk3,
5662 user_switch, user, handle);
5663 default:
5664 return ERROR_INVALID_LEVEL;
5668 /****************************************************************************
5669 ****************************************************************************/
5670 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5671 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5673 uint32 err = NT_STATUS_NO_PROBLEMO;
5674 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5675 struct current_user user;
5677 ZERO_STRUCT(driver);
5679 get_current_user(&user, p);
5681 convert_printer_driver_info(info, &driver, level);
5683 DEBUG(5,("Cleaning driver's information\n"));
5684 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5685 goto done;
5687 DEBUG(5,("Moving driver to final destination\n"));
5688 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5689 if (err == 0)
5690 err = ERROR_ACCESS_DENIED;
5691 goto done;
5694 if (add_a_printer_driver(driver, level)!=0) {
5695 err = ERROR_ACCESS_DENIED;
5696 goto done;
5699 done:
5700 free_a_printer_driver(driver, level);
5701 return err;
5704 /****************************************************************************
5705 ****************************************************************************/
5706 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5708 init_unistr(&info->name, name);
5711 /****************************************************************************
5712 ****************************************************************************/
5713 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5715 pstring path;
5716 pstring long_archi;
5717 pstring short_archi;
5718 DRIVER_DIRECTORY_1 *info=NULL;
5720 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5722 if (get_short_archi(short_archi, long_archi)==FALSE)
5723 return ERROR_INVALID_ENVIRONMENT;
5725 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5726 return ERROR_NOT_ENOUGH_MEMORY;
5728 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5730 DEBUG(4,("printer driver directory: [%s]\n", path));
5732 fill_driverdir_1(info, path);
5734 *needed += spoolss_size_driverdir_info_1(info);
5736 if (!alloc_buffer_size(buffer, *needed)) {
5737 safe_free(info);
5738 return ERROR_INSUFFICIENT_BUFFER;
5741 new_smb_io_driverdir_1("", buffer, info, 0);
5743 safe_free(info);
5745 if (*needed > offered)
5746 return ERROR_INSUFFICIENT_BUFFER;
5747 else
5748 return NT_STATUS_NO_PROBLEMO;
5751 /****************************************************************************
5752 ****************************************************************************/
5753 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5754 NEW_BUFFER *buffer, uint32 offered,
5755 uint32 *needed)
5757 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5759 *needed=0;
5761 switch(level) {
5762 case 1:
5763 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5764 default:
5765 return ERROR_INVALID_LEVEL;
5769 /****************************************************************************
5770 ****************************************************************************/
5771 uint32 _spoolss_enumprinterdata(pipes_struct *p, POLICY_HND *handle, uint32 idx,
5772 uint32 in_value_len, uint32 in_data_len,
5773 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5774 uint32 *out_type,
5775 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5777 NT_PRINTER_INFO_LEVEL *printer = NULL;
5779 fstring value;
5781 uint32 param_index;
5782 uint32 biggest_valuesize;
5783 uint32 biggest_datasize;
5784 uint32 data_len;
5785 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5786 int snum;
5787 uint8 *data=NULL;
5788 uint32 type;
5790 ZERO_STRUCT(printer);
5792 *out_max_value_len=0;
5793 *out_value=NULL;
5794 *out_value_len=0;
5796 *out_type=0;
5798 *out_max_data_len=0;
5799 *data_out=NULL;
5800 *out_data_len=0;
5802 DEBUG(5,("spoolss_enumprinterdata\n"));
5804 if (!OPEN_HANDLE(Printer)) {
5805 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5806 return ERROR_INVALID_HANDLE;
5809 if (!get_printer_snum(handle, &snum))
5810 return ERROR_INVALID_HANDLE;
5812 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5813 return ERROR_INVALID_HANDLE;
5816 * The NT machine wants to know the biggest size of value and data
5818 * cf: MSDN EnumPrinterData remark section
5820 if ( (in_value_len==0) && (in_data_len==0) ) {
5821 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5823 #if 0
5825 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5826 * if this parameter size doesn't exist.
5827 * Ok - my opinion here is that the client is not asking for the greatest
5828 * possible size of all the parameters, but is asking specifically for the size needed
5829 * for this specific parameter. In that case we can remove the loop below and
5830 * simplify this lookup code considerably. JF - comments welcome. JRA.
5833 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5834 safe_free(data);
5835 free_a_printer(&printer, 2);
5836 return ERROR_NO_MORE_ITEMS;
5838 #endif
5840 safe_free(data);
5841 data = NULL;
5843 param_index=0;
5844 biggest_valuesize=0;
5845 biggest_datasize=0;
5847 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5848 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5849 if (data_len > biggest_datasize) biggest_datasize=data_len;
5851 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5853 safe_free(data);
5854 data = NULL;
5855 param_index++;
5859 * I think this is correct, it doesn't break APW and
5860 * allows Gerald's Win32 test programs to work correctly,
5861 * but may need altering.... JRA.
5864 if (param_index == 0) {
5865 /* No parameters found. */
5866 free_a_printer(&printer, 2);
5867 return ERROR_NO_MORE_ITEMS;
5870 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5871 *out_value_len=2*(1+biggest_valuesize);
5872 *out_data_len=biggest_datasize;
5874 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5876 free_a_printer(&printer, 2);
5877 return NT_STATUS_NO_PROBLEMO;
5881 * the value len is wrong in NT sp3
5882 * that's the number of bytes not the number of unicode chars
5885 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5886 safe_free(data);
5887 free_a_printer(&printer, 2);
5888 return ERROR_NO_MORE_ITEMS;
5891 free_a_printer(&printer, 2);
5894 * the value is:
5895 * - counted in bytes in the request
5896 * - counted in UNICODE chars in the max reply
5897 * - counted in bytes in the real size
5899 * take a pause *before* coding not *during* coding
5902 *out_max_value_len=(in_value_len/sizeof(uint16));
5903 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
5904 safe_free(data);
5905 return ERROR_NOT_ENOUGH_MEMORY;
5908 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5910 *out_type=type;
5912 /* the data is counted in bytes */
5913 *out_max_data_len=in_data_len;
5914 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
5915 safe_free(data);
5916 return ERROR_NOT_ENOUGH_MEMORY;
5919 memcpy(*data_out, data, (size_t)data_len);
5920 *out_data_len=data_len;
5922 safe_free(data);
5924 return NT_STATUS_NO_PROBLEMO;
5927 /****************************************************************************
5928 ****************************************************************************/
5929 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5930 const UNISTR2 *value,
5931 uint32 type,
5932 uint32 max_len,
5933 const uint8 *data,
5934 uint32 real_len,
5935 uint32 numeric_data)
5937 NT_PRINTER_INFO_LEVEL *printer = NULL;
5938 NT_PRINTER_PARAM *param = NULL, old_param;
5939 int snum=0;
5940 uint32 status = 0x0;
5941 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5943 DEBUG(5,("spoolss_setprinterdata\n"));
5945 if (!OPEN_HANDLE(Printer)) {
5946 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5947 return ERROR_INVALID_HANDLE;
5950 if (!get_printer_snum(handle, &snum))
5951 return ERROR_INVALID_HANDLE;
5953 status = get_a_printer(&printer, 2, lp_servicename(snum));
5954 if (status != 0x0)
5955 return ERROR_INVALID_NAME;
5957 convert_specific_param(&param, value , type, data, real_len);
5959 /* Check if we are making any changes or not. Return true if
5960 nothing is actually changing. */
5962 ZERO_STRUCT(old_param);
5964 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5965 &old_param.type, (unsigned int *)&old_param.data_len)) {
5967 if (param->type == old_param.type &&
5968 param->data_len == old_param.data_len &&
5969 memcmp(param->data, old_param.data,
5970 old_param.data_len) == 0) {
5972 DEBUG(3, ("setprinterdata hasn't changed\n"));
5973 status = NT_STATUS_NO_PROBLEMO;
5974 goto done;
5978 /* Access check */
5980 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5981 DEBUG(3, ("security descriptor change denied by existing "
5982 "security descriptor\n"));
5983 status = ERROR_ACCESS_DENIED;
5984 goto done;
5987 unlink_specific_param_if_exist(printer->info_2, param);
5989 add_a_specific_param(printer->info_2, &param);
5990 status = mod_a_printer(*printer, 2);
5992 done:
5993 free_a_printer(&printer, 2);
5994 if (param)
5995 free_nt_printer_param(&param);
5996 safe_free(old_param.data);
5998 return status;
6001 /****************************************************************************
6002 ****************************************************************************/
6004 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6006 POLICY_HND *handle = &q_u->handle;
6007 UNISTR2 *value = &q_u->valuename;
6009 NT_PRINTER_INFO_LEVEL *printer = NULL;
6010 NT_PRINTER_PARAM param;
6011 int snum=0;
6012 uint32 status = 0x0;
6013 Printer_entry *Printer=find_printer_index_by_hnd(handle);
6015 DEBUG(5,("spoolss_deleteprinterdata\n"));
6017 if (!OPEN_HANDLE(Printer)) {
6018 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6019 return ERROR_INVALID_HANDLE;
6022 if (!get_printer_snum(handle, &snum))
6023 return ERROR_INVALID_HANDLE;
6025 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6026 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6027 "change denied by existing security descriptor\n"));
6028 return ERROR_ACCESS_DENIED;
6031 status = get_a_printer(&printer, 2, lp_servicename(snum));
6032 if (status != 0x0)
6033 return ERROR_INVALID_NAME;
6035 ZERO_STRUCTP(&param);
6036 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6038 if(!unlink_specific_param_if_exist(printer->info_2, &param))
6039 status = ERROR_INVALID_PARAMETER;
6040 else
6041 status = mod_a_printer(*printer, 2);
6043 free_a_printer(&printer, 2);
6044 return status;
6047 /****************************************************************************
6048 ****************************************************************************/
6049 uint32 _spoolss_addform( POLICY_HND *handle,
6050 uint32 level,
6051 const FORM *form)
6053 int count=0;
6054 nt_forms_struct *list=NULL;
6055 Printer_entry *Printer = find_printer_index_by_hnd(handle);
6057 DEBUG(5,("spoolss_addform\n"));
6059 if (!OPEN_HANDLE(Printer)) {
6060 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6061 return ERROR_INVALID_HANDLE;
6064 count=get_ntforms(&list);
6065 if(!add_a_form(&list, form, &count))
6066 return ERROR_NOT_ENOUGH_MEMORY;
6067 write_ntforms(&list, count);
6069 safe_free(list);
6071 return 0x0;
6074 /****************************************************************************
6075 ****************************************************************************/
6076 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
6078 int count=0;
6079 uint32 ret = 0;
6080 nt_forms_struct *list=NULL;
6081 Printer_entry *Printer = find_printer_index_by_hnd(handle);
6083 DEBUG(5,("spoolss_deleteform\n"));
6085 if (!OPEN_HANDLE(Printer)) {
6086 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6087 return ERROR_INVALID_HANDLE;
6090 count = get_ntforms(&list);
6091 if(!delete_a_form(&list, form_name, &count, &ret))
6092 return ERROR_INVALID_PARAMETER;
6094 safe_free(list);
6096 return ret;
6099 /****************************************************************************
6100 ****************************************************************************/
6101 uint32 _spoolss_setform( POLICY_HND *handle,
6102 const UNISTR2 *uni_name,
6103 uint32 level,
6104 const FORM *form)
6106 int count=0;
6107 nt_forms_struct *list=NULL;
6108 Printer_entry *Printer = find_printer_index_by_hnd(handle);
6110 DEBUG(5,("spoolss_setform\n"));
6112 if (!OPEN_HANDLE(Printer)) {
6113 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6114 return ERROR_INVALID_HANDLE;
6116 count=get_ntforms(&list);
6117 update_a_form(&list, form, count);
6118 write_ntforms(&list, count);
6120 safe_free(list);
6122 return 0x0;
6125 /****************************************************************************
6126 enumprintprocessors level 1.
6127 ****************************************************************************/
6128 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6130 PRINTPROCESSOR_1 *info_1=NULL;
6132 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6133 return ERROR_NOT_ENOUGH_MEMORY;
6135 (*returned) = 0x1;
6137 init_unistr(&info_1->name, "winprint");
6139 *needed += spoolss_size_printprocessor_info_1(info_1);
6141 if (!alloc_buffer_size(buffer, *needed))
6142 return ERROR_INSUFFICIENT_BUFFER;
6144 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6146 safe_free(info_1);
6148 if (*needed > offered) {
6149 *returned=0;
6150 return ERROR_INSUFFICIENT_BUFFER;
6152 else
6153 return NT_STATUS_NO_PROBLEMO;
6156 /****************************************************************************
6157 ****************************************************************************/
6158 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
6159 NEW_BUFFER *buffer, uint32 offered,
6160 uint32 *needed, uint32 *returned)
6162 DEBUG(5,("spoolss_enumprintprocessors\n"));
6165 * Enumerate the print processors ...
6167 * Just reply with "winprint", to keep NT happy
6168 * and I can use my nice printer checker.
6171 *returned=0;
6172 *needed=0;
6174 switch (level) {
6175 case 1:
6176 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6177 default:
6178 return ERROR_INVALID_LEVEL;
6182 /****************************************************************************
6183 enumprintprocdatatypes level 1.
6184 ****************************************************************************/
6185 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6187 PRINTPROCDATATYPE_1 *info_1=NULL;
6189 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6190 return ERROR_NOT_ENOUGH_MEMORY;
6192 (*returned) = 0x1;
6194 init_unistr(&info_1->name, "RAW");
6196 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6198 if (!alloc_buffer_size(buffer, *needed))
6199 return ERROR_INSUFFICIENT_BUFFER;
6201 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6203 safe_free(info_1);
6205 if (*needed > offered) {
6206 *returned=0;
6207 return ERROR_INSUFFICIENT_BUFFER;
6209 else
6210 return NT_STATUS_NO_PROBLEMO;
6213 /****************************************************************************
6214 ****************************************************************************/
6215 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
6216 NEW_BUFFER *buffer, uint32 offered,
6217 uint32 *needed, uint32 *returned)
6219 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6221 *returned=0;
6222 *needed=0;
6224 switch (level) {
6225 case 1:
6226 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6227 default:
6228 return ERROR_INVALID_LEVEL;
6232 /****************************************************************************
6233 enumprintmonitors level 1.
6234 ****************************************************************************/
6235 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6237 PRINTMONITOR_1 *info_1=NULL;
6239 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6240 return ERROR_NOT_ENOUGH_MEMORY;
6242 (*returned) = 0x1;
6244 init_unistr(&info_1->name, "Local Port");
6246 *needed += spoolss_size_printmonitor_info_1(info_1);
6248 if (!alloc_buffer_size(buffer, *needed))
6249 return ERROR_INSUFFICIENT_BUFFER;
6251 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6253 safe_free(info_1);
6255 if (*needed > offered) {
6256 *returned=0;
6257 return ERROR_INSUFFICIENT_BUFFER;
6259 else
6260 return NT_STATUS_NO_PROBLEMO;
6263 /****************************************************************************
6264 enumprintmonitors level 2.
6265 ****************************************************************************/
6266 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6268 PRINTMONITOR_2 *info_2=NULL;
6270 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6271 return ERROR_NOT_ENOUGH_MEMORY;
6273 (*returned) = 0x1;
6275 init_unistr(&info_2->name, "Local Port");
6276 init_unistr(&info_2->environment, "Windows NT X86");
6277 init_unistr(&info_2->dll_name, "localmon.dll");
6279 *needed += spoolss_size_printmonitor_info_2(info_2);
6281 if (!alloc_buffer_size(buffer, *needed))
6282 return ERROR_INSUFFICIENT_BUFFER;
6284 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6286 safe_free(info_2);
6288 if (*needed > offered) {
6289 *returned=0;
6290 return ERROR_INSUFFICIENT_BUFFER;
6292 else
6293 return NT_STATUS_NO_PROBLEMO;
6296 /****************************************************************************
6297 ****************************************************************************/
6298 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6299 NEW_BUFFER *buffer, uint32 offered,
6300 uint32 *needed, uint32 *returned)
6302 DEBUG(5,("spoolss_enumprintmonitors\n"));
6305 * Enumerate the print monitors ...
6307 * Just reply with "Local Port", to keep NT happy
6308 * and I can use my nice printer checker.
6311 *returned=0;
6312 *needed=0;
6314 switch (level) {
6315 case 1:
6316 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6317 case 2:
6318 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6319 default:
6320 return ERROR_INVALID_LEVEL;
6324 /****************************************************************************
6325 ****************************************************************************/
6326 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6328 int i=0;
6329 BOOL found=False;
6330 JOB_INFO_1 *info_1=NULL;
6332 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6334 if (info_1 == NULL) {
6335 safe_free(queue);
6336 return ERROR_NOT_ENOUGH_MEMORY;
6339 for (i=0; i<count && found==False; i++) {
6340 if (queue[i].job==(int)jobid)
6341 found=True;
6344 if (found==False) {
6345 safe_free(queue);
6346 safe_free(info_1);
6347 /* I shoud reply something else ... I can't find the good one */
6348 return NT_STATUS_NO_PROBLEMO;
6351 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6353 safe_free(queue);
6355 *needed += spoolss_size_job_info_1(info_1);
6357 if (!alloc_buffer_size(buffer, *needed)) {
6358 safe_free(info_1);
6359 return ERROR_INSUFFICIENT_BUFFER;
6362 new_smb_io_job_info_1("", buffer, info_1, 0);
6364 safe_free(info_1);
6366 if (*needed > offered)
6367 return ERROR_INSUFFICIENT_BUFFER;
6368 else
6369 return NT_STATUS_NO_PROBLEMO;
6373 /****************************************************************************
6374 ****************************************************************************/
6375 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6377 int i=0;
6378 BOOL found=False;
6379 JOB_INFO_2 *info_2;
6380 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6382 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6384 ZERO_STRUCTP(info_2);
6386 if (info_2 == NULL) {
6387 safe_free(queue);
6388 return ERROR_NOT_ENOUGH_MEMORY;
6391 for (i=0; i<count && found==False; i++) {
6392 if (queue[i].job==(int)jobid)
6393 found=True;
6396 if (found==False) {
6397 safe_free(queue);
6398 safe_free(info_2);
6399 /* I shoud reply something else ... I can't find the good one */
6400 return NT_STATUS_NO_PROBLEMO;
6403 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6404 safe_free(queue);
6405 return ERROR_NOT_ENOUGH_MEMORY;
6408 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6410 free_a_printer(&ntprinter, 2);
6411 safe_free(queue);
6413 *needed += spoolss_size_job_info_2(info_2);
6415 if (!alloc_buffer_size(buffer, *needed)) {
6416 safe_free(info_2);
6417 return ERROR_INSUFFICIENT_BUFFER;
6420 new_smb_io_job_info_2("", buffer, info_2, 0);
6422 free_job_info_2(info_2);
6423 free(info_2);
6425 if (*needed > offered)
6426 return ERROR_INSUFFICIENT_BUFFER;
6427 else
6428 return NT_STATUS_NO_PROBLEMO;
6431 /****************************************************************************
6432 ****************************************************************************/
6433 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6434 NEW_BUFFER *buffer, uint32 offered,
6435 uint32 *needed)
6437 int snum;
6438 int count;
6439 print_queue_struct *queue=NULL;
6440 print_status_struct prt_status;
6442 DEBUG(5,("spoolss_getjob\n"));
6444 memset(&prt_status, 0, sizeof(prt_status));
6446 *needed=0;
6448 if (!get_printer_snum(handle, &snum))
6449 return ERROR_INVALID_HANDLE;
6451 count = print_queue_status(snum, &queue, &prt_status);
6453 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6454 count, prt_status.status, prt_status.message));
6456 switch (level) {
6457 case 1:
6458 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6459 case 2:
6460 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6461 default:
6462 safe_free(queue);
6463 return ERROR_INVALID_LEVEL;