merge from APPLIANCE_HEAD
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob2a412ccc98b1f80a77c7e4889656699e188e41b1
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 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 extern int DEBUGLEVEL;
31 extern pstring global_myname;
33 #ifndef MAX_OPEN_PRINTER_EXS
34 #define MAX_OPEN_PRINTER_EXS 50
35 #endif
37 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
38 #define PRINTER_HANDLE_IS_PRINTER 0
39 #define PRINTER_HANDLE_IS_PRINTSERVER 1
41 struct table_node {
42 char *long_archi;
43 char *short_archi;
44 int version;
48 /* structure to store the printer handles */
49 /* and a reference to what it's pointing to */
50 /* and the notify info asked about */
51 /* that's the central struct */
52 typedef struct _Printer{
53 BOOL document_started;
54 BOOL page_started;
55 int jobid; /* jobid in printing backend */
56 BOOL printer_type;
57 union {
58 fstring handlename;
59 fstring printerservername;
60 } dev;
61 uint32 type;
62 uint32 access;
63 struct {
64 uint32 flags;
65 uint32 options;
66 fstring localmachine;
67 uint32 printerlocal;
68 SPOOL_NOTIFY_OPTION *option;
69 POLICY_HND client_hnd;
70 uint32 client_connected;
71 } notify;
72 struct {
73 fstring machine;
74 fstring user;
75 } client;
76 } Printer_entry;
78 typedef struct _counter_printer_0 {
79 ubi_dlNode Next;
80 ubi_dlNode Prev;
82 int snum;
83 uint32 counter;
84 } counter_printer_0;
86 static ubi_dlList counter_list;
88 static struct cli_state cli;
89 static uint32 smb_connections=0;
91 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
93 /* translate between internal status numbers and NT status numbers */
94 static int nt_printj_status(int v)
96 switch (v) {
97 case LPQ_QUEUED:
98 return 0;
99 case LPQ_PAUSED:
100 return JOB_STATUS_PAUSED;
101 case LPQ_SPOOLING:
102 return JOB_STATUS_SPOOLING;
103 case LPQ_PRINTING:
104 return JOB_STATUS_PRINTING;
105 case LPQ_ERROR:
106 return JOB_STATUS_ERROR;
107 case LPQ_DELETING:
108 return JOB_STATUS_DELETING;
109 case LPQ_OFFLINE:
110 return JOB_STATUS_OFFLINE;
111 case LPQ_PAPEROUT:
112 return JOB_STATUS_PAPEROUT;
113 case LPQ_PRINTED:
114 return JOB_STATUS_PRINTED;
115 case LPQ_DELETED:
116 return JOB_STATUS_DELETED;
117 case LPQ_BLOCKED:
118 return JOB_STATUS_BLOCKED;
119 case LPQ_USER_INTERVENTION:
120 return JOB_STATUS_USER_INTERVENTION;
122 return 0;
125 static int nt_printq_status(int v)
127 switch (v) {
128 case LPQ_PAUSED:
129 return PRINTER_STATUS_PAUSED;
130 case LPQ_QUEUED:
131 case LPQ_SPOOLING:
132 case LPQ_PRINTING:
133 return 0;
135 return 0;
138 /****************************************************************************
139 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
140 ****************************************************************************/
142 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
144 SPOOL_NOTIFY_OPTION *sp = *pp;
146 *pp = NULL;
148 if (!sp)
149 return;
151 if (sp->ctr.type)
152 safe_free(sp->ctr.type);
154 free(sp);
157 /***************************************************************************
158 Disconnect from the client
159 ****************************************************************************/
161 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
163 WERROR status;
165 /* weird if the test succeds !!! */
166 if (smb_connections==0) {
167 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
168 return;
171 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
174 /* if it's the last connection, deconnect the IPC$ share */
175 if (smb_connections==1) {
176 if(!spoolss_disconnect_from_client(&cli))
177 return;
179 message_deregister(MSG_PRINTER_NOTIFY);
182 smb_connections--;
185 /****************************************************************************
186 Functions to free a printer entry datastruct.
187 ****************************************************************************/
189 static void free_printer_entry(void *ptr)
191 Printer_entry *Printer = (Printer_entry *)ptr;
193 if (Printer->notify.client_connected==True)
194 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
196 Printer->notify.flags=0;
197 Printer->notify.options=0;
198 Printer->notify.localmachine[0]='\0';
199 Printer->notify.printerlocal=0;
200 free_spool_notify_option(&Printer->notify.option);
201 Printer->notify.option=NULL;
202 Printer->notify.client_connected=False;
204 safe_free(Printer);
207 /****************************************************************************
208 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
209 ****************************************************************************/
211 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
213 SPOOL_NOTIFY_OPTION *new_sp = NULL;
215 if (!sp)
216 return NULL;
218 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
219 if (!new_sp)
220 return NULL;
222 *new_sp = *sp;
224 if (sp->ctr.count) {
225 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
227 if (!new_sp->ctr.type) {
228 safe_free(new_sp);
229 return NULL;
233 return new_sp;
236 /****************************************************************************
237 find printer index by handle
238 ****************************************************************************/
240 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
242 Printer_entry *find_printer = NULL;
244 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
245 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
246 return NULL;
249 return find_printer;
252 /****************************************************************************
253 close printer index by handle
254 ****************************************************************************/
256 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
260 if (!Printer) {
261 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
262 return False;
265 close_policy_hnd(p, hnd);
267 return True;
270 /****************************************************************************
271 delete a printer given a handle
272 ****************************************************************************/
273 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
275 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
277 if (!Printer) {
278 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
279 return WERR_BADFID;
282 if (del_a_printer(Printer->dev.handlename) != 0) {
283 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
284 return WERR_BADFID;
287 /* Check calling user has permission to delete printer. Note that
288 since we set the snum parameter to -1 only administrators can
289 delete the printer. This stops people with the Full Control
290 permission from deleting the printer. */
292 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
293 DEBUG(3, ("printer delete denied by security descriptor\n"));
294 return WERR_ACCESS_DENIED;
297 if (*lp_deleteprinter_cmd()) {
299 char *cmd = lp_deleteprinter_cmd();
300 pstring command;
301 int ret;
302 int i;
304 /* Printer->dev.handlename equals portname equals sharename */
305 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
306 Printer->dev.handlename);
308 DEBUG(10,("Running [%s]\n", command));
309 ret = smbrun(command, NULL);
310 if (ret != 0) {
311 return WERR_BADFID; /* What to return here? */
313 DEBUGADD(10,("returned [%d]\n", ret));
315 /* Send SIGHUP to process group... is there a better way? */
316 kill(0, SIGHUP);
318 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
319 lp_killservice( i );
320 return WERR_OK;
321 } else
322 return WERR_ACCESS_DENIED;
325 return WERR_OK;
328 /****************************************************************************
329 return the snum of a printer corresponding to an handle
330 ****************************************************************************/
331 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
333 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
335 if (!Printer) {
336 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
337 return False;
340 switch (Printer->printer_type) {
341 case PRINTER_HANDLE_IS_PRINTER:
342 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
343 *number = print_queue_snum(Printer->dev.handlename);
344 return (*number != -1);
345 case PRINTER_HANDLE_IS_PRINTSERVER:
346 return False;
347 default:
348 return False;
352 /****************************************************************************
353 set printer handle type.
354 ****************************************************************************/
355 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
357 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
359 if (!Printer) {
360 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
361 return False;
364 DEBUG(4,("Setting printer access=%x\n", access_required));
365 Printer->access = access_required;
366 return True;
369 /****************************************************************************
370 Set printer handle type.
371 Check if it's \\server or \\server\printer
372 ****************************************************************************/
374 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
376 DEBUG(3,("Setting printer type=%s\n", handlename));
378 if ( strlen(handlename) < 3 ) {
379 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
380 return False;
383 /* it's a print server */
384 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
385 DEBUGADD(4,("Printer is a print server\n"));
386 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
388 /* it's a printer */
389 else {
390 DEBUGADD(4,("Printer is a printer\n"));
391 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
394 return True;
397 /****************************************************************************
398 Set printer handle name.
399 ****************************************************************************/
401 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
403 NT_PRINTER_INFO_LEVEL *printer = NULL;
404 int snum;
405 int n_services=lp_numservices();
406 char *aprinter;
407 BOOL found=False;
409 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
411 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
412 ZERO_STRUCT(Printer->dev.printerservername);
413 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
414 return True;
417 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
418 return False;
420 if (*handlename=='\\') {
421 aprinter=strchr_m(handlename+2, '\\');
422 aprinter++;
424 else {
425 aprinter=handlename;
428 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
431 * store the Samba share name in it
432 * in back we have the long printer name
433 * need to iterate all the snum and do a
434 * get_a_printer each time to find the printer
435 * faster to do it here than later.
438 for (snum=0;snum<n_services && found==False;snum++) {
439 char *printername;
441 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
442 continue;
444 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
446 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
447 continue;
449 printername=strchr_m(printer->info_2->printername+2, '\\');
450 printername++;
452 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
453 printer->info_2->printername, aprinter ));
455 if ( strlen(printername) != strlen(aprinter) ) {
456 free_a_printer(&printer, 2);
457 continue;
460 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
461 free_a_printer(&printer, 2);
462 continue;
465 found=True;
469 * if we haven't found a printer with the given handlename
470 * then it can be a share name as you can open both \\server\printer and
471 * \\server\share
475 * we still check if the printer description file exists as NT won't be happy
476 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
479 if (found==False) {
480 DEBUGADD(5,("Printer not found, checking for share now\n"));
482 for (snum=0;snum<n_services && found==False;snum++) {
484 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
485 continue;
487 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
489 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
490 continue;
492 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
493 printer->info_2->printername, aprinter ));
495 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
496 free_a_printer(&printer, 2);
497 continue;
500 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
501 free_a_printer(&printer, 2);
502 continue;
505 found=True;
509 if (found==False) {
510 DEBUGADD(4,("Printer not found\n"));
511 return False;
514 snum--;
515 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
516 printer->info_2->printername, lp_servicename(snum),snum));
518 ZERO_STRUCT(Printer->dev.handlename);
519 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
521 free_a_printer(&printer, 2);
523 return True;
526 /****************************************************************************
527 find first available printer slot. creates a printer handle for you.
528 ****************************************************************************/
530 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
532 Printer_entry *new_printer;
534 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
536 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
537 return False;
539 ZERO_STRUCTP(new_printer);
541 new_printer->notify.option=NULL;
543 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
544 safe_free(new_printer);
545 return False;
548 if (!set_printer_hnd_printertype(new_printer, name)) {
549 close_printer_handle(p, hnd);
550 return False;
553 if (!set_printer_hnd_name(new_printer, name)) {
554 close_printer_handle(p, hnd);
555 return False;
558 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
560 return True;
563 /********************************************************************
564 Return True is the handle is a print server.
565 ********************************************************************/
567 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
569 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
571 if (!Printer)
572 return False;
574 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
575 return False;
577 return True;
580 /****************************************************************************
581 allocate more memory for a BUFFER.
582 ****************************************************************************/
583 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
585 prs_struct *ps;
586 uint32 extra_space;
587 uint32 old_offset;
589 ps= &buffer->prs;
591 /* damn, I'm doing the reverse operation of prs_grow() :) */
592 if (buffer_size < prs_data_size(ps))
593 extra_space=0;
594 else
595 extra_space = buffer_size - prs_data_size(ps);
598 * save the offset and move to the end of the buffer
599 * prs_grow() checks the extra_space against the offset
601 old_offset=prs_offset(ps);
602 prs_set_offset(ps, prs_data_size(ps));
604 if (!prs_grow(ps, extra_space))
605 return False;
607 prs_set_offset(ps, old_offset);
609 buffer->string_at_end=prs_data_size(ps);
611 return True;
614 /***************************************************************************
615 receive the notify message
616 ****************************************************************************/
618 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
620 fstring printer;
621 WERROR status;
622 struct pipes_struct *p;
623 struct policy *pol;
624 struct handle_list *hl;
626 *printer = '\0';
627 fstrcpy(printer,buf);
629 if (len == 0) {
630 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
631 return;
634 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
637 * We need to enumerate all printers. The handle list is shared
638 * across pipes of the same name, so just find the first open
639 * spoolss pipe.
642 hl = NULL;
643 for ( p = get_first_pipe(); p; get_next_pipe(p)) {
644 if (strequal(p->name, "spoolss")) {
645 hl = p->pipe_handles;
646 break;
650 if (!hl) {
651 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
652 return;
655 /* Iterate the printer list on this pipe. */
656 for (pol = hl->Policy; pol; pol = pol->next ) {
657 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
659 if (!find_printer)
660 continue;
663 * if the entry is the given printer or if it's a printerserver
664 * we send the message
667 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
668 if (strcmp(find_printer->dev.handlename, printer))
669 continue;
671 if (find_printer->notify.client_connected==True)
672 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
676 /***************************************************************************
677 send a notify event
678 ****************************************************************************/
679 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
681 fstring printer;
683 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
685 if (!Printer) {
686 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
687 return False;
690 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
691 fstrcpy(printer, Printer->dev.handlename);
692 else
693 fstrcpy(printer, "");
695 /*srv_spoolss_receive_message(printer);*/
696 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
698 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
700 return True;
703 /********************************************************************
704 * spoolss_open_printer
706 * called from the spoolss dispatcher
707 ********************************************************************/
709 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
711 #if 0
712 WERROR result = WERR_OK;
713 #endif
715 UNISTR2 *printername = NULL;
716 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
717 /* uint32 user_switch = q_u->user_switch; - notused */
718 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
719 POLICY_HND *handle = &r_u->handle;
721 fstring name;
722 int snum;
723 struct current_user user;
725 if (q_u->printername_ptr != 0)
726 printername = &q_u->printername;
728 if (printername == NULL)
729 return WERR_INVALID_PRINTER_NAME;
731 /* some sanity check because you can open a printer or a print server */
732 /* aka: \\server\printer or \\server */
733 unistr2_to_ascii(name, printername, sizeof(name)-1);
735 DEBUGADD(3,("checking name: %s\n",name));
737 if (!open_printer_hnd(p, handle, name))
738 return WERR_INVALID_PRINTER_NAME;
741 if (printer_default->datatype_ptr != NULL)
743 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
744 set_printer_hnd_datatype(handle, datatype);
746 else
747 set_printer_hnd_datatype(handle, "");
750 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
751 close_printer_handle(p, handle);
752 return WERR_ACCESS_DENIED;
756 First case: the user is opening the print server:
758 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
759 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
761 Then both Win2k and WinNT clients try an OpenPrinterEx with
762 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
763 or if the user is listed in the smb.conf printer admin parameter.
765 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
766 client view printer folder, but does not show the MSAPW.
768 Note: this test needs code to check access rights here too. Jeremy
769 could you look at this?
772 Second case: the user is opening a printer:
773 NT doesn't let us connect to a printer if the connecting user
774 doesn't have print permission.
778 get_current_user(&user, p);
780 if (handle_is_printserver(p, handle)) {
781 if (printer_default->access_required == 0) {
782 return WERR_OK;
784 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
786 /* Printserver handles use global struct... */
787 snum = -1;
789 if (!lp_ms_add_printer_wizard()) {
790 close_printer_handle(p, handle);
791 return WERR_ACCESS_DENIED;
793 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
794 return WERR_OK;
796 else {
797 close_printer_handle(p, handle);
798 return WERR_ACCESS_DENIED;
802 else
804 /* NT doesn't let us connect to a printer if the connecting user
805 doesn't have print permission. */
807 if (!get_printer_snum(p, handle, &snum))
808 return WERR_BADFID;
810 /* map an empty access mask to the minimum access mask */
811 if (printer_default->access_required == 0x0)
812 printer_default->access_required = PRINTER_ACCESS_USE;
815 * If we are not serving the printer driver for this printer,
816 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
817 * will keep NT clients happy --jerry
820 if (lp_use_client_driver(snum)
821 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
823 printer_default->access_required = PRINTER_ACCESS_USE;
826 if (!print_access_check(&user, snum, printer_default->access_required)) {
827 DEBUG(3, ("access DENIED for printer open\n"));
828 close_printer_handle(p, handle);
829 return WERR_ACCESS_DENIED;
833 * If we have a default device pointer in the
834 * printer_default struct, then we need to get
835 * the printer info from the tdb and if there is
836 * no default devicemode there then we do a *SET*
837 * here ! This is insanity.... JRA.
841 * If the openprinterex rpc call contains a devmode,
842 * it's a per-user one. This per-user devmode is derivated
843 * from the global devmode. Openprinterex() contains a per-user
844 * devmode for when you do EMF printing and spooling.
845 * In the EMF case, the NT workstation is only doing half the job
846 * of rendering the page. The other half is done by running the printer
847 * driver on the server.
848 * The EMF file doesn't contain the page description (paper size, orientation, ...).
849 * The EMF file only contains what is to be printed on the page.
850 * So in order for the server to know how to print, the NT client sends
851 * a devicemode attached to the openprinterex call.
852 * But this devicemode is short lived, it's only valid for the current print job.
854 * If Samba would have supported EMF spooling, this devicemode would
855 * have been attached to the handle, to sent it to the driver to correctly
856 * rasterize the EMF file.
858 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
859 * we just act as a pass-thru between windows and the printer.
861 * In order to know that Samba supports only RAW spooling, NT has to call
862 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
863 * and until NT sends a RAW job, we refuse it.
865 * But to call getprinter() or startdoc(), you first need a valid handle,
866 * and to get an handle you have to call openprintex(). Hence why you have
867 * a devicemode in the openprinterex() call.
870 * Differences between NT4 and NT 2000.
871 * NT4:
872 * ---
873 * On NT4, you only have a global devicemode. This global devicemode can be changed
874 * by the administrator (or by a user with enough privs). Everytime a user
875 * wants to print, the devicemode is resetted to the default. In Word, everytime
876 * you print, the printer's characteristics are always reset to the global devicemode.
878 * NT 2000:
879 * -------
880 * In W2K, there is the notion of per-user devicemode. The first time you use
881 * a printer, a per-user devicemode is build from the global devicemode.
882 * If you change your per-user devicemode, it is saved in the registry, under the
883 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
884 * printer preferences available.
886 * To change the per-user devicemode: it's the "Printing Preferences ..." button
887 * on the General Tab of the printer properties windows.
889 * To change the global devicemode: it's the "Printing Defaults..." button
890 * on the Advanced Tab of the printer properties window.
892 * JFM.
897 #if 0
898 if (printer_default->devmode_cont.devmode != NULL) {
899 result = printer_write_default_dev( snum, printer_default);
900 if (result != 0) {
901 close_printer_handle(p, handle);
902 return result;
905 #endif
908 return WERR_OK;
911 /****************************************************************************
912 ****************************************************************************/
913 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
914 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
916 switch (level) {
917 case 2:
918 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
919 break;
920 default:
921 break;
924 return True;
927 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
928 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
930 BOOL result = True;
932 switch (level) {
933 case 3:
934 printer->info_3=NULL;
935 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
936 result = False;
937 break;
938 case 6:
939 printer->info_6=NULL;
940 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
941 result = False;
942 break;
943 default:
944 break;
947 return result;
950 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
951 NT_DEVICEMODE **pp_nt_devmode)
953 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
956 * Ensure nt_devmode is a valid pointer
957 * as we will be overwriting it.
960 if (nt_devmode == NULL) {
961 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
962 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
963 return False;
966 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
967 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
969 nt_devmode->specversion=devmode->specversion;
970 nt_devmode->driverversion=devmode->driverversion;
971 nt_devmode->size=devmode->size;
972 nt_devmode->fields=devmode->fields;
973 nt_devmode->orientation=devmode->orientation;
974 nt_devmode->papersize=devmode->papersize;
975 nt_devmode->paperlength=devmode->paperlength;
976 nt_devmode->paperwidth=devmode->paperwidth;
977 nt_devmode->scale=devmode->scale;
978 nt_devmode->copies=devmode->copies;
979 nt_devmode->defaultsource=devmode->defaultsource;
980 nt_devmode->printquality=devmode->printquality;
981 nt_devmode->color=devmode->color;
982 nt_devmode->duplex=devmode->duplex;
983 nt_devmode->yresolution=devmode->yresolution;
984 nt_devmode->ttoption=devmode->ttoption;
985 nt_devmode->collate=devmode->collate;
987 nt_devmode->logpixels=devmode->logpixels;
988 nt_devmode->bitsperpel=devmode->bitsperpel;
989 nt_devmode->pelswidth=devmode->pelswidth;
990 nt_devmode->pelsheight=devmode->pelsheight;
991 nt_devmode->displayflags=devmode->displayflags;
992 nt_devmode->displayfrequency=devmode->displayfrequency;
993 nt_devmode->icmmethod=devmode->icmmethod;
994 nt_devmode->icmintent=devmode->icmintent;
995 nt_devmode->mediatype=devmode->mediatype;
996 nt_devmode->dithertype=devmode->dithertype;
997 nt_devmode->reserved1=devmode->reserved1;
998 nt_devmode->reserved2=devmode->reserved2;
999 nt_devmode->panningwidth=devmode->panningwidth;
1000 nt_devmode->panningheight=devmode->panningheight;
1003 * Only change private and driverextra if the incoming devmode
1004 * has a new one. JRA.
1007 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1008 safe_free(nt_devmode->private);
1009 nt_devmode->driverextra=devmode->driverextra;
1010 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1011 return False;
1012 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1015 *pp_nt_devmode = nt_devmode;
1017 return True;
1020 /********************************************************************
1021 * _spoolss_enddocprinter_internal.
1022 ********************************************************************/
1024 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1026 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1028 if (!Printer) {
1029 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1030 return WERR_BADFID;
1033 Printer->document_started=False;
1034 print_job_end(Printer->jobid,True);
1035 /* error codes unhandled so far ... */
1037 return WERR_OK;
1040 /********************************************************************
1041 * api_spoolss_closeprinter
1042 ********************************************************************/
1044 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1046 POLICY_HND *handle = &q_u->handle;
1048 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1050 if (Printer && Printer->document_started)
1051 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1053 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1055 if (!close_printer_handle(p, handle))
1056 return WERR_BADFID;
1058 return WERR_OK;
1061 /********************************************************************
1062 * api_spoolss_deleteprinter
1064 ********************************************************************/
1066 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1068 POLICY_HND *handle = &q_u->handle;
1069 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1070 WERROR result;
1072 if (Printer && Printer->document_started)
1073 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1075 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1077 result = delete_printer_handle(p, handle);
1079 if (W_ERROR_IS_OK(result)) {
1080 srv_spoolss_sendnotify(p, handle);
1083 return result;
1086 /*******************************************************************
1087 * static function to lookup the version id corresponding to an
1088 * long architecture string
1089 ******************************************************************/
1090 static int get_version_id (char * arch)
1092 int i;
1093 struct table_node archi_table[]= {
1095 {"Windows 4.0", "WIN40", 0 },
1096 {"Windows NT x86", "W32X86", 2 },
1097 {"Windows NT R4000", "W32MIPS", 2 },
1098 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1099 {"Windows NT PowerPC", "W32PPC", 2 },
1100 {NULL, "", -1 }
1103 for (i=0; archi_table[i].long_archi != NULL; i++)
1105 if (strcmp(arch, archi_table[i].long_archi) == 0)
1106 return (archi_table[i].version);
1109 return -1;
1112 /********************************************************************
1113 * _spoolss_deleteprinterdriver
1115 * We currently delete the driver for the architecture only.
1116 * This can leave the driver for other archtectures. However,
1117 * since every printer associates a "Windows NT x86" driver name
1118 * and we cannot delete that one while it is in use, **and** since
1119 * it is impossible to assign a driver to a Samba printer without
1120 * having the "Windows NT x86" driver installed,...
1122 * ....we should not get into trouble here.
1124 * --jerry
1125 ********************************************************************/
1127 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1128 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1130 fstring driver;
1131 fstring arch;
1132 NT_PRINTER_DRIVER_INFO_LEVEL info;
1133 int version;
1135 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1136 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1138 /* check that we have a valid driver name first */
1139 if ((version=get_version_id(arch)) == -1) {
1140 return WERR_INVALID_ENVIRONMENT;
1143 ZERO_STRUCT(info);
1144 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1145 return WERR_UNKNOWN_PRINTER_DRIVER;
1149 if (printer_driver_in_use(arch, driver))
1151 return WERR_PRINTER_DRIVER_IN_USE;
1154 return delete_printer_driver(info.info_3);
1158 /********************************************************************
1159 GetPrinterData on a printer server Handle.
1160 ********************************************************************/
1161 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1163 int i;
1165 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1167 if (!strcmp(value, "BeepEnabled")) {
1168 *type = 0x4;
1169 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1170 return False;
1171 SIVAL(*data, 0, 0x01);
1172 *needed = 0x4;
1173 return True;
1176 if (!strcmp(value, "EventLog")) {
1177 *type = 0x4;
1178 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1179 return False;
1180 SIVAL(*data, 0, 0x1B);
1181 *needed = 0x4;
1182 return True;
1185 if (!strcmp(value, "NetPopup")) {
1186 *type = 0x4;
1187 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1188 return False;
1189 SIVAL(*data, 0, 0x01);
1190 *needed = 0x4;
1191 return True;
1194 if (!strcmp(value, "MajorVersion")) {
1195 *type = 0x4;
1196 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1197 return False;
1198 SIVAL(*data, 0, 0x02);
1199 *needed = 0x4;
1200 return True;
1203 if (!strcmp(value, "DefaultSpoolDirectory")) {
1204 pstring string="You are using a Samba server";
1205 *type = 0x1;
1206 *needed = 2*(strlen(string)+1);
1207 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1208 return False;
1209 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1211 /* it's done by hand ready to go on the wire */
1212 for (i=0; i<strlen(string); i++) {
1213 (*data)[2*i]=string[i];
1214 (*data)[2*i+1]='\0';
1216 return True;
1219 if (!strcmp(value, "Architecture")) {
1220 pstring string="Windows NT x86";
1221 *type = 0x1;
1222 *needed = 2*(strlen(string)+1);
1223 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1224 return False;
1225 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1226 for (i=0; i<strlen(string); i++) {
1227 (*data)[2*i]=string[i];
1228 (*data)[2*i+1]='\0';
1230 return True;
1233 return False;
1236 /********************************************************************
1237 GetPrinterData on a printer Handle.
1238 ********************************************************************/
1239 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1240 fstring value, uint32 *type,
1241 uint8 **data, uint32 *needed, uint32 in_size )
1243 NT_PRINTER_INFO_LEVEL *printer = NULL;
1244 int snum=0;
1245 uint8 *idata=NULL;
1246 uint32 len;
1247 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1249 DEBUG(5,("getprinterdata_printer\n"));
1251 if (!Printer) {
1252 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1253 return False;
1256 if(!get_printer_snum(p, handle, &snum))
1257 return False;
1259 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1260 return False;
1262 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1263 free_a_printer(&printer, 2);
1264 return False;
1267 free_a_printer(&printer, 2);
1269 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1271 if (in_size) {
1272 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1273 return False;
1276 memset(*data, 0, in_size *sizeof(uint8));
1277 /* copy the min(in_size, len) */
1278 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1279 } else {
1280 *data = NULL;
1283 *needed = len;
1285 DEBUG(5,("getprinterdata_printer:copy done\n"));
1287 safe_free(idata);
1289 return True;
1292 /********************************************************************
1293 * spoolss_getprinterdata
1294 ********************************************************************/
1296 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1298 POLICY_HND *handle = &q_u->handle;
1299 UNISTR2 *valuename = &q_u->valuename;
1300 uint32 in_size = q_u->size;
1301 uint32 *type = &r_u->type;
1302 uint32 *out_size = &r_u->size;
1303 uint8 **data = &r_u->data;
1304 uint32 *needed = &r_u->needed;
1306 fstring value;
1307 BOOL found=False;
1308 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1311 * Reminder: when it's a string, the length is in BYTES
1312 * even if UNICODE is negociated.
1314 * JFM, 4/19/1999
1317 *out_size=in_size;
1319 /* in case of problem, return some default values */
1320 *needed=0;
1321 *type=0;
1323 DEBUG(4,("_spoolss_getprinterdata\n"));
1325 if (!Printer) {
1326 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1327 return WERR_NOMEM;
1328 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1329 return WERR_BADFID;
1332 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1334 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1335 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1336 else
1337 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1339 if (found==False) {
1340 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1341 /* reply this param doesn't exist */
1342 if (*out_size) {
1343 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1344 return WERR_NOMEM;
1345 } else {
1346 *data = NULL;
1349 return WERR_INVALID_PARAM;
1352 if (*needed > *out_size)
1353 return WERR_STATUS_MORE_ENTRIES;
1354 else {
1355 return WERR_OK;
1359 /***************************************************************************
1360 connect to the client
1361 ****************************************************************************/
1362 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1364 WERROR status;
1367 * If it's the first connection, contact the client
1368 * and connect to the IPC$ share anonumously
1370 if (smb_connections==0) {
1371 fstring unix_printer;
1373 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1375 if(!spoolss_connect_to_client(&cli, unix_printer))
1376 return False;
1377 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1381 smb_connections++;
1383 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1384 return False;
1386 return True;
1389 /********************************************************************
1390 * _spoolss_rffpcnex
1391 * ReplyFindFirstPrinterChangeNotifyEx
1393 * jfmxxxx: before replying OK: status=0
1394 * should do a rpc call to the workstation asking ReplyOpenPrinter
1395 * have to code it, later.
1397 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1398 * called from api_spoolss_rffpcnex
1399 ********************************************************************/
1401 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1403 POLICY_HND *handle = &q_u->handle;
1404 uint32 flags = q_u->flags;
1405 uint32 options = q_u->options;
1406 UNISTR2 *localmachine = &q_u->localmachine;
1407 uint32 printerlocal = q_u->printerlocal;
1408 SPOOL_NOTIFY_OPTION *option = q_u->option;
1410 /* store the notify value in the printer struct */
1412 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1414 if (!Printer) {
1415 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1416 return WERR_BADFID;
1419 Printer->notify.flags=flags;
1420 Printer->notify.options=options;
1421 Printer->notify.printerlocal=printerlocal;
1423 if (Printer->notify.option)
1424 free_spool_notify_option(&Printer->notify.option);
1426 Printer->notify.option=dup_spool_notify_option(option);
1428 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1430 /* connect to the client machine and send a ReplyOpenPrinter */
1431 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1432 Printer->notify.printerlocal, 1,
1433 &Printer->notify.client_hnd))
1434 Printer->notify.client_connected=True;
1436 return WERR_OK;
1439 /*******************************************************************
1440 * fill a notify_info_data with the servername
1441 ********************************************************************/
1443 static void spoolss_notify_server_name(int snum,
1444 SPOOL_NOTIFY_INFO_DATA *data,
1445 print_queue_struct *queue,
1446 NT_PRINTER_INFO_LEVEL *printer,
1447 TALLOC_CTX *mem_ctx)
1449 pstring temp_name, temp;
1450 uint32 len;
1452 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1454 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, 0);
1456 data->notify_data.data.length = len / 2 - 1;
1457 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1459 if (!data->notify_data.data.string) {
1460 data->notify_data.data.length = 0;
1461 return;
1464 memcpy(data->notify_data.data.string, temp, len);
1467 /*******************************************************************
1468 * fill a notify_info_data with the printername (not including the servername).
1469 ********************************************************************/
1470 static void spoolss_notify_printer_name(int snum,
1471 SPOOL_NOTIFY_INFO_DATA *data,
1472 print_queue_struct *queue,
1473 NT_PRINTER_INFO_LEVEL *printer,
1474 TALLOC_CTX *mem_ctx)
1476 pstring temp;
1477 uint32 len;
1479 /* the notify name should not contain the \\server\ part */
1480 char *p = strrchr_m(printer->info_2->printername, '\\');
1482 if (!p) {
1483 p = printer->info_2->printername;
1484 } else {
1485 p++;
1488 len = rpcstr_push(temp, p, sizeof(temp)-2, 0);
1489 data->notify_data.data.length = len / 2 - 1;
1490 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1492 if (!data->notify_data.data.string) {
1493 data->notify_data.data.length = 0;
1494 return;
1497 memcpy(data->notify_data.data.string, temp, len);
1500 /*******************************************************************
1501 * fill a notify_info_data with the servicename
1502 ********************************************************************/
1503 static void spoolss_notify_share_name(int snum,
1504 SPOOL_NOTIFY_INFO_DATA *data,
1505 print_queue_struct *queue,
1506 NT_PRINTER_INFO_LEVEL *printer,
1507 TALLOC_CTX *mem_ctx)
1509 pstring temp;
1510 uint32 len;
1512 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp) - 2, 0);
1514 data->notify_data.data.length = len / 2 - 1;
1515 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1517 if (!data->notify_data.data.string) {
1518 data->notify_data.data.length = 0;
1519 return;
1522 memcpy(data->notify_data.data.string, temp, len);
1525 /*******************************************************************
1526 * fill a notify_info_data with the port name
1527 ********************************************************************/
1528 static void spoolss_notify_port_name(int snum,
1529 SPOOL_NOTIFY_INFO_DATA *data,
1530 print_queue_struct *queue,
1531 NT_PRINTER_INFO_LEVEL *printer,
1532 TALLOC_CTX *mem_ctx)
1534 pstring temp;
1535 uint32 len;
1537 /* even if it's strange, that's consistant in all the code */
1539 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp) - 2, 0);
1541 data->notify_data.data.length = len / 2 - 1;
1542 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1544 if (!data->notify_data.data.string) {
1545 data->notify_data.data.length = 0;
1546 return;
1549 memcpy(data->notify_data.data.string, temp, len);
1552 /*******************************************************************
1553 * fill a notify_info_data with the printername
1554 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1555 * but it doesn't exist, have to see what to do
1556 ********************************************************************/
1557 static void spoolss_notify_driver_name(int snum,
1558 SPOOL_NOTIFY_INFO_DATA *data,
1559 print_queue_struct *queue,
1560 NT_PRINTER_INFO_LEVEL *printer,
1561 TALLOC_CTX *mem_ctx)
1563 pstring temp;
1564 uint32 len;
1566 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp) - 2, 0);
1567 data->notify_data.data.length = len / 2 - 1;
1568 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1570 if (!data->notify_data.data.string) {
1571 data->notify_data.data.length = 0;
1572 return;
1575 memcpy(data->notify_data.data.string, temp, len);
1578 /*******************************************************************
1579 * fill a notify_info_data with the comment
1580 ********************************************************************/
1581 static void spoolss_notify_comment(int snum,
1582 SPOOL_NOTIFY_INFO_DATA *data,
1583 print_queue_struct *queue,
1584 NT_PRINTER_INFO_LEVEL *printer,
1585 TALLOC_CTX *mem_ctx)
1587 pstring temp;
1588 uint32 len;
1590 if (*printer->info_2->comment == '\0')
1591 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp) - 2, 0);
1593 else
1594 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp) - 2, 0);
1596 data->notify_data.data.length = len / 2 - 1;
1597 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1599 if (!data->notify_data.data.string) {
1600 data->notify_data.data.length = 0;
1601 return;
1604 memcpy(data->notify_data.data.string, temp, len);
1607 /*******************************************************************
1608 * fill a notify_info_data with the comment
1609 * jfm:xxxx incorrect, have to create a new smb.conf option
1610 * location = "Room 1, floor 2, building 3"
1611 ********************************************************************/
1612 static void spoolss_notify_location(int snum,
1613 SPOOL_NOTIFY_INFO_DATA *data,
1614 print_queue_struct *queue,
1615 NT_PRINTER_INFO_LEVEL *printer,
1616 TALLOC_CTX *mem_ctx)
1618 pstring temp;
1619 uint32 len;
1621 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp) - 2, 0);
1623 data->notify_data.data.length = len / 2 - 1;
1624 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1626 if (!data->notify_data.data.string) {
1627 data->notify_data.data.length = 0;
1628 return;
1631 memcpy(data->notify_data.data.string, temp, len);
1634 /*******************************************************************
1635 * fill a notify_info_data with the device mode
1636 * jfm:xxxx don't to it for know but that's a real problem !!!
1637 ********************************************************************/
1638 static void spoolss_notify_devmode(int snum,
1639 SPOOL_NOTIFY_INFO_DATA *data,
1640 print_queue_struct *queue,
1641 NT_PRINTER_INFO_LEVEL *printer,
1642 TALLOC_CTX *mem_ctx)
1646 /*******************************************************************
1647 * fill a notify_info_data with the separator file name
1648 * jfm:xxxx just return no file could add an option to smb.conf
1649 * separator file = "separator.txt"
1650 ********************************************************************/
1651 static void spoolss_notify_sepfile(int snum,
1652 SPOOL_NOTIFY_INFO_DATA *data,
1653 print_queue_struct *queue,
1654 NT_PRINTER_INFO_LEVEL *printer,
1655 TALLOC_CTX *mem_ctx)
1657 pstring temp;
1658 uint32 len;
1660 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp) - 2, 0);
1662 data->notify_data.data.length = len / 2 - 1;
1663 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1665 if (!data->notify_data.data.string) {
1666 data->notify_data.data.length = 0;
1667 return;
1670 memcpy(data->notify_data.data.string, temp, len);
1673 /*******************************************************************
1674 * fill a notify_info_data with the print processor
1675 * jfm:xxxx return always winprint to indicate we don't do anything to it
1676 ********************************************************************/
1677 static void spoolss_notify_print_processor(int snum,
1678 SPOOL_NOTIFY_INFO_DATA *data,
1679 print_queue_struct *queue,
1680 NT_PRINTER_INFO_LEVEL *printer,
1681 TALLOC_CTX *mem_ctx)
1683 pstring temp;
1684 uint32 len;
1686 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp) - 2, 0);
1688 data->notify_data.data.length = len / 2 - 1;
1689 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1691 if (!data->notify_data.data.string) {
1692 data->notify_data.data.length = 0;
1693 return;
1696 memcpy(data->notify_data.data.string, temp, len);
1699 /*******************************************************************
1700 * fill a notify_info_data with the print processor options
1701 * jfm:xxxx send an empty string
1702 ********************************************************************/
1703 static void spoolss_notify_parameters(int snum,
1704 SPOOL_NOTIFY_INFO_DATA *data,
1705 print_queue_struct *queue,
1706 NT_PRINTER_INFO_LEVEL *printer,
1707 TALLOC_CTX *mem_ctx)
1709 pstring temp;
1710 uint32 len;
1712 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp) -
1713 2, 0);
1715 data->notify_data.data.length = len / 2 - 1;
1716 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1718 if (!data->notify_data.data.string) {
1719 data->notify_data.data.length = 0;
1720 return;
1723 memcpy(data->notify_data.data.string, temp, len);
1726 /*******************************************************************
1727 * fill a notify_info_data with the data type
1728 * jfm:xxxx always send RAW as data type
1729 ********************************************************************/
1730 static void spoolss_notify_datatype(int snum,
1731 SPOOL_NOTIFY_INFO_DATA *data,
1732 print_queue_struct *queue,
1733 NT_PRINTER_INFO_LEVEL *printer,
1734 TALLOC_CTX *mem_ctx)
1736 pstring temp;
1737 uint32 len;
1739 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, 0);
1741 data->notify_data.data.length = len / 2 - 1;
1742 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1744 if (!data->notify_data.data.string) {
1745 data->notify_data.data.length = 0;
1746 return;
1749 memcpy(data->notify_data.data.string, temp, len);
1752 /*******************************************************************
1753 * fill a notify_info_data with the security descriptor
1754 * jfm:xxxx send an null pointer to say no security desc
1755 * have to implement security before !
1756 ********************************************************************/
1757 static void spoolss_notify_security_desc(int snum,
1758 SPOOL_NOTIFY_INFO_DATA *data,
1759 print_queue_struct *queue,
1760 NT_PRINTER_INFO_LEVEL *printer,
1761 TALLOC_CTX *mem_ctx)
1763 data->notify_data.data.length=0;
1764 data->notify_data.data.string = NULL;
1767 /*******************************************************************
1768 * fill a notify_info_data with the attributes
1769 * jfm:xxxx a samba printer is always shared
1770 ********************************************************************/
1771 static void spoolss_notify_attributes(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 data->notify_data.value[0] = printer->info_2->attributes;
1780 /*******************************************************************
1781 * fill a notify_info_data with the priority
1782 ********************************************************************/
1783 static void spoolss_notify_priority(int snum,
1784 SPOOL_NOTIFY_INFO_DATA *data,
1785 print_queue_struct *queue,
1786 NT_PRINTER_INFO_LEVEL *printer,
1787 TALLOC_CTX *mem_ctx)
1789 data->notify_data.value[0] = printer->info_2->priority;
1792 /*******************************************************************
1793 * fill a notify_info_data with the default priority
1794 ********************************************************************/
1795 static void spoolss_notify_default_priority(int snum,
1796 SPOOL_NOTIFY_INFO_DATA *data,
1797 print_queue_struct *queue,
1798 NT_PRINTER_INFO_LEVEL *printer,
1799 TALLOC_CTX *mem_ctx)
1801 data->notify_data.value[0] = printer->info_2->default_priority;
1804 /*******************************************************************
1805 * fill a notify_info_data with the start time
1806 ********************************************************************/
1807 static void spoolss_notify_start_time(int snum,
1808 SPOOL_NOTIFY_INFO_DATA *data,
1809 print_queue_struct *queue,
1810 NT_PRINTER_INFO_LEVEL *printer,
1811 TALLOC_CTX *mem_ctx)
1813 data->notify_data.value[0] = printer->info_2->starttime;
1816 /*******************************************************************
1817 * fill a notify_info_data with the until time
1818 ********************************************************************/
1819 static void spoolss_notify_until_time(int snum,
1820 SPOOL_NOTIFY_INFO_DATA *data,
1821 print_queue_struct *queue,
1822 NT_PRINTER_INFO_LEVEL *printer,
1823 TALLOC_CTX *mem_ctx)
1825 data->notify_data.value[0] = printer->info_2->untiltime;
1828 /*******************************************************************
1829 * fill a notify_info_data with the status
1830 ********************************************************************/
1831 static void spoolss_notify_status(int snum,
1832 SPOOL_NOTIFY_INFO_DATA *data,
1833 print_queue_struct *queue,
1834 NT_PRINTER_INFO_LEVEL *printer,
1835 TALLOC_CTX *mem_ctx)
1837 print_queue_struct *q=NULL;
1838 print_status_struct status;
1840 memset(&status, 0, sizeof(status));
1841 print_queue_status(snum, &q, &status);
1842 data->notify_data.value[0]=(uint32) status.status;
1843 safe_free(q);
1846 /*******************************************************************
1847 * fill a notify_info_data with the number of jobs queued
1848 ********************************************************************/
1849 static void spoolss_notify_cjobs(int snum,
1850 SPOOL_NOTIFY_INFO_DATA *data,
1851 print_queue_struct *queue,
1852 NT_PRINTER_INFO_LEVEL *printer,
1853 TALLOC_CTX *mem_ctx)
1855 print_queue_struct *q=NULL;
1856 print_status_struct status;
1858 memset(&status, 0, sizeof(status));
1859 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1860 safe_free(q);
1863 /*******************************************************************
1864 * fill a notify_info_data with the average ppm
1865 ********************************************************************/
1866 static void spoolss_notify_average_ppm(int snum,
1867 SPOOL_NOTIFY_INFO_DATA *data,
1868 print_queue_struct *queue,
1869 NT_PRINTER_INFO_LEVEL *printer,
1870 TALLOC_CTX *mem_ctx)
1872 /* always respond 8 pages per minutes */
1873 /* a little hard ! */
1874 data->notify_data.value[0] = printer->info_2->averageppm;
1877 /*******************************************************************
1878 * fill a notify_info_data with username
1879 ********************************************************************/
1880 static void spoolss_notify_username(int snum,
1881 SPOOL_NOTIFY_INFO_DATA *data,
1882 print_queue_struct *queue,
1883 NT_PRINTER_INFO_LEVEL *printer,
1884 TALLOC_CTX *mem_ctx)
1886 pstring temp;
1887 uint32 len;
1889 len = rpcstr_push(temp, queue->user, sizeof(temp) - 2, 0);
1892 data->notify_data.data.length = len / 2 - 1;
1893 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1895 if (!data->notify_data.data.string) {
1896 data->notify_data.data.length = 0;
1897 return;
1900 memcpy(data->notify_data.data.string, temp, len);
1903 /*******************************************************************
1904 * fill a notify_info_data with job status
1905 ********************************************************************/
1906 static void spoolss_notify_job_status(int snum,
1907 SPOOL_NOTIFY_INFO_DATA *data,
1908 print_queue_struct *queue,
1909 NT_PRINTER_INFO_LEVEL *printer,
1910 TALLOC_CTX *mem_ctx)
1912 data->notify_data.value[0]=nt_printj_status(queue->status);
1915 /*******************************************************************
1916 * fill a notify_info_data with job name
1917 ********************************************************************/
1918 static void spoolss_notify_job_name(int snum,
1919 SPOOL_NOTIFY_INFO_DATA *data,
1920 print_queue_struct *queue,
1921 NT_PRINTER_INFO_LEVEL *printer,
1922 TALLOC_CTX *mem_ctx)
1924 pstring temp;
1925 uint32 len;
1927 len = rpcstr_push(temp, queue->file, sizeof(temp) - 2, 0);
1929 data->notify_data.data.length = len / 2 - 1;
1930 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1932 if (!data->notify_data.data.string) {
1933 data->notify_data.data.length = 0;
1934 return;
1937 memcpy(data->notify_data.data.string, temp, len);
1940 /*******************************************************************
1941 * fill a notify_info_data with job status
1942 ********************************************************************/
1943 static void spoolss_notify_job_status_string(int snum,
1944 SPOOL_NOTIFY_INFO_DATA *data,
1945 print_queue_struct *queue,
1946 NT_PRINTER_INFO_LEVEL *printer,
1947 TALLOC_CTX *mem_ctx)
1950 * Now we're returning job status codes we just return a "" here. JRA.
1953 char *p = "";
1954 pstring temp;
1955 uint32 len;
1957 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1958 p = "unknown";
1960 switch (queue->status) {
1961 case LPQ_QUEUED:
1962 p = "Queued";
1963 break;
1964 case LPQ_PAUSED:
1965 p = ""; /* NT provides the paused string */
1966 break;
1967 case LPQ_SPOOLING:
1968 p = "Spooling";
1969 break;
1970 case LPQ_PRINTING:
1971 p = "Printing";
1972 break;
1974 #endif /* NO LONGER NEEDED. */
1976 len = rpcstr_push(temp, p, sizeof(temp) - 2, 0);
1978 data->notify_data.data.length = len / 2 - 1;
1979 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1981 if (!data->notify_data.data.string) {
1982 data->notify_data.data.length = 0;
1983 return;
1986 memcpy(data->notify_data.data.string, temp, len);
1989 /*******************************************************************
1990 * fill a notify_info_data with job time
1991 ********************************************************************/
1992 static void spoolss_notify_job_time(int snum,
1993 SPOOL_NOTIFY_INFO_DATA *data,
1994 print_queue_struct *queue,
1995 NT_PRINTER_INFO_LEVEL *printer,
1996 TALLOC_CTX *mem_ctx)
1998 data->notify_data.value[0]=0x0;
2001 /*******************************************************************
2002 * fill a notify_info_data with job size
2003 ********************************************************************/
2004 static void spoolss_notify_job_size(int snum,
2005 SPOOL_NOTIFY_INFO_DATA *data,
2006 print_queue_struct *queue,
2007 NT_PRINTER_INFO_LEVEL *printer,
2008 TALLOC_CTX *mem_ctx)
2010 data->notify_data.value[0]=queue->size;
2013 /*******************************************************************
2014 * fill a notify_info_data with job position
2015 ********************************************************************/
2016 static void spoolss_notify_job_position(int snum,
2017 SPOOL_NOTIFY_INFO_DATA *data,
2018 print_queue_struct *queue,
2019 NT_PRINTER_INFO_LEVEL *printer,
2020 TALLOC_CTX *mem_ctx)
2022 data->notify_data.value[0]=queue->job;
2025 /*******************************************************************
2026 * fill a notify_info_data with submitted time
2027 ********************************************************************/
2028 static void spoolss_notify_submitted_time(int snum,
2029 SPOOL_NOTIFY_INFO_DATA *data,
2030 print_queue_struct *queue,
2031 NT_PRINTER_INFO_LEVEL *printer,
2032 TALLOC_CTX *mem_ctx)
2034 struct tm *t;
2035 uint32 len;
2036 SYSTEMTIME st;
2038 t=gmtime(&queue->time);
2040 len = sizeof(SYSTEMTIME);
2042 data->notify_data.data.length = len/2 - 1;
2043 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2045 if (!data->notify_data.data.string) {
2046 data->notify_data.data.length = 0;
2047 return;
2050 make_systemtime(&st, t);
2051 memcpy(data->notify_data.data.string,&st,len);
2054 #define END 65535
2056 struct s_notify_info_data_table
2058 uint16 type;
2059 uint16 field;
2060 char *name;
2061 uint32 size;
2062 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2063 print_queue_struct *queue,
2064 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2067 struct s_notify_info_data_table notify_info_data_table[] =
2069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2095 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2100 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2101 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2102 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2103 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2104 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2105 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2106 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2118 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2119 { END, END, "", END, NULL }
2122 /*******************************************************************
2123 return the size of info_data structure
2124 ********************************************************************/
2125 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2127 int i=0;
2129 while (notify_info_data_table[i].type != END)
2131 if ( (notify_info_data_table[i].type == type ) &&
2132 (notify_info_data_table[i].field == field ) )
2134 return (notify_info_data_table[i].size);
2136 i++;
2138 return (65535);
2141 /*******************************************************************
2142 return the type of notify_info_data
2143 ********************************************************************/
2144 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2146 int i=0;
2148 while (notify_info_data_table[i].type != END)
2150 if ( (notify_info_data_table[i].type == type ) &&
2151 (notify_info_data_table[i].field == field ) )
2153 if (notify_info_data_table[i].size == POINTER)
2155 return (False);
2157 else
2159 return (True);
2162 i++;
2164 return (False);
2167 /****************************************************************************
2168 ****************************************************************************/
2169 static int search_notify(uint16 type, uint16 field, int *value)
2171 int j;
2172 BOOL found;
2174 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2176 if ( (notify_info_data_table[j].type == type ) &&
2177 (notify_info_data_table[j].field == field ) )
2178 found=True;
2180 *value=--j;
2182 if ( found && (notify_info_data_table[j].fn != NULL) )
2183 return True;
2184 else
2185 return False;
2188 /****************************************************************************
2189 ****************************************************************************/
2190 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2192 info_data->type = type;
2193 info_data->field = field;
2194 info_data->reserved = 0;
2195 info_data->id = id;
2196 info_data->size = size_of_notify_info_data(type, field);
2197 info_data->enc_type = type_of_notify_info_data(type, field);
2201 /*******************************************************************
2203 * fill a notify_info struct with info asked
2205 ********************************************************************/
2206 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2207 snum, SPOOL_NOTIFY_OPTION_TYPE
2208 *option_type, uint32 id,
2209 TALLOC_CTX *mem_ctx)
2211 int field_num,j;
2212 uint16 type;
2213 uint16 field;
2215 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2216 NT_PRINTER_INFO_LEVEL *printer = NULL;
2217 print_queue_struct *queue=NULL;
2219 type=option_type->type;
2221 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2222 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2223 option_type->count, lp_servicename(snum)));
2225 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2226 return False;
2228 for(field_num=0; field_num<option_type->count; field_num++) {
2229 field = option_type->fields[field_num];
2230 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2232 if (!search_notify(type, field, &j) )
2233 continue;
2235 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2236 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2237 return False;
2239 else info->data = tid;
2241 current_data=&info->data[info->count];
2243 construct_info_data(current_data, type, field, id);
2245 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2246 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2248 notify_info_data_table[j].fn(snum, current_data, queue,
2249 printer, mem_ctx);
2251 info->count++;
2254 free_a_printer(&printer, 2);
2255 return True;
2258 /*******************************************************************
2260 * fill a notify_info struct with info asked
2262 ********************************************************************/
2263 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2264 SPOOL_NOTIFY_INFO *info,
2265 NT_PRINTER_INFO_LEVEL *printer,
2266 int snum, SPOOL_NOTIFY_OPTION_TYPE
2267 *option_type, uint32 id,
2268 TALLOC_CTX *mem_ctx)
2270 int field_num,j;
2271 uint16 type;
2272 uint16 field;
2274 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2276 DEBUG(4,("construct_notify_jobs_info\n"));
2278 type = option_type->type;
2280 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2281 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2282 option_type->count));
2284 for(field_num=0; field_num<option_type->count; field_num++) {
2285 field = option_type->fields[field_num];
2287 if (!search_notify(type, field, &j) )
2288 continue;
2290 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2291 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2292 return False;
2294 else info->data = tid;
2296 current_data=&(info->data[info->count]);
2298 construct_info_data(current_data, type, field, id);
2299 notify_info_data_table[j].fn(snum, current_data, queue,
2300 printer, mem_ctx);
2301 info->count++;
2304 return True;
2308 * JFM: The enumeration is not that simple, it's even non obvious.
2310 * let's take an example: I want to monitor the PRINTER SERVER for
2311 * the printer's name and the number of jobs currently queued.
2312 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2313 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2315 * I have 3 printers on the back of my server.
2317 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2318 * structures.
2319 * Number Data Id
2320 * 1 printer 1 name 1
2321 * 2 printer 1 cjob 1
2322 * 3 printer 2 name 2
2323 * 4 printer 2 cjob 2
2324 * 5 printer 3 name 3
2325 * 6 printer 3 name 3
2327 * that's the print server case, the printer case is even worse.
2330 /*******************************************************************
2332 * enumerate all printers on the printserver
2333 * fill a notify_info struct with info asked
2335 ********************************************************************/
2337 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2338 SPOOL_NOTIFY_INFO *info,
2339 TALLOC_CTX *mem_ctx)
2341 int snum;
2342 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2343 int n_services=lp_numservices();
2344 int i;
2345 uint32 id;
2346 SPOOL_NOTIFY_OPTION *option;
2347 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2349 DEBUG(4,("printserver_notify_info\n"));
2351 option=Printer->notify.option;
2352 id=1;
2353 info->version=2;
2354 info->data=NULL;
2355 info->count=0;
2357 for (i=0; i<option->count; i++) {
2358 option_type=&(option->ctr.type[i]);
2360 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2361 continue;
2363 for (snum=0; snum<n_services; snum++)
2364 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2365 if (construct_notify_printer_info
2366 (info, snum, option_type, id, mem_ctx))
2367 id++;
2371 * Debugging information, don't delete.
2374 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2375 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2376 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2378 for (i=0; i<info->count; i++) {
2379 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2380 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2381 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2385 return WERR_OK;
2388 /*******************************************************************
2390 * fill a notify_info struct with info asked
2392 ********************************************************************/
2393 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2394 TALLOC_CTX *mem_ctx)
2396 int snum;
2397 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2398 int i;
2399 uint32 id;
2400 SPOOL_NOTIFY_OPTION *option;
2401 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2402 int count,j;
2403 print_queue_struct *queue=NULL;
2404 print_status_struct status;
2406 DEBUG(4,("printer_notify_info\n"));
2408 option=Printer->notify.option;
2409 id=0xffffffff;
2410 info->version=2;
2411 info->data=NULL;
2412 info->count=0;
2414 get_printer_snum(p, hnd, &snum);
2416 for (i=0; i<option->count; i++) {
2417 option_type=&option->ctr.type[i];
2419 switch ( option_type->type ) {
2420 case PRINTER_NOTIFY_TYPE:
2421 if(construct_notify_printer_info(info, snum,
2422 option_type, id,
2423 mem_ctx))
2424 id--;
2425 break;
2427 case JOB_NOTIFY_TYPE: {
2428 NT_PRINTER_INFO_LEVEL *printer = NULL;
2430 memset(&status, 0, sizeof(status));
2431 count = print_queue_status(snum, &queue, &status);
2433 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2434 lp_servicename(snum))))
2435 goto done;
2437 for (j=0; j<count; j++) {
2438 construct_notify_jobs_info(&queue[j], info,
2439 printer, snum,
2440 option_type,
2441 queue[j].job,
2442 mem_ctx);
2445 free_a_printer(&printer, 2);
2447 done:
2448 safe_free(queue);
2449 break;
2455 * Debugging information, don't delete.
2458 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2459 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2460 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2462 for (i=0; i<info->count; i++) {
2463 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2464 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2465 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2468 return WERR_OK;
2471 /********************************************************************
2472 * spoolss_rfnpcnex
2473 ********************************************************************/
2475 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2477 POLICY_HND *handle = &q_u->handle;
2478 /* uint32 change = q_u->change; - notused. */
2479 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2480 SPOOL_NOTIFY_INFO *info = &r_u->info;
2482 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2483 WERROR result = WERR_BADFID;
2485 /* we always have a NOTIFY_INFO struct */
2486 r_u->info_ptr=0x1;
2488 if (!Printer) {
2489 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2490 OUR_HANDLE(handle)));
2491 goto done;
2494 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2496 /* jfm: the change value isn't used right now.
2497 * we will honour it when
2498 * a) we'll be able to send notification to the client
2499 * b) we'll have a way to communicate between the spoolss process.
2501 * same thing for option->flags
2502 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2503 * I don't have a global notification system, I'm sending back all the
2504 * informations even when _NOTHING_ has changed.
2507 /* just ignore the SPOOL_NOTIFY_OPTION */
2509 switch (Printer->printer_type) {
2510 case PRINTER_HANDLE_IS_PRINTSERVER:
2511 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2512 break;
2514 case PRINTER_HANDLE_IS_PRINTER:
2515 result = printer_notify_info(p, handle, info, p->mem_ctx);
2516 break;
2519 done:
2520 return result;
2523 /********************************************************************
2524 * construct_printer_info_0
2525 * fill a printer_info_0 struct
2526 ********************************************************************/
2527 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2529 pstring chaine;
2530 int count;
2531 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2532 counter_printer_0 *session_counter;
2533 uint32 global_counter;
2534 struct tm *t;
2535 time_t setuptime;
2537 print_queue_struct *queue=NULL;
2538 print_status_struct status;
2540 memset(&status, 0, sizeof(status));
2542 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2543 return False;
2545 count = print_queue_status(snum, &queue, &status);
2547 /* check if we already have a counter for this printer */
2548 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2550 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2551 if (session_counter->snum == snum)
2552 break;
2555 /* it's the first time, add it to the list */
2556 if (session_counter==NULL) {
2557 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2558 free_a_printer(&ntprinter, 2);
2559 return False;
2561 ZERO_STRUCTP(session_counter);
2562 session_counter->snum=snum;
2563 session_counter->counter=0;
2564 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2567 /* increment it */
2568 session_counter->counter++;
2570 /* JFM:
2571 * the global_counter should be stored in a TDB as it's common to all the clients
2572 * and should be zeroed on samba startup
2574 global_counter=session_counter->counter;
2576 pstrcpy(chaine,ntprinter->info_2->printername);
2578 init_unistr(&printer->printername, chaine);
2580 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2581 init_unistr(&printer->servername, chaine);
2583 printer->cjobs = count;
2584 printer->total_jobs = 0;
2585 printer->total_bytes = 0;
2587 setuptime = (time_t)ntprinter->info_2->setuptime;
2588 t=gmtime(&setuptime);
2590 printer->year = t->tm_year+1900;
2591 printer->month = t->tm_mon+1;
2592 printer->dayofweek = t->tm_wday;
2593 printer->day = t->tm_mday;
2594 printer->hour = t->tm_hour;
2595 printer->minute = t->tm_min;
2596 printer->second = t->tm_sec;
2597 printer->milliseconds = 0;
2599 printer->global_counter = global_counter;
2600 printer->total_pages = 0;
2601 printer->major_version = 0x0004; /* NT 4 */
2602 printer->build_version = 0x0565; /* build 1381 */
2603 printer->unknown7 = 0x1;
2604 printer->unknown8 = 0x0;
2605 printer->unknown9 = 0x0;
2606 printer->session_counter = session_counter->counter;
2607 printer->unknown11 = 0x0;
2608 printer->printer_errors = 0x0; /* number of print failure */
2609 printer->unknown13 = 0x0;
2610 printer->unknown14 = 0x1;
2611 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2612 printer->unknown16 = 0x0;
2613 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2614 printer->unknown18 = 0x0;
2615 printer->status = nt_printq_status(status.status);
2616 printer->unknown20 = 0x0;
2617 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2618 printer->unknown22 = 0x0;
2619 printer->unknown23 = 0x6; /* 6 ???*/
2620 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2621 printer->unknown25 = 0;
2622 printer->unknown26 = 0;
2623 printer->unknown27 = 0;
2624 printer->unknown28 = 0;
2625 printer->unknown29 = 0;
2627 safe_free(queue);
2628 free_a_printer(&ntprinter,2);
2629 return (True);
2632 /********************************************************************
2633 * construct_printer_info_1
2634 * fill a printer_info_1 struct
2635 ********************************************************************/
2636 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2638 pstring chaine;
2639 pstring chaine2;
2640 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2642 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2643 return False;
2645 printer->flags=flags;
2647 if (*ntprinter->info_2->comment == '\0') {
2648 init_unistr(&printer->comment, lp_comment(snum));
2649 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2650 ntprinter->info_2->drivername, lp_comment(snum));
2652 else {
2653 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2654 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2655 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2658 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2660 init_unistr(&printer->description, chaine);
2661 init_unistr(&printer->name, chaine2);
2663 free_a_printer(&ntprinter,2);
2665 return True;
2668 /****************************************************************************
2669 Free a DEVMODE struct.
2670 ****************************************************************************/
2672 static void free_dev_mode(DEVICEMODE *dev)
2674 if (dev == NULL)
2675 return;
2677 if (dev->private)
2678 safe_free(dev->private);
2680 safe_free(dev);
2683 /****************************************************************************
2684 Create a DEVMODE struct. Returns malloced memory.
2685 ****************************************************************************/
2687 static DEVICEMODE *construct_dev_mode(int snum)
2689 char adevice[32];
2690 char aform[32];
2691 NT_PRINTER_INFO_LEVEL *printer = NULL;
2692 NT_DEVICEMODE *ntdevmode = NULL;
2693 DEVICEMODE *devmode = NULL;
2695 DEBUG(7,("construct_dev_mode\n"));
2697 DEBUGADD(8,("getting printer characteristics\n"));
2699 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2700 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2701 return NULL;
2704 ZERO_STRUCTP(devmode);
2706 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2707 goto fail;
2709 if (printer->info_2->devmode)
2710 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2712 if (ntdevmode == NULL)
2713 goto fail;
2715 DEBUGADD(8,("loading DEVICEMODE\n"));
2717 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2718 init_unistr(&devmode->devicename, adevice);
2720 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2721 init_unistr(&devmode->formname, aform);
2723 devmode->specversion = ntdevmode->specversion;
2724 devmode->driverversion = ntdevmode->driverversion;
2725 devmode->size = ntdevmode->size;
2726 devmode->driverextra = ntdevmode->driverextra;
2727 devmode->fields = ntdevmode->fields;
2729 devmode->orientation = ntdevmode->orientation;
2730 devmode->papersize = ntdevmode->papersize;
2731 devmode->paperlength = ntdevmode->paperlength;
2732 devmode->paperwidth = ntdevmode->paperwidth;
2733 devmode->scale = ntdevmode->scale;
2734 devmode->copies = ntdevmode->copies;
2735 devmode->defaultsource = ntdevmode->defaultsource;
2736 devmode->printquality = ntdevmode->printquality;
2737 devmode->color = ntdevmode->color;
2738 devmode->duplex = ntdevmode->duplex;
2739 devmode->yresolution = ntdevmode->yresolution;
2740 devmode->ttoption = ntdevmode->ttoption;
2741 devmode->collate = ntdevmode->collate;
2742 devmode->icmmethod = ntdevmode->icmmethod;
2743 devmode->icmintent = ntdevmode->icmintent;
2744 devmode->mediatype = ntdevmode->mediatype;
2745 devmode->dithertype = ntdevmode->dithertype;
2747 if (ntdevmode->private != NULL) {
2748 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2749 goto fail;
2752 free_nt_devicemode(&ntdevmode);
2753 free_a_printer(&printer,2);
2755 return devmode;
2757 fail:
2759 if (ntdevmode)
2760 free_nt_devicemode(&ntdevmode);
2761 if (printer)
2762 free_a_printer(&printer,2);
2763 free_dev_mode(devmode);
2765 return NULL;
2768 /********************************************************************
2769 * construct_printer_info_2
2770 * fill a printer_info_2 struct
2771 ********************************************************************/
2773 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2775 int count;
2776 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2778 print_queue_struct *queue=NULL;
2779 print_status_struct status;
2780 memset(&status, 0, sizeof(status));
2782 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2783 return False;
2785 memset(&status, 0, sizeof(status));
2786 count = print_queue_status(snum, &queue, &status);
2788 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2789 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2790 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2791 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2792 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2794 if (*ntprinter->info_2->comment == '\0')
2795 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2796 else
2797 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2799 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2800 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2801 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2802 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2803 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2805 printer->attributes = ntprinter->info_2->attributes;
2807 printer->priority = ntprinter->info_2->priority; /* priority */
2808 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2809 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2810 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2811 printer->status = nt_printq_status(status.status); /* status */
2812 printer->cjobs = count; /* jobs */
2813 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2815 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2816 DEBUG(8, ("Returning NULL Devicemode!\n"));
2819 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2820 /* steal the printer info sec_desc structure. [badly done]. */
2821 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2822 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2823 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2824 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2826 else {
2827 printer->secdesc = NULL;
2830 free_a_printer(&ntprinter, 2);
2831 safe_free(queue);
2832 return True;
2835 /********************************************************************
2836 * construct_printer_info_3
2837 * fill a printer_info_3 struct
2838 ********************************************************************/
2839 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2841 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2842 PRINTER_INFO_3 *printer = NULL;
2844 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2845 return False;
2847 *pp_printer = NULL;
2848 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2849 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2850 return False;
2853 ZERO_STRUCTP(printer);
2855 printer->flags = 4; /* These are the components of the SD we are returning. */
2856 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2857 /* steal the printer info sec_desc structure. [badly done]. */
2858 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2860 #if 0
2862 * Set the flags for the components we are returning.
2865 if (printer->secdesc->owner_sid)
2866 printer->flags |= OWNER_SECURITY_INFORMATION;
2868 if (printer->secdesc->grp_sid)
2869 printer->flags |= GROUP_SECURITY_INFORMATION;
2871 if (printer->secdesc->dacl)
2872 printer->flags |= DACL_SECURITY_INFORMATION;
2874 if (printer->secdesc->sacl)
2875 printer->flags |= SACL_SECURITY_INFORMATION;
2876 #endif
2878 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2879 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2880 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2883 free_a_printer(&ntprinter, 2);
2885 *pp_printer = printer;
2886 return True;
2889 /********************************************************************
2890 Spoolss_enumprinters.
2891 ********************************************************************/
2892 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2894 int snum;
2895 int i;
2896 int n_services=lp_numservices();
2897 PRINTER_INFO_1 *tp, *printers=NULL;
2898 PRINTER_INFO_1 current_prt;
2900 DEBUG(4,("enum_all_printers_info_1\n"));
2902 for (snum=0; snum<n_services; snum++) {
2903 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2904 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2906 if (construct_printer_info_1(flags, &current_prt, snum)) {
2907 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2908 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2909 safe_free(printers);
2910 *returned=0;
2911 return WERR_NOMEM;
2913 else printers = tp;
2914 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2915 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2916 (*returned)++;
2921 /* check the required size. */
2922 for (i=0; i<*returned; i++)
2923 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2925 if (!alloc_buffer_size(buffer, *needed))
2926 return WERR_INSUFFICIENT_BUFFER;
2928 /* fill the buffer with the structures */
2929 for (i=0; i<*returned; i++)
2930 smb_io_printer_info_1("", buffer, &printers[i], 0);
2932 /* clear memory */
2933 safe_free(printers);
2935 if (*needed > offered) {
2936 *returned=0;
2937 return WERR_INSUFFICIENT_BUFFER;
2939 else
2940 return WERR_OK;
2943 /********************************************************************
2944 enum_all_printers_info_1_local.
2945 *********************************************************************/
2946 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2948 DEBUG(4,("enum_all_printers_info_1_local\n"));
2950 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2953 /********************************************************************
2954 enum_all_printers_info_1_name.
2955 *********************************************************************/
2956 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2958 fstring temp;
2959 DEBUG(4,("enum_all_printers_info_1_name\n"));
2961 fstrcpy(temp, "\\\\");
2962 fstrcat(temp, global_myname);
2964 if (strequal(name, temp)) {
2965 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2967 else
2968 return WERR_INVALID_NAME;
2971 /********************************************************************
2972 enum_all_printers_info_1_remote.
2973 *********************************************************************/
2974 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2976 PRINTER_INFO_1 *printer;
2977 fstring printername;
2978 fstring desc;
2979 fstring comment;
2980 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2982 /* JFM: currently it's more a place holder than anything else.
2983 * In the spooler world there is a notion of server registration.
2984 * the print servers are registring (sp ?) on the PDC (in the same domain)
2986 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2989 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2990 return WERR_NOMEM;
2992 *returned=1;
2994 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2995 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2996 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2998 init_unistr(&printer->description, desc);
2999 init_unistr(&printer->name, printername);
3000 init_unistr(&printer->comment, comment);
3001 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3003 /* check the required size. */
3004 *needed += spoolss_size_printer_info_1(printer);
3006 if (!alloc_buffer_size(buffer, *needed)) {
3007 safe_free(printer);
3008 return WERR_INSUFFICIENT_BUFFER;
3011 /* fill the buffer with the structures */
3012 smb_io_printer_info_1("", buffer, printer, 0);
3014 /* clear memory */
3015 safe_free(printer);
3017 if (*needed > offered) {
3018 *returned=0;
3019 return WERR_INSUFFICIENT_BUFFER;
3021 else
3022 return WERR_OK;
3025 /********************************************************************
3026 enum_all_printers_info_1_network.
3027 *********************************************************************/
3029 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3031 DEBUG(4,("enum_all_printers_info_1_network\n"));
3033 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3036 /********************************************************************
3037 * api_spoolss_enumprinters
3039 * called from api_spoolss_enumprinters (see this to understand)
3040 ********************************************************************/
3042 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3044 int snum;
3045 int i;
3046 int n_services=lp_numservices();
3047 PRINTER_INFO_2 *tp, *printers=NULL;
3048 PRINTER_INFO_2 current_prt;
3050 for (snum=0; snum<n_services; snum++) {
3051 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3052 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3054 if (construct_printer_info_2(&current_prt, snum)) {
3055 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3056 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3057 safe_free(printers);
3058 *returned = 0;
3059 return WERR_NOMEM;
3061 else printers = tp;
3062 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3063 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3064 (*returned)++;
3069 /* check the required size. */
3070 for (i=0; i<*returned; i++)
3071 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3073 if (!alloc_buffer_size(buffer, *needed)) {
3074 for (i=0; i<*returned; i++) {
3075 free_devmode(printers[i].devmode);
3077 safe_free(printers);
3078 return WERR_INSUFFICIENT_BUFFER;
3081 /* fill the buffer with the structures */
3082 for (i=0; i<*returned; i++)
3083 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3085 /* clear memory */
3086 for (i=0; i<*returned; i++) {
3087 free_devmode(printers[i].devmode);
3089 safe_free(printers);
3091 if (*needed > offered) {
3092 *returned=0;
3093 return WERR_INSUFFICIENT_BUFFER;
3095 else
3096 return WERR_OK;
3099 /********************************************************************
3100 * handle enumeration of printers at level 1
3101 ********************************************************************/
3102 static WERROR enumprinters_level1( uint32 flags, fstring name,
3103 NEW_BUFFER *buffer, uint32 offered,
3104 uint32 *needed, uint32 *returned)
3106 /* Not all the flags are equals */
3108 if (flags & PRINTER_ENUM_LOCAL)
3109 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3111 if (flags & PRINTER_ENUM_NAME)
3112 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3114 if (flags & PRINTER_ENUM_REMOTE)
3115 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3117 if (flags & PRINTER_ENUM_NETWORK)
3118 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3120 return WERR_OK; /* NT4sp5 does that */
3123 /********************************************************************
3124 * handle enumeration of printers at level 2
3125 ********************************************************************/
3126 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3127 NEW_BUFFER *buffer, uint32 offered,
3128 uint32 *needed, uint32 *returned)
3130 fstring temp;
3132 fstrcpy(temp, "\\\\");
3133 fstrcat(temp, global_myname);
3135 if (flags & PRINTER_ENUM_LOCAL) {
3136 if (strequal(servername, temp))
3137 return enum_all_printers_info_2(buffer, offered, needed, returned);
3138 else
3139 return enum_all_printers_info_2(buffer, offered, needed, returned);
3142 if (flags & PRINTER_ENUM_NAME) {
3143 if (strequal(servername, temp))
3144 return enum_all_printers_info_2(buffer, offered, needed, returned);
3145 else
3146 return WERR_INVALID_NAME;
3149 if (flags & PRINTER_ENUM_REMOTE)
3150 return WERR_UNKNOWN_LEVEL;
3152 return WERR_OK;
3155 /********************************************************************
3156 * handle enumeration of printers at level 5
3157 ********************************************************************/
3158 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3159 NEW_BUFFER *buffer, uint32 offered,
3160 uint32 *needed, uint32 *returned)
3162 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3163 return WERR_OK;
3166 /********************************************************************
3167 * api_spoolss_enumprinters
3169 * called from api_spoolss_enumprinters (see this to understand)
3170 ********************************************************************/
3172 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3174 uint32 flags = q_u->flags;
3175 UNISTR2 *servername = &q_u->servername;
3176 uint32 level = q_u->level;
3177 NEW_BUFFER *buffer = NULL;
3178 uint32 offered = q_u->offered;
3179 uint32 *needed = &r_u->needed;
3180 uint32 *returned = &r_u->returned;
3181 fstring name;
3183 /* that's an [in out] buffer */
3184 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3185 buffer = r_u->buffer;
3187 DEBUG(4,("_spoolss_enumprinters\n"));
3189 *needed=0;
3190 *returned=0;
3193 * Level 1:
3194 * flags==PRINTER_ENUM_NAME
3195 * if name=="" then enumerates all printers
3196 * if name!="" then enumerate the printer
3197 * flags==PRINTER_ENUM_REMOTE
3198 * name is NULL, enumerate printers
3199 * Level 2: name!="" enumerates printers, name can't be NULL
3200 * Level 3: doesn't exist
3201 * Level 4: does a local registry lookup
3202 * Level 5: same as Level 2
3205 unistr2_to_ascii(name, servername, sizeof(name)-1);
3206 strupper(name);
3208 switch (level) {
3209 case 1:
3210 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3211 case 2:
3212 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3213 case 5:
3214 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3215 case 3:
3216 case 4:
3217 break;
3219 return WERR_UNKNOWN_LEVEL;
3222 /****************************************************************************
3223 ****************************************************************************/
3224 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3226 PRINTER_INFO_0 *printer=NULL;
3228 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3229 return WERR_NOMEM;
3231 construct_printer_info_0(printer, snum);
3233 /* check the required size. */
3234 *needed += spoolss_size_printer_info_0(printer);
3236 if (!alloc_buffer_size(buffer, *needed)) {
3237 safe_free(printer);
3238 return WERR_INSUFFICIENT_BUFFER;
3241 /* fill the buffer with the structures */
3242 smb_io_printer_info_0("", buffer, printer, 0);
3244 /* clear memory */
3245 safe_free(printer);
3247 if (*needed > offered) {
3248 return WERR_INSUFFICIENT_BUFFER;
3251 return WERR_OK;
3254 /****************************************************************************
3255 ****************************************************************************/
3256 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3258 PRINTER_INFO_1 *printer=NULL;
3260 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3261 return WERR_NOMEM;
3263 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3265 /* check the required size. */
3266 *needed += spoolss_size_printer_info_1(printer);
3268 if (!alloc_buffer_size(buffer, *needed)) {
3269 safe_free(printer);
3270 return WERR_INSUFFICIENT_BUFFER;
3273 /* fill the buffer with the structures */
3274 smb_io_printer_info_1("", buffer, printer, 0);
3276 /* clear memory */
3277 safe_free(printer);
3279 if (*needed > offered) {
3280 return WERR_INSUFFICIENT_BUFFER;
3283 return WERR_OK;
3286 /****************************************************************************
3287 ****************************************************************************/
3288 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3290 PRINTER_INFO_2 *printer=NULL;
3292 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3293 return WERR_NOMEM;
3295 construct_printer_info_2(printer, snum);
3297 /* check the required size. */
3298 *needed += spoolss_size_printer_info_2(printer);
3300 if (!alloc_buffer_size(buffer, *needed)) {
3301 free_printer_info_2(printer);
3302 return WERR_INSUFFICIENT_BUFFER;
3305 /* fill the buffer with the structures */
3306 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3307 free_printer_info_2(printer);
3308 return WERR_NOMEM;
3311 /* clear memory */
3312 free_printer_info_2(printer);
3314 if (*needed > offered) {
3315 return WERR_INSUFFICIENT_BUFFER;
3318 return WERR_OK;
3321 /****************************************************************************
3322 ****************************************************************************/
3323 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3325 PRINTER_INFO_3 *printer=NULL;
3327 if (!construct_printer_info_3(&printer, snum))
3328 return WERR_NOMEM;
3330 /* check the required size. */
3331 *needed += spoolss_size_printer_info_3(printer);
3333 if (!alloc_buffer_size(buffer, *needed)) {
3334 free_printer_info_3(printer);
3335 return WERR_INSUFFICIENT_BUFFER;
3338 /* fill the buffer with the structures */
3339 smb_io_printer_info_3("", buffer, printer, 0);
3341 /* clear memory */
3342 free_printer_info_3(printer);
3344 if (*needed > offered) {
3345 return WERR_INSUFFICIENT_BUFFER;
3348 return WERR_OK;
3351 /****************************************************************************
3352 ****************************************************************************/
3354 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3356 POLICY_HND *handle = &q_u->handle;
3357 uint32 level = q_u->level;
3358 NEW_BUFFER *buffer = NULL;
3359 uint32 offered = q_u->offered;
3360 uint32 *needed = &r_u->needed;
3362 int snum;
3364 /* that's an [in out] buffer */
3365 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3366 buffer = r_u->buffer;
3368 *needed=0;
3370 if (!get_printer_snum(p, handle, &snum))
3371 return WERR_BADFID;
3373 switch (level) {
3374 case 0:
3375 return getprinter_level_0(snum, buffer, offered, needed);
3376 case 1:
3377 return getprinter_level_1(snum, buffer, offered, needed);
3378 case 2:
3379 return getprinter_level_2(snum, buffer, offered, needed);
3380 case 3:
3381 return getprinter_level_3(snum, buffer, offered, needed);
3383 return WERR_UNKNOWN_LEVEL;
3386 /********************************************************************
3387 * fill a DRIVER_INFO_1 struct
3388 ********************************************************************/
3389 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3391 init_unistr( &info->name, driver.info_3->name);
3394 /********************************************************************
3395 * construct_printer_driver_info_1
3396 ********************************************************************/
3397 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3399 NT_PRINTER_INFO_LEVEL *printer = NULL;
3400 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3402 ZERO_STRUCT(driver);
3404 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3405 return WERR_INVALID_PRINTER_NAME;
3407 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3408 return WERR_UNKNOWN_PRINTER_DRIVER;
3410 fill_printer_driver_info_1(info, driver, servername, architecture);
3412 free_a_printer(&printer,2);
3414 return WERR_OK;
3417 /********************************************************************
3418 * construct_printer_driver_info_2
3419 * fill a printer_info_2 struct
3420 ********************************************************************/
3421 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3423 pstring temp;
3425 info->version=driver.info_3->cversion;
3427 init_unistr( &info->name, driver.info_3->name );
3428 init_unistr( &info->architecture, driver.info_3->environment );
3431 if (strlen(driver.info_3->driverpath)) {
3432 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3433 init_unistr( &info->driverpath, temp );
3434 } else
3435 init_unistr( &info->driverpath, "" );
3437 if (strlen(driver.info_3->datafile)) {
3438 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3439 init_unistr( &info->datafile, temp );
3440 } else
3441 init_unistr( &info->datafile, "" );
3443 if (strlen(driver.info_3->configfile)) {
3444 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3445 init_unistr( &info->configfile, temp );
3446 } else
3447 init_unistr( &info->configfile, "" );
3450 /********************************************************************
3451 * construct_printer_driver_info_2
3452 * fill a printer_info_2 struct
3453 ********************************************************************/
3454 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3456 NT_PRINTER_INFO_LEVEL *printer = NULL;
3457 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3459 ZERO_STRUCT(printer);
3460 ZERO_STRUCT(driver);
3462 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3463 return WERR_INVALID_PRINTER_NAME;
3465 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3466 return WERR_UNKNOWN_PRINTER_DRIVER;
3468 fill_printer_driver_info_2(info, driver, servername);
3470 free_a_printer(&printer,2);
3472 return WERR_OK;
3475 /********************************************************************
3476 * copy a strings array and convert to UNICODE
3478 * convert an array of ascii string to a UNICODE string
3479 ********************************************************************/
3480 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3482 int i=0;
3483 int j=0;
3484 char *v;
3485 pstring line;
3486 uint16 *tuary;
3488 DEBUG(6,("init_unistr_array\n"));
3489 *uni_array=NULL;
3491 while (1) {
3492 if (char_array == NULL)
3493 v = "";
3494 else {
3495 v = char_array[i];
3496 if (!v) v = ""; /* hack to handle null lists */
3498 if (strlen(v) == 0) break;
3499 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3500 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3501 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3502 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3503 return;
3505 else *uni_array = tuary;
3506 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3507 i++;
3510 if (*uni_array) {
3511 (*uni_array)[j]=0x0000;
3514 DEBUGADD(6,("last one:done\n"));
3517 /********************************************************************
3518 * construct_printer_info_3
3519 * fill a printer_info_3 struct
3520 ********************************************************************/
3521 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3523 pstring temp;
3525 ZERO_STRUCTP(info);
3527 info->version=driver.info_3->cversion;
3529 init_unistr( &info->name, driver.info_3->name );
3530 init_unistr( &info->architecture, driver.info_3->environment );
3532 if (strlen(driver.info_3->driverpath)) {
3533 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3534 init_unistr( &info->driverpath, temp );
3535 } else
3536 init_unistr( &info->driverpath, "" );
3538 if (strlen(driver.info_3->datafile)) {
3539 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3540 init_unistr( &info->datafile, temp );
3541 } else
3542 init_unistr( &info->datafile, "" );
3544 if (strlen(driver.info_3->configfile)) {
3545 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3546 init_unistr( &info->configfile, temp );
3547 } else
3548 init_unistr( &info->configfile, "" );
3550 if (strlen(driver.info_3->helpfile)) {
3551 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3552 init_unistr( &info->helpfile, temp );
3553 } else
3554 init_unistr( &info->helpfile, "" );
3556 init_unistr( &info->monitorname, driver.info_3->monitorname );
3557 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3559 info->dependentfiles=NULL;
3560 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3563 /********************************************************************
3564 * construct_printer_info_3
3565 * fill a printer_info_3 struct
3566 ********************************************************************/
3567 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3569 NT_PRINTER_INFO_LEVEL *printer = NULL;
3570 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3571 WERROR status;
3572 ZERO_STRUCT(driver);
3574 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3575 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3576 if (!W_ERROR_IS_OK(status))
3577 return WERR_INVALID_PRINTER_NAME;
3579 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3580 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3581 if (!W_ERROR_IS_OK(status)) {
3582 free_a_printer(&printer,2);
3583 return WERR_UNKNOWN_PRINTER_DRIVER;
3586 fill_printer_driver_info_3(info, driver, servername);
3588 free_a_printer(&printer,2);
3590 return WERR_OK;
3593 /********************************************************************
3594 * construct_printer_info_6
3595 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3596 ********************************************************************/
3598 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3600 pstring temp;
3601 fstring nullstr;
3603 ZERO_STRUCTP(info);
3604 memset(&nullstr, '\0', sizeof(fstring));
3606 info->version=driver.info_3->cversion;
3608 init_unistr( &info->name, driver.info_3->name );
3609 init_unistr( &info->architecture, driver.info_3->environment );
3611 if (strlen(driver.info_3->driverpath)) {
3612 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3613 init_unistr( &info->driverpath, temp );
3614 } else
3615 init_unistr( &info->driverpath, "" );
3617 if (strlen(driver.info_3->datafile)) {
3618 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3619 init_unistr( &info->datafile, temp );
3620 } else
3621 init_unistr( &info->datafile, "" );
3623 if (strlen(driver.info_3->configfile)) {
3624 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3625 init_unistr( &info->configfile, temp );
3626 } else
3627 init_unistr( &info->configfile, "" );
3629 if (strlen(driver.info_3->helpfile)) {
3630 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3631 init_unistr( &info->helpfile, temp );
3632 } else
3633 init_unistr( &info->helpfile, "" );
3635 init_unistr( &info->monitorname, driver.info_3->monitorname );
3636 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3638 info->dependentfiles=NULL;
3639 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3641 info->previousdrivernames=NULL;
3642 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3644 info->driver_date.low=0;
3645 info->driver_date.high=0;
3647 info->padding=0;
3648 info->driver_version_low=0;
3649 info->driver_version_high=0;
3651 init_unistr( &info->mfgname, "");
3652 init_unistr( &info->oem_url, "");
3653 init_unistr( &info->hardware_id, "");
3654 init_unistr( &info->provider, "");
3657 /********************************************************************
3658 * construct_printer_info_6
3659 * fill a printer_info_6 struct
3660 ********************************************************************/
3661 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3663 NT_PRINTER_INFO_LEVEL *printer = NULL;
3664 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3665 WERROR status;
3666 ZERO_STRUCT(driver);
3668 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3669 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3670 if (!W_ERROR_IS_OK(status))
3671 return WERR_INVALID_PRINTER_NAME;
3673 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3674 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3675 if (!W_ERROR_IS_OK(status)) {
3677 * Is this a W2k client ?
3680 if (version < 3) {
3681 free_a_printer(&printer,2);
3682 return WERR_UNKNOWN_PRINTER_DRIVER;
3685 /* Yes - try again with a WinNT driver. */
3686 version = 2;
3687 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3688 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3689 if (!W_ERROR_IS_OK(status)) {
3690 free_a_printer(&printer,2);
3691 return WERR_UNKNOWN_PRINTER_DRIVER;
3695 fill_printer_driver_info_6(info, driver, servername);
3697 free_a_printer(&printer,2);
3699 return WERR_OK;
3702 /****************************************************************************
3703 ****************************************************************************/
3705 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3707 safe_free(info->dependentfiles);
3710 /****************************************************************************
3711 ****************************************************************************/
3713 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3715 safe_free(info->dependentfiles);
3719 /****************************************************************************
3720 ****************************************************************************/
3721 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3723 DRIVER_INFO_1 *info=NULL;
3724 WERROR status;
3726 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3727 return WERR_NOMEM;
3729 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3730 if (!W_ERROR_IS_OK(status)) {
3731 safe_free(info);
3732 return status;
3735 /* check the required size. */
3736 *needed += spoolss_size_printer_driver_info_1(info);
3738 if (!alloc_buffer_size(buffer, *needed)) {
3739 safe_free(info);
3740 return WERR_INSUFFICIENT_BUFFER;
3743 /* fill the buffer with the structures */
3744 smb_io_printer_driver_info_1("", buffer, info, 0);
3746 /* clear memory */
3747 safe_free(info);
3749 if (*needed > offered)
3750 return WERR_INSUFFICIENT_BUFFER;
3752 return WERR_OK;
3755 /****************************************************************************
3756 ****************************************************************************/
3757 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3759 DRIVER_INFO_2 *info=NULL;
3760 WERROR status;
3762 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3763 return WERR_NOMEM;
3765 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3766 if (!W_ERROR_IS_OK(status)) {
3767 safe_free(info);
3768 return status;
3771 /* check the required size. */
3772 *needed += spoolss_size_printer_driver_info_2(info);
3774 if (!alloc_buffer_size(buffer, *needed)) {
3775 safe_free(info);
3776 return WERR_INSUFFICIENT_BUFFER;
3779 /* fill the buffer with the structures */
3780 smb_io_printer_driver_info_2("", buffer, info, 0);
3782 /* clear memory */
3783 safe_free(info);
3785 if (*needed > offered)
3786 return WERR_INSUFFICIENT_BUFFER;
3788 return WERR_OK;
3791 /****************************************************************************
3792 ****************************************************************************/
3793 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3795 DRIVER_INFO_3 info;
3796 WERROR status;
3798 ZERO_STRUCT(info);
3800 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3801 if (!W_ERROR_IS_OK(status)) {
3802 return status;
3805 /* check the required size. */
3806 *needed += spoolss_size_printer_driver_info_3(&info);
3808 if (!alloc_buffer_size(buffer, *needed)) {
3809 free_printer_driver_info_3(&info);
3810 return WERR_INSUFFICIENT_BUFFER;
3813 /* fill the buffer with the structures */
3814 smb_io_printer_driver_info_3("", buffer, &info, 0);
3816 free_printer_driver_info_3(&info);
3818 if (*needed > offered)
3819 return WERR_INSUFFICIENT_BUFFER;
3821 return WERR_OK;
3824 /****************************************************************************
3825 ****************************************************************************/
3826 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3828 DRIVER_INFO_6 info;
3829 WERROR status;
3831 ZERO_STRUCT(info);
3833 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3834 if (!W_ERROR_IS_OK(status)) {
3835 return status;
3838 /* check the required size. */
3839 *needed += spoolss_size_printer_driver_info_6(&info);
3841 if (!alloc_buffer_size(buffer, *needed)) {
3842 free_printer_driver_info_6(&info);
3843 return WERR_INSUFFICIENT_BUFFER;
3846 /* fill the buffer with the structures */
3847 smb_io_printer_driver_info_6("", buffer, &info, 0);
3849 free_printer_driver_info_6(&info);
3851 if (*needed > offered)
3852 return WERR_INSUFFICIENT_BUFFER;
3854 return WERR_OK;
3857 /****************************************************************************
3858 ****************************************************************************/
3860 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3862 POLICY_HND *handle = &q_u->handle;
3863 UNISTR2 *uni_arch = &q_u->architecture;
3864 uint32 level = q_u->level;
3865 uint32 clientmajorversion = q_u->clientmajorversion;
3866 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3867 NEW_BUFFER *buffer = NULL;
3868 uint32 offered = q_u->offered;
3869 uint32 *needed = &r_u->needed;
3870 uint32 *servermajorversion = &r_u->servermajorversion;
3871 uint32 *serverminorversion = &r_u->serverminorversion;
3873 fstring servername;
3874 fstring architecture;
3875 int snum;
3877 /* that's an [in out] buffer */
3878 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3879 buffer = r_u->buffer;
3881 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3883 *needed=0;
3884 *servermajorversion=0;
3885 *serverminorversion=0;
3887 pstrcpy(servername, global_myname);
3888 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3890 if (!get_printer_snum(p, handle, &snum))
3891 return WERR_BADFID;
3893 switch (level) {
3894 case 1:
3895 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3896 case 2:
3897 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3898 case 3:
3899 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3900 case 6:
3901 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3903 return WERR_UNKNOWN_LEVEL;
3906 /****************************************************************************
3907 ****************************************************************************/
3909 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3911 POLICY_HND *handle = &q_u->handle;
3913 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3915 if (Printer) {
3916 Printer->page_started=True;
3917 return WERR_OK;
3920 DEBUG(3,("Error in startpageprinter printer handle\n"));
3921 return WERR_BADFID;
3924 /****************************************************************************
3925 ****************************************************************************/
3927 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3929 POLICY_HND *handle = &q_u->handle;
3931 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3933 if (!Printer) {
3934 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3935 return WERR_BADFID;
3938 Printer->page_started=False;
3940 return WERR_OK;
3943 /********************************************************************
3944 * api_spoolss_getprinter
3945 * called from the spoolss dispatcher
3947 ********************************************************************/
3949 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3951 POLICY_HND *handle = &q_u->handle;
3952 /* uint32 level = q_u->doc_info_container.level; - notused. */
3953 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3954 uint32 *jobid = &r_u->jobid;
3956 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3957 int snum;
3958 pstring jobname;
3959 fstring datatype;
3960 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3961 struct current_user user;
3963 if (!Printer) {
3964 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3965 return WERR_BADFID;
3968 get_current_user(&user, p);
3971 * a nice thing with NT is it doesn't listen to what you tell it.
3972 * when asked to send _only_ RAW datas, it tries to send datas
3973 * in EMF format.
3975 * So I add checks like in NT Server ...
3977 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3978 * there's a bug in NT client-side code, so we'll fix it in the
3979 * server-side code. *nnnnnggggh!*
3982 if (info_1->p_datatype != 0) {
3983 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3984 if (strcmp(datatype, "RAW") != 0) {
3985 (*jobid)=0;
3986 return WERR_INVALID_DATATYPE;
3990 /* get the share number of the printer */
3991 if (!get_printer_snum(p, handle, &snum)) {
3992 return WERR_BADFID;
3995 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3997 Printer->jobid = print_job_start(&user, snum, jobname);
3999 /* An error occured in print_job_start() so return an appropriate
4000 NT error code. */
4002 if (Printer->jobid == -1) {
4003 return map_werror_from_unix(errno);
4006 Printer->document_started=True;
4007 (*jobid) = Printer->jobid;
4009 return WERR_OK;
4012 /********************************************************************
4013 * api_spoolss_getprinter
4014 * called from the spoolss dispatcher
4016 ********************************************************************/
4018 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4020 POLICY_HND *handle = &q_u->handle;
4022 return _spoolss_enddocprinter_internal(p, handle);
4025 /****************************************************************************
4026 ****************************************************************************/
4028 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4030 POLICY_HND *handle = &q_u->handle;
4031 uint32 buffer_size = q_u->buffer_size;
4032 uint8 *buffer = q_u->buffer;
4033 uint32 *buffer_written = &q_u->buffer_size2;
4035 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4037 if (!Printer) {
4038 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4039 r_u->buffer_written = q_u->buffer_size2;
4040 return WERR_BADFID;
4043 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4046 r_u->buffer_written = q_u->buffer_size2;
4048 return WERR_OK;
4051 /********************************************************************
4052 * api_spoolss_getprinter
4053 * called from the spoolss dispatcher
4055 ********************************************************************/
4056 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4057 pipes_struct *p)
4059 struct current_user user;
4060 int snum;
4061 WERROR errcode = WERR_BADFUNC;
4062 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4064 get_current_user(&user, p);
4066 if (!Printer) {
4067 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4068 return WERR_BADFID;
4071 if (!get_printer_snum(p, handle, &snum))
4072 return WERR_BADFID;
4074 switch (command) {
4075 case PRINTER_CONTROL_PAUSE:
4076 if (print_queue_pause(&user, snum, &errcode)) {
4077 errcode = WERR_OK;
4079 break;
4080 case PRINTER_CONTROL_RESUME:
4081 case PRINTER_CONTROL_UNPAUSE:
4082 if (print_queue_resume(&user, snum, &errcode)) {
4083 errcode = WERR_OK;
4085 break;
4086 case PRINTER_CONTROL_PURGE:
4087 if (print_queue_purge(&user, snum, &errcode)) {
4088 errcode = WERR_OK;
4090 break;
4091 default:
4092 return WERR_UNKNOWN_LEVEL;
4095 return errcode;
4098 /********************************************************************
4099 * api_spoolss_abortprinter
4100 ********************************************************************/
4102 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4104 POLICY_HND *handle = &q_u->handle;
4106 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4109 /********************************************************************
4110 * called by spoolss_api_setprinter
4111 * when updating a printer description
4112 ********************************************************************/
4113 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4114 const SPOOL_PRINTER_INFO_LEVEL *info,
4115 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4117 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4118 struct current_user user;
4119 WERROR result;
4120 int snum;
4122 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4124 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4125 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4126 OUR_HANDLE(handle)));
4128 result = WERR_BADFID;
4129 goto done;
4132 /* NT seems to like setting the security descriptor even though
4133 nothing may have actually changed. This causes annoying
4134 dialog boxes when the user doesn't have permission to change
4135 the security descriptor. */
4137 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4139 if (DEBUGLEVEL >= 10) {
4140 SEC_ACL *the_acl;
4141 int i;
4143 the_acl = old_secdesc_ctr->sec->dacl;
4144 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4145 PRINTERNAME(snum), the_acl->num_aces));
4147 for (i = 0; i < the_acl->num_aces; i++) {
4148 fstring sid_str;
4150 sid_to_string(sid_str, &the_acl->ace[i].sid);
4152 DEBUG(10, ("%s 0x%08x\n", sid_str,
4153 the_acl->ace[i].info.mask));
4156 the_acl = secdesc_ctr->sec->dacl;
4158 if (the_acl) {
4159 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4160 PRINTERNAME(snum), the_acl->num_aces));
4162 for (i = 0; i < the_acl->num_aces; i++) {
4163 fstring sid_str;
4165 sid_to_string(sid_str, &the_acl->ace[i].sid);
4167 DEBUG(10, ("%s 0x%08x\n", sid_str,
4168 the_acl->ace[i].info.mask));
4170 } else {
4171 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4175 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4177 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4178 result = WERR_OK;
4179 goto done;
4182 /* Work out which user is performing the operation */
4184 get_current_user(&user, p);
4186 /* Check the user has permissions to change the security
4187 descriptor. By experimentation with two NT machines, the user
4188 requires Full Access to the printer to change security
4189 information. */
4191 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4192 result = WERR_ACCESS_DENIED;
4193 goto done;
4196 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4198 done:
4200 return result;
4203 /********************************************************************
4204 Do Samba sanity checks on a printer info struct.
4205 this has changed purpose: it now "canonicalises" printer
4206 info from a client rather than just checking it is correct
4207 ********************************************************************/
4209 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4211 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4212 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4214 /* we force some elements to "correct" values */
4215 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4216 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4217 global_myname, lp_servicename(snum));
4218 fstrcpy(info->sharename, lp_servicename(snum));
4219 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4220 | PRINTER_ATTRIBUTE_LOCAL \
4221 | PRINTER_ATTRIBUTE_RAW_ONLY \
4222 | PRINTER_ATTRIBUTE_QUEUED ;
4224 return True;
4227 /****************************************************************************
4228 ****************************************************************************/
4229 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4231 char *cmd = lp_addprinter_cmd();
4232 char **qlines;
4233 pstring command;
4234 pstring driverlocation;
4235 int numlines;
4236 int ret;
4237 int fd;
4239 /* build driver path... only 9X architecture is needed for legacy reasons */
4240 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4241 global_myname);
4242 /* change \ to \\ for the shell */
4243 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4245 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4246 cmd, printer->info_2->printername, printer->info_2->sharename,
4247 printer->info_2->portname, printer->info_2->drivername,
4248 printer->info_2->location, driverlocation);
4250 DEBUG(10,("Running [%s]\n", command));
4251 ret = smbrun(command, &fd);
4252 DEBUGADD(10,("returned [%d]\n", ret));
4254 if ( ret != 0 ) {
4255 if (fd != -1)
4256 close(fd);
4257 return False;
4260 numlines = 0;
4261 /* Get lines and convert them back to dos-codepage */
4262 qlines = fd_lines_load(fd, &numlines);
4263 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4264 close(fd);
4266 if(numlines) {
4267 /* Set the portname to what the script says the portname should be. */
4268 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4269 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4271 /* Send SIGHUP to process group... is there a better way? */
4272 kill(0, SIGHUP);
4273 add_all_printers();
4276 file_lines_free(qlines);
4277 return True;
4280 /* Return true if two devicemodes are equal */
4282 #define DEVMODE_CHECK_INT(field) \
4283 if (d1->field != d2->field) { \
4284 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4285 d1->field, d2->field)); \
4286 return False; \
4289 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4291 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4293 if (!d1 ^ !d2) {
4294 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4295 return False; /* if either is exclusively NULL are not equal */
4298 if (!strequal(d1->devicename, d2->devicename)) {
4299 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4300 return False;
4303 if (!strequal(d1->formname, d2->formname)) {
4304 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4305 return False;
4308 DEVMODE_CHECK_INT(specversion);
4309 DEVMODE_CHECK_INT(driverversion);
4310 DEVMODE_CHECK_INT(driverextra);
4311 DEVMODE_CHECK_INT(orientation);
4312 DEVMODE_CHECK_INT(papersize);
4313 DEVMODE_CHECK_INT(paperlength);
4314 DEVMODE_CHECK_INT(paperwidth);
4315 DEVMODE_CHECK_INT(scale);
4316 DEVMODE_CHECK_INT(copies);
4317 DEVMODE_CHECK_INT(defaultsource);
4318 DEVMODE_CHECK_INT(printquality);
4319 DEVMODE_CHECK_INT(color);
4320 DEVMODE_CHECK_INT(duplex);
4321 DEVMODE_CHECK_INT(yresolution);
4322 DEVMODE_CHECK_INT(ttoption);
4323 DEVMODE_CHECK_INT(collate);
4324 DEVMODE_CHECK_INT(logpixels);
4326 DEVMODE_CHECK_INT(fields);
4327 DEVMODE_CHECK_INT(bitsperpel);
4328 DEVMODE_CHECK_INT(pelswidth);
4329 DEVMODE_CHECK_INT(pelsheight);
4330 DEVMODE_CHECK_INT(displayflags);
4331 DEVMODE_CHECK_INT(displayfrequency);
4332 DEVMODE_CHECK_INT(icmmethod);
4333 DEVMODE_CHECK_INT(icmintent);
4334 DEVMODE_CHECK_INT(mediatype);
4335 DEVMODE_CHECK_INT(dithertype);
4336 DEVMODE_CHECK_INT(reserved1);
4337 DEVMODE_CHECK_INT(reserved2);
4338 DEVMODE_CHECK_INT(panningwidth);
4339 DEVMODE_CHECK_INT(panningheight);
4341 /* compare the private data if it exists */
4342 if (!d1->driverextra && !d2->driverextra) goto equal;
4345 DEVMODE_CHECK_INT(driverextra);
4347 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4348 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4349 return False;
4352 equal:
4353 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4354 return True;
4357 /* Return true if two NT_PRINTER_PARAM structures are equal */
4359 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4360 NT_PRINTER_PARAM *p2)
4362 if (!p1 && !p2) goto equal;
4364 if ((!p1 && p2) || (p1 && !p2)) {
4365 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4366 return False;
4369 /* Compare lists of printer parameters */
4371 while (p1) {
4372 BOOL found = False;
4373 NT_PRINTER_PARAM *q = p1;
4375 /* Find the parameter in the second structure */
4377 while(q) {
4379 if (strequal(p1->value, q->value)) {
4381 if (p1->type != q->type) {
4382 DEBUG(10, ("nt_printer_param_equal():"
4383 "types for %s differ (%d != %d)\n",
4384 p1->value, p1->type,
4385 q->type));
4386 break;
4389 if (p1->data_len != q->data_len) {
4390 DEBUG(10, ("nt_printer_param_equal():"
4391 "len for %s differs (%d != %d)\n",
4392 p1->value, p1->data_len,
4393 q->data_len));
4394 break;
4397 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4398 found = True;
4399 } else {
4400 DEBUG(10, ("nt_printer_param_equal():"
4401 "data for %s differs\n", p1->value));
4404 break;
4407 q = q->next;
4410 if (!found) {
4411 DEBUG(10, ("nt_printer_param_equal(): param %s "
4412 "does not exist\n", p1->value));
4413 return False;
4416 p1 = p1->next;
4419 equal:
4421 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4422 return True;
4425 /********************************************************************
4426 * Called by update_printer when trying to work out whether to
4427 * actually update printer info.
4428 ********************************************************************/
4430 #define PI_CHECK_INT(field) \
4431 if (pi1->field != pi2->field) { \
4432 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4433 pi1->field, pi2->field)); \
4434 return False; \
4437 #define PI_CHECK_STR(field) \
4438 if (!strequal(pi1->field, pi2->field)) { \
4439 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4440 pi1->field, pi2->field)); \
4441 return False; \
4444 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4445 NT_PRINTER_INFO_LEVEL *p2)
4447 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4449 /* Trivial conditions */
4451 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4452 goto equal;
4455 if ((!p1 && p2) || (p1 && !p2) ||
4456 (!p1->info_2 && p2->info_2) ||
4457 (p1->info_2 && !p2->info_2)) {
4458 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4459 "differ\n"));
4460 return False;
4463 /* Compare two nt_printer_info_level structures. Don't compare
4464 status or cjobs as they seem to have something to do with the
4465 printer queue. */
4467 pi1 = p1->info_2;
4468 pi2 = p2->info_2;
4470 /* Don't check the attributes as we stomp on the value in
4471 check_printer_ok() anyway. */
4473 #if 0
4474 PI_CHECK_INT(attributes);
4475 #endif
4477 PI_CHECK_INT(priority);
4478 PI_CHECK_INT(default_priority);
4479 PI_CHECK_INT(starttime);
4480 PI_CHECK_INT(untiltime);
4481 PI_CHECK_INT(averageppm);
4483 /* Yuck - don't check the printername or servername as the
4484 add_a_printer() code plays games with them. You can't
4485 change the printername or the sharename through this interface
4486 in Samba. */
4488 PI_CHECK_STR(sharename);
4489 PI_CHECK_STR(portname);
4490 PI_CHECK_STR(drivername);
4491 PI_CHECK_STR(comment);
4492 PI_CHECK_STR(location);
4494 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4495 return False;
4498 PI_CHECK_STR(sepfile);
4499 PI_CHECK_STR(printprocessor);
4500 PI_CHECK_STR(datatype);
4501 PI_CHECK_STR(parameters);
4503 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4504 return False;
4507 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4508 return False;
4511 PI_CHECK_INT(changeid);
4512 PI_CHECK_INT(c_setprinter);
4513 PI_CHECK_INT(setuptime);
4515 equal:
4516 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4517 return True;
4520 /********************************************************************
4521 * called by spoolss_api_setprinter
4522 * when updating a printer description
4523 ********************************************************************/
4525 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4526 const SPOOL_PRINTER_INFO_LEVEL *info,
4527 DEVICEMODE *devmode)
4529 int snum;
4530 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4531 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4532 WERROR result;
4534 DEBUG(8,("update_printer\n"));
4536 result = WERR_OK;
4538 if (level!=2) {
4539 DEBUG(0,("Send a mail to samba@samba.org\n"));
4540 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4541 result = WERR_UNKNOWN_LEVEL;
4542 goto done;
4545 if (!Printer) {
4546 result = WERR_BADFID;
4547 goto done;
4550 if (!get_printer_snum(p, handle, &snum)) {
4551 result = WERR_BADFID;
4552 goto done;
4555 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4556 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4557 result = WERR_BADFID;
4558 goto done;
4561 DEBUGADD(8,("Converting info_2 struct\n"));
4564 * convert_printer_info converts the incoming
4565 * info from the client and overwrites the info
4566 * just read from the tdb in the pointer 'printer'.
4569 convert_printer_info(info, printer, level);
4571 if (info->info_2->devmode_ptr != 0) {
4572 /* we have a valid devmode
4573 convert it and link it*/
4575 DEBUGADD(8,("Converting the devicemode struct\n"));
4576 if (!convert_devicemode(printer->info_2->printername, devmode,
4577 &printer->info_2->devmode)) {
4578 result = WERR_NOMEM;
4579 goto done;
4583 /* Do sanity check on the requested changes for Samba */
4585 if (!check_printer_ok(printer->info_2, snum)) {
4586 result = WERR_INVALID_PARAM;
4587 goto done;
4590 /* NT likes to call this function even though nothing has actually
4591 changed. Check this so the user doesn't end up with an
4592 annoying permission denied dialog box. */
4594 if (nt_printer_info_level_equal(printer, old_printer)) {
4595 DEBUG(3, ("printer info has not changed\n"));
4596 result = WERR_OK;
4597 goto done;
4600 /* Check calling user has permission to update printer description */
4602 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4603 DEBUG(3, ("printer property change denied by security "
4604 "descriptor\n"));
4605 result = WERR_ACCESS_DENIED;
4606 goto done;
4609 /* Call addprinter hook */
4611 if (*lp_addprinter_cmd()) {
4612 if (!add_printer_hook(printer)) {
4613 result = WERR_ACCESS_DENIED;
4614 goto done;
4618 /* Update printer info */
4619 result = add_a_printer(*printer, 2);
4621 done:
4622 free_a_printer(&printer, 2);
4623 free_a_printer(&old_printer, 2);
4625 srv_spoolss_sendnotify(p, handle);
4627 return result;
4630 /****************************************************************************
4631 ****************************************************************************/
4633 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4635 POLICY_HND *handle = &q_u->handle;
4636 uint32 level = q_u->level;
4637 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4638 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4639 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4640 uint32 command = q_u->command;
4642 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4644 if (!Printer) {
4645 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4646 return WERR_BADFID;
4649 /* check the level */
4650 switch (level) {
4651 case 0:
4652 return control_printer(handle, command, p);
4653 case 2:
4654 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4655 case 3:
4656 return update_printer_sec(handle, level, info, p,
4657 secdesc_ctr);
4658 default:
4659 return WERR_UNKNOWN_LEVEL;
4663 /****************************************************************************
4664 ****************************************************************************/
4666 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4668 POLICY_HND *handle = &q_u->handle;
4670 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4672 if (!Printer) {
4673 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4674 return WERR_BADFID;
4677 if (Printer->notify.client_connected==True)
4678 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4680 Printer->notify.flags=0;
4681 Printer->notify.options=0;
4682 Printer->notify.localmachine[0]='\0';
4683 Printer->notify.printerlocal=0;
4684 if (Printer->notify.option)
4685 free_spool_notify_option(&Printer->notify.option);
4686 Printer->notify.client_connected=False;
4688 return WERR_OK;
4691 /****************************************************************************
4692 ****************************************************************************/
4694 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4696 /* that's an [in out] buffer (despite appearences to the contrary) */
4697 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4699 r_u->needed = 0;
4700 return WERR_INVALID_PARAM; /* this is what a NT server
4701 returns for AddJob. AddJob
4702 must fail on non-local
4703 printers */
4706 /****************************************************************************
4707 ****************************************************************************/
4708 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4709 int position, int snum)
4711 pstring temp_name;
4713 struct tm *t;
4715 t=gmtime(&queue->time);
4716 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4718 job_info->jobid=queue->job;
4719 init_unistr(&job_info->printername, lp_servicename(snum));
4720 init_unistr(&job_info->machinename, temp_name);
4721 init_unistr(&job_info->username, queue->user);
4722 init_unistr(&job_info->document, queue->file);
4723 init_unistr(&job_info->datatype, "RAW");
4724 init_unistr(&job_info->text_status, "");
4725 job_info->status=nt_printj_status(queue->status);
4726 job_info->priority=queue->priority;
4727 job_info->position=position;
4728 job_info->totalpages=0;
4729 job_info->pagesprinted=0;
4731 make_systemtime(&job_info->submitted, t);
4734 /****************************************************************************
4735 ****************************************************************************/
4736 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4737 int position, int snum,
4738 NT_PRINTER_INFO_LEVEL *ntprinter)
4740 pstring temp_name;
4741 pstring chaine;
4742 struct tm *t;
4744 t=gmtime(&queue->time);
4745 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4747 job_info->jobid=queue->job;
4749 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4751 init_unistr(&job_info->printername, chaine);
4753 init_unistr(&job_info->machinename, temp_name);
4754 init_unistr(&job_info->username, queue->user);
4755 init_unistr(&job_info->document, queue->file);
4756 init_unistr(&job_info->notifyname, queue->user);
4757 init_unistr(&job_info->datatype, "RAW");
4758 init_unistr(&job_info->printprocessor, "winprint");
4759 init_unistr(&job_info->parameters, "");
4760 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4761 init_unistr(&job_info->text_status, "");
4763 /* and here the security descriptor */
4765 job_info->status=nt_printj_status(queue->status);
4766 job_info->priority=queue->priority;
4767 job_info->position=position;
4768 job_info->starttime=0;
4769 job_info->untiltime=0;
4770 job_info->totalpages=0;
4771 job_info->size=queue->size;
4772 make_systemtime(&(job_info->submitted), t);
4773 job_info->timeelapsed=0;
4774 job_info->pagesprinted=0;
4776 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4777 return False;
4780 return (True);
4783 /****************************************************************************
4784 Enumjobs at level 1.
4785 ****************************************************************************/
4786 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4787 NEW_BUFFER *buffer, uint32 offered,
4788 uint32 *needed, uint32 *returned)
4790 JOB_INFO_1 *info;
4791 int i;
4793 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4794 if (info==NULL) {
4795 safe_free(queue);
4796 *returned=0;
4797 return WERR_NOMEM;
4800 for (i=0; i<*returned; i++)
4801 fill_job_info_1(&info[i], &queue[i], i, snum);
4803 safe_free(queue);
4805 /* check the required size. */
4806 for (i=0; i<*returned; i++)
4807 (*needed) += spoolss_size_job_info_1(&info[i]);
4809 if (!alloc_buffer_size(buffer, *needed)) {
4810 safe_free(info);
4811 return WERR_INSUFFICIENT_BUFFER;
4814 /* fill the buffer with the structures */
4815 for (i=0; i<*returned; i++)
4816 smb_io_job_info_1("", buffer, &info[i], 0);
4818 /* clear memory */
4819 safe_free(info);
4821 if (*needed > offered) {
4822 *returned=0;
4823 return WERR_INSUFFICIENT_BUFFER;
4826 return WERR_OK;
4829 /****************************************************************************
4830 Enumjobs at level 2.
4831 ****************************************************************************/
4832 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4833 NEW_BUFFER *buffer, uint32 offered,
4834 uint32 *needed, uint32 *returned)
4836 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4837 JOB_INFO_2 *info;
4838 int i;
4839 WERROR result;
4841 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4842 if (info==NULL) {
4843 *returned=0;
4844 return WERR_NOMEM;
4847 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4848 if (!W_ERROR_IS_OK(result)) {
4849 *returned = 0;
4850 return result;
4853 for (i=0; i<*returned; i++)
4854 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4856 free_a_printer(&ntprinter, 2);
4857 safe_free(queue);
4859 /* check the required size. */
4860 for (i=0; i<*returned; i++)
4861 (*needed) += spoolss_size_job_info_2(&info[i]);
4863 if (!alloc_buffer_size(buffer, *needed)) {
4864 safe_free(info);
4865 return WERR_INSUFFICIENT_BUFFER;
4868 /* fill the buffer with the structures */
4869 for (i=0; i<*returned; i++)
4870 smb_io_job_info_2("", buffer, &info[i], 0);
4872 /* clear memory */
4873 for (i = 0; i < *returned; i++)
4874 free_job_info_2(&info[i]);
4876 free(info);
4878 if (*needed > offered) {
4879 *returned=0;
4880 return WERR_INSUFFICIENT_BUFFER;
4883 return WERR_OK;
4886 /****************************************************************************
4887 Enumjobs.
4888 ****************************************************************************/
4890 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4892 POLICY_HND *handle = &q_u->handle;
4893 /* uint32 firstjob = q_u->firstjob; - notused. */
4894 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4895 uint32 level = q_u->level;
4896 NEW_BUFFER *buffer = NULL;
4897 uint32 offered = q_u->offered;
4898 uint32 *needed = &r_u->needed;
4899 uint32 *returned = &r_u->returned;
4901 int snum;
4902 print_queue_struct *queue=NULL;
4903 print_status_struct prt_status;
4905 /* that's an [in out] buffer */
4906 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4907 buffer = r_u->buffer;
4909 DEBUG(4,("_spoolss_enumjobs\n"));
4911 ZERO_STRUCT(prt_status);
4913 *needed=0;
4914 *returned=0;
4916 if (!get_printer_snum(p, handle, &snum))
4917 return WERR_BADFID;
4919 *returned = print_queue_status(snum, &queue, &prt_status);
4920 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4922 if (*returned == 0) {
4923 safe_free(queue);
4924 return WERR_OK;
4927 switch (level) {
4928 case 1:
4929 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4930 case 2:
4931 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4932 default:
4933 safe_free(queue);
4934 *returned=0;
4935 return WERR_UNKNOWN_LEVEL;
4939 /****************************************************************************
4940 ****************************************************************************/
4942 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4944 return WERR_OK;
4947 /****************************************************************************
4948 ****************************************************************************/
4950 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4952 POLICY_HND *handle = &q_u->handle;
4953 uint32 jobid = q_u->jobid;
4954 /* uint32 level = q_u->level; - notused. */
4955 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4956 uint32 command = q_u->command;
4958 struct current_user user;
4959 print_status_struct prt_status;
4960 int snum;
4961 WERROR errcode = WERR_BADFUNC;
4963 memset(&prt_status, 0, sizeof(prt_status));
4965 if (!get_printer_snum(p, handle, &snum)) {
4966 return WERR_BADFID;
4969 if (!print_job_exists(jobid)) {
4970 return WERR_INVALID_PRINTER_NAME;
4973 get_current_user(&user, p);
4975 switch (command) {
4976 case JOB_CONTROL_CANCEL:
4977 case JOB_CONTROL_DELETE:
4978 if (print_job_delete(&user, jobid, &errcode)) {
4979 errcode = WERR_OK;
4981 break;
4982 case JOB_CONTROL_PAUSE:
4983 if (print_job_pause(&user, jobid, &errcode)) {
4984 errcode = WERR_OK;
4986 break;
4987 case JOB_CONTROL_RESTART:
4988 case JOB_CONTROL_RESUME:
4989 if (print_job_resume(&user, jobid, &errcode)) {
4990 errcode = WERR_OK;
4992 break;
4993 default:
4994 return WERR_UNKNOWN_LEVEL;
4997 return errcode;
5000 /****************************************************************************
5001 Enumerates all printer drivers at level 1.
5002 ****************************************************************************/
5003 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5005 int i;
5006 int ndrivers;
5007 uint32 version;
5008 fstring *list = NULL;
5009 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5010 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5012 *returned=0;
5014 #define MAX_VERSION 4
5016 for (version=0; version<MAX_VERSION; version++) {
5017 list=NULL;
5018 ndrivers=get_ntdrivers(&list, architecture, version);
5019 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5021 if(ndrivers == -1)
5022 return WERR_NOMEM;
5024 if(ndrivers != 0) {
5025 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5026 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5027 safe_free(driver_info_1);
5028 safe_free(list);
5029 return WERR_NOMEM;
5031 else driver_info_1 = tdi1;
5034 for (i=0; i<ndrivers; i++) {
5035 WERROR status;
5036 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5037 ZERO_STRUCT(driver);
5038 status = get_a_printer_driver(&driver, 3, list[i],
5039 architecture, version);
5040 if (!W_ERROR_IS_OK(status)) {
5041 safe_free(list);
5042 return status;
5044 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5045 free_a_printer_driver(driver, 3);
5048 *returned+=ndrivers;
5049 safe_free(list);
5052 /* check the required size. */
5053 for (i=0; i<*returned; i++) {
5054 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5055 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5058 if (!alloc_buffer_size(buffer, *needed)) {
5059 safe_free(driver_info_1);
5060 return WERR_INSUFFICIENT_BUFFER;
5063 /* fill the buffer with the driver structures */
5064 for (i=0; i<*returned; i++) {
5065 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5066 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5069 safe_free(driver_info_1);
5071 if (*needed > offered) {
5072 *returned=0;
5073 return WERR_INSUFFICIENT_BUFFER;
5076 return WERR_OK;
5079 /****************************************************************************
5080 Enumerates all printer drivers at level 2.
5081 ****************************************************************************/
5082 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5084 int i;
5085 int ndrivers;
5086 uint32 version;
5087 fstring *list = NULL;
5088 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5089 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5091 *returned=0;
5093 #define MAX_VERSION 4
5095 for (version=0; version<MAX_VERSION; version++) {
5096 list=NULL;
5097 ndrivers=get_ntdrivers(&list, architecture, version);
5098 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5100 if(ndrivers == -1)
5101 return WERR_NOMEM;
5103 if(ndrivers != 0) {
5104 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5105 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5106 safe_free(driver_info_2);
5107 safe_free(list);
5108 return WERR_NOMEM;
5110 else driver_info_2 = tdi2;
5113 for (i=0; i<ndrivers; i++) {
5114 WERROR status;
5116 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5117 ZERO_STRUCT(driver);
5118 status = get_a_printer_driver(&driver, 3, list[i],
5119 architecture, version);
5120 if (!W_ERROR_IS_OK(status)) {
5121 safe_free(list);
5122 return status;
5124 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5125 free_a_printer_driver(driver, 3);
5128 *returned+=ndrivers;
5129 safe_free(list);
5132 /* check the required size. */
5133 for (i=0; i<*returned; i++) {
5134 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5135 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5138 if (!alloc_buffer_size(buffer, *needed)) {
5139 safe_free(driver_info_2);
5140 return WERR_INSUFFICIENT_BUFFER;
5143 /* fill the buffer with the form structures */
5144 for (i=0; i<*returned; i++) {
5145 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5146 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5149 safe_free(driver_info_2);
5151 if (*needed > offered) {
5152 *returned=0;
5153 return WERR_INSUFFICIENT_BUFFER;
5156 return WERR_OK;
5159 /****************************************************************************
5160 Enumerates all printer drivers at level 3.
5161 ****************************************************************************/
5162 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5164 int i;
5165 int ndrivers;
5166 uint32 version;
5167 fstring *list = NULL;
5168 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5169 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5171 *returned=0;
5173 #define MAX_VERSION 4
5175 for (version=0; version<MAX_VERSION; version++) {
5176 list=NULL;
5177 ndrivers=get_ntdrivers(&list, architecture, version);
5178 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5180 if(ndrivers == -1)
5181 return WERR_NOMEM;
5183 if(ndrivers != 0) {
5184 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5185 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5186 safe_free(driver_info_3);
5187 safe_free(list);
5188 return WERR_NOMEM;
5190 else driver_info_3 = tdi3;
5193 for (i=0; i<ndrivers; i++) {
5194 WERROR status;
5196 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5197 ZERO_STRUCT(driver);
5198 status = get_a_printer_driver(&driver, 3, list[i],
5199 architecture, version);
5200 if (!W_ERROR_IS_OK(status)) {
5201 safe_free(list);
5202 return status;
5204 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5205 free_a_printer_driver(driver, 3);
5208 *returned+=ndrivers;
5209 safe_free(list);
5212 /* check the required size. */
5213 for (i=0; i<*returned; i++) {
5214 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5215 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5218 if (!alloc_buffer_size(buffer, *needed)) {
5219 safe_free(driver_info_3);
5220 return WERR_INSUFFICIENT_BUFFER;
5223 /* fill the buffer with the driver structures */
5224 for (i=0; i<*returned; i++) {
5225 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5226 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5229 for (i=0; i<*returned; i++)
5230 safe_free(driver_info_3[i].dependentfiles);
5232 safe_free(driver_info_3);
5234 if (*needed > offered) {
5235 *returned=0;
5236 return WERR_INSUFFICIENT_BUFFER;
5239 return WERR_OK;
5242 /****************************************************************************
5243 Enumerates all printer drivers.
5244 ****************************************************************************/
5246 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5248 /* UNISTR2 *name = &q_u->name; - notused. */
5249 UNISTR2 *environment = &q_u->environment;
5250 uint32 level = q_u->level;
5251 NEW_BUFFER *buffer = NULL;
5252 uint32 offered = q_u->offered;
5253 uint32 *needed = &r_u->needed;
5254 uint32 *returned = &r_u->returned;
5256 fstring *list = NULL;
5257 fstring servername;
5258 fstring architecture;
5260 /* that's an [in out] buffer */
5261 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5262 buffer = r_u->buffer;
5264 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5265 fstrcpy(servername, global_myname);
5266 *needed=0;
5267 *returned=0;
5269 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5271 switch (level) {
5272 case 1:
5273 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5274 case 2:
5275 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5276 case 3:
5277 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5278 default:
5279 *returned=0;
5280 safe_free(list);
5281 return WERR_UNKNOWN_LEVEL;
5285 /****************************************************************************
5286 ****************************************************************************/
5288 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5290 form->flag=list->flag;
5291 init_unistr(&form->name, list->name);
5292 form->width=list->width;
5293 form->length=list->length;
5294 form->left=list->left;
5295 form->top=list->top;
5296 form->right=list->right;
5297 form->bottom=list->bottom;
5300 /****************************************************************************
5301 ****************************************************************************/
5303 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5305 /* POLICY_HND *handle = &q_u->handle; - notused. */
5306 uint32 level = q_u->level;
5307 NEW_BUFFER *buffer = NULL;
5308 uint32 offered = q_u->offered;
5309 uint32 *needed = &r_u->needed;
5310 uint32 *numofforms = &r_u->numofforms;
5311 uint32 numbuiltinforms;
5313 nt_forms_struct *list=NULL;
5314 nt_forms_struct *builtinlist=NULL;
5315 FORM_1 *forms_1;
5316 int buffer_size=0;
5317 int i;
5319 /* that's an [in out] buffer */
5320 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5321 buffer = r_u->buffer;
5323 DEBUG(4,("_spoolss_enumforms\n"));
5324 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5325 DEBUGADD(5,("Info level [%d]\n", level));
5327 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5328 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5329 *numofforms = get_ntforms(&list);
5330 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5331 *numofforms += numbuiltinforms;
5333 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5335 switch (level) {
5336 case 1:
5337 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5338 *numofforms=0;
5339 return WERR_NOMEM;
5342 /* construct the list of form structures */
5343 for (i=0; i<numbuiltinforms; i++) {
5344 DEBUGADD(6,("Filling form number [%d]\n",i));
5345 fill_form_1(&forms_1[i], &builtinlist[i]);
5348 safe_free(builtinlist);
5350 for (; i<*numofforms; i++) {
5351 DEBUGADD(6,("Filling form number [%d]\n",i));
5352 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5355 safe_free(list);
5357 /* check the required size. */
5358 for (i=0; i<numbuiltinforms; i++) {
5359 DEBUGADD(6,("adding form [%d]'s size\n",i));
5360 buffer_size += spoolss_size_form_1(&forms_1[i]);
5362 for (; i<*numofforms; i++) {
5363 DEBUGADD(6,("adding form [%d]'s size\n",i));
5364 buffer_size += spoolss_size_form_1(&forms_1[i]);
5367 *needed=buffer_size;
5369 if (!alloc_buffer_size(buffer, buffer_size)){
5370 safe_free(forms_1);
5371 return WERR_INSUFFICIENT_BUFFER;
5374 /* fill the buffer with the form structures */
5375 for (i=0; i<numbuiltinforms; i++) {
5376 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5377 smb_io_form_1("", buffer, &forms_1[i], 0);
5379 for (; i<*numofforms; i++) {
5380 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5381 smb_io_form_1("", buffer, &forms_1[i], 0);
5384 safe_free(forms_1);
5386 if (*needed > offered) {
5387 *numofforms=0;
5388 return WERR_INSUFFICIENT_BUFFER;
5390 else
5391 return WERR_OK;
5393 default:
5394 safe_free(list);
5395 safe_free(builtinlist);
5396 return WERR_UNKNOWN_LEVEL;
5401 /****************************************************************************
5402 ****************************************************************************/
5404 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5406 /* POLICY_HND *handle = &q_u->handle; - notused. */
5407 uint32 level = q_u->level;
5408 UNISTR2 *uni_formname = &q_u->formname;
5409 NEW_BUFFER *buffer = NULL;
5410 uint32 offered = q_u->offered;
5411 uint32 *needed = &r_u->needed;
5413 nt_forms_struct *list=NULL;
5414 nt_forms_struct builtin_form;
5415 BOOL foundBuiltin;
5416 FORM_1 form_1;
5417 fstring form_name;
5418 int buffer_size=0;
5419 int numofforms=0, i=0;
5421 /* that's an [in out] buffer */
5422 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5423 buffer = r_u->buffer;
5425 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5427 DEBUG(4,("_spoolss_getform\n"));
5428 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5429 DEBUGADD(5,("Info level [%d]\n", level));
5431 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5432 if (!foundBuiltin) {
5433 numofforms = get_ntforms(&list);
5434 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5436 if (numofforms == 0)
5437 return WERR_BADFID;
5440 switch (level) {
5441 case 1:
5442 if (foundBuiltin) {
5443 fill_form_1(&form_1, &builtin_form);
5444 } else {
5446 /* Check if the requested name is in the list of form structures */
5447 for (i=0; i<numofforms; i++) {
5449 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5451 if (strequal(form_name, list[i].name)) {
5452 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5453 fill_form_1(&form_1, &list[i]);
5454 break;
5458 safe_free(list);
5459 if (i == numofforms) {
5460 return WERR_BADFID;
5463 /* check the required size. */
5465 *needed=spoolss_size_form_1(&form_1);
5467 if (!alloc_buffer_size(buffer, buffer_size)){
5468 return WERR_INSUFFICIENT_BUFFER;
5471 if (*needed > offered) {
5472 return WERR_INSUFFICIENT_BUFFER;
5475 /* fill the buffer with the form structures */
5476 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5477 smb_io_form_1("", buffer, &form_1, 0);
5479 return WERR_OK;
5481 default:
5482 safe_free(list);
5483 return WERR_UNKNOWN_LEVEL;
5487 /****************************************************************************
5488 ****************************************************************************/
5489 static void fill_port_1(PORT_INFO_1 *port, char *name)
5491 init_unistr(&port->port_name, name);
5494 /****************************************************************************
5495 ****************************************************************************/
5496 static void fill_port_2(PORT_INFO_2 *port, char *name)
5498 init_unistr(&port->port_name, name);
5499 init_unistr(&port->monitor_name, "Local Monitor");
5500 init_unistr(&port->description, "Local Port");
5501 #define PORT_TYPE_WRITE 1
5502 port->port_type=PORT_TYPE_WRITE;
5503 port->reserved=0x0;
5506 /****************************************************************************
5507 enumports level 1.
5508 ****************************************************************************/
5509 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5511 PORT_INFO_1 *ports=NULL;
5512 int i=0;
5514 if (*lp_enumports_cmd()) {
5515 char *cmd = lp_enumports_cmd();
5516 char **qlines;
5517 pstring command;
5518 int numlines;
5519 int ret;
5520 int fd;
5522 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5524 DEBUG(10,("Running [%s]\n", command));
5525 ret = smbrun(command, &fd);
5526 DEBUG(10,("Returned [%d]\n", ret));
5527 if (ret != 0) {
5528 if (fd != -1)
5529 close(fd);
5530 /* Is this the best error to return here? */
5531 return WERR_ACCESS_DENIED;
5534 numlines = 0;
5535 qlines = fd_lines_load(fd, &numlines);
5536 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5537 close(fd);
5539 if(numlines) {
5540 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5541 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5542 werror_str(WERR_NOMEM)));
5543 file_lines_free(qlines);
5544 return WERR_NOMEM;
5547 for (i=0; i<numlines; i++) {
5548 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5549 fill_port_1(&ports[i], qlines[i]);
5552 file_lines_free(qlines);
5555 *returned = numlines;
5557 } else {
5558 *returned = 1; /* Sole Samba port returned. */
5560 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5561 return WERR_NOMEM;
5563 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5565 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5568 /* check the required size. */
5569 for (i=0; i<*returned; i++) {
5570 DEBUGADD(6,("adding port [%d]'s size\n", i));
5571 *needed += spoolss_size_port_info_1(&ports[i]);
5574 if (!alloc_buffer_size(buffer, *needed)) {
5575 safe_free(ports);
5576 return WERR_INSUFFICIENT_BUFFER;
5579 /* fill the buffer with the ports structures */
5580 for (i=0; i<*returned; i++) {
5581 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5582 smb_io_port_1("", buffer, &ports[i], 0);
5585 safe_free(ports);
5587 if (*needed > offered) {
5588 *returned=0;
5589 return WERR_INSUFFICIENT_BUFFER;
5592 return WERR_OK;
5595 /****************************************************************************
5596 enumports level 2.
5597 ****************************************************************************/
5599 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5601 PORT_INFO_2 *ports=NULL;
5602 int i=0;
5604 if (*lp_enumports_cmd()) {
5605 char *cmd = lp_enumports_cmd();
5606 char *path;
5607 char **qlines;
5608 pstring tmp_file;
5609 pstring command;
5610 int numlines;
5611 int ret;
5612 int fd;
5614 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5615 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5616 else
5617 path = lp_lockdir();
5619 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5620 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5622 unlink(tmp_file);
5623 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5624 ret = smbrun(command, &fd);
5625 DEBUGADD(10,("returned [%d]\n", ret));
5626 if (ret != 0) {
5627 if (fd != -1)
5628 close(fd);
5629 /* Is this the best error to return here? */
5630 return WERR_ACCESS_DENIED;
5633 numlines = 0;
5634 qlines = fd_lines_load(fd, &numlines);
5635 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5636 close(fd);
5638 if(numlines) {
5639 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5640 file_lines_free(qlines);
5641 return WERR_NOMEM;
5644 for (i=0; i<numlines; i++) {
5645 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5646 fill_port_2(&(ports[i]), qlines[i]);
5649 file_lines_free(qlines);
5652 *returned = numlines;
5654 } else {
5656 *returned = 1;
5658 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5659 return WERR_NOMEM;
5661 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5663 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5666 /* check the required size. */
5667 for (i=0; i<*returned; i++) {
5668 DEBUGADD(6,("adding port [%d]'s size\n", i));
5669 *needed += spoolss_size_port_info_2(&ports[i]);
5672 if (!alloc_buffer_size(buffer, *needed)) {
5673 safe_free(ports);
5674 return WERR_INSUFFICIENT_BUFFER;
5677 /* fill the buffer with the ports structures */
5678 for (i=0; i<*returned; i++) {
5679 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5680 smb_io_port_2("", buffer, &ports[i], 0);
5683 safe_free(ports);
5685 if (*needed > offered) {
5686 *returned=0;
5687 return WERR_INSUFFICIENT_BUFFER;
5690 return WERR_OK;
5693 /****************************************************************************
5694 enumports.
5695 ****************************************************************************/
5697 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5699 /* UNISTR2 *name = &q_u->name; - notused. */
5700 uint32 level = q_u->level;
5701 NEW_BUFFER *buffer = NULL;
5702 uint32 offered = q_u->offered;
5703 uint32 *needed = &r_u->needed;
5704 uint32 *returned = &r_u->returned;
5706 /* that's an [in out] buffer */
5707 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5708 buffer = r_u->buffer;
5710 DEBUG(4,("_spoolss_enumports\n"));
5712 *returned=0;
5713 *needed=0;
5715 switch (level) {
5716 case 1:
5717 return enumports_level_1(buffer, offered, needed, returned);
5718 case 2:
5719 return enumports_level_2(buffer, offered, needed, returned);
5720 default:
5721 return WERR_UNKNOWN_LEVEL;
5725 /****************************************************************************
5726 ****************************************************************************/
5727 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5728 const SPOOL_PRINTER_INFO_LEVEL *info,
5729 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5730 uint32 user_switch, const SPOOL_USER_CTR *user,
5731 POLICY_HND *handle)
5733 NT_PRINTER_INFO_LEVEL *printer = NULL;
5734 WERROR err;
5735 fstring name;
5736 int snum;
5738 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5739 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5740 return WERR_NOMEM;
5743 ZERO_STRUCTP(printer);
5745 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5746 convert_printer_info(info, printer, 2);
5748 if (*lp_addprinter_cmd() )
5749 if ( !add_printer_hook(printer) ) {
5750 free_a_printer(&printer,2);
5751 return WERR_ACCESS_DENIED;
5754 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5755 printer->info_2->sharename);
5757 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5758 free_a_printer(&printer,2);
5759 return WERR_ACCESS_DENIED;
5762 /* you must be a printer admin to add a new printer */
5763 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5764 free_a_printer(&printer,2);
5765 return WERR_ACCESS_DENIED;
5769 * Do sanity check on the requested changes for Samba.
5772 if (!check_printer_ok(printer->info_2, snum)) {
5773 free_a_printer(&printer,2);
5774 return WERR_INVALID_PARAM;
5778 * When a printer is created, the drivername bound to the printer is used
5779 * to lookup previously saved driver initialization info, which is then
5780 * bound to the new printer, simulating what happens in the Windows arch.
5782 set_driver_init(printer, 2);
5784 /* write the ASCII on disk */
5785 err = add_a_printer(*printer, 2);
5786 if (!W_ERROR_IS_OK(err)) {
5787 free_a_printer(&printer,2);
5788 return err;
5791 if (!open_printer_hnd(p, handle, name)) {
5792 /* Handle open failed - remove addition. */
5793 del_a_printer(printer->info_2->sharename);
5794 free_a_printer(&printer,2);
5795 return WERR_ACCESS_DENIED;
5798 free_a_printer(&printer,2);
5800 srv_spoolss_sendnotify(p, handle);
5802 return WERR_OK;
5805 /****************************************************************************
5806 ****************************************************************************/
5808 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5810 UNISTR2 *uni_srv_name = &q_u->server_name;
5811 uint32 level = q_u->level;
5812 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5813 uint32 unk0 = q_u->unk0;
5814 uint32 unk1 = q_u->unk1;
5815 uint32 unk2 = q_u->unk2;
5816 uint32 unk3 = q_u->unk3;
5817 uint32 user_switch = q_u->user_switch;
5818 SPOOL_USER_CTR *user = &q_u->user_ctr;
5819 POLICY_HND *handle = &r_u->handle;
5821 switch (level) {
5822 case 1:
5823 /* we don't handle yet */
5824 /* but I know what to do ... */
5825 return WERR_UNKNOWN_LEVEL;
5826 case 2:
5827 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5828 unk0, unk1, unk2, unk3,
5829 user_switch, user, handle);
5830 default:
5831 return WERR_UNKNOWN_LEVEL;
5835 /****************************************************************************
5836 ****************************************************************************/
5838 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5840 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5841 uint32 level = q_u->level;
5842 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5843 WERROR err = WERR_OK;
5844 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5845 struct current_user user;
5847 ZERO_STRUCT(driver);
5849 get_current_user(&user, p);
5851 if (!convert_printer_driver_info(info, &driver, level)) {
5852 err = WERR_NOMEM;
5853 goto done;
5856 DEBUG(5,("Cleaning driver's information\n"));
5857 err = clean_up_driver_struct(driver, level, &user);
5858 if (!W_ERROR_IS_OK(err))
5859 goto done;
5861 DEBUG(5,("Moving driver to final destination\n"));
5862 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5863 if (W_ERROR_IS_OK(err))
5864 err = WERR_ACCESS_DENIED;
5865 goto done;
5868 if (add_a_printer_driver(driver, level)!=0) {
5869 err = WERR_ACCESS_DENIED;
5870 goto done;
5873 done:
5874 free_a_printer_driver(driver, level);
5875 return err;
5878 /****************************************************************************
5879 ****************************************************************************/
5880 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5882 init_unistr(&info->name, name);
5885 /****************************************************************************
5886 ****************************************************************************/
5887 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5889 pstring path;
5890 pstring long_archi;
5891 pstring short_archi;
5892 DRIVER_DIRECTORY_1 *info=NULL;
5894 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5896 if (get_short_archi(short_archi, long_archi)==FALSE)
5897 return WERR_INVALID_ENVIRONMENT;
5899 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5900 return WERR_NOMEM;
5902 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5904 DEBUG(4,("printer driver directory: [%s]\n", path));
5906 fill_driverdir_1(info, path);
5908 *needed += spoolss_size_driverdir_info_1(info);
5910 if (!alloc_buffer_size(buffer, *needed)) {
5911 safe_free(info);
5912 return WERR_INSUFFICIENT_BUFFER;
5915 smb_io_driverdir_1("", buffer, info, 0);
5917 safe_free(info);
5919 if (*needed > offered)
5920 return WERR_INSUFFICIENT_BUFFER;
5922 return WERR_OK;
5925 /****************************************************************************
5926 ****************************************************************************/
5928 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5930 UNISTR2 *name = &q_u->name;
5931 UNISTR2 *uni_environment = &q_u->environment;
5932 uint32 level = q_u->level;
5933 NEW_BUFFER *buffer = NULL;
5934 uint32 offered = q_u->offered;
5935 uint32 *needed = &r_u->needed;
5937 /* that's an [in out] buffer */
5938 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5939 buffer = r_u->buffer;
5941 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5943 *needed=0;
5945 switch(level) {
5946 case 1:
5947 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5948 default:
5949 return WERR_UNKNOWN_LEVEL;
5953 /****************************************************************************
5954 ****************************************************************************/
5956 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5958 POLICY_HND *handle = &q_u->handle;
5959 uint32 idx = q_u->index;
5960 uint32 in_value_len = q_u->valuesize;
5961 uint32 in_data_len = q_u->datasize;
5962 uint32 *out_max_value_len = &r_u->valuesize;
5963 uint16 **out_value = &r_u->value;
5964 uint32 *out_value_len = &r_u->realvaluesize;
5965 uint32 *out_type = &r_u->type;
5966 uint32 *out_max_data_len = &r_u->datasize;
5967 uint8 **data_out = &r_u->data;
5968 uint32 *out_data_len = &r_u->realdatasize;
5970 NT_PRINTER_INFO_LEVEL *printer = NULL;
5972 fstring value;
5974 uint32 param_index;
5975 uint32 biggest_valuesize;
5976 uint32 biggest_datasize;
5977 uint32 data_len;
5978 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5979 int snum;
5980 uint8 *data=NULL;
5981 uint32 type;
5982 WERROR result;
5984 ZERO_STRUCT(printer);
5986 *out_max_value_len=0;
5987 *out_value=NULL;
5988 *out_value_len=0;
5990 *out_type=0;
5992 *out_max_data_len=0;
5993 *data_out=NULL;
5994 *out_data_len=0;
5996 DEBUG(5,("spoolss_enumprinterdata\n"));
5998 if (!Printer) {
5999 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6000 return WERR_BADFID;
6003 if (!get_printer_snum(p,handle, &snum))
6004 return WERR_BADFID;
6006 result = get_a_printer(&printer, 2, lp_servicename(snum));
6007 if (!W_ERROR_IS_OK(result))
6008 return result;
6011 * The NT machine wants to know the biggest size of value and data
6013 * cf: MSDN EnumPrinterData remark section
6015 if ( (in_value_len==0) && (in_data_len==0) ) {
6016 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6018 #if 0
6020 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6021 * if this parameter size doesn't exist.
6022 * Ok - my opinion here is that the client is not asking for the greatest
6023 * possible size of all the parameters, but is asking specifically for the size needed
6024 * for this specific parameter. In that case we can remove the loop below and
6025 * simplify this lookup code considerably. JF - comments welcome. JRA.
6028 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6029 safe_free(data);
6030 free_a_printer(&printer, 2);
6031 return WERR_NO_MORE_ITEMS;
6033 #endif
6035 safe_free(data);
6036 data = NULL;
6038 param_index=0;
6039 biggest_valuesize=0;
6040 biggest_datasize=0;
6042 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6043 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6044 if (data_len > biggest_datasize) biggest_datasize=data_len;
6046 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6048 safe_free(data);
6049 data = NULL;
6050 param_index++;
6054 * I think this is correct, it doesn't break APW and
6055 * allows Gerald's Win32 test programs to work correctly,
6056 * but may need altering.... JRA.
6059 if (param_index == 0) {
6060 /* No parameters found. */
6061 free_a_printer(&printer, 2);
6062 return WERR_NO_MORE_ITEMS;
6065 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6066 *out_value_len=2*(1+biggest_valuesize);
6067 *out_data_len=biggest_datasize;
6069 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6071 free_a_printer(&printer, 2);
6072 return WERR_OK;
6076 * the value len is wrong in NT sp3
6077 * that's the number of bytes not the number of unicode chars
6080 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6081 safe_free(data);
6082 free_a_printer(&printer, 2);
6083 return WERR_NO_MORE_ITEMS;
6086 free_a_printer(&printer, 2);
6089 * the value is:
6090 * - counted in bytes in the request
6091 * - counted in UNICODE chars in the max reply
6092 * - counted in bytes in the real size
6094 * take a pause *before* coding not *during* coding
6097 *out_max_value_len=(in_value_len/sizeof(uint16));
6098 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6099 safe_free(data);
6100 return WERR_NOMEM;
6103 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6105 *out_type=type;
6107 /* the data is counted in bytes */
6108 *out_max_data_len=in_data_len;
6109 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6110 safe_free(data);
6111 return WERR_NOMEM;
6114 memcpy(*data_out, data, (size_t)data_len);
6115 *out_data_len=data_len;
6117 safe_free(data);
6119 return WERR_OK;
6122 /****************************************************************************
6123 ****************************************************************************/
6125 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6127 POLICY_HND *handle = &q_u->handle;
6128 UNISTR2 *value = &q_u->value;
6129 uint32 type = q_u->type;
6130 /* uint32 max_len = q_u->max_len; - notused. */
6131 uint8 *data = q_u->data;
6132 uint32 real_len = q_u->real_len;
6133 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6135 NT_PRINTER_INFO_LEVEL *printer = NULL;
6136 NT_PRINTER_PARAM *param = NULL, old_param;
6137 int snum=0;
6138 WERROR status = WERR_OK;
6139 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6141 DEBUG(5,("spoolss_setprinterdata\n"));
6143 if (!Printer) {
6144 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6145 return WERR_BADFID;
6148 if (!get_printer_snum(p,handle, &snum))
6149 return WERR_BADFID;
6151 status = get_a_printer(&printer, 2, lp_servicename(snum));
6152 if (!W_ERROR_IS_OK(status))
6153 return status;
6155 convert_specific_param(&param, value , type, data, real_len);
6157 ZERO_STRUCT(old_param);
6160 * Access check : NT returns "access denied" if you make a
6161 * SetPrinterData call without the necessary privildge.
6162 * we were originally returning OK if nothing changed
6163 * which made Win2k issue **a lot** of SetPrinterData
6164 * when connecting to a printer --jerry
6167 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6168 DEBUG(3, ("security descriptor change denied by existing "
6169 "security descriptor\n"));
6170 status = ERROR_ACCESS_DENIED;
6171 goto done;
6175 /* Check if we are making any changes or not. Return true if
6176 nothing is actually changing. This is not needed anymore but
6177 has been left in as an optimization to keep from from
6178 writing to disk as often --jerry */
6180 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6181 &old_param.type, (uint32 *)&old_param.data_len)) {
6183 if (param->type == old_param.type &&
6184 param->data_len == old_param.data_len &&
6185 memcmp(param->data, old_param.data,
6186 old_param.data_len) == 0) {
6188 DEBUG(3, ("setprinterdata hasn't changed\n"));
6189 status = WERR_OK;
6190 goto done;
6194 unlink_specific_param_if_exist(printer->info_2, param);
6197 * When client side code sets a magic printer data key, detect it and save
6198 * the current printer data and the magic key's data (its the DEVMODE) for
6199 * future printer/driver initializations.
6201 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6203 * Set devmode and printer initialization info
6205 status = save_driver_init(printer, 2, param);
6207 else {
6208 add_a_specific_param(printer->info_2, &param);
6209 status = mod_a_printer(*printer, 2);
6212 done:
6213 free_a_printer(&printer, 2);
6214 if (param)
6215 free_nt_printer_param(&param);
6216 safe_free(old_param.data);
6218 return status;
6221 /****************************************************************************
6222 ****************************************************************************/
6224 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6226 POLICY_HND *handle = &q_u->handle;
6227 UNISTR2 *value = &q_u->valuename;
6229 NT_PRINTER_INFO_LEVEL *printer = NULL;
6230 NT_PRINTER_PARAM param;
6231 int snum=0;
6232 WERROR status = WERR_OK;
6233 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6235 DEBUG(5,("spoolss_deleteprinterdata\n"));
6237 if (!Printer) {
6238 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6239 return WERR_BADFID;
6242 if (!get_printer_snum(p, handle, &snum))
6243 return WERR_BADFID;
6245 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6246 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6247 "change denied by existing security descriptor\n"));
6248 return WERR_ACCESS_DENIED;
6251 status = get_a_printer(&printer, 2, lp_servicename(snum));
6252 if (!W_ERROR_IS_OK(status))
6253 return status;
6255 ZERO_STRUCTP(&param);
6256 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6258 if(!unlink_specific_param_if_exist(printer->info_2, &param))
6259 status = WERR_INVALID_PARAM;
6260 else
6261 status = mod_a_printer(*printer, 2);
6263 free_a_printer(&printer, 2);
6264 return status;
6267 /****************************************************************************
6268 ****************************************************************************/
6270 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6272 POLICY_HND *handle = &q_u->handle;
6273 /* uint32 level = q_u->level; - notused. */
6274 FORM *form = &q_u->form;
6275 nt_forms_struct tmpForm;
6277 int count=0;
6278 nt_forms_struct *list=NULL;
6279 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6281 DEBUG(5,("spoolss_addform\n"));
6283 if (!Printer) {
6284 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6285 return WERR_BADFID;
6288 /* can't add if builtin */
6289 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6290 return WERR_INVALID_PARAM;
6293 count=get_ntforms(&list);
6294 if(!add_a_form(&list, form, &count))
6295 return WERR_NOMEM;
6296 write_ntforms(&list, count);
6298 safe_free(list);
6300 return WERR_OK;
6303 /****************************************************************************
6304 ****************************************************************************/
6306 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6308 POLICY_HND *handle = &q_u->handle;
6309 UNISTR2 *form_name = &q_u->name;
6310 nt_forms_struct tmpForm;
6311 int count=0;
6312 WERROR ret = WERR_OK;
6313 nt_forms_struct *list=NULL;
6314 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6316 DEBUG(5,("spoolss_deleteform\n"));
6318 if (!Printer) {
6319 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6320 return WERR_BADFID;
6323 /* can't delete if builtin */
6324 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6325 return WERR_INVALID_PARAM;
6328 count = get_ntforms(&list);
6329 if (!delete_a_form(&list, form_name, &count, &ret))
6330 return WERR_INVALID_PARAM;
6332 safe_free(list);
6334 return ret;
6337 /****************************************************************************
6338 ****************************************************************************/
6340 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6342 POLICY_HND *handle = &q_u->handle;
6343 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6344 /* uint32 level = q_u->level; - notused. */
6345 FORM *form = &q_u->form;
6346 nt_forms_struct tmpForm;
6348 int count=0;
6349 nt_forms_struct *list=NULL;
6350 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6352 DEBUG(5,("spoolss_setform\n"));
6354 if (!Printer) {
6355 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6356 return WERR_BADFID;
6358 /* can't set if builtin */
6359 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6360 return WERR_INVALID_PARAM;
6363 count=get_ntforms(&list);
6364 update_a_form(&list, form, count);
6365 write_ntforms(&list, count);
6367 safe_free(list);
6369 return WERR_OK;
6372 /****************************************************************************
6373 enumprintprocessors level 1.
6374 ****************************************************************************/
6375 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6377 PRINTPROCESSOR_1 *info_1=NULL;
6379 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6380 return WERR_NOMEM;
6382 (*returned) = 0x1;
6384 init_unistr(&info_1->name, "winprint");
6386 *needed += spoolss_size_printprocessor_info_1(info_1);
6388 if (!alloc_buffer_size(buffer, *needed))
6389 return WERR_INSUFFICIENT_BUFFER;
6391 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6393 safe_free(info_1);
6395 if (*needed > offered) {
6396 *returned=0;
6397 return WERR_INSUFFICIENT_BUFFER;
6400 return WERR_OK;
6403 /****************************************************************************
6404 ****************************************************************************/
6406 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6408 /* UNISTR2 *name = &q_u->name; - notused. */
6409 /* UNISTR2 *environment = &q_u->environment; - notused. */
6410 uint32 level = q_u->level;
6411 NEW_BUFFER *buffer = NULL;
6412 uint32 offered = q_u->offered;
6413 uint32 *needed = &r_u->needed;
6414 uint32 *returned = &r_u->returned;
6416 /* that's an [in out] buffer */
6417 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6418 buffer = r_u->buffer;
6420 DEBUG(5,("spoolss_enumprintprocessors\n"));
6423 * Enumerate the print processors ...
6425 * Just reply with "winprint", to keep NT happy
6426 * and I can use my nice printer checker.
6429 *returned=0;
6430 *needed=0;
6432 switch (level) {
6433 case 1:
6434 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6435 default:
6436 return WERR_UNKNOWN_LEVEL;
6440 /****************************************************************************
6441 enumprintprocdatatypes level 1.
6442 ****************************************************************************/
6443 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6445 PRINTPROCDATATYPE_1 *info_1=NULL;
6447 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6448 return WERR_NOMEM;
6450 (*returned) = 0x1;
6452 init_unistr(&info_1->name, "RAW");
6454 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6456 if (!alloc_buffer_size(buffer, *needed))
6457 return WERR_INSUFFICIENT_BUFFER;
6459 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6461 safe_free(info_1);
6463 if (*needed > offered) {
6464 *returned=0;
6465 return WERR_INSUFFICIENT_BUFFER;
6468 return WERR_OK;
6471 /****************************************************************************
6472 ****************************************************************************/
6474 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6476 /* UNISTR2 *name = &q_u->name; - notused. */
6477 /* UNISTR2 *processor = &q_u->processor; - notused. */
6478 uint32 level = q_u->level;
6479 NEW_BUFFER *buffer = NULL;
6480 uint32 offered = q_u->offered;
6481 uint32 *needed = &r_u->needed;
6482 uint32 *returned = &r_u->returned;
6484 /* that's an [in out] buffer */
6485 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6486 buffer = r_u->buffer;
6488 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6490 *returned=0;
6491 *needed=0;
6493 switch (level) {
6494 case 1:
6495 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6496 default:
6497 return WERR_UNKNOWN_LEVEL;
6501 /****************************************************************************
6502 enumprintmonitors level 1.
6503 ****************************************************************************/
6505 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6507 PRINTMONITOR_1 *info_1=NULL;
6509 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6510 return WERR_NOMEM;
6512 (*returned) = 0x1;
6514 init_unistr(&info_1->name, "Local Port");
6516 *needed += spoolss_size_printmonitor_info_1(info_1);
6518 if (!alloc_buffer_size(buffer, *needed))
6519 return WERR_INSUFFICIENT_BUFFER;
6521 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6523 safe_free(info_1);
6525 if (*needed > offered) {
6526 *returned=0;
6527 return WERR_INSUFFICIENT_BUFFER;
6530 return WERR_OK;
6533 /****************************************************************************
6534 enumprintmonitors level 2.
6535 ****************************************************************************/
6536 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6538 PRINTMONITOR_2 *info_2=NULL;
6540 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6541 return WERR_NOMEM;
6543 (*returned) = 0x1;
6545 init_unistr(&info_2->name, "Local Port");
6546 init_unistr(&info_2->environment, "Windows NT X86");
6547 init_unistr(&info_2->dll_name, "localmon.dll");
6549 *needed += spoolss_size_printmonitor_info_2(info_2);
6551 if (!alloc_buffer_size(buffer, *needed))
6552 return WERR_INSUFFICIENT_BUFFER;
6554 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6556 safe_free(info_2);
6558 if (*needed > offered) {
6559 *returned=0;
6560 return WERR_INSUFFICIENT_BUFFER;
6563 return WERR_OK;
6566 /****************************************************************************
6567 ****************************************************************************/
6569 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6571 /* UNISTR2 *name = &q_u->name; - notused. */
6572 uint32 level = q_u->level;
6573 NEW_BUFFER *buffer = NULL;
6574 uint32 offered = q_u->offered;
6575 uint32 *needed = &r_u->needed;
6576 uint32 *returned = &r_u->returned;
6578 /* that's an [in out] buffer */
6579 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6580 buffer = r_u->buffer;
6582 DEBUG(5,("spoolss_enumprintmonitors\n"));
6585 * Enumerate the print monitors ...
6587 * Just reply with "Local Port", to keep NT happy
6588 * and I can use my nice printer checker.
6591 *returned=0;
6592 *needed=0;
6594 switch (level) {
6595 case 1:
6596 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6597 case 2:
6598 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6599 default:
6600 return WERR_UNKNOWN_LEVEL;
6604 /****************************************************************************
6605 ****************************************************************************/
6606 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6608 int i=0;
6609 BOOL found=False;
6610 JOB_INFO_1 *info_1=NULL;
6612 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6614 if (info_1 == NULL) {
6615 safe_free(queue);
6616 return WERR_NOMEM;
6619 for (i=0; i<count && found==False; i++) {
6620 if (queue[i].job==(int)jobid)
6621 found=True;
6624 if (found==False) {
6625 safe_free(queue);
6626 safe_free(info_1);
6627 /* I shoud reply something else ... I can't find the good one */
6628 return WERR_OK;
6631 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6633 safe_free(queue);
6635 *needed += spoolss_size_job_info_1(info_1);
6637 if (!alloc_buffer_size(buffer, *needed)) {
6638 safe_free(info_1);
6639 return WERR_INSUFFICIENT_BUFFER;
6642 smb_io_job_info_1("", buffer, info_1, 0);
6644 safe_free(info_1);
6646 if (*needed > offered)
6647 return WERR_INSUFFICIENT_BUFFER;
6649 return WERR_OK;
6653 /****************************************************************************
6654 ****************************************************************************/
6655 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6657 int i=0;
6658 BOOL found=False;
6659 JOB_INFO_2 *info_2;
6660 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6661 WERROR ret;
6663 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6665 ZERO_STRUCTP(info_2);
6667 if (info_2 == NULL) {
6668 safe_free(queue);
6669 return WERR_NOMEM;
6672 for (i=0; i<count && found==False; i++) {
6673 if (queue[i].job==(int)jobid)
6674 found=True;
6677 if (found==False) {
6678 safe_free(queue);
6679 safe_free(info_2);
6680 /* I shoud reply something else ... I can't find the good one */
6681 return WERR_OK;
6684 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6685 if (!W_ERROR_IS_OK(ret)) {
6686 safe_free(queue);
6687 return ret;
6690 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6692 free_a_printer(&ntprinter, 2);
6693 safe_free(queue);
6695 *needed += spoolss_size_job_info_2(info_2);
6697 if (!alloc_buffer_size(buffer, *needed)) {
6698 safe_free(info_2);
6699 return WERR_INSUFFICIENT_BUFFER;
6702 smb_io_job_info_2("", buffer, info_2, 0);
6704 free_job_info_2(info_2);
6705 free(info_2);
6707 if (*needed > offered)
6708 return WERR_INSUFFICIENT_BUFFER;
6710 return WERR_OK;
6713 /****************************************************************************
6714 ****************************************************************************/
6716 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6718 POLICY_HND *handle = &q_u->handle;
6719 uint32 jobid = q_u->jobid;
6720 uint32 level = q_u->level;
6721 NEW_BUFFER *buffer = NULL;
6722 uint32 offered = q_u->offered;
6723 uint32 *needed = &r_u->needed;
6725 int snum;
6726 int count;
6727 print_queue_struct *queue=NULL;
6728 print_status_struct prt_status;
6730 /* that's an [in out] buffer */
6731 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6732 buffer = r_u->buffer;
6734 DEBUG(5,("spoolss_getjob\n"));
6736 memset(&prt_status, 0, sizeof(prt_status));
6738 *needed=0;
6740 if (!get_printer_snum(p, handle, &snum))
6741 return WERR_BADFID;
6743 count = print_queue_status(snum, &queue, &prt_status);
6745 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6746 count, prt_status.status, prt_status.message));
6748 switch (level) {
6749 case 1:
6750 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6751 case 2:
6752 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6753 default:
6754 safe_free(queue);
6755 return WERR_UNKNOWN_LEVEL;