Improved efficiency of enumerating print queue's under a particular
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_spoolss_nt.c
blobd49cee0d25b409b86367e9f2dc6621a25fb93057
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.
9 * Copyright (C) Gerald Carter 2000-2001.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
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 if (*pp == NULL)
145 return;
147 SAFE_FREE((*pp)->ctr.type);
148 SAFE_FREE(*pp);
151 /***************************************************************************
152 Disconnect from the client
153 ****************************************************************************/
155 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
157 WERROR status;
159 /* weird if the test succeds !!! */
160 if (smb_connections==0) {
161 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
162 return;
165 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
166 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
168 /* if it's the last connection, deconnect the IPC$ share */
169 if (smb_connections==1) {
170 if(!spoolss_disconnect_from_client(&cli))
171 return;
173 message_deregister(MSG_PRINTER_NOTIFY);
176 smb_connections--;
179 /****************************************************************************
180 Functions to free a printer entry datastruct.
181 ****************************************************************************/
183 static void free_printer_entry(void *ptr)
185 Printer_entry *Printer = (Printer_entry *)ptr;
187 if (Printer->notify.client_connected==True)
188 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
190 Printer->notify.flags=0;
191 Printer->notify.options=0;
192 Printer->notify.localmachine[0]='\0';
193 Printer->notify.printerlocal=0;
194 free_spool_notify_option(&Printer->notify.option);
195 Printer->notify.option=NULL;
196 Printer->notify.client_connected=False;
198 SAFE_FREE(Printer);
201 /****************************************************************************
202 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
203 ****************************************************************************/
205 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
207 SPOOL_NOTIFY_OPTION *new_sp = NULL;
209 if (!sp)
210 return NULL;
212 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
213 if (!new_sp)
214 return NULL;
216 *new_sp = *sp;
218 if (sp->ctr.count) {
219 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
221 if (!new_sp->ctr.type) {
222 SAFE_FREE(new_sp);
223 return NULL;
227 return new_sp;
230 /****************************************************************************
231 find printer index by handle
232 ****************************************************************************/
234 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
236 Printer_entry *find_printer = NULL;
238 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
239 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
240 return NULL;
243 return find_printer;
246 /****************************************************************************
247 close printer index by handle
248 ****************************************************************************/
250 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
252 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
254 if (!Printer) {
255 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
256 return False;
259 close_policy_hnd(p, hnd);
261 return True;
264 /****************************************************************************
265 delete a printer given a handle
266 ****************************************************************************/
267 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
269 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
271 if (!Printer) {
272 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
273 return WERR_BADFID;
276 if (del_a_printer(Printer->dev.handlename) != 0) {
277 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
278 return WERR_BADFID;
281 /* Check calling user has permission to delete printer. Note that
282 since we set the snum parameter to -1 only administrators can
283 delete the printer. This stops people with the Full Control
284 permission from deleting the printer. */
286 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
287 DEBUG(3, ("printer delete denied by security descriptor\n"));
288 return WERR_ACCESS_DENIED;
291 if (*lp_deleteprinter_cmd()) {
293 char *cmd = lp_deleteprinter_cmd();
294 pstring command;
295 int ret;
296 int i;
298 /* Printer->dev.handlename equals portname equals sharename */
299 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
300 Printer->dev.handlename);
302 DEBUG(10,("Running [%s]\n", command));
303 ret = smbrun(command, NULL);
304 if (ret != 0) {
305 return WERR_BADFID; /* What to return here? */
307 DEBUGADD(10,("returned [%d]\n", ret));
309 /* Send SIGHUP to process group... is there a better way? */
310 kill(0, SIGHUP);
312 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
313 lp_killservice( i );
314 return WERR_OK;
315 } else
316 return WERR_ACCESS_DENIED;
319 return WERR_OK;
322 /****************************************************************************
323 return the snum of a printer corresponding to an handle
324 ****************************************************************************/
325 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
327 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
329 if (!Printer) {
330 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
331 return False;
334 switch (Printer->printer_type) {
335 case PRINTER_HANDLE_IS_PRINTER:
336 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
337 *number = print_queue_snum(Printer->dev.handlename);
338 return (*number != -1);
339 case PRINTER_HANDLE_IS_PRINTSERVER:
340 return False;
341 default:
342 return False;
346 /****************************************************************************
347 set printer handle type.
348 ****************************************************************************/
349 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
351 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
353 if (!Printer) {
354 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
355 return False;
358 DEBUG(4,("Setting printer access=%x\n", access_required));
359 Printer->access = access_required;
360 return True;
363 /****************************************************************************
364 Set printer handle type.
365 Check if it's \\server or \\server\printer
366 ****************************************************************************/
368 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
370 DEBUG(3,("Setting printer type=%s\n", handlename));
372 if ( strlen(handlename) < 3 ) {
373 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
374 return False;
377 /* it's a print server */
378 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
379 DEBUGADD(4,("Printer is a print server\n"));
380 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
382 /* it's a printer */
383 else {
384 DEBUGADD(4,("Printer is a printer\n"));
385 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
388 return True;
391 /****************************************************************************
392 Set printer handle name.
393 ****************************************************************************/
395 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
397 NT_PRINTER_INFO_LEVEL *printer = NULL;
398 int snum;
399 int n_services=lp_numservices();
400 char *aprinter;
401 BOOL found=False;
403 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
405 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
406 ZERO_STRUCT(Printer->dev.printerservername);
407 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
408 return True;
411 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
412 return False;
414 if (*handlename=='\\') {
415 aprinter=strchr_m(handlename+2, '\\');
416 aprinter++;
418 else {
419 aprinter=handlename;
422 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
425 * store the Samba share name in it
426 * in back we have the long printer name
427 * need to iterate all the snum and do a
428 * get_a_printer each time to find the printer
429 * faster to do it here than later.
432 for (snum=0;snum<n_services && found==False;snum++) {
433 char *printername;
435 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
436 continue;
438 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
440 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
441 continue;
443 printername=strchr_m(printer->info_2->printername+2, '\\');
444 printername++;
446 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
447 printer->info_2->printername, aprinter ));
449 if ( strlen(printername) != strlen(aprinter) ) {
450 free_a_printer(&printer, 2);
451 continue;
454 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
455 free_a_printer(&printer, 2);
456 continue;
459 found=True;
463 * if we haven't found a printer with the given handlename
464 * then it can be a share name as you can open both \\server\printer and
465 * \\server\share
469 * we still check if the printer description file exists as NT won't be happy
470 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
473 if (found==False) {
474 DEBUGADD(5,("Printer not found, checking for share now\n"));
476 for (snum=0;snum<n_services && found==False;snum++) {
478 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
479 continue;
481 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
483 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
484 continue;
486 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
487 printer->info_2->printername, aprinter ));
489 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
490 free_a_printer(&printer, 2);
491 continue;
494 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
495 free_a_printer(&printer, 2);
496 continue;
499 found=True;
503 if (found==False) {
504 DEBUGADD(4,("Printer not found\n"));
505 return False;
508 snum--;
509 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
510 printer->info_2->printername, lp_servicename(snum),snum));
512 ZERO_STRUCT(Printer->dev.handlename);
513 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
515 free_a_printer(&printer, 2);
517 return True;
520 /****************************************************************************
521 find first available printer slot. creates a printer handle for you.
522 ****************************************************************************/
524 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
526 Printer_entry *new_printer;
528 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
530 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
531 return False;
533 ZERO_STRUCTP(new_printer);
535 new_printer->notify.option=NULL;
537 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
538 SAFE_FREE(new_printer);
539 return False;
542 if (!set_printer_hnd_printertype(new_printer, name)) {
543 close_printer_handle(p, hnd);
544 return False;
547 if (!set_printer_hnd_name(new_printer, name)) {
548 close_printer_handle(p, hnd);
549 return False;
552 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
554 return True;
557 /********************************************************************
558 Return True is the handle is a print server.
559 ********************************************************************/
561 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
563 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
565 if (!Printer)
566 return False;
568 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
569 return False;
571 return True;
574 /****************************************************************************
575 allocate more memory for a BUFFER.
576 ****************************************************************************/
577 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
579 prs_struct *ps;
580 uint32 extra_space;
581 uint32 old_offset;
583 ps= &buffer->prs;
585 /* damn, I'm doing the reverse operation of prs_grow() :) */
586 if (buffer_size < prs_data_size(ps))
587 extra_space=0;
588 else
589 extra_space = buffer_size - prs_data_size(ps);
592 * save the offset and move to the end of the buffer
593 * prs_grow() checks the extra_space against the offset
595 old_offset=prs_offset(ps);
596 prs_set_offset(ps, prs_data_size(ps));
598 if (!prs_grow(ps, extra_space))
599 return False;
601 prs_set_offset(ps, old_offset);
603 buffer->string_at_end=prs_data_size(ps);
605 return True;
608 /***************************************************************************
609 receive the notify message
610 ****************************************************************************/
612 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
614 fstring printer;
615 WERROR status;
616 struct pipes_struct *p;
617 struct policy *pol;
618 struct handle_list *hl;
620 *printer = '\0';
621 fstrcpy(printer,buf);
623 if (len == 0) {
624 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
625 return;
628 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
631 * We need to enumerate all printers. The handle list is shared
632 * across pipes of the same name, so just find the first open
633 * spoolss pipe.
636 hl = NULL;
637 for ( p = get_first_pipe(); p; get_next_pipe(p)) {
638 if (strequal(p->name, "spoolss")) {
639 hl = p->pipe_handles;
640 break;
644 if (!hl) {
645 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
646 return;
649 /* Iterate the printer list on this pipe. */
650 for (pol = hl->Policy; pol; pol = pol->next ) {
651 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
653 if (!find_printer)
654 continue;
657 * if the entry is the given printer or if it's a printerserver
658 * we send the message
661 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
662 if (strcmp(find_printer->dev.handlename, printer))
663 continue;
665 if (find_printer->notify.client_connected==True)
666 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
670 /***************************************************************************
671 send a notify event
672 ****************************************************************************/
673 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
675 fstring printer;
677 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
679 if (!Printer) {
680 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
681 return False;
684 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
685 fstrcpy(printer, Printer->dev.handlename);
686 else
687 fstrcpy(printer, "");
689 /*srv_spoolss_receive_message(printer);*/
690 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
692 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
694 return True;
697 /********************************************************************
698 * spoolss_open_printer
700 * called from the spoolss dispatcher
701 ********************************************************************/
703 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
705 #if 0
706 WERROR result = WERR_OK;
707 #endif
709 UNISTR2 *printername = NULL;
710 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
711 /* uint32 user_switch = q_u->user_switch; - notused */
712 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
713 POLICY_HND *handle = &r_u->handle;
715 fstring name;
716 int snum;
717 struct current_user user;
719 if (q_u->printername_ptr != 0)
720 printername = &q_u->printername;
722 if (printername == NULL)
723 return WERR_INVALID_PRINTER_NAME;
725 /* some sanity check because you can open a printer or a print server */
726 /* aka: \\server\printer or \\server */
727 unistr2_to_ascii(name, printername, sizeof(name)-1);
729 DEBUGADD(3,("checking name: %s\n",name));
731 if (!open_printer_hnd(p, handle, name))
732 return WERR_INVALID_PRINTER_NAME;
735 if (printer_default->datatype_ptr != NULL)
737 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
738 set_printer_hnd_datatype(handle, datatype);
740 else
741 set_printer_hnd_datatype(handle, "");
744 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
745 close_printer_handle(p, handle);
746 return WERR_ACCESS_DENIED;
750 First case: the user is opening the print server:
752 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
753 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
755 Then both Win2k and WinNT clients try an OpenPrinterEx with
756 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
757 or if the user is listed in the smb.conf printer admin parameter.
759 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
760 client view printer folder, but does not show the MSAPW.
762 Note: this test needs code to check access rights here too. Jeremy
763 could you look at this?
766 Second case: the user is opening a printer:
767 NT doesn't let us connect to a printer if the connecting user
768 doesn't have print permission.
772 get_current_user(&user, p);
774 if (handle_is_printserver(p, handle)) {
775 if (printer_default->access_required == 0) {
776 return WERR_OK;
778 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
780 /* Printserver handles use global struct... */
781 snum = -1;
783 if (!lp_ms_add_printer_wizard()) {
784 close_printer_handle(p, handle);
785 return WERR_ACCESS_DENIED;
787 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
788 return WERR_OK;
790 else {
791 close_printer_handle(p, handle);
792 return WERR_ACCESS_DENIED;
796 else
798 /* NT doesn't let us connect to a printer if the connecting user
799 doesn't have print permission. */
801 if (!get_printer_snum(p, handle, &snum))
802 return WERR_BADFID;
804 /* map an empty access mask to the minimum access mask */
805 if (printer_default->access_required == 0x0)
806 printer_default->access_required = PRINTER_ACCESS_USE;
810 * If we are not serving the printer driver for this printer,
811 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
812 * will keep NT clients happy --jerry
815 if (lp_use_client_driver(snum)
816 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
818 printer_default->access_required = PRINTER_ACCESS_USE;
821 if (!print_access_check(&user, snum, printer_default->access_required)) {
822 DEBUG(3, ("access DENIED for printer open\n"));
823 close_printer_handle(p, handle);
824 return WERR_ACCESS_DENIED;
828 * If we have a default device pointer in the
829 * printer_default struct, then we need to get
830 * the printer info from the tdb and if there is
831 * no default devicemode there then we do a *SET*
832 * here ! This is insanity.... JRA.
836 * If the openprinterex rpc call contains a devmode,
837 * it's a per-user one. This per-user devmode is derivated
838 * from the global devmode. Openprinterex() contains a per-user
839 * devmode for when you do EMF printing and spooling.
840 * In the EMF case, the NT workstation is only doing half the job
841 * of rendering the page. The other half is done by running the printer
842 * driver on the server.
843 * The EMF file doesn't contain the page description (paper size, orientation, ...).
844 * The EMF file only contains what is to be printed on the page.
845 * So in order for the server to know how to print, the NT client sends
846 * a devicemode attached to the openprinterex call.
847 * But this devicemode is short lived, it's only valid for the current print job.
849 * If Samba would have supported EMF spooling, this devicemode would
850 * have been attached to the handle, to sent it to the driver to correctly
851 * rasterize the EMF file.
853 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
854 * we just act as a pass-thru between windows and the printer.
856 * In order to know that Samba supports only RAW spooling, NT has to call
857 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
858 * and until NT sends a RAW job, we refuse it.
860 * But to call getprinter() or startdoc(), you first need a valid handle,
861 * and to get an handle you have to call openprintex(). Hence why you have
862 * a devicemode in the openprinterex() call.
865 * Differences between NT4 and NT 2000.
866 * NT4:
867 * ---
868 * On NT4, you only have a global devicemode. This global devicemode can be changed
869 * by the administrator (or by a user with enough privs). Everytime a user
870 * wants to print, the devicemode is resetted to the default. In Word, everytime
871 * you print, the printer's characteristics are always reset to the global devicemode.
873 * NT 2000:
874 * -------
875 * In W2K, there is the notion of per-user devicemode. The first time you use
876 * a printer, a per-user devicemode is build from the global devicemode.
877 * If you change your per-user devicemode, it is saved in the registry, under the
878 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
879 * printer preferences available.
881 * To change the per-user devicemode: it's the "Printing Preferences ..." button
882 * on the General Tab of the printer properties windows.
884 * To change the global devicemode: it's the "Printing Defaults..." button
885 * on the Advanced Tab of the printer properties window.
887 * JFM.
892 #if 0
893 if (printer_default->devmode_cont.devmode != NULL) {
894 result = printer_write_default_dev( snum, printer_default);
895 if (result != 0) {
896 close_printer_handle(p, handle);
897 return result;
900 #endif
903 return WERR_OK;
906 /****************************************************************************
907 ****************************************************************************/
908 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
909 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
911 BOOL ret = True;
913 switch (level) {
914 case 2:
915 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
916 break;
917 default:
918 break;
921 return ret;
924 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
925 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
927 BOOL result = True;
929 switch (level) {
930 case 3:
931 printer->info_3=NULL;
932 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
933 result = False;
934 break;
935 case 6:
936 printer->info_6=NULL;
937 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
938 result = False;
939 break;
940 default:
941 break;
944 return result;
947 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
948 NT_DEVICEMODE **pp_nt_devmode)
950 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
953 * Ensure nt_devmode is a valid pointer
954 * as we will be overwriting it.
957 if (nt_devmode == NULL) {
958 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
959 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
960 return False;
963 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
964 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
966 nt_devmode->specversion=devmode->specversion;
967 nt_devmode->driverversion=devmode->driverversion;
968 nt_devmode->size=devmode->size;
969 nt_devmode->fields=devmode->fields;
970 nt_devmode->orientation=devmode->orientation;
971 nt_devmode->papersize=devmode->papersize;
972 nt_devmode->paperlength=devmode->paperlength;
973 nt_devmode->paperwidth=devmode->paperwidth;
974 nt_devmode->scale=devmode->scale;
975 nt_devmode->copies=devmode->copies;
976 nt_devmode->defaultsource=devmode->defaultsource;
977 nt_devmode->printquality=devmode->printquality;
978 nt_devmode->color=devmode->color;
979 nt_devmode->duplex=devmode->duplex;
980 nt_devmode->yresolution=devmode->yresolution;
981 nt_devmode->ttoption=devmode->ttoption;
982 nt_devmode->collate=devmode->collate;
984 nt_devmode->logpixels=devmode->logpixels;
985 nt_devmode->bitsperpel=devmode->bitsperpel;
986 nt_devmode->pelswidth=devmode->pelswidth;
987 nt_devmode->pelsheight=devmode->pelsheight;
988 nt_devmode->displayflags=devmode->displayflags;
989 nt_devmode->displayfrequency=devmode->displayfrequency;
990 nt_devmode->icmmethod=devmode->icmmethod;
991 nt_devmode->icmintent=devmode->icmintent;
992 nt_devmode->mediatype=devmode->mediatype;
993 nt_devmode->dithertype=devmode->dithertype;
994 nt_devmode->reserved1=devmode->reserved1;
995 nt_devmode->reserved2=devmode->reserved2;
996 nt_devmode->panningwidth=devmode->panningwidth;
997 nt_devmode->panningheight=devmode->panningheight;
1000 * Only change private and driverextra if the incoming devmode
1001 * has a new one. JRA.
1004 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1005 SAFE_FREE(nt_devmode->private);
1006 nt_devmode->driverextra=devmode->driverextra;
1007 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1008 return False;
1009 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1012 *pp_nt_devmode = nt_devmode;
1014 return True;
1017 /********************************************************************
1018 * _spoolss_enddocprinter_internal.
1019 ********************************************************************/
1021 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1023 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1025 if (!Printer) {
1026 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1027 return WERR_BADFID;
1030 Printer->document_started=False;
1031 print_job_end(Printer->jobid,True);
1032 /* error codes unhandled so far ... */
1034 return WERR_OK;
1037 /********************************************************************
1038 * api_spoolss_closeprinter
1039 ********************************************************************/
1041 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1043 POLICY_HND *handle = &q_u->handle;
1045 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1047 if (Printer && Printer->document_started)
1048 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1050 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1052 if (!close_printer_handle(p, handle))
1053 return WERR_BADFID;
1055 return WERR_OK;
1058 /********************************************************************
1059 * api_spoolss_deleteprinter
1061 ********************************************************************/
1063 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1065 POLICY_HND *handle = &q_u->handle;
1066 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1067 WERROR result;
1069 if (Printer && Printer->document_started)
1070 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1072 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1074 result = delete_printer_handle(p, handle);
1076 if (W_ERROR_IS_OK(result)) {
1077 srv_spoolss_sendnotify(p, handle);
1080 return result;
1083 /*******************************************************************
1084 * static function to lookup the version id corresponding to an
1085 * long architecture string
1086 ******************************************************************/
1087 static int get_version_id (char * arch)
1089 int i;
1090 struct table_node archi_table[]= {
1092 {"Windows 4.0", "WIN40", 0 },
1093 {"Windows NT x86", "W32X86", 2 },
1094 {"Windows NT R4000", "W32MIPS", 2 },
1095 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1096 {"Windows NT PowerPC", "W32PPC", 2 },
1097 {NULL, "", -1 }
1100 for (i=0; archi_table[i].long_archi != NULL; i++)
1102 if (strcmp(arch, archi_table[i].long_archi) == 0)
1103 return (archi_table[i].version);
1106 return -1;
1109 /********************************************************************
1110 * _spoolss_deleteprinterdriver
1112 * We currently delete the driver for the architecture only.
1113 * This can leave the driver for other archtectures. However,
1114 * since every printer associates a "Windows NT x86" driver name
1115 * and we cannot delete that one while it is in use, **and** since
1116 * it is impossible to assign a driver to a Samba printer without
1117 * having the "Windows NT x86" driver installed,...
1119 * ....we should not get into trouble here.
1121 * --jerry
1122 ********************************************************************/
1124 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1125 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1127 fstring driver;
1128 fstring arch;
1129 NT_PRINTER_DRIVER_INFO_LEVEL info;
1130 int version;
1132 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1133 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1135 /* check that we have a valid driver name first */
1136 if ((version=get_version_id(arch)) == -1) {
1137 /* this is what NT returns */
1138 return WERR_INVALID_ENVIRONMENT;
1141 ZERO_STRUCT(info);
1142 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1143 return WERR_UNKNOWN_PRINTER_DRIVER;
1147 if (printer_driver_in_use(arch, driver))
1149 return WERR_PRINTER_DRIVER_IN_USE;
1152 return delete_printer_driver(info.info_3);
1156 /********************************************************************
1157 GetPrinterData on a printer server Handle.
1158 ********************************************************************/
1159 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1161 int i;
1163 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1165 if (!strcmp(value, "BeepEnabled")) {
1166 *type = 0x4;
1167 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1168 return False;
1169 SIVAL(*data, 0, 0x01);
1170 *needed = 0x4;
1171 return True;
1174 if (!strcmp(value, "EventLog")) {
1175 *type = 0x4;
1176 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1177 return False;
1178 SIVAL(*data, 0, 0x1B);
1179 *needed = 0x4;
1180 return True;
1183 if (!strcmp(value, "NetPopup")) {
1184 *type = 0x4;
1185 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1186 return False;
1187 SIVAL(*data, 0, 0x01);
1188 *needed = 0x4;
1189 return True;
1192 if (!strcmp(value, "MajorVersion")) {
1193 *type = 0x4;
1194 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1195 return False;
1196 SIVAL(*data, 0, 0x02);
1197 *needed = 0x4;
1198 return True;
1201 if (!strcmp(value, "DefaultSpoolDirectory")) {
1202 pstring string="You are using a Samba server";
1203 *type = 0x1;
1204 *needed = 2*(strlen(string)+1);
1205 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1206 return False;
1207 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1209 /* it's done by hand ready to go on the wire */
1210 for (i=0; i<strlen(string); i++) {
1211 (*data)[2*i]=string[i];
1212 (*data)[2*i+1]='\0';
1214 return True;
1217 if (!strcmp(value, "Architecture")) {
1218 pstring string="Windows NT x86";
1219 *type = 0x1;
1220 *needed = 2*(strlen(string)+1);
1221 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1222 return False;
1223 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1224 for (i=0; i<strlen(string); i++) {
1225 (*data)[2*i]=string[i];
1226 (*data)[2*i+1]='\0';
1228 return True;
1231 return False;
1234 /********************************************************************
1235 GetPrinterData on a printer Handle.
1236 ********************************************************************/
1237 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1238 fstring value, uint32 *type,
1239 uint8 **data, uint32 *needed, uint32 in_size )
1241 NT_PRINTER_INFO_LEVEL *printer = NULL;
1242 int snum=0;
1243 uint8 *idata=NULL;
1244 uint32 len;
1245 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1247 DEBUG(5,("getprinterdata_printer\n"));
1249 if (!Printer) {
1250 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1251 return False;
1254 if(!get_printer_snum(p, handle, &snum))
1255 return False;
1257 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1258 return False;
1260 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1261 free_a_printer(&printer, 2);
1262 return False;
1265 free_a_printer(&printer, 2);
1267 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1269 if (in_size) {
1270 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1271 return False;
1274 memset(*data, 0, in_size *sizeof(uint8));
1275 /* copy the min(in_size, len) */
1276 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1277 } else {
1278 *data = NULL;
1281 *needed = len;
1283 DEBUG(5,("getprinterdata_printer:copy done\n"));
1285 SAFE_FREE(idata);
1287 return True;
1290 /********************************************************************
1291 * spoolss_getprinterdata
1292 ********************************************************************/
1294 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1296 POLICY_HND *handle = &q_u->handle;
1297 UNISTR2 *valuename = &q_u->valuename;
1298 uint32 in_size = q_u->size;
1299 uint32 *type = &r_u->type;
1300 uint32 *out_size = &r_u->size;
1301 uint8 **data = &r_u->data;
1302 uint32 *needed = &r_u->needed;
1304 fstring value;
1305 BOOL found=False;
1306 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1309 * Reminder: when it's a string, the length is in BYTES
1310 * even if UNICODE is negociated.
1312 * JFM, 4/19/1999
1315 *out_size=in_size;
1317 /* in case of problem, return some default values */
1318 *needed=0;
1319 *type=0;
1321 DEBUG(4,("_spoolss_getprinterdata\n"));
1323 if (!Printer) {
1324 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1325 return WERR_NOMEM;
1326 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1327 return WERR_BADFID;
1330 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1332 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1333 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1334 else
1335 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1337 if (found==False) {
1338 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1339 /* reply this param doesn't exist */
1340 if (*out_size) {
1341 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1342 return WERR_NOMEM;
1343 } else {
1344 *data = NULL;
1347 return WERR_INVALID_PARAM;
1350 if (*needed > *out_size)
1351 return WERR_STATUS_MORE_ENTRIES;
1352 else
1353 return WERR_OK;
1356 /***************************************************************************
1357 connect to the client
1358 ****************************************************************************/
1359 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1361 WERROR status;
1364 * If it's the first connection, contact the client
1365 * and connect to the IPC$ share anonumously
1367 if (smb_connections==0) {
1368 fstring unix_printer;
1370 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1372 if(!spoolss_connect_to_client(&cli, unix_printer))
1373 return False;
1374 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1378 smb_connections++;
1380 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1381 return False;
1383 return True;
1386 /********************************************************************
1387 * _spoolss_rffpcnex
1388 * ReplyFindFirstPrinterChangeNotifyEx
1390 * jfmxxxx: before replying OK: status=0
1391 * should do a rpc call to the workstation asking ReplyOpenPrinter
1392 * have to code it, later.
1394 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1395 * called from api_spoolss_rffpcnex
1396 ********************************************************************/
1398 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1400 POLICY_HND *handle = &q_u->handle;
1401 uint32 flags = q_u->flags;
1402 uint32 options = q_u->options;
1403 UNISTR2 *localmachine = &q_u->localmachine;
1404 uint32 printerlocal = q_u->printerlocal;
1405 SPOOL_NOTIFY_OPTION *option = q_u->option;
1407 /* store the notify value in the printer struct */
1409 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1411 if (!Printer) {
1412 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1413 return WERR_BADFID;
1416 Printer->notify.flags=flags;
1417 Printer->notify.options=options;
1418 Printer->notify.printerlocal=printerlocal;
1420 if (Printer->notify.option)
1421 free_spool_notify_option(&Printer->notify.option);
1423 Printer->notify.option=dup_spool_notify_option(option);
1425 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1427 /* connect to the client machine and send a ReplyOpenPrinter */
1428 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1429 Printer->notify.printerlocal, 1,
1430 &Printer->notify.client_hnd))
1431 Printer->notify.client_connected=True;
1433 return WERR_OK;
1436 /*******************************************************************
1437 * fill a notify_info_data with the servername
1438 ********************************************************************/
1440 static void spoolss_notify_server_name(int snum,
1441 SPOOL_NOTIFY_INFO_DATA *data,
1442 print_queue_struct *queue,
1443 NT_PRINTER_INFO_LEVEL *printer,
1444 TALLOC_CTX *mem_ctx)
1446 pstring temp_name, temp;
1447 uint32 len;
1449 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1451 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1453 data->notify_data.data.length = len / 2;
1454 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1456 if (!data->notify_data.data.string) {
1457 data->notify_data.data.length = 0;
1458 return;
1461 memcpy(data->notify_data.data.string, temp, len);
1464 /*******************************************************************
1465 * fill a notify_info_data with the printername (not including the servername).
1466 ********************************************************************/
1467 static void spoolss_notify_printer_name(int snum,
1468 SPOOL_NOTIFY_INFO_DATA *data,
1469 print_queue_struct *queue,
1470 NT_PRINTER_INFO_LEVEL *printer,
1471 TALLOC_CTX *mem_ctx)
1473 pstring temp;
1474 uint32 len;
1476 /* the notify name should not contain the \\server\ part */
1477 char *p = strrchr_m(printer->info_2->printername, '\\');
1479 if (!p) {
1480 p = printer->info_2->printername;
1481 } else {
1482 p++;
1485 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1486 data->notify_data.data.length = len / 2;
1487 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1489 if (!data->notify_data.data.string) {
1490 data->notify_data.data.length = 0;
1491 return;
1494 memcpy(data->notify_data.data.string, temp, len);
1497 /*******************************************************************
1498 * fill a notify_info_data with the servicename
1499 ********************************************************************/
1500 static void spoolss_notify_share_name(int snum,
1501 SPOOL_NOTIFY_INFO_DATA *data,
1502 print_queue_struct *queue,
1503 NT_PRINTER_INFO_LEVEL *printer,
1504 TALLOC_CTX *mem_ctx)
1506 pstring temp;
1507 uint32 len;
1509 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1511 data->notify_data.data.length = len / 2;
1512 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1514 if (!data->notify_data.data.string) {
1515 data->notify_data.data.length = 0;
1516 return;
1519 memcpy(data->notify_data.data.string, temp, len);
1522 /*******************************************************************
1523 * fill a notify_info_data with the port name
1524 ********************************************************************/
1525 static void spoolss_notify_port_name(int snum,
1526 SPOOL_NOTIFY_INFO_DATA *data,
1527 print_queue_struct *queue,
1528 NT_PRINTER_INFO_LEVEL *printer,
1529 TALLOC_CTX *mem_ctx)
1531 pstring temp;
1532 uint32 len;
1534 /* even if it's strange, that's consistant in all the code */
1536 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1538 data->notify_data.data.length = len / 2;
1539 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1541 if (!data->notify_data.data.string) {
1542 data->notify_data.data.length = 0;
1543 return;
1546 memcpy(data->notify_data.data.string, temp, len);
1549 /*******************************************************************
1550 * fill a notify_info_data with the printername
1551 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1552 * but it doesn't exist, have to see what to do
1553 ********************************************************************/
1554 static void spoolss_notify_driver_name(int snum,
1555 SPOOL_NOTIFY_INFO_DATA *data,
1556 print_queue_struct *queue,
1557 NT_PRINTER_INFO_LEVEL *printer,
1558 TALLOC_CTX *mem_ctx)
1560 pstring temp;
1561 uint32 len;
1563 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1564 data->notify_data.data.length = len / 2;
1565 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1567 if (!data->notify_data.data.string) {
1568 data->notify_data.data.length = 0;
1569 return;
1572 memcpy(data->notify_data.data.string, temp, len);
1575 /*******************************************************************
1576 * fill a notify_info_data with the comment
1577 ********************************************************************/
1578 static void spoolss_notify_comment(int snum,
1579 SPOOL_NOTIFY_INFO_DATA *data,
1580 print_queue_struct *queue,
1581 NT_PRINTER_INFO_LEVEL *printer,
1582 TALLOC_CTX *mem_ctx)
1584 pstring temp;
1585 uint32 len;
1587 if (*printer->info_2->comment == '\0')
1588 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1590 else
1591 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1593 data->notify_data.data.length = len / 2;
1594 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1596 if (!data->notify_data.data.string) {
1597 data->notify_data.data.length = 0;
1598 return;
1601 memcpy(data->notify_data.data.string, temp, len);
1604 /*******************************************************************
1605 * fill a notify_info_data with the comment
1606 * jfm:xxxx incorrect, have to create a new smb.conf option
1607 * location = "Room 1, floor 2, building 3"
1608 ********************************************************************/
1609 static void spoolss_notify_location(int snum,
1610 SPOOL_NOTIFY_INFO_DATA *data,
1611 print_queue_struct *queue,
1612 NT_PRINTER_INFO_LEVEL *printer,
1613 TALLOC_CTX *mem_ctx)
1615 pstring temp;
1616 uint32 len;
1618 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1620 data->notify_data.data.length = len / 2;
1621 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1623 if (!data->notify_data.data.string) {
1624 data->notify_data.data.length = 0;
1625 return;
1628 memcpy(data->notify_data.data.string, temp, len);
1631 /*******************************************************************
1632 * fill a notify_info_data with the device mode
1633 * jfm:xxxx don't to it for know but that's a real problem !!!
1634 ********************************************************************/
1635 static void spoolss_notify_devmode(int snum,
1636 SPOOL_NOTIFY_INFO_DATA *data,
1637 print_queue_struct *queue,
1638 NT_PRINTER_INFO_LEVEL *printer,
1639 TALLOC_CTX *mem_ctx)
1643 /*******************************************************************
1644 * fill a notify_info_data with the separator file name
1645 * jfm:xxxx just return no file could add an option to smb.conf
1646 * separator file = "separator.txt"
1647 ********************************************************************/
1648 static void spoolss_notify_sepfile(int snum,
1649 SPOOL_NOTIFY_INFO_DATA *data,
1650 print_queue_struct *queue,
1651 NT_PRINTER_INFO_LEVEL *printer,
1652 TALLOC_CTX *mem_ctx)
1654 pstring temp;
1655 uint32 len;
1657 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1659 data->notify_data.data.length = len / 2;
1660 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1662 if (!data->notify_data.data.string) {
1663 data->notify_data.data.length = 0;
1664 return;
1667 memcpy(data->notify_data.data.string, temp, len);
1670 /*******************************************************************
1671 * fill a notify_info_data with the print processor
1672 * jfm:xxxx return always winprint to indicate we don't do anything to it
1673 ********************************************************************/
1674 static void spoolss_notify_print_processor(int snum,
1675 SPOOL_NOTIFY_INFO_DATA *data,
1676 print_queue_struct *queue,
1677 NT_PRINTER_INFO_LEVEL *printer,
1678 TALLOC_CTX *mem_ctx)
1680 pstring temp;
1681 uint32 len;
1683 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1685 data->notify_data.data.length = len / 2;
1686 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1688 if (!data->notify_data.data.string) {
1689 data->notify_data.data.length = 0;
1690 return;
1693 memcpy(data->notify_data.data.string, temp, len);
1696 /*******************************************************************
1697 * fill a notify_info_data with the print processor options
1698 * jfm:xxxx send an empty string
1699 ********************************************************************/
1700 static void spoolss_notify_parameters(int snum,
1701 SPOOL_NOTIFY_INFO_DATA *data,
1702 print_queue_struct *queue,
1703 NT_PRINTER_INFO_LEVEL *printer,
1704 TALLOC_CTX *mem_ctx)
1706 pstring temp;
1707 uint32 len;
1709 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1711 data->notify_data.data.length = len / 2;
1712 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1714 if (!data->notify_data.data.string) {
1715 data->notify_data.data.length = 0;
1716 return;
1719 memcpy(data->notify_data.data.string, temp, len);
1722 /*******************************************************************
1723 * fill a notify_info_data with the data type
1724 * jfm:xxxx always send RAW as data type
1725 ********************************************************************/
1726 static void spoolss_notify_datatype(int snum,
1727 SPOOL_NOTIFY_INFO_DATA *data,
1728 print_queue_struct *queue,
1729 NT_PRINTER_INFO_LEVEL *printer,
1730 TALLOC_CTX *mem_ctx)
1732 pstring temp;
1733 uint32 len;
1735 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
1737 data->notify_data.data.length = len / 2;
1738 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1740 if (!data->notify_data.data.string) {
1741 data->notify_data.data.length = 0;
1742 return;
1745 memcpy(data->notify_data.data.string, temp, len);
1748 /*******************************************************************
1749 * fill a notify_info_data with the security descriptor
1750 * jfm:xxxx send an null pointer to say no security desc
1751 * have to implement security before !
1752 ********************************************************************/
1753 static void spoolss_notify_security_desc(int snum,
1754 SPOOL_NOTIFY_INFO_DATA *data,
1755 print_queue_struct *queue,
1756 NT_PRINTER_INFO_LEVEL *printer,
1757 TALLOC_CTX *mem_ctx)
1759 data->notify_data.data.length=0;
1760 data->notify_data.data.string = NULL;
1763 /*******************************************************************
1764 * fill a notify_info_data with the attributes
1765 * jfm:xxxx a samba printer is always shared
1766 ********************************************************************/
1767 static void spoolss_notify_attributes(int snum,
1768 SPOOL_NOTIFY_INFO_DATA *data,
1769 print_queue_struct *queue,
1770 NT_PRINTER_INFO_LEVEL *printer,
1771 TALLOC_CTX *mem_ctx)
1773 data->notify_data.value[0] = printer->info_2->attributes;
1774 data->notify_data.value[1] = 0;
1777 /*******************************************************************
1778 * fill a notify_info_data with the priority
1779 ********************************************************************/
1780 static void spoolss_notify_priority(int snum,
1781 SPOOL_NOTIFY_INFO_DATA *data,
1782 print_queue_struct *queue,
1783 NT_PRINTER_INFO_LEVEL *printer,
1784 TALLOC_CTX *mem_ctx)
1786 data->notify_data.value[0] = printer->info_2->priority;
1787 data->notify_data.value[1] = 0;
1790 /*******************************************************************
1791 * fill a notify_info_data with the default priority
1792 ********************************************************************/
1793 static void spoolss_notify_default_priority(int snum,
1794 SPOOL_NOTIFY_INFO_DATA *data,
1795 print_queue_struct *queue,
1796 NT_PRINTER_INFO_LEVEL *printer,
1797 TALLOC_CTX *mem_ctx)
1799 data->notify_data.value[0] = printer->info_2->default_priority;
1800 data->notify_data.value[1] = 0;
1803 /*******************************************************************
1804 * fill a notify_info_data with the start time
1805 ********************************************************************/
1806 static void spoolss_notify_start_time(int snum,
1807 SPOOL_NOTIFY_INFO_DATA *data,
1808 print_queue_struct *queue,
1809 NT_PRINTER_INFO_LEVEL *printer,
1810 TALLOC_CTX *mem_ctx)
1812 data->notify_data.value[0] = printer->info_2->starttime;
1813 data->notify_data.value[1] = 0;
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;
1826 data->notify_data.value[1] = 0;
1829 /*******************************************************************
1830 * fill a notify_info_data with the status
1831 ********************************************************************/
1832 static void spoolss_notify_status(int snum,
1833 SPOOL_NOTIFY_INFO_DATA *data,
1834 print_queue_struct *queue,
1835 NT_PRINTER_INFO_LEVEL *printer,
1836 TALLOC_CTX *mem_ctx)
1838 print_status_struct status;
1840 memset(&status, 0, sizeof(status));
1841 print_queue_length(snum, &status);
1842 data->notify_data.value[0]=(uint32) status.status;
1843 data->notify_data.value[1] = 0;
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 data->notify_data.value[0] = print_queue_length(snum, NULL);
1856 data->notify_data.value[1] = 0;
1859 /*******************************************************************
1860 * fill a notify_info_data with the average ppm
1861 ********************************************************************/
1862 static void spoolss_notify_average_ppm(int snum,
1863 SPOOL_NOTIFY_INFO_DATA *data,
1864 print_queue_struct *queue,
1865 NT_PRINTER_INFO_LEVEL *printer,
1866 TALLOC_CTX *mem_ctx)
1868 /* always respond 8 pages per minutes */
1869 /* a little hard ! */
1870 data->notify_data.value[0] = printer->info_2->averageppm;
1871 data->notify_data.value[1] = 0;
1874 /*******************************************************************
1875 * fill a notify_info_data with username
1876 ********************************************************************/
1877 static void spoolss_notify_username(int snum,
1878 SPOOL_NOTIFY_INFO_DATA *data,
1879 print_queue_struct *queue,
1880 NT_PRINTER_INFO_LEVEL *printer,
1881 TALLOC_CTX *mem_ctx)
1883 pstring temp;
1884 uint32 len;
1886 len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
1889 data->notify_data.data.length = len / 2;
1890 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1892 if (!data->notify_data.data.string) {
1893 data->notify_data.data.length = 0;
1894 return;
1897 memcpy(data->notify_data.data.string, temp, len);
1900 /*******************************************************************
1901 * fill a notify_info_data with job status
1902 ********************************************************************/
1903 static void spoolss_notify_job_status(int snum,
1904 SPOOL_NOTIFY_INFO_DATA *data,
1905 print_queue_struct *queue,
1906 NT_PRINTER_INFO_LEVEL *printer,
1907 TALLOC_CTX *mem_ctx)
1909 data->notify_data.value[0]=nt_printj_status(queue->status);
1910 data->notify_data.value[1] = 0;
1913 /*******************************************************************
1914 * fill a notify_info_data with job name
1915 ********************************************************************/
1916 static void spoolss_notify_job_name(int snum,
1917 SPOOL_NOTIFY_INFO_DATA *data,
1918 print_queue_struct *queue,
1919 NT_PRINTER_INFO_LEVEL *printer,
1920 TALLOC_CTX *mem_ctx)
1922 pstring temp;
1923 uint32 len;
1925 len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
1927 data->notify_data.data.length = len / 2;
1928 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1930 if (!data->notify_data.data.string) {
1931 data->notify_data.data.length = 0;
1932 return;
1935 memcpy(data->notify_data.data.string, temp, len);
1938 /*******************************************************************
1939 * fill a notify_info_data with job status
1940 ********************************************************************/
1941 static void spoolss_notify_job_status_string(int snum,
1942 SPOOL_NOTIFY_INFO_DATA *data,
1943 print_queue_struct *queue,
1944 NT_PRINTER_INFO_LEVEL *printer,
1945 TALLOC_CTX *mem_ctx)
1948 * Now we're returning job status codes we just return a "" here. JRA.
1951 char *p = "";
1952 pstring temp;
1953 uint32 len;
1955 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1956 p = "unknown";
1958 switch (queue->status) {
1959 case LPQ_QUEUED:
1960 p = "Queued";
1961 break;
1962 case LPQ_PAUSED:
1963 p = ""; /* NT provides the paused string */
1964 break;
1965 case LPQ_SPOOLING:
1966 p = "Spooling";
1967 break;
1968 case LPQ_PRINTING:
1969 p = "Printing";
1970 break;
1972 #endif /* NO LONGER NEEDED. */
1974 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
1976 data->notify_data.data.length = len / 2;
1977 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1979 if (!data->notify_data.data.string) {
1980 data->notify_data.data.length = 0;
1981 return;
1984 memcpy(data->notify_data.data.string, temp, len);
1987 /*******************************************************************
1988 * fill a notify_info_data with job time
1989 ********************************************************************/
1990 static void spoolss_notify_job_time(int snum,
1991 SPOOL_NOTIFY_INFO_DATA *data,
1992 print_queue_struct *queue,
1993 NT_PRINTER_INFO_LEVEL *printer,
1994 TALLOC_CTX *mem_ctx)
1996 data->notify_data.value[0]=0x0;
1997 data->notify_data.value[1]=0;
2000 /*******************************************************************
2001 * fill a notify_info_data with job size
2002 ********************************************************************/
2003 static void spoolss_notify_job_size(int snum,
2004 SPOOL_NOTIFY_INFO_DATA *data,
2005 print_queue_struct *queue,
2006 NT_PRINTER_INFO_LEVEL *printer,
2007 TALLOC_CTX *mem_ctx)
2009 data->notify_data.value[0]=queue->size;
2010 data->notify_data.value[1]=0;
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;
2023 data->notify_data.value[1]=0;
2026 /*******************************************************************
2027 * fill a notify_info_data with submitted time
2028 ********************************************************************/
2029 static void spoolss_notify_submitted_time(int snum,
2030 SPOOL_NOTIFY_INFO_DATA *data,
2031 print_queue_struct *queue,
2032 NT_PRINTER_INFO_LEVEL *printer,
2033 TALLOC_CTX *mem_ctx)
2035 struct tm *t;
2036 uint32 len;
2037 SYSTEMTIME st;
2039 t=gmtime(&queue->time);
2041 len = sizeof(SYSTEMTIME);
2043 data->notify_data.data.length = len;
2044 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2046 if (!data->notify_data.data.string) {
2047 data->notify_data.data.length = 0;
2048 return;
2051 make_systemtime(&st, t);
2052 memcpy(data->notify_data.data.string,&st,len);
2055 #define END 65535
2057 struct s_notify_info_data_table
2059 uint16 type;
2060 uint16 field;
2061 char *name;
2062 uint32 size;
2063 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2064 print_queue_struct *queue,
2065 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2068 struct s_notify_info_data_table notify_info_data_table[] =
2070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2095 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2100 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2101 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2102 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2103 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2104 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2105 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2106 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2118 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2119 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2120 { END, END, "", END, NULL }
2123 /*******************************************************************
2124 return the size of info_data structure
2125 ********************************************************************/
2126 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2128 int i=0;
2130 while (notify_info_data_table[i].type != END)
2132 if ( (notify_info_data_table[i].type == type ) &&
2133 (notify_info_data_table[i].field == field ) )
2135 return (notify_info_data_table[i].size);
2137 i++;
2139 return (65535);
2142 /*******************************************************************
2143 return the type of notify_info_data
2144 ********************************************************************/
2145 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2147 int i=0;
2149 while (notify_info_data_table[i].type != END)
2151 if ( (notify_info_data_table[i].type == type ) &&
2152 (notify_info_data_table[i].field == field ) )
2154 if (notify_info_data_table[i].size == POINTER)
2156 return (False);
2158 else
2160 return (True);
2163 i++;
2165 return (False);
2168 /****************************************************************************
2169 ****************************************************************************/
2170 static int search_notify(uint16 type, uint16 field, int *value)
2172 int j;
2173 BOOL found;
2175 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2177 if ( (notify_info_data_table[j].type == type ) &&
2178 (notify_info_data_table[j].field == field ) )
2179 found=True;
2181 *value=--j;
2183 if ( found && (notify_info_data_table[j].fn != NULL) )
2184 return True;
2185 else
2186 return False;
2189 /****************************************************************************
2190 ****************************************************************************/
2191 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2193 info_data->type = type;
2194 info_data->field = field;
2195 info_data->reserved = 0;
2196 info_data->id = id;
2197 info_data->size = size_of_notify_info_data(type, field);
2198 info_data->enc_type = type_of_notify_info_data(type, field);
2202 /*******************************************************************
2204 * fill a notify_info struct with info asked
2206 ********************************************************************/
2207 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2208 snum, SPOOL_NOTIFY_OPTION_TYPE
2209 *option_type, uint32 id,
2210 TALLOC_CTX *mem_ctx)
2212 int field_num,j;
2213 uint16 type;
2214 uint16 field;
2216 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2217 NT_PRINTER_INFO_LEVEL *printer = NULL;
2218 print_queue_struct *queue=NULL;
2220 type=option_type->type;
2222 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2223 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2224 option_type->count, lp_servicename(snum)));
2226 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2227 return False;
2229 for(field_num=0; field_num<option_type->count; field_num++) {
2230 field = option_type->fields[field_num];
2231 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2233 if (!search_notify(type, field, &j) )
2234 continue;
2236 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2237 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2238 return False;
2240 else info->data = tid;
2242 current_data=&info->data[info->count];
2244 construct_info_data(current_data, type, field, id);
2246 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2247 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2249 notify_info_data_table[j].fn(snum, current_data, queue,
2250 printer, mem_ctx);
2252 info->count++;
2255 free_a_printer(&printer, 2);
2256 return True;
2259 /*******************************************************************
2261 * fill a notify_info struct with info asked
2263 ********************************************************************/
2264 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2265 SPOOL_NOTIFY_INFO *info,
2266 NT_PRINTER_INFO_LEVEL *printer,
2267 int snum, SPOOL_NOTIFY_OPTION_TYPE
2268 *option_type, uint32 id,
2269 TALLOC_CTX *mem_ctx)
2271 int field_num,j;
2272 uint16 type;
2273 uint16 field;
2275 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2277 DEBUG(4,("construct_notify_jobs_info\n"));
2279 type = option_type->type;
2281 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2282 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2283 option_type->count));
2285 for(field_num=0; field_num<option_type->count; field_num++) {
2286 field = option_type->fields[field_num];
2288 if (!search_notify(type, field, &j) )
2289 continue;
2291 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2292 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2293 return False;
2295 else info->data = tid;
2297 current_data=&(info->data[info->count]);
2299 construct_info_data(current_data, type, field, id);
2300 notify_info_data_table[j].fn(snum, current_data, queue,
2301 printer, mem_ctx);
2302 info->count++;
2305 return True;
2309 * JFM: The enumeration is not that simple, it's even non obvious.
2311 * let's take an example: I want to monitor the PRINTER SERVER for
2312 * the printer's name and the number of jobs currently queued.
2313 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2314 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2316 * I have 3 printers on the back of my server.
2318 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2319 * structures.
2320 * Number Data Id
2321 * 1 printer 1 name 1
2322 * 2 printer 1 cjob 1
2323 * 3 printer 2 name 2
2324 * 4 printer 2 cjob 2
2325 * 5 printer 3 name 3
2326 * 6 printer 3 name 3
2328 * that's the print server case, the printer case is even worse.
2331 /*******************************************************************
2333 * enumerate all printers on the printserver
2334 * fill a notify_info struct with info asked
2336 ********************************************************************/
2338 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2339 SPOOL_NOTIFY_INFO *info,
2340 TALLOC_CTX *mem_ctx)
2342 int snum;
2343 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2344 int n_services=lp_numservices();
2345 int i;
2346 uint32 id;
2347 SPOOL_NOTIFY_OPTION *option;
2348 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2350 DEBUG(4,("printserver_notify_info\n"));
2352 option=Printer->notify.option;
2353 id=1;
2354 info->version=2;
2355 info->data=NULL;
2356 info->count=0;
2358 for (i=0; i<option->count; i++) {
2359 option_type=&(option->ctr.type[i]);
2361 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2362 continue;
2364 for (snum=0; snum<n_services; snum++)
2365 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2366 if (construct_notify_printer_info
2367 (info, snum, option_type, id, mem_ctx))
2368 id++;
2372 * Debugging information, don't delete.
2375 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2376 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2377 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2379 for (i=0; i<info->count; i++) {
2380 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2381 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2382 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2386 return WERR_OK;
2389 /*******************************************************************
2391 * fill a notify_info struct with info asked
2393 ********************************************************************/
2394 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2395 TALLOC_CTX *mem_ctx)
2397 int snum;
2398 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2399 int i;
2400 uint32 id;
2401 SPOOL_NOTIFY_OPTION *option;
2402 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2403 int count,j;
2404 print_queue_struct *queue=NULL;
2405 print_status_struct status;
2407 DEBUG(4,("printer_notify_info\n"));
2409 option=Printer->notify.option;
2410 id=0xffffffff;
2411 info->version=2;
2412 info->data=NULL;
2413 info->count=0;
2415 get_printer_snum(p, hnd, &snum);
2417 for (i=0; i<option->count; i++) {
2418 option_type=&option->ctr.type[i];
2420 switch ( option_type->type ) {
2421 case PRINTER_NOTIFY_TYPE:
2422 if(construct_notify_printer_info(info, snum,
2423 option_type, id,
2424 mem_ctx))
2425 id--;
2426 break;
2428 case JOB_NOTIFY_TYPE: {
2429 NT_PRINTER_INFO_LEVEL *printer = NULL;
2431 memset(&status, 0, sizeof(status));
2432 count = print_queue_status(snum, &queue, &status);
2434 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2435 lp_servicename(snum))))
2436 goto done;
2438 for (j=0; j<count; j++) {
2439 construct_notify_jobs_info(&queue[j], info,
2440 printer, snum,
2441 option_type,
2442 queue[j].job,
2443 mem_ctx);
2446 free_a_printer(&printer, 2);
2448 done:
2449 SAFE_FREE(queue);
2450 break;
2456 * Debugging information, don't delete.
2459 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2460 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2461 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2463 for (i=0; i<info->count; i++) {
2464 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2465 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2466 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2469 return WERR_OK;
2472 /********************************************************************
2473 * spoolss_rfnpcnex
2474 ********************************************************************/
2476 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2478 POLICY_HND *handle = &q_u->handle;
2479 /* uint32 change = q_u->change; - notused. */
2480 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2481 SPOOL_NOTIFY_INFO *info = &r_u->info;
2483 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2484 WERROR result = WERR_BADFID;
2486 /* we always have a NOTIFY_INFO struct */
2487 r_u->info_ptr=0x1;
2489 if (!Printer) {
2490 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2491 OUR_HANDLE(handle)));
2492 goto done;
2495 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2497 /* jfm: the change value isn't used right now.
2498 * we will honour it when
2499 * a) we'll be able to send notification to the client
2500 * b) we'll have a way to communicate between the spoolss process.
2502 * same thing for option->flags
2503 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2504 * I don't have a global notification system, I'm sending back all the
2505 * informations even when _NOTHING_ has changed.
2508 /* just ignore the SPOOL_NOTIFY_OPTION */
2510 switch (Printer->printer_type) {
2511 case PRINTER_HANDLE_IS_PRINTSERVER:
2512 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2513 break;
2515 case PRINTER_HANDLE_IS_PRINTER:
2516 result = printer_notify_info(p, handle, info, p->mem_ctx);
2517 break;
2520 done:
2521 return result;
2524 /********************************************************************
2525 * construct_printer_info_0
2526 * fill a printer_info_0 struct
2527 ********************************************************************/
2528 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2530 pstring chaine;
2531 int count;
2532 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2533 counter_printer_0 *session_counter;
2534 uint32 global_counter;
2535 struct tm *t;
2536 time_t setuptime;
2538 print_queue_struct *queue=NULL;
2539 print_status_struct status;
2541 memset(&status, 0, sizeof(status));
2543 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2544 return False;
2546 count = print_queue_status(snum, &queue, &status);
2548 /* check if we already have a counter for this printer */
2549 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2551 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2552 if (session_counter->snum == snum)
2553 break;
2556 /* it's the first time, add it to the list */
2557 if (session_counter==NULL) {
2558 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2559 free_a_printer(&ntprinter, 2);
2560 return False;
2562 ZERO_STRUCTP(session_counter);
2563 session_counter->snum=snum;
2564 session_counter->counter=0;
2565 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2568 /* increment it */
2569 session_counter->counter++;
2571 /* JFM:
2572 * the global_counter should be stored in a TDB as it's common to all the clients
2573 * and should be zeroed on samba startup
2575 global_counter=session_counter->counter;
2577 pstrcpy(chaine,ntprinter->info_2->printername);
2579 init_unistr(&printer->printername, chaine);
2581 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2582 init_unistr(&printer->servername, chaine);
2584 printer->cjobs = count;
2585 printer->total_jobs = 0;
2586 printer->total_bytes = 0;
2588 setuptime = (time_t)ntprinter->info_2->setuptime;
2589 t=gmtime(&setuptime);
2591 printer->year = t->tm_year+1900;
2592 printer->month = t->tm_mon+1;
2593 printer->dayofweek = t->tm_wday;
2594 printer->day = t->tm_mday;
2595 printer->hour = t->tm_hour;
2596 printer->minute = t->tm_min;
2597 printer->second = t->tm_sec;
2598 printer->milliseconds = 0;
2600 printer->global_counter = global_counter;
2601 printer->total_pages = 0;
2602 printer->major_version = 0x0004; /* NT 4 */
2603 printer->build_version = 0x0565; /* build 1381 */
2604 printer->unknown7 = 0x1;
2605 printer->unknown8 = 0x0;
2606 printer->unknown9 = 0x0;
2607 printer->session_counter = session_counter->counter;
2608 printer->unknown11 = 0x0;
2609 printer->printer_errors = 0x0; /* number of print failure */
2610 printer->unknown13 = 0x0;
2611 printer->unknown14 = 0x1;
2612 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2613 printer->unknown16 = 0x0;
2614 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2615 printer->unknown18 = 0x0;
2616 printer->status = nt_printq_status(status.status);
2617 printer->unknown20 = 0x0;
2618 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2619 printer->unknown22 = 0x0;
2620 printer->unknown23 = 0x6; /* 6 ???*/
2621 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2622 printer->unknown25 = 0;
2623 printer->unknown26 = 0;
2624 printer->unknown27 = 0;
2625 printer->unknown28 = 0;
2626 printer->unknown29 = 0;
2628 SAFE_FREE(queue);
2629 free_a_printer(&ntprinter,2);
2630 return (True);
2633 /********************************************************************
2634 * construct_printer_info_1
2635 * fill a printer_info_1 struct
2636 ********************************************************************/
2637 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2639 pstring chaine;
2640 pstring chaine2;
2641 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2643 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2644 return False;
2646 printer->flags=flags;
2648 if (*ntprinter->info_2->comment == '\0') {
2649 init_unistr(&printer->comment, lp_comment(snum));
2650 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2651 ntprinter->info_2->drivername, lp_comment(snum));
2653 else {
2654 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2655 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2656 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2659 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2661 init_unistr(&printer->description, chaine);
2662 init_unistr(&printer->name, chaine2);
2664 free_a_printer(&ntprinter,2);
2666 return True;
2669 /****************************************************************************
2670 Free a DEVMODE struct.
2671 ****************************************************************************/
2673 static void free_dev_mode(DEVICEMODE *dev)
2675 if (dev == NULL)
2676 return;
2678 SAFE_FREE(dev->private);
2679 SAFE_FREE(dev);
2682 /****************************************************************************
2683 Create a DEVMODE struct. Returns malloced memory.
2684 ****************************************************************************/
2686 static DEVICEMODE *construct_dev_mode(int snum)
2688 char adevice[32];
2689 char aform[32];
2690 NT_PRINTER_INFO_LEVEL *printer = NULL;
2691 NT_DEVICEMODE *ntdevmode = NULL;
2692 DEVICEMODE *devmode = NULL;
2694 DEBUG(7,("construct_dev_mode\n"));
2696 DEBUGADD(8,("getting printer characteristics\n"));
2698 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2699 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2700 return NULL;
2703 ZERO_STRUCTP(devmode);
2705 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2706 goto fail;
2708 if (printer->info_2->devmode)
2709 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2711 if (ntdevmode == NULL)
2712 goto fail;
2714 DEBUGADD(8,("loading DEVICEMODE\n"));
2716 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2717 init_unistr(&devmode->devicename, adevice);
2719 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2720 init_unistr(&devmode->formname, aform);
2722 devmode->specversion = ntdevmode->specversion;
2723 devmode->driverversion = ntdevmode->driverversion;
2724 devmode->size = ntdevmode->size;
2725 devmode->driverextra = ntdevmode->driverextra;
2726 devmode->fields = ntdevmode->fields;
2728 devmode->orientation = ntdevmode->orientation;
2729 devmode->papersize = ntdevmode->papersize;
2730 devmode->paperlength = ntdevmode->paperlength;
2731 devmode->paperwidth = ntdevmode->paperwidth;
2732 devmode->scale = ntdevmode->scale;
2733 devmode->copies = ntdevmode->copies;
2734 devmode->defaultsource = ntdevmode->defaultsource;
2735 devmode->printquality = ntdevmode->printquality;
2736 devmode->color = ntdevmode->color;
2737 devmode->duplex = ntdevmode->duplex;
2738 devmode->yresolution = ntdevmode->yresolution;
2739 devmode->ttoption = ntdevmode->ttoption;
2740 devmode->collate = ntdevmode->collate;
2741 devmode->icmmethod = ntdevmode->icmmethod;
2742 devmode->icmintent = ntdevmode->icmintent;
2743 devmode->mediatype = ntdevmode->mediatype;
2744 devmode->dithertype = ntdevmode->dithertype;
2746 if (ntdevmode->private != NULL) {
2747 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2748 goto fail;
2751 free_nt_devicemode(&ntdevmode);
2752 free_a_printer(&printer,2);
2754 return devmode;
2756 fail:
2758 if (ntdevmode)
2759 free_nt_devicemode(&ntdevmode);
2760 if (printer)
2761 free_a_printer(&printer,2);
2762 free_dev_mode(devmode);
2764 return NULL;
2767 /********************************************************************
2768 * construct_printer_info_2
2769 * fill a printer_info_2 struct
2770 ********************************************************************/
2772 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2774 int count;
2775 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2777 print_queue_struct *queue=NULL;
2778 print_status_struct status;
2779 memset(&status, 0, sizeof(status));
2781 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2782 return False;
2784 memset(&status, 0, sizeof(status));
2785 count = print_queue_status(snum, &queue, &status);
2787 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2788 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2789 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2790 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2791 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2793 if (*ntprinter->info_2->comment == '\0')
2794 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2795 else
2796 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2798 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2799 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2800 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2801 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2802 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2804 printer->attributes = ntprinter->info_2->attributes;
2806 printer->priority = ntprinter->info_2->priority; /* priority */
2807 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2808 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2809 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2810 printer->status = nt_printq_status(status.status); /* status */
2811 printer->cjobs = count; /* jobs */
2812 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2814 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2815 DEBUG(8, ("Returning NULL Devicemode!\n"));
2818 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2819 /* steal the printer info sec_desc structure. [badly done]. */
2820 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2821 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2822 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2823 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2825 else {
2826 printer->secdesc = NULL;
2829 free_a_printer(&ntprinter, 2);
2830 SAFE_FREE(queue);
2831 return True;
2834 /********************************************************************
2835 * construct_printer_info_3
2836 * fill a printer_info_3 struct
2837 ********************************************************************/
2838 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2840 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2841 PRINTER_INFO_3 *printer = NULL;
2843 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2844 return False;
2846 *pp_printer = NULL;
2847 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2848 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2849 return False;
2852 ZERO_STRUCTP(printer);
2854 printer->flags = 4; /* These are the components of the SD we are returning. */
2855 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2856 /* steal the printer info sec_desc structure. [badly done]. */
2857 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2859 #if 0
2861 * Set the flags for the components we are returning.
2864 if (printer->secdesc->owner_sid)
2865 printer->flags |= OWNER_SECURITY_INFORMATION;
2867 if (printer->secdesc->grp_sid)
2868 printer->flags |= GROUP_SECURITY_INFORMATION;
2870 if (printer->secdesc->dacl)
2871 printer->flags |= DACL_SECURITY_INFORMATION;
2873 if (printer->secdesc->sacl)
2874 printer->flags |= SACL_SECURITY_INFORMATION;
2875 #endif
2877 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2878 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2879 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2882 free_a_printer(&ntprinter, 2);
2884 *pp_printer = printer;
2885 return True;
2888 /********************************************************************
2889 Spoolss_enumprinters.
2890 ********************************************************************/
2891 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2893 int snum;
2894 int i;
2895 int n_services=lp_numservices();
2896 PRINTER_INFO_1 *tp, *printers=NULL;
2897 PRINTER_INFO_1 current_prt;
2899 DEBUG(4,("enum_all_printers_info_1\n"));
2901 for (snum=0; snum<n_services; snum++) {
2902 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2903 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2905 if (construct_printer_info_1(flags, &current_prt, snum)) {
2906 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2907 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2908 SAFE_FREE(printers);
2909 *returned=0;
2910 return WERR_NOMEM;
2912 else printers = tp;
2913 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2914 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2915 (*returned)++;
2920 /* check the required size. */
2921 for (i=0; i<*returned; i++)
2922 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2924 if (!alloc_buffer_size(buffer, *needed))
2925 return WERR_INSUFFICIENT_BUFFER;
2927 /* fill the buffer with the structures */
2928 for (i=0; i<*returned; i++)
2929 smb_io_printer_info_1("", buffer, &printers[i], 0);
2931 /* clear memory */
2932 SAFE_FREE(printers);
2934 if (*needed > offered) {
2935 *returned=0;
2936 return WERR_INSUFFICIENT_BUFFER;
2938 else
2939 return WERR_OK;
2942 /********************************************************************
2943 enum_all_printers_info_1_local.
2944 *********************************************************************/
2945 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2947 DEBUG(4,("enum_all_printers_info_1_local\n"));
2949 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2952 /********************************************************************
2953 enum_all_printers_info_1_name.
2954 *********************************************************************/
2955 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2957 char *s = name;
2959 DEBUG(4,("enum_all_printers_info_1_name\n"));
2961 if ((name[0] == '\\') && (name[1] == '\\'))
2962 s = name + 2;
2964 if (is_myname_or_ipaddr(s)) {
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 char *s = servername;
3132 if (flags & PRINTER_ENUM_LOCAL) {
3133 return enum_all_printers_info_2(buffer, offered, needed, returned);
3136 if (flags & PRINTER_ENUM_NAME) {
3137 if ((servername[0] == '\\') && (servername[1] == '\\'))
3138 s = servername + 2;
3139 if (is_myname_or_ipaddr(s))
3140 return enum_all_printers_info_2(buffer, offered, needed, returned);
3141 else
3142 return WERR_INVALID_NAME;
3145 if (flags & PRINTER_ENUM_REMOTE)
3146 return WERR_UNKNOWN_LEVEL;
3148 return WERR_OK;
3151 /********************************************************************
3152 * handle enumeration of printers at level 5
3153 ********************************************************************/
3154 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3155 NEW_BUFFER *buffer, uint32 offered,
3156 uint32 *needed, uint32 *returned)
3158 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3159 return WERR_OK;
3162 /********************************************************************
3163 * api_spoolss_enumprinters
3165 * called from api_spoolss_enumprinters (see this to understand)
3166 ********************************************************************/
3168 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3170 uint32 flags = q_u->flags;
3171 UNISTR2 *servername = &q_u->servername;
3172 uint32 level = q_u->level;
3173 NEW_BUFFER *buffer = NULL;
3174 uint32 offered = q_u->offered;
3175 uint32 *needed = &r_u->needed;
3176 uint32 *returned = &r_u->returned;
3178 fstring name;
3180 /* that's an [in out] buffer */
3181 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3182 buffer = r_u->buffer;
3184 DEBUG(4,("_spoolss_enumprinters\n"));
3186 *needed=0;
3187 *returned=0;
3190 * Level 1:
3191 * flags==PRINTER_ENUM_NAME
3192 * if name=="" then enumerates all printers
3193 * if name!="" then enumerate the printer
3194 * flags==PRINTER_ENUM_REMOTE
3195 * name is NULL, enumerate printers
3196 * Level 2: name!="" enumerates printers, name can't be NULL
3197 * Level 3: doesn't exist
3198 * Level 4: does a local registry lookup
3199 * Level 5: same as Level 2
3202 unistr2_to_ascii(name, servername, sizeof(name)-1);
3203 strupper(name);
3205 switch (level) {
3206 case 1:
3207 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3208 case 2:
3209 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3210 case 5:
3211 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3212 case 3:
3213 case 4:
3214 break;
3216 return WERR_UNKNOWN_LEVEL;
3219 /****************************************************************************
3220 ****************************************************************************/
3221 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3223 PRINTER_INFO_0 *printer=NULL;
3225 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3226 return WERR_NOMEM;
3228 construct_printer_info_0(printer, snum);
3230 /* check the required size. */
3231 *needed += spoolss_size_printer_info_0(printer);
3233 if (!alloc_buffer_size(buffer, *needed)) {
3234 SAFE_FREE(printer);
3235 return WERR_INSUFFICIENT_BUFFER;
3238 /* fill the buffer with the structures */
3239 smb_io_printer_info_0("", buffer, printer, 0);
3241 /* clear memory */
3242 SAFE_FREE(printer);
3244 if (*needed > offered) {
3245 return WERR_INSUFFICIENT_BUFFER;
3248 return WERR_OK;
3251 /****************************************************************************
3252 ****************************************************************************/
3253 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3255 PRINTER_INFO_1 *printer=NULL;
3257 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3258 return WERR_NOMEM;
3260 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3262 /* check the required size. */
3263 *needed += spoolss_size_printer_info_1(printer);
3265 if (!alloc_buffer_size(buffer, *needed)) {
3266 SAFE_FREE(printer);
3267 return WERR_INSUFFICIENT_BUFFER;
3270 /* fill the buffer with the structures */
3271 smb_io_printer_info_1("", buffer, printer, 0);
3273 /* clear memory */
3274 SAFE_FREE(printer);
3276 if (*needed > offered) {
3277 return WERR_INSUFFICIENT_BUFFER;
3280 return WERR_OK;
3283 /****************************************************************************
3284 ****************************************************************************/
3285 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3287 PRINTER_INFO_2 *printer=NULL;
3289 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3290 return WERR_NOMEM;
3292 construct_printer_info_2(printer, snum);
3294 /* check the required size. */
3295 *needed += spoolss_size_printer_info_2(printer);
3297 if (!alloc_buffer_size(buffer, *needed)) {
3298 free_printer_info_2(printer);
3299 return WERR_INSUFFICIENT_BUFFER;
3302 /* fill the buffer with the structures */
3303 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3304 free_printer_info_2(printer);
3305 return WERR_NOMEM;
3308 /* clear memory */
3309 free_printer_info_2(printer);
3311 if (*needed > offered) {
3312 return WERR_INSUFFICIENT_BUFFER;
3315 return WERR_OK;
3318 /****************************************************************************
3319 ****************************************************************************/
3320 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3322 PRINTER_INFO_3 *printer=NULL;
3324 if (!construct_printer_info_3(&printer, snum))
3325 return WERR_NOMEM;
3327 /* check the required size. */
3328 *needed += spoolss_size_printer_info_3(printer);
3330 if (!alloc_buffer_size(buffer, *needed)) {
3331 free_printer_info_3(printer);
3332 return WERR_INSUFFICIENT_BUFFER;
3335 /* fill the buffer with the structures */
3336 smb_io_printer_info_3("", buffer, printer, 0);
3338 /* clear memory */
3339 free_printer_info_3(printer);
3341 if (*needed > offered) {
3342 return WERR_INSUFFICIENT_BUFFER;
3345 return WERR_OK;
3348 /****************************************************************************
3349 ****************************************************************************/
3351 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3353 POLICY_HND *handle = &q_u->handle;
3354 uint32 level = q_u->level;
3355 NEW_BUFFER *buffer = NULL;
3356 uint32 offered = q_u->offered;
3357 uint32 *needed = &r_u->needed;
3359 int snum;
3361 /* that's an [in out] buffer */
3362 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3363 buffer = r_u->buffer;
3365 *needed=0;
3367 if (!get_printer_snum(p, handle, &snum))
3368 return WERR_BADFID;
3370 switch (level) {
3371 case 0:
3372 return getprinter_level_0(snum, buffer, offered, needed);
3373 case 1:
3374 return getprinter_level_1(snum, buffer, offered, needed);
3375 case 2:
3376 return getprinter_level_2(snum, buffer, offered, needed);
3377 case 3:
3378 return getprinter_level_3(snum, buffer, offered, needed);
3380 return WERR_UNKNOWN_LEVEL;
3383 /********************************************************************
3384 * fill a DRIVER_INFO_1 struct
3385 ********************************************************************/
3386 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3388 init_unistr( &info->name, driver.info_3->name);
3391 /********************************************************************
3392 * construct_printer_driver_info_1
3393 ********************************************************************/
3394 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3396 NT_PRINTER_INFO_LEVEL *printer = NULL;
3397 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3399 ZERO_STRUCT(driver);
3401 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3402 return WERR_INVALID_PRINTER_NAME;
3404 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3405 return WERR_UNKNOWN_PRINTER_DRIVER;
3407 fill_printer_driver_info_1(info, driver, servername, architecture);
3409 free_a_printer(&printer,2);
3411 return WERR_OK;
3414 /********************************************************************
3415 * construct_printer_driver_info_2
3416 * fill a printer_info_2 struct
3417 ********************************************************************/
3418 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3420 pstring temp;
3422 info->version=driver.info_3->cversion;
3424 init_unistr( &info->name, driver.info_3->name );
3425 init_unistr( &info->architecture, driver.info_3->environment );
3428 if (strlen(driver.info_3->driverpath)) {
3429 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3430 init_unistr( &info->driverpath, temp );
3431 } else
3432 init_unistr( &info->driverpath, "" );
3434 if (strlen(driver.info_3->datafile)) {
3435 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3436 init_unistr( &info->datafile, temp );
3437 } else
3438 init_unistr( &info->datafile, "" );
3440 if (strlen(driver.info_3->configfile)) {
3441 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3442 init_unistr( &info->configfile, temp );
3443 } else
3444 init_unistr( &info->configfile, "" );
3447 /********************************************************************
3448 * construct_printer_driver_info_2
3449 * fill a printer_info_2 struct
3450 ********************************************************************/
3451 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3453 NT_PRINTER_INFO_LEVEL *printer = NULL;
3454 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3456 ZERO_STRUCT(printer);
3457 ZERO_STRUCT(driver);
3459 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3460 return WERR_INVALID_PRINTER_NAME;
3462 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3463 return WERR_UNKNOWN_PRINTER_DRIVER;
3465 fill_printer_driver_info_2(info, driver, servername);
3467 free_a_printer(&printer,2);
3469 return WERR_OK;
3472 /********************************************************************
3473 * copy a strings array and convert to UNICODE
3475 * convert an array of ascii string to a UNICODE string
3476 ********************************************************************/
3477 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3479 int i=0;
3480 int j=0;
3481 char *v;
3482 pstring line;
3483 uint16 *tuary;
3485 DEBUG(6,("init_unistr_array\n"));
3486 *uni_array=NULL;
3488 while (1) {
3489 if (char_array == NULL)
3490 v = "";
3491 else {
3492 v = char_array[i];
3493 if (!v) v = ""; /* hack to handle null lists */
3495 if (strlen(v) == 0) break;
3496 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3497 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3498 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3499 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3500 return;
3502 else *uni_array = tuary;
3503 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3504 i++;
3507 if (*uni_array) {
3508 (*uni_array)[j]=0x0000;
3511 DEBUGADD(6,("last one:done\n"));
3514 /********************************************************************
3515 * construct_printer_info_3
3516 * fill a printer_info_3 struct
3517 ********************************************************************/
3518 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3520 pstring temp;
3522 ZERO_STRUCTP(info);
3524 info->version=driver.info_3->cversion;
3526 init_unistr( &info->name, driver.info_3->name );
3527 init_unistr( &info->architecture, driver.info_3->environment );
3529 if (strlen(driver.info_3->driverpath)) {
3530 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3531 init_unistr( &info->driverpath, temp );
3532 } else
3533 init_unistr( &info->driverpath, "" );
3535 if (strlen(driver.info_3->datafile)) {
3536 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3537 init_unistr( &info->datafile, temp );
3538 } else
3539 init_unistr( &info->datafile, "" );
3541 if (strlen(driver.info_3->configfile)) {
3542 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3543 init_unistr( &info->configfile, temp );
3544 } else
3545 init_unistr( &info->configfile, "" );
3547 if (strlen(driver.info_3->helpfile)) {
3548 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3549 init_unistr( &info->helpfile, temp );
3550 } else
3551 init_unistr( &info->helpfile, "" );
3553 init_unistr( &info->monitorname, driver.info_3->monitorname );
3554 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3556 info->dependentfiles=NULL;
3557 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3560 /********************************************************************
3561 * construct_printer_info_3
3562 * fill a printer_info_3 struct
3563 ********************************************************************/
3564 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3566 NT_PRINTER_INFO_LEVEL *printer = NULL;
3567 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3568 WERROR status;
3569 ZERO_STRUCT(driver);
3571 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3572 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3573 if (!W_ERROR_IS_OK(status))
3574 return WERR_INVALID_PRINTER_NAME;
3576 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3577 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3578 if (!W_ERROR_IS_OK(status)) {
3579 free_a_printer(&printer,2);
3580 return WERR_UNKNOWN_PRINTER_DRIVER;
3583 fill_printer_driver_info_3(info, driver, servername);
3585 free_a_printer(&printer,2);
3587 return WERR_OK;
3590 /********************************************************************
3591 * construct_printer_info_6
3592 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3593 ********************************************************************/
3595 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3597 pstring temp;
3598 fstring nullstr;
3600 ZERO_STRUCTP(info);
3601 memset(&nullstr, '\0', sizeof(fstring));
3603 info->version=driver.info_3->cversion;
3605 init_unistr( &info->name, driver.info_3->name );
3606 init_unistr( &info->architecture, driver.info_3->environment );
3608 if (strlen(driver.info_3->driverpath)) {
3609 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3610 init_unistr( &info->driverpath, temp );
3611 } else
3612 init_unistr( &info->driverpath, "" );
3614 if (strlen(driver.info_3->datafile)) {
3615 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3616 init_unistr( &info->datafile, temp );
3617 } else
3618 init_unistr( &info->datafile, "" );
3620 if (strlen(driver.info_3->configfile)) {
3621 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3622 init_unistr( &info->configfile, temp );
3623 } else
3624 init_unistr( &info->configfile, "" );
3626 if (strlen(driver.info_3->helpfile)) {
3627 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3628 init_unistr( &info->helpfile, temp );
3629 } else
3630 init_unistr( &info->helpfile, "" );
3632 init_unistr( &info->monitorname, driver.info_3->monitorname );
3633 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3635 info->dependentfiles=NULL;
3636 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3638 info->previousdrivernames=NULL;
3639 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3641 info->driver_date.low=0;
3642 info->driver_date.high=0;
3644 info->padding=0;
3645 info->driver_version_low=0;
3646 info->driver_version_high=0;
3648 init_unistr( &info->mfgname, "");
3649 init_unistr( &info->oem_url, "");
3650 init_unistr( &info->hardware_id, "");
3651 init_unistr( &info->provider, "");
3654 /********************************************************************
3655 * construct_printer_info_6
3656 * fill a printer_info_6 struct
3657 ********************************************************************/
3658 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3660 NT_PRINTER_INFO_LEVEL *printer = NULL;
3661 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3662 WERROR status;
3663 ZERO_STRUCT(driver);
3665 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3666 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3667 if (!W_ERROR_IS_OK(status))
3668 return WERR_INVALID_PRINTER_NAME;
3670 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3671 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3672 if (!W_ERROR_IS_OK(status)) {
3674 * Is this a W2k client ?
3677 if (version < 3) {
3678 free_a_printer(&printer,2);
3679 return WERR_UNKNOWN_PRINTER_DRIVER;
3682 /* Yes - try again with a WinNT driver. */
3683 version = 2;
3684 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3685 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3686 if (!W_ERROR_IS_OK(status)) {
3687 free_a_printer(&printer,2);
3688 return WERR_UNKNOWN_PRINTER_DRIVER;
3692 fill_printer_driver_info_6(info, driver, servername);
3694 free_a_printer(&printer,2);
3696 return WERR_OK;
3699 /****************************************************************************
3700 ****************************************************************************/
3702 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3704 SAFE_FREE(info->dependentfiles);
3707 /****************************************************************************
3708 ****************************************************************************/
3710 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3712 SAFE_FREE(info->dependentfiles);
3716 /****************************************************************************
3717 ****************************************************************************/
3718 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3720 DRIVER_INFO_1 *info=NULL;
3721 WERROR status;
3723 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3724 return WERR_NOMEM;
3726 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3727 if (!W_ERROR_IS_OK(status)) {
3728 SAFE_FREE(info);
3729 return status;
3732 /* check the required size. */
3733 *needed += spoolss_size_printer_driver_info_1(info);
3735 if (!alloc_buffer_size(buffer, *needed)) {
3736 SAFE_FREE(info);
3737 return WERR_INSUFFICIENT_BUFFER;
3740 /* fill the buffer with the structures */
3741 smb_io_printer_driver_info_1("", buffer, info, 0);
3743 /* clear memory */
3744 SAFE_FREE(info);
3746 if (*needed > offered)
3747 return WERR_INSUFFICIENT_BUFFER;
3749 return WERR_OK;
3752 /****************************************************************************
3753 ****************************************************************************/
3754 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3756 DRIVER_INFO_2 *info=NULL;
3757 WERROR status;
3759 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3760 return WERR_NOMEM;
3762 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3763 if (!W_ERROR_IS_OK(status)) {
3764 SAFE_FREE(info);
3765 return status;
3768 /* check the required size. */
3769 *needed += spoolss_size_printer_driver_info_2(info);
3771 if (!alloc_buffer_size(buffer, *needed)) {
3772 SAFE_FREE(info);
3773 return WERR_INSUFFICIENT_BUFFER;
3776 /* fill the buffer with the structures */
3777 smb_io_printer_driver_info_2("", buffer, info, 0);
3779 /* clear memory */
3780 SAFE_FREE(info);
3782 if (*needed > offered)
3783 return WERR_INSUFFICIENT_BUFFER;
3785 return WERR_OK;
3788 /****************************************************************************
3789 ****************************************************************************/
3790 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3792 DRIVER_INFO_3 info;
3793 WERROR status;
3795 ZERO_STRUCT(info);
3797 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3798 if (!W_ERROR_IS_OK(status)) {
3799 return status;
3802 /* check the required size. */
3803 *needed += spoolss_size_printer_driver_info_3(&info);
3805 if (!alloc_buffer_size(buffer, *needed)) {
3806 free_printer_driver_info_3(&info);
3807 return WERR_INSUFFICIENT_BUFFER;
3810 /* fill the buffer with the structures */
3811 smb_io_printer_driver_info_3("", buffer, &info, 0);
3813 free_printer_driver_info_3(&info);
3815 if (*needed > offered)
3816 return WERR_INSUFFICIENT_BUFFER;
3818 return WERR_OK;
3821 /****************************************************************************
3822 ****************************************************************************/
3823 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3825 DRIVER_INFO_6 info;
3826 WERROR status;
3828 ZERO_STRUCT(info);
3830 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3831 if (!W_ERROR_IS_OK(status)) {
3832 return status;
3835 /* check the required size. */
3836 *needed += spoolss_size_printer_driver_info_6(&info);
3838 if (!alloc_buffer_size(buffer, *needed)) {
3839 free_printer_driver_info_6(&info);
3840 return WERR_INSUFFICIENT_BUFFER;
3843 /* fill the buffer with the structures */
3844 smb_io_printer_driver_info_6("", buffer, &info, 0);
3846 free_printer_driver_info_6(&info);
3848 if (*needed > offered)
3849 return WERR_INSUFFICIENT_BUFFER;
3851 return WERR_OK;
3854 /****************************************************************************
3855 ****************************************************************************/
3857 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3859 POLICY_HND *handle = &q_u->handle;
3860 UNISTR2 *uni_arch = &q_u->architecture;
3861 uint32 level = q_u->level;
3862 uint32 clientmajorversion = q_u->clientmajorversion;
3863 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3864 NEW_BUFFER *buffer = NULL;
3865 uint32 offered = q_u->offered;
3866 uint32 *needed = &r_u->needed;
3867 uint32 *servermajorversion = &r_u->servermajorversion;
3868 uint32 *serverminorversion = &r_u->serverminorversion;
3870 fstring servername;
3871 fstring architecture;
3872 int snum;
3874 /* that's an [in out] buffer */
3875 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3876 buffer = r_u->buffer;
3878 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3880 *needed=0;
3881 *servermajorversion=0;
3882 *serverminorversion=0;
3884 pstrcpy(servername, global_myname);
3885 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3887 if (!get_printer_snum(p, handle, &snum))
3888 return WERR_BADFID;
3890 switch (level) {
3891 case 1:
3892 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3893 case 2:
3894 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3895 case 3:
3896 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3897 case 6:
3898 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3901 return WERR_UNKNOWN_LEVEL;
3904 /****************************************************************************
3905 ****************************************************************************/
3907 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3909 POLICY_HND *handle = &q_u->handle;
3911 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3913 if (Printer) {
3914 Printer->page_started=True;
3915 return WERR_OK;
3918 DEBUG(3,("Error in startpageprinter printer handle\n"));
3919 return WERR_BADFID;
3922 /****************************************************************************
3923 ****************************************************************************/
3925 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3927 POLICY_HND *handle = &q_u->handle;
3929 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3931 if (!Printer) {
3932 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3933 return WERR_BADFID;
3936 Printer->page_started=False;
3938 return WERR_OK;
3941 /********************************************************************
3942 * api_spoolss_getprinter
3943 * called from the spoolss dispatcher
3945 ********************************************************************/
3947 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3949 POLICY_HND *handle = &q_u->handle;
3950 /* uint32 level = q_u->doc_info_container.level; - notused. */
3951 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3952 uint32 *jobid = &r_u->jobid;
3954 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3955 int snum;
3956 pstring jobname;
3957 fstring datatype;
3958 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3959 struct current_user user;
3961 if (!Printer) {
3962 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3963 return WERR_BADFID;
3966 get_current_user(&user, p);
3969 * a nice thing with NT is it doesn't listen to what you tell it.
3970 * when asked to send _only_ RAW datas, it tries to send datas
3971 * in EMF format.
3973 * So I add checks like in NT Server ...
3975 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3976 * there's a bug in NT client-side code, so we'll fix it in the
3977 * server-side code. *nnnnnggggh!*
3980 if (info_1->p_datatype != 0) {
3981 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3982 if (strcmp(datatype, "RAW") != 0) {
3983 (*jobid)=0;
3984 return WERR_INVALID_DATATYPE;
3988 /* get the share number of the printer */
3989 if (!get_printer_snum(p, handle, &snum)) {
3990 return WERR_BADFID;
3993 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3995 Printer->jobid = print_job_start(&user, snum, jobname);
3997 /* An error occured in print_job_start() so return an appropriate
3998 NT error code. */
4000 if (Printer->jobid == -1) {
4001 return map_werror_from_unix(errno);
4004 Printer->document_started=True;
4005 (*jobid) = Printer->jobid;
4007 return WERR_OK;
4010 /********************************************************************
4011 * api_spoolss_getprinter
4012 * called from the spoolss dispatcher
4014 ********************************************************************/
4016 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4018 POLICY_HND *handle = &q_u->handle;
4020 return _spoolss_enddocprinter_internal(p, handle);
4023 /****************************************************************************
4024 ****************************************************************************/
4026 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4028 POLICY_HND *handle = &q_u->handle;
4029 uint32 buffer_size = q_u->buffer_size;
4030 uint8 *buffer = q_u->buffer;
4031 uint32 *buffer_written = &q_u->buffer_size2;
4033 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4035 if (!Printer) {
4036 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4037 r_u->buffer_written = q_u->buffer_size2;
4038 return WERR_BADFID;
4041 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4044 r_u->buffer_written = q_u->buffer_size2;
4046 return WERR_OK;
4049 /********************************************************************
4050 * api_spoolss_getprinter
4051 * called from the spoolss dispatcher
4053 ********************************************************************/
4054 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4055 pipes_struct *p)
4057 struct current_user user;
4058 int snum;
4059 WERROR errcode = WERR_BADFUNC;
4060 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4062 get_current_user(&user, p);
4064 if (!Printer) {
4065 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4066 return WERR_BADFID;
4069 if (!get_printer_snum(p, handle, &snum))
4070 return WERR_BADFID;
4072 switch (command) {
4073 case PRINTER_CONTROL_PAUSE:
4074 if (print_queue_pause(&user, snum, &errcode)) {
4075 errcode = WERR_OK;
4077 break;
4078 case PRINTER_CONTROL_RESUME:
4079 case PRINTER_CONTROL_UNPAUSE:
4080 if (print_queue_resume(&user, snum, &errcode)) {
4081 errcode = WERR_OK;
4083 break;
4084 case PRINTER_CONTROL_PURGE:
4085 if (print_queue_purge(&user, snum, &errcode)) {
4086 errcode = WERR_OK;
4088 break;
4089 default:
4090 return WERR_UNKNOWN_LEVEL;
4093 return errcode;
4096 /********************************************************************
4097 * api_spoolss_abortprinter
4098 ********************************************************************/
4100 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4102 POLICY_HND *handle = &q_u->handle;
4104 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4107 /********************************************************************
4108 * called by spoolss_api_setprinter
4109 * when updating a printer description
4110 ********************************************************************/
4111 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4112 const SPOOL_PRINTER_INFO_LEVEL *info,
4113 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4115 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4116 struct current_user user;
4117 WERROR result;
4118 int snum;
4120 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4122 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4123 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4124 OUR_HANDLE(handle)));
4126 result = WERR_BADFID;
4127 goto done;
4130 /* NT seems to like setting the security descriptor even though
4131 nothing may have actually changed. This causes annoying
4132 dialog boxes when the user doesn't have permission to change
4133 the security descriptor. */
4135 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4137 if (DEBUGLEVEL >= 10) {
4138 SEC_ACL *the_acl;
4139 int i;
4141 the_acl = old_secdesc_ctr->sec->dacl;
4142 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4143 PRINTERNAME(snum), the_acl->num_aces));
4145 for (i = 0; i < the_acl->num_aces; i++) {
4146 fstring sid_str;
4148 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4150 DEBUG(10, ("%s 0x%08x\n", sid_str,
4151 the_acl->ace[i].info.mask));
4154 the_acl = secdesc_ctr->sec->dacl;
4156 if (the_acl) {
4157 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4158 PRINTERNAME(snum), the_acl->num_aces));
4160 for (i = 0; i < the_acl->num_aces; i++) {
4161 fstring sid_str;
4163 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4165 DEBUG(10, ("%s 0x%08x\n", sid_str,
4166 the_acl->ace[i].info.mask));
4168 } else {
4169 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4173 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4175 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4176 result = WERR_OK;
4177 goto done;
4180 /* Work out which user is performing the operation */
4182 get_current_user(&user, p);
4184 /* Check the user has permissions to change the security
4185 descriptor. By experimentation with two NT machines, the user
4186 requires Full Access to the printer to change security
4187 information. */
4189 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4190 result = WERR_ACCESS_DENIED;
4191 goto done;
4194 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4196 done:
4198 return result;
4201 /********************************************************************
4202 Do Samba sanity checks on a printer info struct.
4203 this has changed purpose: it now "canonicalises" printer
4204 info from a client rather than just checking it is correct
4205 ********************************************************************/
4207 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4209 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4210 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4212 /* we force some elements to "correct" values */
4213 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4214 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4215 global_myname, lp_servicename(snum));
4216 fstrcpy(info->sharename, lp_servicename(snum));
4217 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4218 | PRINTER_ATTRIBUTE_LOCAL \
4219 | PRINTER_ATTRIBUTE_RAW_ONLY \
4220 | PRINTER_ATTRIBUTE_QUEUED ;
4222 return True;
4225 /****************************************************************************
4226 ****************************************************************************/
4227 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4229 char *cmd = lp_addprinter_cmd();
4230 char **qlines;
4231 pstring command;
4232 pstring driverlocation;
4233 int numlines;
4234 int ret;
4235 int fd;
4237 /* build driver path... only 9X architecture is needed for legacy reasons */
4238 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4239 global_myname);
4240 /* change \ to \\ for the shell */
4241 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4243 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4244 cmd, printer->info_2->printername, printer->info_2->sharename,
4245 printer->info_2->portname, printer->info_2->drivername,
4246 printer->info_2->location, driverlocation);
4248 DEBUG(10,("Running [%s]\n", command));
4249 ret = smbrun(command, &fd);
4250 DEBUGADD(10,("returned [%d]\n", ret));
4252 if ( ret != 0 ) {
4253 if (fd != -1)
4254 close(fd);
4255 return False;
4258 numlines = 0;
4259 /* Get lines and convert them back to dos-codepage */
4260 qlines = fd_lines_load(fd, &numlines);
4261 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4262 close(fd);
4264 if(numlines) {
4265 /* Set the portname to what the script says the portname should be. */
4266 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4267 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4269 /* Send SIGHUP to process group... is there a better way? */
4270 kill(0, SIGHUP);
4271 add_all_printers();
4274 file_lines_free(qlines);
4275 return True;
4278 /* Return true if two devicemodes are equal */
4280 #define DEVMODE_CHECK_INT(field) \
4281 if (d1->field != d2->field) { \
4282 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4283 d1->field, d2->field)); \
4284 return False; \
4287 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4289 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4291 if (!d1 ^ !d2) {
4292 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4293 return False; /* if either is exclusively NULL are not equal */
4296 if (!strequal(d1->devicename, d2->devicename)) {
4297 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4298 return False;
4301 if (!strequal(d1->formname, d2->formname)) {
4302 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4303 return False;
4306 DEVMODE_CHECK_INT(specversion);
4307 DEVMODE_CHECK_INT(driverversion);
4308 DEVMODE_CHECK_INT(driverextra);
4309 DEVMODE_CHECK_INT(orientation);
4310 DEVMODE_CHECK_INT(papersize);
4311 DEVMODE_CHECK_INT(paperlength);
4312 DEVMODE_CHECK_INT(paperwidth);
4313 DEVMODE_CHECK_INT(scale);
4314 DEVMODE_CHECK_INT(copies);
4315 DEVMODE_CHECK_INT(defaultsource);
4316 DEVMODE_CHECK_INT(printquality);
4317 DEVMODE_CHECK_INT(color);
4318 DEVMODE_CHECK_INT(duplex);
4319 DEVMODE_CHECK_INT(yresolution);
4320 DEVMODE_CHECK_INT(ttoption);
4321 DEVMODE_CHECK_INT(collate);
4322 DEVMODE_CHECK_INT(logpixels);
4324 DEVMODE_CHECK_INT(fields);
4325 DEVMODE_CHECK_INT(bitsperpel);
4326 DEVMODE_CHECK_INT(pelswidth);
4327 DEVMODE_CHECK_INT(pelsheight);
4328 DEVMODE_CHECK_INT(displayflags);
4329 DEVMODE_CHECK_INT(displayfrequency);
4330 DEVMODE_CHECK_INT(icmmethod);
4331 DEVMODE_CHECK_INT(icmintent);
4332 DEVMODE_CHECK_INT(mediatype);
4333 DEVMODE_CHECK_INT(dithertype);
4334 DEVMODE_CHECK_INT(reserved1);
4335 DEVMODE_CHECK_INT(reserved2);
4336 DEVMODE_CHECK_INT(panningwidth);
4337 DEVMODE_CHECK_INT(panningheight);
4339 /* compare the private data if it exists */
4340 if (!d1->driverextra && !d2->driverextra) goto equal;
4343 DEVMODE_CHECK_INT(driverextra);
4345 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4346 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4347 return False;
4350 equal:
4351 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4352 return True;
4355 /* Return true if two NT_PRINTER_PARAM structures are equal */
4357 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4358 NT_PRINTER_PARAM *p2)
4360 if (!p1 && !p2) goto equal;
4362 if ((!p1 && p2) || (p1 && !p2)) {
4363 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4364 return False;
4367 /* Compare lists of printer parameters */
4369 while (p1) {
4370 BOOL found = False;
4371 NT_PRINTER_PARAM *q = p1;
4373 /* Find the parameter in the second structure */
4375 while(q) {
4377 if (strequal(p1->value, q->value)) {
4379 if (p1->type != q->type) {
4380 DEBUG(10, ("nt_printer_param_equal():"
4381 "types for %s differ (%d != %d)\n",
4382 p1->value, p1->type,
4383 q->type));
4384 break;
4387 if (p1->data_len != q->data_len) {
4388 DEBUG(10, ("nt_printer_param_equal():"
4389 "len for %s differs (%d != %d)\n",
4390 p1->value, p1->data_len,
4391 q->data_len));
4392 break;
4395 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4396 found = True;
4397 } else {
4398 DEBUG(10, ("nt_printer_param_equal():"
4399 "data for %s differs\n", p1->value));
4402 break;
4405 q = q->next;
4408 if (!found) {
4409 DEBUG(10, ("nt_printer_param_equal(): param %s "
4410 "does not exist\n", p1->value));
4411 return False;
4414 p1 = p1->next;
4417 equal:
4419 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4420 return True;
4423 /********************************************************************
4424 * Called by update_printer when trying to work out whether to
4425 * actually update printer info.
4426 ********************************************************************/
4428 #define PI_CHECK_INT(field) \
4429 if (pi1->field != pi2->field) { \
4430 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4431 pi1->field, pi2->field)); \
4432 return False; \
4435 #define PI_CHECK_STR(field) \
4436 if (!strequal(pi1->field, pi2->field)) { \
4437 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4438 pi1->field, pi2->field)); \
4439 return False; \
4442 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4443 NT_PRINTER_INFO_LEVEL *p2)
4445 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4447 /* Trivial conditions */
4449 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4450 goto equal;
4453 if ((!p1 && p2) || (p1 && !p2) ||
4454 (!p1->info_2 && p2->info_2) ||
4455 (p1->info_2 && !p2->info_2)) {
4456 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4457 "differ\n"));
4458 return False;
4461 /* Compare two nt_printer_info_level structures. Don't compare
4462 status or cjobs as they seem to have something to do with the
4463 printer queue. */
4465 pi1 = p1->info_2;
4466 pi2 = p2->info_2;
4468 /* Don't check the attributes as we stomp on the value in
4469 check_printer_ok() anyway. */
4471 #if 0
4472 PI_CHECK_INT(attributes);
4473 #endif
4475 PI_CHECK_INT(priority);
4476 PI_CHECK_INT(default_priority);
4477 PI_CHECK_INT(starttime);
4478 PI_CHECK_INT(untiltime);
4479 PI_CHECK_INT(averageppm);
4481 /* Yuck - don't check the printername or servername as the
4482 add_a_printer() code plays games with them. You can't
4483 change the printername or the sharename through this interface
4484 in Samba. */
4486 PI_CHECK_STR(sharename);
4487 PI_CHECK_STR(portname);
4488 PI_CHECK_STR(drivername);
4489 PI_CHECK_STR(comment);
4490 PI_CHECK_STR(location);
4492 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4493 return False;
4496 PI_CHECK_STR(sepfile);
4497 PI_CHECK_STR(printprocessor);
4498 PI_CHECK_STR(datatype);
4499 PI_CHECK_STR(parameters);
4501 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4502 return False;
4505 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4506 return False;
4509 PI_CHECK_INT(changeid);
4510 PI_CHECK_INT(c_setprinter);
4511 PI_CHECK_INT(setuptime);
4513 equal:
4514 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4515 return True;
4518 /********************************************************************
4519 * called by spoolss_api_setprinter
4520 * when updating a printer description
4521 ********************************************************************/
4523 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4524 const SPOOL_PRINTER_INFO_LEVEL *info,
4525 DEVICEMODE *devmode)
4527 int snum;
4528 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4529 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4530 WERROR result;
4532 DEBUG(8,("update_printer\n"));
4534 result = WERR_OK;
4536 if (level!=2) {
4537 DEBUG(0,("Send a mail to samba@samba.org\n"));
4538 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4539 result = WERR_UNKNOWN_LEVEL;
4540 goto done;
4543 if (!Printer) {
4544 result = WERR_BADFID;
4545 goto done;
4548 if (!get_printer_snum(p, handle, &snum)) {
4549 result = WERR_BADFID;
4550 goto done;
4553 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4554 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4555 result = WERR_BADFID;
4556 goto done;
4559 DEBUGADD(8,("Converting info_2 struct\n"));
4562 * convert_printer_info converts the incoming
4563 * info from the client and overwrites the info
4564 * just read from the tdb in the pointer 'printer'.
4567 if (!convert_printer_info(info, printer, level)) {
4568 result = WERR_NOMEM;
4569 goto done;
4572 if (info->info_2->devmode_ptr != 0) {
4573 /* we have a valid devmode
4574 convert it and link it*/
4576 DEBUGADD(8,("Converting the devicemode struct\n"));
4577 if (!convert_devicemode(printer->info_2->printername, devmode,
4578 &printer->info_2->devmode)) {
4579 result = WERR_NOMEM;
4580 goto done;
4584 /* Do sanity check on the requested changes for Samba */
4586 if (!check_printer_ok(printer->info_2, snum)) {
4587 result = WERR_INVALID_PARAM;
4588 goto done;
4591 /* NT likes to call this function even though nothing has actually
4592 changed. Check this so the user doesn't end up with an
4593 annoying permission denied dialog box. */
4595 if (nt_printer_info_level_equal(printer, old_printer)) {
4596 DEBUG(3, ("printer info has not changed\n"));
4597 result = WERR_OK;
4598 goto done;
4601 /* Check calling user has permission to update printer description */
4603 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4604 DEBUG(3, ("printer property change denied by security "
4605 "descriptor\n"));
4606 result = WERR_ACCESS_DENIED;
4607 goto done;
4610 /* Call addprinter hook */
4612 if (*lp_addprinter_cmd()) {
4613 if (!add_printer_hook(printer)) {
4614 result = WERR_ACCESS_DENIED;
4615 goto done;
4619 /* Update printer info */
4620 result = add_a_printer(*printer, 2);
4622 done:
4623 free_a_printer(&printer, 2);
4624 free_a_printer(&old_printer, 2);
4626 srv_spoolss_sendnotify(p, handle);
4628 return result;
4631 /****************************************************************************
4632 ****************************************************************************/
4634 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4636 POLICY_HND *handle = &q_u->handle;
4637 uint32 level = q_u->level;
4638 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4639 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4640 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4641 uint32 command = q_u->command;
4643 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4645 if (!Printer) {
4646 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4647 return WERR_BADFID;
4650 /* check the level */
4651 switch (level) {
4652 case 0:
4653 return control_printer(handle, command, p);
4654 case 2:
4655 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4656 case 3:
4657 return update_printer_sec(handle, level, info, p,
4658 secdesc_ctr);
4659 default:
4660 return WERR_UNKNOWN_LEVEL;
4664 /****************************************************************************
4665 ****************************************************************************/
4667 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4669 POLICY_HND *handle = &q_u->handle;
4671 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4673 if (!Printer) {
4674 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4675 return WERR_BADFID;
4678 if (Printer->notify.client_connected==True)
4679 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4681 Printer->notify.flags=0;
4682 Printer->notify.options=0;
4683 Printer->notify.localmachine[0]='\0';
4684 Printer->notify.printerlocal=0;
4685 if (Printer->notify.option)
4686 free_spool_notify_option(&Printer->notify.option);
4687 Printer->notify.client_connected=False;
4689 return WERR_OK;
4692 /****************************************************************************
4693 ****************************************************************************/
4695 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4697 /* that's an [in out] buffer (despite appearences to the contrary) */
4698 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4700 r_u->needed = 0;
4701 return WERR_INVALID_PARAM; /* this is what a NT server
4702 returns for AddJob. AddJob
4703 must fail on non-local
4704 printers */
4707 /****************************************************************************
4708 ****************************************************************************/
4709 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4710 int position, int snum)
4712 pstring temp_name;
4714 struct tm *t;
4716 t=gmtime(&queue->time);
4717 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4719 job_info->jobid=queue->job;
4720 init_unistr(&job_info->printername, lp_servicename(snum));
4721 init_unistr(&job_info->machinename, temp_name);
4722 init_unistr(&job_info->username, queue->user);
4723 init_unistr(&job_info->document, queue->file);
4724 init_unistr(&job_info->datatype, "RAW");
4725 init_unistr(&job_info->text_status, "");
4726 job_info->status=nt_printj_status(queue->status);
4727 job_info->priority=queue->priority;
4728 job_info->position=position;
4729 job_info->totalpages=0;
4730 job_info->pagesprinted=0;
4732 make_systemtime(&job_info->submitted, t);
4735 /****************************************************************************
4736 ****************************************************************************/
4737 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4738 int position, int snum,
4739 NT_PRINTER_INFO_LEVEL *ntprinter)
4741 pstring temp_name;
4742 pstring chaine;
4743 struct tm *t;
4745 t=gmtime(&queue->time);
4746 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4748 job_info->jobid=queue->job;
4750 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4752 init_unistr(&job_info->printername, chaine);
4754 init_unistr(&job_info->machinename, temp_name);
4755 init_unistr(&job_info->username, queue->user);
4756 init_unistr(&job_info->document, queue->file);
4757 init_unistr(&job_info->notifyname, queue->user);
4758 init_unistr(&job_info->datatype, "RAW");
4759 init_unistr(&job_info->printprocessor, "winprint");
4760 init_unistr(&job_info->parameters, "");
4761 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4762 init_unistr(&job_info->text_status, "");
4764 /* and here the security descriptor */
4766 job_info->status=nt_printj_status(queue->status);
4767 job_info->priority=queue->priority;
4768 job_info->position=position;
4769 job_info->starttime=0;
4770 job_info->untiltime=0;
4771 job_info->totalpages=0;
4772 job_info->size=queue->size;
4773 make_systemtime(&(job_info->submitted), t);
4774 job_info->timeelapsed=0;
4775 job_info->pagesprinted=0;
4777 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4778 return False;
4781 return (True);
4784 /****************************************************************************
4785 Enumjobs at level 1.
4786 ****************************************************************************/
4787 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4788 NEW_BUFFER *buffer, uint32 offered,
4789 uint32 *needed, uint32 *returned)
4791 JOB_INFO_1 *info;
4792 int i;
4794 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4795 if (info==NULL) {
4796 SAFE_FREE(queue);
4797 *returned=0;
4798 return WERR_NOMEM;
4801 for (i=0; i<*returned; i++)
4802 fill_job_info_1(&info[i], &queue[i], i, snum);
4804 SAFE_FREE(queue);
4806 /* check the required size. */
4807 for (i=0; i<*returned; i++)
4808 (*needed) += spoolss_size_job_info_1(&info[i]);
4810 if (!alloc_buffer_size(buffer, *needed)) {
4811 SAFE_FREE(info);
4812 return WERR_INSUFFICIENT_BUFFER;
4815 /* fill the buffer with the structures */
4816 for (i=0; i<*returned; i++)
4817 smb_io_job_info_1("", buffer, &info[i], 0);
4819 /* clear memory */
4820 SAFE_FREE(info);
4822 if (*needed > offered) {
4823 *returned=0;
4824 return WERR_INSUFFICIENT_BUFFER;
4827 return WERR_OK;
4830 /****************************************************************************
4831 Enumjobs at level 2.
4832 ****************************************************************************/
4833 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4834 NEW_BUFFER *buffer, uint32 offered,
4835 uint32 *needed, uint32 *returned)
4837 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4838 JOB_INFO_2 *info;
4839 int i;
4840 WERROR result;
4842 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4843 if (info==NULL) {
4844 *returned=0;
4845 return WERR_NOMEM;
4848 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4849 if (!W_ERROR_IS_OK(result)) {
4850 *returned = 0;
4851 return result;
4854 for (i=0; i<*returned; i++)
4855 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4857 free_a_printer(&ntprinter, 2);
4858 SAFE_FREE(queue);
4860 /* check the required size. */
4861 for (i=0; i<*returned; i++)
4862 (*needed) += spoolss_size_job_info_2(&info[i]);
4864 if (!alloc_buffer_size(buffer, *needed)) {
4865 SAFE_FREE(info);
4866 return WERR_INSUFFICIENT_BUFFER;
4869 /* fill the buffer with the structures */
4870 for (i=0; i<*returned; i++)
4871 smb_io_job_info_2("", buffer, &info[i], 0);
4873 /* clear memory */
4874 for (i = 0; i < *returned; i++)
4875 free_job_info_2(&info[i]);
4877 SAFE_FREE(info);
4879 if (*needed > offered) {
4880 *returned=0;
4881 return WERR_INSUFFICIENT_BUFFER;
4884 return WERR_OK;
4887 /****************************************************************************
4888 Enumjobs.
4889 ****************************************************************************/
4891 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4893 POLICY_HND *handle = &q_u->handle;
4894 /* uint32 firstjob = q_u->firstjob; - notused. */
4895 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4896 uint32 level = q_u->level;
4897 NEW_BUFFER *buffer = NULL;
4898 uint32 offered = q_u->offered;
4899 uint32 *needed = &r_u->needed;
4900 uint32 *returned = &r_u->returned;
4902 int snum;
4903 print_queue_struct *queue=NULL;
4904 print_status_struct prt_status;
4906 /* that's an [in out] buffer */
4907 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4908 buffer = r_u->buffer;
4910 DEBUG(4,("_spoolss_enumjobs\n"));
4912 ZERO_STRUCT(prt_status);
4914 *needed=0;
4915 *returned=0;
4917 if (!get_printer_snum(p, handle, &snum))
4918 return WERR_BADFID;
4920 *returned = print_queue_status(snum, &queue, &prt_status);
4921 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4923 if (*returned == 0) {
4924 SAFE_FREE(queue);
4925 return WERR_OK;
4928 switch (level) {
4929 case 1:
4930 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4931 case 2:
4932 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4933 default:
4934 SAFE_FREE(queue);
4935 *returned=0;
4936 return WERR_UNKNOWN_LEVEL;
4940 /****************************************************************************
4941 ****************************************************************************/
4943 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4945 return WERR_OK;
4948 /****************************************************************************
4949 ****************************************************************************/
4951 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4953 POLICY_HND *handle = &q_u->handle;
4954 uint32 jobid = q_u->jobid;
4955 /* uint32 level = q_u->level; - notused. */
4956 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4957 uint32 command = q_u->command;
4959 struct current_user user;
4960 print_status_struct prt_status;
4961 int snum;
4962 WERROR errcode = WERR_BADFUNC;
4964 memset(&prt_status, 0, sizeof(prt_status));
4966 if (!get_printer_snum(p, handle, &snum)) {
4967 return WERR_BADFID;
4970 if (!print_job_exists(jobid)) {
4971 return WERR_INVALID_PRINTER_NAME;
4974 get_current_user(&user, p);
4976 switch (command) {
4977 case JOB_CONTROL_CANCEL:
4978 case JOB_CONTROL_DELETE:
4979 if (print_job_delete(&user, jobid, &errcode)) {
4980 errcode = WERR_OK;
4982 break;
4983 case JOB_CONTROL_PAUSE:
4984 if (print_job_pause(&user, jobid, &errcode)) {
4985 errcode = WERR_OK;
4987 break;
4988 case JOB_CONTROL_RESTART:
4989 case JOB_CONTROL_RESUME:
4990 if (print_job_resume(&user, jobid, &errcode)) {
4991 errcode = WERR_OK;
4993 break;
4994 default:
4995 return WERR_UNKNOWN_LEVEL;
4998 return errcode;
5001 /****************************************************************************
5002 Enumerates all printer drivers at level 1.
5003 ****************************************************************************/
5004 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5006 int i;
5007 int ndrivers;
5008 uint32 version;
5009 fstring *list = NULL;
5011 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5012 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5014 *returned=0;
5016 #define MAX_VERSION 4
5018 for (version=0; version<MAX_VERSION; version++) {
5019 list=NULL;
5020 ndrivers=get_ntdrivers(&list, architecture, version);
5021 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5023 if(ndrivers == -1)
5024 return WERR_NOMEM;
5026 if(ndrivers != 0) {
5027 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5028 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5029 SAFE_FREE(driver_info_1);
5030 SAFE_FREE(list);
5031 return WERR_NOMEM;
5033 else driver_info_1 = tdi1;
5036 for (i=0; i<ndrivers; i++) {
5037 WERROR status;
5038 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5039 ZERO_STRUCT(driver);
5040 status = get_a_printer_driver(&driver, 3, list[i],
5041 architecture, version);
5042 if (!W_ERROR_IS_OK(status)) {
5043 SAFE_FREE(list);
5044 return status;
5046 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5047 free_a_printer_driver(driver, 3);
5050 *returned+=ndrivers;
5051 SAFE_FREE(list);
5054 /* check the required size. */
5055 for (i=0; i<*returned; i++) {
5056 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5057 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5060 if (!alloc_buffer_size(buffer, *needed)) {
5061 SAFE_FREE(driver_info_1);
5062 return WERR_INSUFFICIENT_BUFFER;
5065 /* fill the buffer with the driver structures */
5066 for (i=0; i<*returned; i++) {
5067 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5068 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5071 SAFE_FREE(driver_info_1);
5073 if (*needed > offered) {
5074 *returned=0;
5075 return WERR_INSUFFICIENT_BUFFER;
5078 return WERR_OK;
5081 /****************************************************************************
5082 Enumerates all printer drivers at level 2.
5083 ****************************************************************************/
5084 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5086 int i;
5087 int ndrivers;
5088 uint32 version;
5089 fstring *list = NULL;
5091 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5092 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5094 *returned=0;
5096 #define MAX_VERSION 4
5098 for (version=0; version<MAX_VERSION; version++) {
5099 list=NULL;
5100 ndrivers=get_ntdrivers(&list, architecture, version);
5101 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5103 if(ndrivers == -1)
5104 return WERR_NOMEM;
5106 if(ndrivers != 0) {
5107 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5108 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5109 SAFE_FREE(driver_info_2);
5110 SAFE_FREE(list);
5111 return WERR_NOMEM;
5113 else driver_info_2 = tdi2;
5116 for (i=0; i<ndrivers; i++) {
5117 WERROR status;
5119 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5120 ZERO_STRUCT(driver);
5121 status = get_a_printer_driver(&driver, 3, list[i],
5122 architecture, version);
5123 if (!W_ERROR_IS_OK(status)) {
5124 SAFE_FREE(list);
5125 return status;
5127 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5128 free_a_printer_driver(driver, 3);
5131 *returned+=ndrivers;
5132 SAFE_FREE(list);
5135 /* check the required size. */
5136 for (i=0; i<*returned; i++) {
5137 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5138 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5141 if (!alloc_buffer_size(buffer, *needed)) {
5142 SAFE_FREE(driver_info_2);
5143 return WERR_INSUFFICIENT_BUFFER;
5146 /* fill the buffer with the form structures */
5147 for (i=0; i<*returned; i++) {
5148 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5149 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5152 SAFE_FREE(driver_info_2);
5154 if (*needed > offered) {
5155 *returned=0;
5156 return WERR_INSUFFICIENT_BUFFER;
5159 return WERR_OK;
5162 /****************************************************************************
5163 Enumerates all printer drivers at level 3.
5164 ****************************************************************************/
5165 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5167 int i;
5168 int ndrivers;
5169 uint32 version;
5170 fstring *list = NULL;
5172 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5173 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5175 *returned=0;
5177 #define MAX_VERSION 4
5179 for (version=0; version<MAX_VERSION; version++) {
5180 list=NULL;
5181 ndrivers=get_ntdrivers(&list, architecture, version);
5182 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5184 if(ndrivers == -1)
5185 return WERR_NOMEM;
5187 if(ndrivers != 0) {
5188 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5189 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5190 SAFE_FREE(driver_info_3);
5191 SAFE_FREE(list);
5192 return WERR_NOMEM;
5194 else driver_info_3 = tdi3;
5197 for (i=0; i<ndrivers; i++) {
5198 WERROR status;
5200 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5201 ZERO_STRUCT(driver);
5202 status = get_a_printer_driver(&driver, 3, list[i],
5203 architecture, version);
5204 if (!W_ERROR_IS_OK(status)) {
5205 SAFE_FREE(list);
5206 return status;
5208 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5209 free_a_printer_driver(driver, 3);
5212 *returned+=ndrivers;
5213 SAFE_FREE(list);
5216 /* check the required size. */
5217 for (i=0; i<*returned; i++) {
5218 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5219 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5222 if (!alloc_buffer_size(buffer, *needed)) {
5223 SAFE_FREE(driver_info_3);
5224 return WERR_INSUFFICIENT_BUFFER;
5227 /* fill the buffer with the driver structures */
5228 for (i=0; i<*returned; i++) {
5229 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5230 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5233 for (i=0; i<*returned; i++)
5234 SAFE_FREE(driver_info_3[i].dependentfiles);
5236 SAFE_FREE(driver_info_3);
5238 if (*needed > offered) {
5239 *returned=0;
5240 return WERR_INSUFFICIENT_BUFFER;
5243 return WERR_OK;
5246 /****************************************************************************
5247 Enumerates all printer drivers.
5248 ****************************************************************************/
5250 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5252 /* UNISTR2 *name = &q_u->name; - notused. */
5253 UNISTR2 *environment = &q_u->environment;
5254 uint32 level = q_u->level;
5255 NEW_BUFFER *buffer = NULL;
5256 uint32 offered = q_u->offered;
5257 uint32 *needed = &r_u->needed;
5258 uint32 *returned = &r_u->returned;
5260 fstring *list = NULL;
5261 fstring servername;
5262 fstring architecture;
5264 /* that's an [in out] buffer */
5265 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5266 buffer = r_u->buffer;
5268 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5269 fstrcpy(servername, global_myname);
5270 *needed=0;
5271 *returned=0;
5273 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5275 switch (level) {
5276 case 1:
5277 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5278 case 2:
5279 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5280 case 3:
5281 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5282 default:
5283 *returned=0;
5284 SAFE_FREE(list);
5285 return WERR_UNKNOWN_LEVEL;
5289 /****************************************************************************
5290 ****************************************************************************/
5292 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5294 form->flag=list->flag;
5295 init_unistr(&form->name, list->name);
5296 form->width=list->width;
5297 form->length=list->length;
5298 form->left=list->left;
5299 form->top=list->top;
5300 form->right=list->right;
5301 form->bottom=list->bottom;
5304 /****************************************************************************
5305 ****************************************************************************/
5307 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5309 /* POLICY_HND *handle = &q_u->handle; - notused. */
5310 uint32 level = q_u->level;
5311 NEW_BUFFER *buffer = NULL;
5312 uint32 offered = q_u->offered;
5313 uint32 *needed = &r_u->needed;
5314 uint32 *numofforms = &r_u->numofforms;
5315 uint32 numbuiltinforms;
5317 nt_forms_struct *list=NULL;
5318 nt_forms_struct *builtinlist=NULL;
5319 FORM_1 *forms_1;
5320 int buffer_size=0;
5321 int i;
5323 /* that's an [in out] buffer */
5324 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5325 buffer = r_u->buffer;
5327 DEBUG(4,("_spoolss_enumforms\n"));
5328 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5329 DEBUGADD(5,("Info level [%d]\n", level));
5331 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5332 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5333 *numofforms = get_ntforms(&list);
5334 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5335 *numofforms += numbuiltinforms;
5337 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5339 switch (level) {
5340 case 1:
5341 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5342 *numofforms=0;
5343 return WERR_NOMEM;
5346 /* construct the list of form structures */
5347 for (i=0; i<numbuiltinforms; i++) {
5348 DEBUGADD(6,("Filling form number [%d]\n",i));
5349 fill_form_1(&forms_1[i], &builtinlist[i]);
5352 SAFE_FREE(builtinlist);
5354 for (; i<*numofforms; i++) {
5355 DEBUGADD(6,("Filling form number [%d]\n",i));
5356 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5359 SAFE_FREE(list);
5361 /* check the required size. */
5362 for (i=0; i<numbuiltinforms; i++) {
5363 DEBUGADD(6,("adding form [%d]'s size\n",i));
5364 buffer_size += spoolss_size_form_1(&forms_1[i]);
5366 for (; i<*numofforms; i++) {
5367 DEBUGADD(6,("adding form [%d]'s size\n",i));
5368 buffer_size += spoolss_size_form_1(&forms_1[i]);
5371 *needed=buffer_size;
5373 if (!alloc_buffer_size(buffer, buffer_size)){
5374 SAFE_FREE(forms_1);
5375 return WERR_INSUFFICIENT_BUFFER;
5378 /* fill the buffer with the form structures */
5379 for (i=0; i<numbuiltinforms; i++) {
5380 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5381 smb_io_form_1("", buffer, &forms_1[i], 0);
5383 for (; i<*numofforms; i++) {
5384 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5385 smb_io_form_1("", buffer, &forms_1[i], 0);
5388 SAFE_FREE(forms_1);
5390 if (*needed > offered) {
5391 *numofforms=0;
5392 return WERR_INSUFFICIENT_BUFFER;
5394 else
5395 return WERR_OK;
5397 default:
5398 SAFE_FREE(list);
5399 SAFE_FREE(builtinlist);
5400 return WERR_UNKNOWN_LEVEL;
5405 /****************************************************************************
5406 ****************************************************************************/
5408 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5410 /* POLICY_HND *handle = &q_u->handle; - notused. */
5411 uint32 level = q_u->level;
5412 UNISTR2 *uni_formname = &q_u->formname;
5413 NEW_BUFFER *buffer = NULL;
5414 uint32 offered = q_u->offered;
5415 uint32 *needed = &r_u->needed;
5417 nt_forms_struct *list=NULL;
5418 nt_forms_struct builtin_form;
5419 BOOL foundBuiltin;
5420 FORM_1 form_1;
5421 fstring form_name;
5422 int buffer_size=0;
5423 int numofforms=0, i=0;
5425 /* that's an [in out] buffer */
5426 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5427 buffer = r_u->buffer;
5429 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5431 DEBUG(4,("_spoolss_getform\n"));
5432 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5433 DEBUGADD(5,("Info level [%d]\n", level));
5435 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5436 if (!foundBuiltin) {
5437 numofforms = get_ntforms(&list);
5438 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5440 if (numofforms == 0)
5441 return WERR_BADFID;
5444 switch (level) {
5445 case 1:
5446 if (foundBuiltin) {
5447 fill_form_1(&form_1, &builtin_form);
5448 } else {
5450 /* Check if the requested name is in the list of form structures */
5451 for (i=0; i<numofforms; i++) {
5453 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5455 if (strequal(form_name, list[i].name)) {
5456 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5457 fill_form_1(&form_1, &list[i]);
5458 break;
5462 SAFE_FREE(list);
5463 if (i == numofforms) {
5464 return WERR_BADFID;
5467 /* check the required size. */
5469 *needed=spoolss_size_form_1(&form_1);
5471 if (!alloc_buffer_size(buffer, buffer_size)){
5472 return WERR_INSUFFICIENT_BUFFER;
5475 if (*needed > offered) {
5476 return WERR_INSUFFICIENT_BUFFER;
5479 /* fill the buffer with the form structures */
5480 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5481 smb_io_form_1("", buffer, &form_1, 0);
5483 return WERR_OK;
5485 default:
5486 SAFE_FREE(list);
5487 return WERR_UNKNOWN_LEVEL;
5491 /****************************************************************************
5492 ****************************************************************************/
5493 static void fill_port_1(PORT_INFO_1 *port, char *name)
5495 init_unistr(&port->port_name, name);
5498 /****************************************************************************
5499 ****************************************************************************/
5500 static void fill_port_2(PORT_INFO_2 *port, char *name)
5502 init_unistr(&port->port_name, name);
5503 init_unistr(&port->monitor_name, "Local Monitor");
5504 init_unistr(&port->description, "Local Port");
5505 #define PORT_TYPE_WRITE 1
5506 port->port_type=PORT_TYPE_WRITE;
5507 port->reserved=0x0;
5510 /****************************************************************************
5511 enumports level 1.
5512 ****************************************************************************/
5513 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5515 PORT_INFO_1 *ports=NULL;
5516 int i=0;
5518 if (*lp_enumports_cmd()) {
5519 char *cmd = lp_enumports_cmd();
5520 char **qlines;
5521 pstring command;
5522 int numlines;
5523 int ret;
5524 int fd;
5526 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5528 DEBUG(10,("Running [%s]\n", command));
5529 ret = smbrun(command, &fd);
5530 DEBUG(10,("Returned [%d]\n", ret));
5531 if (ret != 0) {
5532 if (fd != -1)
5533 close(fd);
5534 /* Is this the best error to return here? */
5535 return WERR_ACCESS_DENIED;
5538 numlines = 0;
5539 qlines = fd_lines_load(fd, &numlines);
5540 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5541 close(fd);
5543 if(numlines) {
5544 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5545 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5546 werror_str(WERR_NOMEM)));
5547 file_lines_free(qlines);
5548 return WERR_NOMEM;
5551 for (i=0; i<numlines; i++) {
5552 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5553 fill_port_1(&ports[i], qlines[i]);
5556 file_lines_free(qlines);
5559 *returned = numlines;
5561 } else {
5562 *returned = 1; /* Sole Samba port returned. */
5564 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5565 return WERR_NOMEM;
5567 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5569 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5572 /* check the required size. */
5573 for (i=0; i<*returned; i++) {
5574 DEBUGADD(6,("adding port [%d]'s size\n", i));
5575 *needed += spoolss_size_port_info_1(&ports[i]);
5578 if (!alloc_buffer_size(buffer, *needed)) {
5579 SAFE_FREE(ports);
5580 return WERR_INSUFFICIENT_BUFFER;
5583 /* fill the buffer with the ports structures */
5584 for (i=0; i<*returned; i++) {
5585 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5586 smb_io_port_1("", buffer, &ports[i], 0);
5589 SAFE_FREE(ports);
5591 if (*needed > offered) {
5592 *returned=0;
5593 return WERR_INSUFFICIENT_BUFFER;
5596 return WERR_OK;
5599 /****************************************************************************
5600 enumports level 2.
5601 ****************************************************************************/
5603 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5605 PORT_INFO_2 *ports=NULL;
5606 int i=0;
5608 if (*lp_enumports_cmd()) {
5609 char *cmd = lp_enumports_cmd();
5610 char *path;
5611 char **qlines;
5612 pstring tmp_file;
5613 pstring command;
5614 int numlines;
5615 int ret;
5616 int fd;
5618 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5619 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5620 else
5621 path = lp_lockdir();
5623 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5624 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5626 unlink(tmp_file);
5627 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5628 ret = smbrun(command, &fd);
5629 DEBUGADD(10,("returned [%d]\n", ret));
5630 if (ret != 0) {
5631 if (fd != -1)
5632 close(fd);
5633 /* Is this the best error to return here? */
5634 return WERR_ACCESS_DENIED;
5637 numlines = 0;
5638 qlines = fd_lines_load(fd, &numlines);
5639 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5640 close(fd);
5642 if(numlines) {
5643 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5644 file_lines_free(qlines);
5645 return WERR_NOMEM;
5648 for (i=0; i<numlines; i++) {
5649 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5650 fill_port_2(&(ports[i]), qlines[i]);
5653 file_lines_free(qlines);
5656 *returned = numlines;
5658 } else {
5660 *returned = 1;
5662 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5663 return WERR_NOMEM;
5665 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5667 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5670 /* check the required size. */
5671 for (i=0; i<*returned; i++) {
5672 DEBUGADD(6,("adding port [%d]'s size\n", i));
5673 *needed += spoolss_size_port_info_2(&ports[i]);
5676 if (!alloc_buffer_size(buffer, *needed)) {
5677 SAFE_FREE(ports);
5678 return WERR_INSUFFICIENT_BUFFER;
5681 /* fill the buffer with the ports structures */
5682 for (i=0; i<*returned; i++) {
5683 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5684 smb_io_port_2("", buffer, &ports[i], 0);
5687 SAFE_FREE(ports);
5689 if (*needed > offered) {
5690 *returned=0;
5691 return WERR_INSUFFICIENT_BUFFER;
5694 return WERR_OK;
5697 /****************************************************************************
5698 enumports.
5699 ****************************************************************************/
5701 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5703 /* UNISTR2 *name = &q_u->name; - notused. */
5704 uint32 level = q_u->level;
5705 NEW_BUFFER *buffer = NULL;
5706 uint32 offered = q_u->offered;
5707 uint32 *needed = &r_u->needed;
5708 uint32 *returned = &r_u->returned;
5710 /* that's an [in out] buffer */
5711 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5712 buffer = r_u->buffer;
5714 DEBUG(4,("_spoolss_enumports\n"));
5716 *returned=0;
5717 *needed=0;
5719 switch (level) {
5720 case 1:
5721 return enumports_level_1(buffer, offered, needed, returned);
5722 case 2:
5723 return enumports_level_2(buffer, offered, needed, returned);
5724 default:
5725 return WERR_UNKNOWN_LEVEL;
5729 /****************************************************************************
5730 ****************************************************************************/
5731 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5732 const SPOOL_PRINTER_INFO_LEVEL *info,
5733 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5734 uint32 user_switch, const SPOOL_USER_CTR *user,
5735 POLICY_HND *handle)
5737 NT_PRINTER_INFO_LEVEL *printer = NULL;
5738 fstring name;
5739 int snum;
5740 WERROR err = WERR_OK;
5742 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5743 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5744 return WERR_NOMEM;
5747 ZERO_STRUCTP(printer);
5749 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5750 if (!convert_printer_info(info, printer, 2)) {
5751 free_a_printer(&printer, 2);
5752 return WERR_NOMEM;
5755 /* check to see if the printer already exists */
5757 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5758 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5759 printer->info_2->sharename));
5760 free_a_printer(&printer, 2);
5761 return WERR_PRINTER_ALREADY_EXISTS;
5764 if (*lp_addprinter_cmd() )
5765 if ( !add_printer_hook(printer) ) {
5766 free_a_printer(&printer,2);
5767 return WERR_ACCESS_DENIED;
5770 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5771 printer->info_2->sharename);
5773 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5774 free_a_printer(&printer,2);
5775 return WERR_ACCESS_DENIED;
5778 /* you must be a printer admin to add a new printer */
5779 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5780 free_a_printer(&printer,2);
5781 return WERR_ACCESS_DENIED;
5785 * Do sanity check on the requested changes for Samba.
5788 if (!check_printer_ok(printer->info_2, snum)) {
5789 free_a_printer(&printer,2);
5790 return WERR_INVALID_PARAM;
5794 * When a printer is created, the drivername bound to the printer is used
5795 * to lookup previously saved driver initialization info, which is then
5796 * bound to the new printer, simulating what happens in the Windows arch.
5798 set_driver_init(printer, 2);
5800 /* write the ASCII on disk */
5801 err = add_a_printer(*printer, 2);
5802 if (!W_ERROR_IS_OK(err)) {
5803 free_a_printer(&printer,2);
5804 return err;
5807 if (!open_printer_hnd(p, handle, name)) {
5808 /* Handle open failed - remove addition. */
5809 del_a_printer(printer->info_2->sharename);
5810 free_a_printer(&printer,2);
5811 return WERR_ACCESS_DENIED;
5814 free_a_printer(&printer,2);
5816 srv_spoolss_sendnotify(p, handle);
5818 return WERR_OK;
5821 /****************************************************************************
5822 ****************************************************************************/
5824 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5826 UNISTR2 *uni_srv_name = &q_u->server_name;
5827 uint32 level = q_u->level;
5828 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5829 uint32 unk0 = q_u->unk0;
5830 uint32 unk1 = q_u->unk1;
5831 uint32 unk2 = q_u->unk2;
5832 uint32 unk3 = q_u->unk3;
5833 uint32 user_switch = q_u->user_switch;
5834 SPOOL_USER_CTR *user = &q_u->user_ctr;
5835 POLICY_HND *handle = &r_u->handle;
5837 switch (level) {
5838 case 1:
5839 /* we don't handle yet */
5840 /* but I know what to do ... */
5841 return WERR_UNKNOWN_LEVEL;
5842 case 2:
5843 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5844 unk0, unk1, unk2, unk3,
5845 user_switch, user, handle);
5846 default:
5847 return WERR_UNKNOWN_LEVEL;
5851 /****************************************************************************
5852 ****************************************************************************/
5854 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5856 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5857 uint32 level = q_u->level;
5858 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5859 WERROR err = WERR_OK;
5860 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5861 struct current_user user;
5863 ZERO_STRUCT(driver);
5865 get_current_user(&user, p);
5867 if (!convert_printer_driver_info(info, &driver, level)) {
5868 err = WERR_NOMEM;
5869 goto done;
5872 DEBUG(5,("Cleaning driver's information\n"));
5873 err = clean_up_driver_struct(driver, level, &user);
5874 if (!W_ERROR_IS_OK(err))
5875 goto done;
5877 DEBUG(5,("Moving driver to final destination\n"));
5878 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5879 if (W_ERROR_IS_OK(err))
5880 err = WERR_ACCESS_DENIED;
5881 goto done;
5884 if (add_a_printer_driver(driver, level)!=0) {
5885 err = WERR_ACCESS_DENIED;
5886 goto done;
5889 done:
5890 free_a_printer_driver(driver, level);
5891 return err;
5894 /****************************************************************************
5895 ****************************************************************************/
5896 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5898 init_unistr(&info->name, name);
5901 /****************************************************************************
5902 ****************************************************************************/
5903 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5905 pstring path;
5906 pstring long_archi;
5907 pstring short_archi;
5908 DRIVER_DIRECTORY_1 *info=NULL;
5910 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5912 if (get_short_archi(short_archi, long_archi)==False)
5913 return WERR_INVALID_ENVIRONMENT;
5915 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5916 return WERR_NOMEM;
5918 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5920 DEBUG(4,("printer driver directory: [%s]\n", path));
5922 fill_driverdir_1(info, path);
5924 *needed += spoolss_size_driverdir_info_1(info);
5926 if (!alloc_buffer_size(buffer, *needed)) {
5927 SAFE_FREE(info);
5928 return WERR_INSUFFICIENT_BUFFER;
5931 smb_io_driverdir_1("", buffer, info, 0);
5933 SAFE_FREE(info);
5935 if (*needed > offered)
5936 return WERR_INSUFFICIENT_BUFFER;
5938 return WERR_OK;
5941 /****************************************************************************
5942 ****************************************************************************/
5944 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5946 UNISTR2 *name = &q_u->name;
5947 UNISTR2 *uni_environment = &q_u->environment;
5948 uint32 level = q_u->level;
5949 NEW_BUFFER *buffer = NULL;
5950 uint32 offered = q_u->offered;
5951 uint32 *needed = &r_u->needed;
5953 /* that's an [in out] buffer */
5954 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5955 buffer = r_u->buffer;
5957 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5959 *needed=0;
5961 switch(level) {
5962 case 1:
5963 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5964 default:
5965 return WERR_UNKNOWN_LEVEL;
5969 /****************************************************************************
5970 ****************************************************************************/
5972 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5974 POLICY_HND *handle = &q_u->handle;
5975 uint32 idx = q_u->index;
5976 uint32 in_value_len = q_u->valuesize;
5977 uint32 in_data_len = q_u->datasize;
5978 uint32 *out_max_value_len = &r_u->valuesize;
5979 uint16 **out_value = &r_u->value;
5980 uint32 *out_value_len = &r_u->realvaluesize;
5981 uint32 *out_type = &r_u->type;
5982 uint32 *out_max_data_len = &r_u->datasize;
5983 uint8 **data_out = &r_u->data;
5984 uint32 *out_data_len = &r_u->realdatasize;
5986 NT_PRINTER_INFO_LEVEL *printer = NULL;
5988 fstring value;
5990 uint32 param_index;
5991 uint32 biggest_valuesize;
5992 uint32 biggest_datasize;
5993 uint32 data_len;
5994 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5995 int snum;
5996 uint8 *data=NULL;
5997 uint32 type;
5998 WERROR result;
6000 ZERO_STRUCT(printer);
6002 *out_type=0;
6004 *out_max_data_len=0;
6005 *data_out=NULL;
6006 *out_data_len=0;
6008 DEBUG(5,("spoolss_enumprinterdata\n"));
6010 if (!Printer) {
6011 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6012 return WERR_BADFID;
6015 if (!get_printer_snum(p,handle, &snum))
6016 return WERR_BADFID;
6018 result = get_a_printer(&printer, 2, lp_servicename(snum));
6019 if (!W_ERROR_IS_OK(result))
6020 return result;
6023 * The NT machine wants to know the biggest size of value and data
6025 * cf: MSDN EnumPrinterData remark section
6027 if ( (in_value_len==0) && (in_data_len==0) ) {
6028 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6030 #if 0
6032 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6033 * if this parameter size doesn't exist.
6034 * Ok - my opinion here is that the client is not asking for the greatest
6035 * possible size of all the parameters, but is asking specifically for the size needed
6036 * for this specific parameter. In that case we can remove the loop below and
6037 * simplify this lookup code considerably. JF - comments welcome. JRA.
6040 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6041 SAFE_FREE(data);
6042 free_a_printer(&printer, 2);
6043 return WERR_NO_MORE_ITEMS;
6045 #endif
6047 SAFE_FREE(data);
6049 param_index=0;
6050 biggest_valuesize=0;
6051 biggest_datasize=0;
6053 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6054 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6055 if (data_len > biggest_datasize) biggest_datasize=data_len;
6057 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6059 SAFE_FREE(data);
6060 param_index++;
6063 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6064 *out_value_len=2*(1+biggest_valuesize);
6065 *out_data_len=biggest_datasize;
6067 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6069 free_a_printer(&printer, 2);
6070 return WERR_OK;
6074 * the value len is wrong in NT sp3
6075 * that's the number of bytes not the number of unicode chars
6078 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6080 SAFE_FREE(data);
6081 free_a_printer(&printer, 2);
6083 /* out_value should default to "" or else NT4 has
6084 problems unmarshalling the response */
6086 *out_max_value_len=(in_value_len/sizeof(uint16));
6087 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
6088 return WERR_NOMEM;
6090 ZERO_STRUCTP(*out_value);
6091 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6093 /* the data is counted in bytes */
6094 *out_max_data_len = in_data_len;
6095 *out_data_len = in_data_len;
6096 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
6097 return WERR_NOMEM;
6099 memset(*data_out,'\0',in_data_len);
6101 return WERR_NO_MORE_ITEMS;
6104 free_a_printer(&printer, 2);
6107 * the value is:
6108 * - counted in bytes in the request
6109 * - counted in UNICODE chars in the max reply
6110 * - counted in bytes in the real size
6112 * take a pause *before* coding not *during* coding
6115 *out_max_value_len=(in_value_len/sizeof(uint16));
6116 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6117 SAFE_FREE(data);
6118 return WERR_NOMEM;
6121 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6123 *out_type=type;
6125 /* the data is counted in bytes */
6126 *out_max_data_len=in_data_len;
6127 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6128 SAFE_FREE(data);
6129 return WERR_NOMEM;
6132 memcpy(*data_out, data, (size_t)data_len);
6133 *out_data_len=data_len;
6135 SAFE_FREE(data);
6137 return WERR_OK;
6140 /****************************************************************************
6141 ****************************************************************************/
6143 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6145 POLICY_HND *handle = &q_u->handle;
6146 UNISTR2 *value = &q_u->value;
6147 uint32 type = q_u->type;
6148 /* uint32 max_len = q_u->max_len; - notused. */
6149 uint8 *data = q_u->data;
6150 uint32 real_len = q_u->real_len;
6151 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6153 NT_PRINTER_INFO_LEVEL *printer = NULL;
6154 NT_PRINTER_PARAM *param = NULL, old_param;
6155 int snum=0;
6156 WERROR status = WERR_OK;
6157 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6159 DEBUG(5,("spoolss_setprinterdata\n"));
6161 if (!Printer) {
6162 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6163 return WERR_BADFID;
6166 if (!get_printer_snum(p,handle, &snum))
6167 return WERR_BADFID;
6169 ZERO_STRUCT(old_param);
6172 * Access check : NT returns "access denied" if you make a
6173 * SetPrinterData call without the necessary privildge.
6174 * we were originally returning OK if nothing changed
6175 * which made Win2k issue **a lot** of SetPrinterData
6176 * when connecting to a printer --jerry
6179 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6180 DEBUG(3, ("security descriptor change denied by existing "
6181 "security descriptor\n"));
6182 status = WERR_ACCESS_DENIED;
6183 goto done;
6186 /* Check if we are making any changes or not. Return true if
6187 nothing is actually changing. This is not needed anymore but
6188 has been left in as an optimization to keep from from
6189 writing to disk as often --jerry */
6191 status = get_a_printer(&printer, 2, lp_servicename(snum));
6192 if (!W_ERROR_IS_OK(status))
6193 return status;
6195 convert_specific_param(&param, value , type, data, real_len);
6198 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6199 &old_param.type, (uint32 *)&old_param.data_len)) {
6201 if (param->type == old_param.type &&
6202 param->data_len == old_param.data_len &&
6203 memcmp(param->data, old_param.data,
6204 old_param.data_len) == 0) {
6206 DEBUG(3, ("setprinterdata hasn't changed\n"));
6207 status = WERR_OK;
6208 goto done;
6212 unlink_specific_param_if_exist(printer->info_2, param);
6215 * When client side code sets a magic printer data key, detect it and save
6216 * the current printer data and the magic key's data (its the DEVMODE) for
6217 * future printer/driver initializations.
6219 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6221 * Set devmode and printer initialization info
6223 status = save_driver_init(printer, 2, param);
6225 else {
6226 add_a_specific_param(printer->info_2, &param);
6227 status = mod_a_printer(*printer, 2);
6230 done:
6231 free_a_printer(&printer, 2);
6232 if (param)
6233 free_nt_printer_param(&param);
6234 SAFE_FREE(old_param.data);
6236 return status;
6239 /****************************************************************************
6240 ****************************************************************************/
6242 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6244 POLICY_HND *handle = &q_u->handle;
6245 UNISTR2 *value = &q_u->valuename;
6247 NT_PRINTER_INFO_LEVEL *printer = NULL;
6248 NT_PRINTER_PARAM param;
6249 int snum=0;
6250 WERROR status = WERR_OK;
6251 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6253 DEBUG(5,("spoolss_deleteprinterdata\n"));
6255 if (!Printer) {
6256 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6257 return WERR_BADFID;
6260 if (!get_printer_snum(p, handle, &snum))
6261 return WERR_BADFID;
6263 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6264 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6265 "change denied by existing security descriptor\n"));
6266 return WERR_ACCESS_DENIED;
6269 status = get_a_printer(&printer, 2, lp_servicename(snum));
6270 if (!W_ERROR_IS_OK(status))
6271 return status;
6273 ZERO_STRUCTP(&param);
6274 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6276 if(!unlink_specific_param_if_exist(printer->info_2, &param))
6277 status = WERR_INVALID_PARAM;
6278 else
6279 status = mod_a_printer(*printer, 2);
6281 free_a_printer(&printer, 2);
6282 return status;
6285 /****************************************************************************
6286 ****************************************************************************/
6288 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6290 POLICY_HND *handle = &q_u->handle;
6291 /* uint32 level = q_u->level; - notused. */
6292 FORM *form = &q_u->form;
6293 nt_forms_struct tmpForm;
6295 int count=0;
6296 nt_forms_struct *list=NULL;
6297 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6299 DEBUG(5,("spoolss_addform\n"));
6301 if (!Printer) {
6302 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6303 return WERR_BADFID;
6306 /* can't add if builtin */
6307 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6308 return WERR_INVALID_PARAM;
6311 count=get_ntforms(&list);
6312 if(!add_a_form(&list, form, &count))
6313 return WERR_NOMEM;
6314 write_ntforms(&list, count);
6316 SAFE_FREE(list);
6318 return WERR_OK;
6321 /****************************************************************************
6322 ****************************************************************************/
6324 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6326 POLICY_HND *handle = &q_u->handle;
6327 UNISTR2 *form_name = &q_u->name;
6328 nt_forms_struct tmpForm;
6329 int count=0;
6330 WERROR ret = WERR_OK;
6331 nt_forms_struct *list=NULL;
6332 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6334 DEBUG(5,("spoolss_deleteform\n"));
6336 if (!Printer) {
6337 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6338 return WERR_BADFID;
6341 /* can't delete if builtin */
6342 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6343 return WERR_INVALID_PARAM;
6346 count = get_ntforms(&list);
6347 if(!delete_a_form(&list, form_name, &count, &ret))
6348 return WERR_INVALID_PARAM;
6350 SAFE_FREE(list);
6352 return ret;
6355 /****************************************************************************
6356 ****************************************************************************/
6358 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6360 POLICY_HND *handle = &q_u->handle;
6361 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6362 /* uint32 level = q_u->level; - notused. */
6363 FORM *form = &q_u->form;
6364 nt_forms_struct tmpForm;
6366 int count=0;
6367 nt_forms_struct *list=NULL;
6368 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6370 DEBUG(5,("spoolss_setform\n"));
6372 if (!Printer) {
6373 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6374 return WERR_BADFID;
6376 /* can't set if builtin */
6377 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6378 return WERR_INVALID_PARAM;
6381 count=get_ntforms(&list);
6382 update_a_form(&list, form, count);
6383 write_ntforms(&list, count);
6385 SAFE_FREE(list);
6387 return WERR_OK;
6390 /****************************************************************************
6391 enumprintprocessors level 1.
6392 ****************************************************************************/
6393 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6395 PRINTPROCESSOR_1 *info_1=NULL;
6397 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6398 return WERR_NOMEM;
6400 (*returned) = 0x1;
6402 init_unistr(&info_1->name, "winprint");
6404 *needed += spoolss_size_printprocessor_info_1(info_1);
6406 if (!alloc_buffer_size(buffer, *needed))
6407 return WERR_INSUFFICIENT_BUFFER;
6409 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6411 SAFE_FREE(info_1);
6413 if (*needed > offered) {
6414 *returned=0;
6415 return WERR_INSUFFICIENT_BUFFER;
6418 return WERR_OK;
6421 /****************************************************************************
6422 ****************************************************************************/
6424 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6426 /* UNISTR2 *name = &q_u->name; - notused. */
6427 /* UNISTR2 *environment = &q_u->environment; - notused. */
6428 uint32 level = q_u->level;
6429 NEW_BUFFER *buffer = NULL;
6430 uint32 offered = q_u->offered;
6431 uint32 *needed = &r_u->needed;
6432 uint32 *returned = &r_u->returned;
6434 /* that's an [in out] buffer */
6435 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6436 buffer = r_u->buffer;
6438 DEBUG(5,("spoolss_enumprintprocessors\n"));
6441 * Enumerate the print processors ...
6443 * Just reply with "winprint", to keep NT happy
6444 * and I can use my nice printer checker.
6447 *returned=0;
6448 *needed=0;
6450 switch (level) {
6451 case 1:
6452 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6453 default:
6454 return WERR_UNKNOWN_LEVEL;
6458 /****************************************************************************
6459 enumprintprocdatatypes level 1.
6460 ****************************************************************************/
6461 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6463 PRINTPROCDATATYPE_1 *info_1=NULL;
6465 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6466 return WERR_NOMEM;
6468 (*returned) = 0x1;
6470 init_unistr(&info_1->name, "RAW");
6472 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6474 if (!alloc_buffer_size(buffer, *needed))
6475 return WERR_INSUFFICIENT_BUFFER;
6477 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6479 SAFE_FREE(info_1);
6481 if (*needed > offered) {
6482 *returned=0;
6483 return WERR_INSUFFICIENT_BUFFER;
6486 return WERR_OK;
6489 /****************************************************************************
6490 ****************************************************************************/
6492 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6494 /* UNISTR2 *name = &q_u->name; - notused. */
6495 /* UNISTR2 *processor = &q_u->processor; - notused. */
6496 uint32 level = q_u->level;
6497 NEW_BUFFER *buffer = NULL;
6498 uint32 offered = q_u->offered;
6499 uint32 *needed = &r_u->needed;
6500 uint32 *returned = &r_u->returned;
6502 /* that's an [in out] buffer */
6503 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6504 buffer = r_u->buffer;
6506 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6508 *returned=0;
6509 *needed=0;
6511 switch (level) {
6512 case 1:
6513 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6514 default:
6515 return WERR_UNKNOWN_LEVEL;
6519 /****************************************************************************
6520 enumprintmonitors level 1.
6521 ****************************************************************************/
6523 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6525 PRINTMONITOR_1 *info_1=NULL;
6527 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6528 return WERR_NOMEM;
6530 (*returned) = 0x1;
6532 init_unistr(&info_1->name, "Local Port");
6534 *needed += spoolss_size_printmonitor_info_1(info_1);
6536 if (!alloc_buffer_size(buffer, *needed))
6537 return WERR_INSUFFICIENT_BUFFER;
6539 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6541 SAFE_FREE(info_1);
6543 if (*needed > offered) {
6544 *returned=0;
6545 return WERR_INSUFFICIENT_BUFFER;
6548 return WERR_OK;
6551 /****************************************************************************
6552 enumprintmonitors level 2.
6553 ****************************************************************************/
6554 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6556 PRINTMONITOR_2 *info_2=NULL;
6558 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6559 return WERR_NOMEM;
6561 (*returned) = 0x1;
6563 init_unistr(&info_2->name, "Local Port");
6564 init_unistr(&info_2->environment, "Windows NT X86");
6565 init_unistr(&info_2->dll_name, "localmon.dll");
6567 *needed += spoolss_size_printmonitor_info_2(info_2);
6569 if (!alloc_buffer_size(buffer, *needed))
6570 return WERR_INSUFFICIENT_BUFFER;
6572 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6574 SAFE_FREE(info_2);
6576 if (*needed > offered) {
6577 *returned=0;
6578 return WERR_INSUFFICIENT_BUFFER;
6581 return WERR_OK;
6584 /****************************************************************************
6585 ****************************************************************************/
6587 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6589 /* UNISTR2 *name = &q_u->name; - notused. */
6590 uint32 level = q_u->level;
6591 NEW_BUFFER *buffer = NULL;
6592 uint32 offered = q_u->offered;
6593 uint32 *needed = &r_u->needed;
6594 uint32 *returned = &r_u->returned;
6596 /* that's an [in out] buffer */
6597 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6598 buffer = r_u->buffer;
6600 DEBUG(5,("spoolss_enumprintmonitors\n"));
6603 * Enumerate the print monitors ...
6605 * Just reply with "Local Port", to keep NT happy
6606 * and I can use my nice printer checker.
6609 *returned=0;
6610 *needed=0;
6612 switch (level) {
6613 case 1:
6614 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6615 case 2:
6616 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6617 default:
6618 return WERR_UNKNOWN_LEVEL;
6622 /****************************************************************************
6623 ****************************************************************************/
6624 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6626 int i=0;
6627 BOOL found=False;
6628 JOB_INFO_1 *info_1=NULL;
6630 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6632 if (info_1 == NULL) {
6633 SAFE_FREE(queue);
6634 return WERR_NOMEM;
6637 for (i=0; i<count && found==False; i++) {
6638 if (queue[i].job==(int)jobid)
6639 found=True;
6642 if (found==False) {
6643 SAFE_FREE(queue);
6644 SAFE_FREE(info_1);
6645 /* NT treats not found as bad param... yet another bad choice */
6646 return WERR_INVALID_PARAM;
6649 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6651 SAFE_FREE(queue);
6653 *needed += spoolss_size_job_info_1(info_1);
6655 if (!alloc_buffer_size(buffer, *needed)) {
6656 SAFE_FREE(info_1);
6657 return WERR_INSUFFICIENT_BUFFER;
6660 smb_io_job_info_1("", buffer, info_1, 0);
6662 SAFE_FREE(info_1);
6664 if (*needed > offered)
6665 return WERR_INSUFFICIENT_BUFFER;
6667 return WERR_OK;
6671 /****************************************************************************
6672 ****************************************************************************/
6673 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6675 int i=0;
6676 BOOL found=False;
6677 JOB_INFO_2 *info_2;
6678 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6679 WERROR ret;
6681 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6683 ZERO_STRUCTP(info_2);
6685 if (info_2 == NULL) {
6686 SAFE_FREE(queue);
6687 return WERR_NOMEM;
6690 for (i=0; i<count && found==False; i++) {
6691 if (queue[i].job==(int)jobid)
6692 found=True;
6695 if (found==False) {
6696 SAFE_FREE(queue);
6697 SAFE_FREE(info_2);
6698 /* NT treats not found as bad param... yet another bad choice */
6699 return WERR_INVALID_PARAM;
6702 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6703 if (!W_ERROR_IS_OK(ret)) {
6704 SAFE_FREE(queue);
6705 return ret;
6708 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6710 free_a_printer(&ntprinter, 2);
6711 SAFE_FREE(queue);
6713 *needed += spoolss_size_job_info_2(info_2);
6715 if (!alloc_buffer_size(buffer, *needed)) {
6716 SAFE_FREE(info_2);
6717 return WERR_INSUFFICIENT_BUFFER;
6720 smb_io_job_info_2("", buffer, info_2, 0);
6722 free_job_info_2(info_2);
6723 SAFE_FREE(info_2);
6725 if (*needed > offered)
6726 return WERR_INSUFFICIENT_BUFFER;
6728 return WERR_OK;
6731 /****************************************************************************
6732 ****************************************************************************/
6734 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6736 POLICY_HND *handle = &q_u->handle;
6737 uint32 jobid = q_u->jobid;
6738 uint32 level = q_u->level;
6739 NEW_BUFFER *buffer = NULL;
6740 uint32 offered = q_u->offered;
6741 uint32 *needed = &r_u->needed;
6743 int snum;
6744 int count;
6745 print_queue_struct *queue=NULL;
6746 print_status_struct prt_status;
6748 /* that's an [in out] buffer */
6749 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6750 buffer = r_u->buffer;
6752 DEBUG(5,("spoolss_getjob\n"));
6754 memset(&prt_status, 0, sizeof(prt_status));
6756 *needed=0;
6758 if (!get_printer_snum(p, handle, &snum))
6759 return WERR_BADFID;
6761 count = print_queue_status(snum, &queue, &prt_status);
6763 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6764 count, prt_status.status, prt_status.message));
6766 switch (level) {
6767 case 1:
6768 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6769 case 2:
6770 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6771 default:
6772 SAFE_FREE(queue);
6773 return WERR_UNKNOWN_LEVEL;
6777 /********************************************************************
6778 * spoolss_getprinterdataex
6779 ********************************************************************/
6781 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6783 POLICY_HND *handle = &q_u->handle;
6784 uint32 in_size = q_u->size;
6785 uint32 *type = &r_u->type;
6786 uint32 *out_size = &r_u->size;
6787 uint8 **data = &r_u->data;
6788 uint32 *needed = &r_u->needed;
6790 fstring key, value;
6791 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6792 BOOL found = False;
6794 DEBUG(4,("_spoolss_getprinterdataex\n"));
6796 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6797 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6799 /* in case of problem, return some default values */
6800 *needed=0;
6801 *type=0;
6802 *out_size=0;
6805 if (!Printer) {
6806 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6807 return WERR_NOMEM;
6808 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6809 return WERR_BADFID;
6813 /* Is the handle to a printer or to the server? */
6815 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6817 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6818 return WERR_INVALID_PARAM;
6820 else
6823 * From MSDN documentation of GetPrinterDataEx: pass request
6824 * to GetPrinterData if key is "PrinterDriverData". This is
6825 * the only key we really support. Other keys to implement:
6826 * (a) DsDriver
6827 * (b) DsSpooler
6828 * (c) PnPData
6831 if (strcmp(key, "PrinterDriverData") != 0)
6832 return WERR_INVALID_PARAM;
6834 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6835 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
6836 type, data, needed, in_size);
6840 if (!found) {
6841 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6843 /* reply this param doesn't exist */
6844 if (*out_size) {
6845 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6846 return WERR_NOMEM;
6847 } else {
6848 *data = NULL;
6851 return WERR_INVALID_PARAM;
6854 if (*needed > *out_size)
6855 return WERR_MORE_DATA;
6856 else
6857 return WERR_OK;
6860 /********************************************************************
6861 * spoolss_setprinterdata
6862 ********************************************************************/
6864 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6866 SPOOL_Q_SETPRINTERDATA q_u_local;
6867 SPOOL_R_SETPRINTERDATA r_u_local;
6868 fstring key;
6870 DEBUG(4,("_spoolss_setprinterdataex\n"));
6872 /* From MSDN documentation of SetPrinterDataEx: pass request to
6873 SetPrinterData if key is "PrinterDriverData" */
6875 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6877 if (strcmp(key, "PrinterDriverData") == 0)
6878 return WERR_INVALID_PARAM;
6880 ZERO_STRUCT(q_u_local);
6881 ZERO_STRUCT(r_u_local);
6883 /* make a copy to call _spoolss_setprinterdata() */
6885 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
6886 copy_unistr2(&q_u_local.value, &q_u->value);
6887 q_u_local.type = q_u->type;
6888 q_u_local.max_len = q_u->max_len;
6889 q_u_local.data = q_u->data;
6890 q_u_local.real_len = q_u->real_len;
6891 q_u_local.numeric_data = q_u->numeric_data;
6893 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
6896 /********************************************************************
6897 * spoolss_enumprinterkey
6898 ********************************************************************/
6900 /* constants for EnumPrinterKey() */
6901 #define ENUMERATED_KEY_SIZE 19
6903 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
6905 fstring key;
6906 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
6907 char* ptr = NULL;
6908 int i;
6909 char *PrinterKey = "PrinterDriverData";
6911 DEBUG(4,("_spoolss_enumprinterkey\n"));
6913 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6916 * we only support enumating all keys (key == "")
6917 * Of course, the only key we support is the "PrinterDriverData"
6918 * key
6920 if (strlen(key) == 0)
6922 r_u->needed = ENUMERATED_KEY_SIZE *2;
6923 if (q_u->size < r_u->needed)
6924 return WERR_MORE_DATA;
6926 ptr = PrinterKey;
6927 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
6929 enumkeys[i] = (uint16)(*ptr);
6930 ptr++;
6933 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
6934 return WERR_BADFILE;
6936 return WERR_OK;
6939 /* The "PrinterDriverData" key should have no subkeys */
6940 if (strcmp(key, PrinterKey) == 0)
6942 r_u-> needed = 2;
6943 if (q_u->size < r_u->needed)
6944 return WERR_MORE_DATA;
6945 enumkeys[0] = 0x0;
6946 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
6947 return WERR_BADFILE;
6949 return WERR_OK;
6953 /* The return value for an unknown key is documented in MSDN
6954 EnumPrinterKey description */
6955 return WERR_BADFILE;
6958 /********************************************************************
6959 * spoolss_enumprinterdataex
6960 ********************************************************************/
6962 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
6964 POLICY_HND *handle = &q_u->handle;
6965 uint32 in_size = q_u->size;
6966 uint32 num_entries,
6967 needed;
6968 NT_PRINTER_INFO_LEVEL *printer = NULL;
6969 PRINTER_ENUM_VALUES *enum_values = NULL;
6970 fstring key, value;
6971 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6972 int snum;
6973 uint32 param_index,
6974 data_len,
6975 type;
6976 WERROR result;
6977 uint8 *data=NULL;
6980 DEBUG(4,("_spoolss_enumprinterdataex\n"));
6982 if (!Printer) {
6983 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6984 return WERR_BADFID;
6989 * The only key we support is "PrinterDriverData". This should return
6990 > an array of all the key/value pairs returned by EnumPrinterDataSee
6991 * _spoolss_getprinterdataex() for details --jerry
6994 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6995 if (strcmp(key, "PrinterDriverData") != 0)
6997 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
6998 return WERR_INVALID_PARAM;
7002 if (!get_printer_snum(p,handle, &snum))
7003 return WERR_BADFID;
7005 ZERO_STRUCT(printer);
7006 result = get_a_printer(&printer, 2, lp_servicename(snum));
7007 if (!W_ERROR_IS_OK(result))
7008 return result;
7012 * loop through all params and build the array to pass
7013 * back to the client
7015 result = WERR_OK;
7016 param_index = 0;
7017 needed = 0;
7018 num_entries = 0;
7020 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7022 PRINTER_ENUM_VALUES *ptr;
7023 uint32 add_len = 0;
7025 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7027 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7029 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7030 result = WERR_NOMEM;
7031 goto done;
7033 enum_values = ptr;
7035 /* copy the data */
7036 init_unistr(&enum_values[num_entries].valuename, value);
7037 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7038 enum_values[num_entries].type = type;
7041 * NULL terminate REG_SZ
7042 * FIXME!!! We should not be correctly problems in the way
7043 * we store PrinterData here. Need to investogate
7044 * SetPrinterData[Ex] --jerry
7047 if (type == REG_SZ) {
7048 /* fix alignment if the string was stored
7049 in a bizarre fashion */
7050 if ((data_len % 2) == 0)
7051 add_len = 2;
7052 else
7053 add_len = data_len % 2;
7056 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7057 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7058 result = WERR_NOMEM;
7059 goto done;
7061 memcpy(enum_values[num_entries].data, data, data_len);
7062 enum_values[num_entries].data_len = data_len + add_len;
7064 /* keep track of the size of the array in bytes */
7066 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7068 num_entries++;
7069 param_index++;
7072 r_u->needed = needed;
7073 r_u->returned = num_entries;
7075 if (needed > in_size) {
7076 result = WERR_MORE_DATA;
7077 goto done;
7080 /* copy data into the reply */
7082 r_u->ctr.size = r_u->needed;
7083 r_u->ctr.size_of_array = r_u->returned;
7084 r_u->ctr.values = enum_values;
7088 done:
7089 free_a_printer(&printer, 2);
7091 return result;