fixed error check which caused domain logons to fail
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob13488c0e67564e0020facc6e25c04ef435fc214a
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);
301 dos_to_unix(command, True); /* Convert printername to unix-codepage */
303 DEBUG(10,("Running [%s]\n", command));
304 ret = smbrun(command, NULL);
305 if (ret != 0) {
306 return WERR_BADFID; /* What to return here? */
308 DEBUGADD(10,("returned [%d]\n", ret));
310 /* Send SIGHUP to process group... is there a better way? */
311 kill(0, SIGHUP);
313 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
314 lp_killservice( i );
315 return WERR_OK;
316 } else
317 return WERR_ACCESS_DENIED;
320 return WERR_OK;
323 /****************************************************************************
324 return the snum of a printer corresponding to an handle
325 ****************************************************************************/
326 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
328 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
330 if (!Printer) {
331 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
332 return False;
335 switch (Printer->printer_type) {
336 case PRINTER_HANDLE_IS_PRINTER:
337 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
338 *number = print_queue_snum(Printer->dev.handlename);
339 return (*number != -1);
340 case PRINTER_HANDLE_IS_PRINTSERVER:
341 return False;
342 default:
343 return False;
347 /****************************************************************************
348 set printer handle type.
349 ****************************************************************************/
350 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
354 if (!Printer) {
355 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
356 return False;
359 DEBUG(4,("Setting printer access=%x\n", access_required));
360 Printer->access = access_required;
361 return True;
364 /****************************************************************************
365 Set printer handle type.
366 Check if it's \\server or \\server\printer
367 ****************************************************************************/
369 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
371 DEBUG(3,("Setting printer type=%s\n", handlename));
373 if ( strlen(handlename) < 3 ) {
374 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
375 return False;
378 /* it's a print server */
379 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr(handlename+2, '\\')) {
380 DEBUGADD(4,("Printer is a print server\n"));
381 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
383 /* it's a printer */
384 else {
385 DEBUGADD(4,("Printer is a printer\n"));
386 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
389 return True;
392 /****************************************************************************
393 Set printer handle name.
394 ****************************************************************************/
396 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
398 NT_PRINTER_INFO_LEVEL *printer = NULL;
399 int snum;
400 int n_services=lp_numservices();
401 char *aprinter;
402 BOOL found=False;
404 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
406 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
407 ZERO_STRUCT(Printer->dev.printerservername);
408 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
409 return True;
412 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
413 return False;
415 if (*handlename=='\\') {
416 aprinter=strchr(handlename+2, '\\');
417 aprinter++;
419 else {
420 aprinter=handlename;
423 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
426 * store the Samba share name in it
427 * in back we have the long printer name
428 * need to iterate all the snum and do a
429 * get_a_printer each time to find the printer
430 * faster to do it here than later.
433 for (snum=0;snum<n_services && found==False;snum++) {
434 char *printername;
436 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
437 continue;
439 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
441 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
442 continue;
444 printername=strchr(printer->info_2->printername+2, '\\');
445 printername++;
447 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
448 printer->info_2->printername, aprinter ));
450 if ( strlen(printername) != strlen(aprinter) ) {
451 free_a_printer(&printer, 2);
452 continue;
455 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
456 free_a_printer(&printer, 2);
457 continue;
460 found=True;
464 * if we haven't found a printer with the given handlename
465 * then it can be a share name as you can open both \\server\printer and
466 * \\server\share
470 * we still check if the printer description file exists as NT won't be happy
471 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
474 if (found==False) {
475 DEBUGADD(5,("Printer not found, checking for share now\n"));
477 for (snum=0;snum<n_services && found==False;snum++) {
479 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
480 continue;
482 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
484 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
485 continue;
487 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
488 printer->info_2->printername, aprinter ));
490 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
491 free_a_printer(&printer, 2);
492 continue;
495 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
496 free_a_printer(&printer, 2);
497 continue;
500 found=True;
504 if (found==False) {
505 DEBUGADD(4,("Printer not found\n"));
506 return False;
509 snum--;
510 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
511 printer->info_2->printername, lp_servicename(snum),snum));
513 ZERO_STRUCT(Printer->dev.handlename);
514 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
516 free_a_printer(&printer, 2);
518 return True;
521 /****************************************************************************
522 find first available printer slot. creates a printer handle for you.
523 ****************************************************************************/
525 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
527 Printer_entry *new_printer;
529 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
531 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
532 return False;
534 ZERO_STRUCTP(new_printer);
536 new_printer->notify.option=NULL;
538 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
539 SAFE_FREE(new_printer);
540 return False;
543 if (!set_printer_hnd_printertype(new_printer, name)) {
544 close_printer_handle(p, hnd);
545 return False;
548 if (!set_printer_hnd_name(new_printer, name)) {
549 close_printer_handle(p, hnd);
550 return False;
553 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
555 return True;
558 /********************************************************************
559 Return True is the handle is a print server.
560 ********************************************************************/
562 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
564 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
566 if (!Printer)
567 return False;
569 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
570 return False;
572 return True;
575 /****************************************************************************
576 allocate more memory for a BUFFER.
577 ****************************************************************************/
578 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
580 prs_struct *ps;
581 uint32 extra_space;
582 uint32 old_offset;
584 ps= &buffer->prs;
586 /* damn, I'm doing the reverse operation of prs_grow() :) */
587 if (buffer_size < prs_data_size(ps))
588 extra_space=0;
589 else
590 extra_space = buffer_size - prs_data_size(ps);
593 * save the offset and move to the end of the buffer
594 * prs_grow() checks the extra_space against the offset
596 old_offset=prs_offset(ps);
597 prs_set_offset(ps, prs_data_size(ps));
599 if (!prs_grow(ps, extra_space))
600 return False;
602 prs_set_offset(ps, old_offset);
604 buffer->string_at_end=prs_data_size(ps);
606 return True;
609 /***************************************************************************
610 receive the notify message
611 ****************************************************************************/
613 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
615 fstring printer;
616 WERROR status;
617 struct pipes_struct *p;
618 struct policy *pol;
619 struct handle_list *hl;
621 *printer = '\0';
622 fstrcpy(printer,buf);
624 if (len == 0) {
625 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
626 return;
629 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
632 * We need to enumerate all printers. The handle list is shared
633 * across pipes of the same name, so just find the first open
634 * spoolss pipe.
637 hl = NULL;
638 for ( p = get_first_pipe(); p; get_next_pipe(p)) {
639 if (strequal(p->name, "spoolss")) {
640 hl = p->pipe_handles;
641 break;
645 if (!hl) {
646 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
647 return;
650 /* Iterate the printer list on this pipe. */
651 for (pol = hl->Policy; pol; pol = pol->next ) {
652 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
654 if (!find_printer)
655 continue;
658 * if the entry is the given printer or if it's a printerserver
659 * we send the message
662 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
663 if (strcmp(find_printer->dev.handlename, printer))
664 continue;
666 if (find_printer->notify.client_connected==True)
667 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
671 /***************************************************************************
672 send a notify event
673 ****************************************************************************/
674 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
676 fstring printer;
678 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
680 if (!Printer) {
681 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
682 return False;
685 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
686 fstrcpy(printer, Printer->dev.handlename);
687 else
688 fstrcpy(printer, "");
690 /*srv_spoolss_receive_message(printer);*/
691 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
693 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
695 return True;
698 /********************************************************************
699 * spoolss_open_printer
701 * called from the spoolss dispatcher
702 ********************************************************************/
704 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
706 #if 0
707 WERROR result = WERR_OK;
708 #endif
710 UNISTR2 *printername = NULL;
711 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
712 /* uint32 user_switch = q_u->user_switch; - notused */
713 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
714 POLICY_HND *handle = &r_u->handle;
716 fstring name;
717 int snum;
718 struct current_user user;
720 if (q_u->printername_ptr != 0)
721 printername = &q_u->printername;
723 if (printername == NULL)
724 return WERR_INVALID_PRINTER_NAME;
726 /* some sanity check because you can open a printer or a print server */
727 /* aka: \\server\printer or \\server */
728 unistr2_to_ascii(name, printername, sizeof(name)-1);
730 DEBUGADD(3,("checking name: %s\n",name));
732 if (!open_printer_hnd(p, handle, name))
733 return WERR_INVALID_PRINTER_NAME;
736 if (printer_default->datatype_ptr != NULL)
738 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
739 set_printer_hnd_datatype(handle, datatype);
741 else
742 set_printer_hnd_datatype(handle, "");
745 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
746 close_printer_handle(p, handle);
747 return WERR_ACCESS_DENIED;
751 First case: the user is opening the print server:
753 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
754 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
756 Then both Win2k and WinNT clients try an OpenPrinterEx with
757 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
758 or if the user is listed in the smb.conf printer admin parameter.
760 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
761 client view printer folder, but does not show the MSAPW.
763 Note: this test needs code to check access rights here too. Jeremy
764 could you look at this?
767 Second case: the user is opening a printer:
768 NT doesn't let us connect to a printer if the connecting user
769 doesn't have print permission.
773 get_current_user(&user, p);
775 if (handle_is_printserver(p, handle)) {
776 if (printer_default->access_required == 0) {
777 return WERR_OK;
779 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
781 /* Printserver handles use global struct... */
782 snum = -1;
784 if (!lp_ms_add_printer_wizard()) {
785 close_printer_handle(p, handle);
786 return WERR_ACCESS_DENIED;
788 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
789 return WERR_OK;
791 else {
792 close_printer_handle(p, handle);
793 return WERR_ACCESS_DENIED;
797 else
799 /* NT doesn't let us connect to a printer if the connecting user
800 doesn't have print permission. */
802 if (!get_printer_snum(p, handle, &snum))
803 return WERR_BADFID;
805 /* map an empty access mask to the minimum access mask */
806 if (printer_default->access_required == 0x0)
807 printer_default->access_required = PRINTER_ACCESS_USE;
811 * If we are not serving the printer driver for this printer,
812 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
813 * will keep NT clients happy --jerry
816 if (lp_use_client_driver(snum)
817 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
819 printer_default->access_required = PRINTER_ACCESS_USE;
822 if (!print_access_check(&user, snum, printer_default->access_required)) {
823 DEBUG(3, ("access DENIED for printer open\n"));
824 close_printer_handle(p, handle);
825 return WERR_ACCESS_DENIED;
829 * If we have a default device pointer in the
830 * printer_default struct, then we need to get
831 * the printer info from the tdb and if there is
832 * no default devicemode there then we do a *SET*
833 * here ! This is insanity.... JRA.
837 * If the openprinterex rpc call contains a devmode,
838 * it's a per-user one. This per-user devmode is derivated
839 * from the global devmode. Openprinterex() contains a per-user
840 * devmode for when you do EMF printing and spooling.
841 * In the EMF case, the NT workstation is only doing half the job
842 * of rendering the page. The other half is done by running the printer
843 * driver on the server.
844 * The EMF file doesn't contain the page description (paper size, orientation, ...).
845 * The EMF file only contains what is to be printed on the page.
846 * So in order for the server to know how to print, the NT client sends
847 * a devicemode attached to the openprinterex call.
848 * But this devicemode is short lived, it's only valid for the current print job.
850 * If Samba would have supported EMF spooling, this devicemode would
851 * have been attached to the handle, to sent it to the driver to correctly
852 * rasterize the EMF file.
854 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
855 * we just act as a pass-thru between windows and the printer.
857 * In order to know that Samba supports only RAW spooling, NT has to call
858 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
859 * and until NT sends a RAW job, we refuse it.
861 * But to call getprinter() or startdoc(), you first need a valid handle,
862 * and to get an handle you have to call openprintex(). Hence why you have
863 * a devicemode in the openprinterex() call.
866 * Differences between NT4 and NT 2000.
867 * NT4:
868 * ---
869 * On NT4, you only have a global devicemode. This global devicemode can be changed
870 * by the administrator (or by a user with enough privs). Everytime a user
871 * wants to print, the devicemode is resetted to the default. In Word, everytime
872 * you print, the printer's characteristics are always reset to the global devicemode.
874 * NT 2000:
875 * -------
876 * In W2K, there is the notion of per-user devicemode. The first time you use
877 * a printer, a per-user devicemode is build from the global devicemode.
878 * If you change your per-user devicemode, it is saved in the registry, under the
879 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
880 * printer preferences available.
882 * To change the per-user devicemode: it's the "Printing Preferences ..." button
883 * on the General Tab of the printer properties windows.
885 * To change the global devicemode: it's the "Printing Defaults..." button
886 * on the Advanced Tab of the printer properties window.
888 * JFM.
893 #if 0
894 if (printer_default->devmode_cont.devmode != NULL) {
895 result = printer_write_default_dev( snum, printer_default);
896 if (result != 0) {
897 close_printer_handle(p, handle);
898 return result;
901 #endif
904 return WERR_OK;
907 /****************************************************************************
908 ****************************************************************************/
909 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
910 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
912 BOOL ret = True;
914 switch (level) {
915 case 2:
916 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
917 break;
918 default:
919 break;
922 return ret;
925 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
926 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
928 BOOL result = True;
930 switch (level) {
931 case 3:
932 printer->info_3=NULL;
933 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
934 result = False;
935 break;
936 case 6:
937 printer->info_6=NULL;
938 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
939 result = False;
940 break;
941 default:
942 break;
945 return result;
948 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
949 NT_DEVICEMODE **pp_nt_devmode)
951 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
954 * Ensure nt_devmode is a valid pointer
955 * as we will be overwriting it.
958 if (nt_devmode == NULL) {
959 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
960 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
961 return False;
964 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
965 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
967 nt_devmode->specversion=devmode->specversion;
968 nt_devmode->driverversion=devmode->driverversion;
969 nt_devmode->size=devmode->size;
970 nt_devmode->fields=devmode->fields;
971 nt_devmode->orientation=devmode->orientation;
972 nt_devmode->papersize=devmode->papersize;
973 nt_devmode->paperlength=devmode->paperlength;
974 nt_devmode->paperwidth=devmode->paperwidth;
975 nt_devmode->scale=devmode->scale;
976 nt_devmode->copies=devmode->copies;
977 nt_devmode->defaultsource=devmode->defaultsource;
978 nt_devmode->printquality=devmode->printquality;
979 nt_devmode->color=devmode->color;
980 nt_devmode->duplex=devmode->duplex;
981 nt_devmode->yresolution=devmode->yresolution;
982 nt_devmode->ttoption=devmode->ttoption;
983 nt_devmode->collate=devmode->collate;
985 nt_devmode->logpixels=devmode->logpixels;
986 nt_devmode->bitsperpel=devmode->bitsperpel;
987 nt_devmode->pelswidth=devmode->pelswidth;
988 nt_devmode->pelsheight=devmode->pelsheight;
989 nt_devmode->displayflags=devmode->displayflags;
990 nt_devmode->displayfrequency=devmode->displayfrequency;
991 nt_devmode->icmmethod=devmode->icmmethod;
992 nt_devmode->icmintent=devmode->icmintent;
993 nt_devmode->mediatype=devmode->mediatype;
994 nt_devmode->dithertype=devmode->dithertype;
995 nt_devmode->reserved1=devmode->reserved1;
996 nt_devmode->reserved2=devmode->reserved2;
997 nt_devmode->panningwidth=devmode->panningwidth;
998 nt_devmode->panningheight=devmode->panningheight;
1001 * Only change private and driverextra if the incoming devmode
1002 * has a new one. JRA.
1005 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1006 SAFE_FREE(nt_devmode->private);
1007 nt_devmode->driverextra=devmode->driverextra;
1008 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1009 return False;
1010 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1013 *pp_nt_devmode = nt_devmode;
1015 return True;
1018 /********************************************************************
1019 * _spoolss_enddocprinter_internal.
1020 ********************************************************************/
1022 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1024 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1026 if (!Printer) {
1027 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1028 return WERR_BADFID;
1031 Printer->document_started=False;
1032 print_job_end(Printer->jobid,True);
1033 /* error codes unhandled so far ... */
1035 return WERR_OK;
1038 /********************************************************************
1039 * api_spoolss_closeprinter
1040 ********************************************************************/
1042 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1044 POLICY_HND *handle = &q_u->handle;
1046 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1048 if (Printer && Printer->document_started)
1049 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1051 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1053 if (!close_printer_handle(p, handle))
1054 return WERR_BADFID;
1056 return WERR_OK;
1059 /********************************************************************
1060 * api_spoolss_deleteprinter
1062 ********************************************************************/
1064 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1066 POLICY_HND *handle = &q_u->handle;
1067 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1068 WERROR result;
1070 if (Printer && Printer->document_started)
1071 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1073 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1075 result = delete_printer_handle(p, handle);
1077 if (W_ERROR_IS_OK(result)) {
1078 srv_spoolss_sendnotify(p, handle);
1081 return result;
1084 /*******************************************************************
1085 * static function to lookup the version id corresponding to an
1086 * long architecture string
1087 ******************************************************************/
1088 static int get_version_id (char * arch)
1090 int i;
1091 struct table_node archi_table[]= {
1093 {"Windows 4.0", "WIN40", 0 },
1094 {"Windows NT x86", "W32X86", 2 },
1095 {"Windows NT R4000", "W32MIPS", 2 },
1096 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1097 {"Windows NT PowerPC", "W32PPC", 2 },
1098 {NULL, "", -1 }
1101 for (i=0; archi_table[i].long_archi != NULL; i++)
1103 if (strcmp(arch, archi_table[i].long_archi) == 0)
1104 return (archi_table[i].version);
1107 return -1;
1110 /********************************************************************
1111 * _spoolss_deleteprinterdriver
1113 * We currently delete the driver for the architecture only.
1114 * This can leave the driver for other archtectures. However,
1115 * since every printer associates a "Windows NT x86" driver name
1116 * and we cannot delete that one while it is in use, **and** since
1117 * it is impossible to assign a driver to a Samba printer without
1118 * having the "Windows NT x86" driver installed,...
1120 * ....we should not get into trouble here.
1122 * --jerry
1123 ********************************************************************/
1125 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1126 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1128 fstring driver;
1129 fstring arch;
1130 NT_PRINTER_DRIVER_INFO_LEVEL info;
1131 int version;
1133 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1134 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1136 /* check that we have a valid driver name first */
1137 if ((version=get_version_id(arch)) == -1) {
1138 /* this is what NT returns */
1139 return WERR_INVALID_ENVIRONMENT;
1142 ZERO_STRUCT(info);
1143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1144 return WERR_UNKNOWN_PRINTER_DRIVER;
1148 if (printer_driver_in_use(arch, driver))
1150 return WERR_PRINTER_DRIVER_IN_USE;
1153 return delete_printer_driver(info.info_3);
1157 /********************************************************************
1158 GetPrinterData on a printer server Handle.
1159 ********************************************************************/
1160 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1162 int i;
1164 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1166 if (!strcmp(value, "BeepEnabled")) {
1167 *type = 0x4;
1168 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1169 return False;
1170 SIVAL(*data, 0, 0x01);
1171 *needed = 0x4;
1172 return True;
1175 if (!strcmp(value, "EventLog")) {
1176 *type = 0x4;
1177 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1178 return False;
1179 SIVAL(*data, 0, 0x1B);
1180 *needed = 0x4;
1181 return True;
1184 if (!strcmp(value, "NetPopup")) {
1185 *type = 0x4;
1186 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1187 return False;
1188 SIVAL(*data, 0, 0x01);
1189 *needed = 0x4;
1190 return True;
1193 if (!strcmp(value, "MajorVersion")) {
1194 *type = 0x4;
1195 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1196 return False;
1197 SIVAL(*data, 0, 0x02);
1198 *needed = 0x4;
1199 return True;
1202 if (!strcmp(value, "DefaultSpoolDirectory")) {
1203 pstring string="You are using a Samba server";
1204 *type = 0x1;
1205 *needed = 2*(strlen(string)+1);
1206 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1207 return False;
1208 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1210 /* it's done by hand ready to go on the wire */
1211 for (i=0; i<strlen(string); i++) {
1212 (*data)[2*i]=string[i];
1213 (*data)[2*i+1]='\0';
1215 return True;
1218 if (!strcmp(value, "Architecture")) {
1219 pstring string="Windows NT x86";
1220 *type = 0x1;
1221 *needed = 2*(strlen(string)+1);
1222 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1223 return False;
1224 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1225 for (i=0; i<strlen(string); i++) {
1226 (*data)[2*i]=string[i];
1227 (*data)[2*i+1]='\0';
1229 return True;
1232 return False;
1235 /********************************************************************
1236 GetPrinterData on a printer Handle.
1237 ********************************************************************/
1238 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1239 fstring value, uint32 *type,
1240 uint8 **data, uint32 *needed, uint32 in_size )
1242 NT_PRINTER_INFO_LEVEL *printer = NULL;
1243 int snum=0;
1244 uint8 *idata=NULL;
1245 uint32 len;
1246 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1248 DEBUG(5,("getprinterdata_printer\n"));
1250 if (!Printer) {
1251 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1252 return False;
1255 if(!get_printer_snum(p, handle, &snum))
1256 return False;
1258 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1259 return False;
1261 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1262 free_a_printer(&printer, 2);
1263 return False;
1266 free_a_printer(&printer, 2);
1268 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1270 if (in_size) {
1271 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1272 return False;
1275 memset(*data, 0, in_size *sizeof(uint8));
1276 /* copy the min(in_size, len) */
1277 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1278 } else {
1279 *data = NULL;
1282 *needed = len;
1284 DEBUG(5,("getprinterdata_printer:copy done\n"));
1286 SAFE_FREE(idata);
1288 return True;
1291 /********************************************************************
1292 * spoolss_getprinterdata
1293 ********************************************************************/
1295 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1297 POLICY_HND *handle = &q_u->handle;
1298 UNISTR2 *valuename = &q_u->valuename;
1299 uint32 in_size = q_u->size;
1300 uint32 *type = &r_u->type;
1301 uint32 *out_size = &r_u->size;
1302 uint8 **data = &r_u->data;
1303 uint32 *needed = &r_u->needed;
1305 fstring value;
1306 BOOL found=False;
1307 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1310 * Reminder: when it's a string, the length is in BYTES
1311 * even if UNICODE is negociated.
1313 * JFM, 4/19/1999
1316 *out_size=in_size;
1318 /* in case of problem, return some default values */
1319 *needed=0;
1320 *type=0;
1322 DEBUG(4,("_spoolss_getprinterdata\n"));
1324 if (!Printer) {
1325 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1326 return WERR_NOMEM;
1327 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1328 return WERR_BADFID;
1331 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1333 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1334 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1335 else
1336 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1338 if (found==False) {
1339 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1340 /* reply this param doesn't exist */
1341 if (*out_size) {
1342 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1343 return WERR_NOMEM;
1344 } else {
1345 *data = NULL;
1348 return WERR_INVALID_PARAM;
1351 if (*needed > *out_size)
1352 return WERR_STATUS_MORE_ENTRIES;
1353 else
1354 return WERR_OK;
1357 /***************************************************************************
1358 connect to the client
1359 ****************************************************************************/
1360 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1362 WERROR status;
1365 * If it's the first connection, contact the client
1366 * and connect to the IPC$ share anonumously
1368 if (smb_connections==0) {
1369 fstring unix_printer;
1371 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1372 dos_to_unix(unix_printer, True);
1374 if(!spoolss_connect_to_client(&cli, unix_printer))
1375 return False;
1376 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1380 smb_connections++;
1382 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1383 return False;
1385 return True;
1388 /********************************************************************
1389 * _spoolss_rffpcnex
1390 * ReplyFindFirstPrinterChangeNotifyEx
1392 * jfmxxxx: before replying OK: status=0
1393 * should do a rpc call to the workstation asking ReplyOpenPrinter
1394 * have to code it, later.
1396 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1397 * called from api_spoolss_rffpcnex
1398 ********************************************************************/
1400 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1402 POLICY_HND *handle = &q_u->handle;
1403 uint32 flags = q_u->flags;
1404 uint32 options = q_u->options;
1405 UNISTR2 *localmachine = &q_u->localmachine;
1406 uint32 printerlocal = q_u->printerlocal;
1407 SPOOL_NOTIFY_OPTION *option = q_u->option;
1409 /* store the notify value in the printer struct */
1411 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1413 if (!Printer) {
1414 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1415 return WERR_BADFID;
1418 Printer->notify.flags=flags;
1419 Printer->notify.options=options;
1420 Printer->notify.printerlocal=printerlocal;
1422 if (Printer->notify.option)
1423 free_spool_notify_option(&Printer->notify.option);
1425 Printer->notify.option=dup_spool_notify_option(option);
1427 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1429 /* connect to the client machine and send a ReplyOpenPrinter */
1430 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1431 Printer->notify.printerlocal, 1,
1432 &Printer->notify.client_hnd))
1433 Printer->notify.client_connected=True;
1435 return WERR_OK;
1438 /*******************************************************************
1439 * fill a notify_info_data with the servername
1440 ********************************************************************/
1442 static void spoolss_notify_server_name(int snum,
1443 SPOOL_NOTIFY_INFO_DATA *data,
1444 print_queue_struct *queue,
1445 NT_PRINTER_INFO_LEVEL *printer,
1446 TALLOC_CTX *mem_ctx)
1448 pstring temp_name, temp;
1449 uint32 len;
1451 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1453 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1455 data->notify_data.data.length = len / 2 - 1;
1456 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1458 if (!data->notify_data.data.string) {
1459 data->notify_data.data.length = 0;
1460 return;
1463 memcpy(data->notify_data.data.string, temp, len);
1466 /*******************************************************************
1467 * fill a notify_info_data with the printername (not including the servername).
1468 ********************************************************************/
1469 static void spoolss_notify_printer_name(int snum,
1470 SPOOL_NOTIFY_INFO_DATA *data,
1471 print_queue_struct *queue,
1472 NT_PRINTER_INFO_LEVEL *printer,
1473 TALLOC_CTX *mem_ctx)
1475 pstring temp;
1476 uint32 len;
1478 /* the notify name should not contain the \\server\ part */
1479 char *p = strrchr(printer->info_2->printername, '\\');
1481 if (!p) {
1482 p = printer->info_2->printername;
1483 } else {
1484 p++;
1487 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1489 data->notify_data.data.length = len / 2 - 1;
1490 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1492 if (!data->notify_data.data.string) {
1493 data->notify_data.data.length = 0;
1494 return;
1497 memcpy(data->notify_data.data.string, temp, len);
1500 /*******************************************************************
1501 * fill a notify_info_data with the servicename
1502 ********************************************************************/
1503 static void spoolss_notify_share_name(int snum,
1504 SPOOL_NOTIFY_INFO_DATA *data,
1505 print_queue_struct *queue,
1506 NT_PRINTER_INFO_LEVEL *printer,
1507 TALLOC_CTX *mem_ctx)
1509 pstring temp;
1510 uint32 len;
1512 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1513 sizeof(temp) - 2, True);
1515 data->notify_data.data.length = len / 2 - 1;
1516 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1518 if (!data->notify_data.data.string) {
1519 data->notify_data.data.length = 0;
1520 return;
1523 memcpy(data->notify_data.data.string, temp, len);
1526 /*******************************************************************
1527 * fill a notify_info_data with the port name
1528 ********************************************************************/
1529 static void spoolss_notify_port_name(int snum,
1530 SPOOL_NOTIFY_INFO_DATA *data,
1531 print_queue_struct *queue,
1532 NT_PRINTER_INFO_LEVEL *printer,
1533 TALLOC_CTX *mem_ctx)
1535 pstring temp;
1536 uint32 len;
1538 /* even if it's strange, that's consistant in all the code */
1540 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1541 sizeof(temp) - 2, True);
1543 data->notify_data.data.length = len / 2 - 1;
1544 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1546 if (!data->notify_data.data.string) {
1547 data->notify_data.data.length = 0;
1548 return;
1551 memcpy(data->notify_data.data.string, temp, len);
1554 /*******************************************************************
1555 * fill a notify_info_data with the printername
1556 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1557 * but it doesn't exist, have to see what to do
1558 ********************************************************************/
1559 static void spoolss_notify_driver_name(int snum,
1560 SPOOL_NOTIFY_INFO_DATA *data,
1561 print_queue_struct *queue,
1562 NT_PRINTER_INFO_LEVEL *printer,
1563 TALLOC_CTX *mem_ctx)
1565 pstring temp;
1566 uint32 len;
1568 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1569 sizeof(temp) - 2, True);
1571 data->notify_data.data.length = len / 2 - 1;
1572 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1574 if (!data->notify_data.data.string) {
1575 data->notify_data.data.length = 0;
1576 return;
1579 memcpy(data->notify_data.data.string, temp, len);
1582 /*******************************************************************
1583 * fill a notify_info_data with the comment
1584 ********************************************************************/
1585 static void spoolss_notify_comment(int snum,
1586 SPOOL_NOTIFY_INFO_DATA *data,
1587 print_queue_struct *queue,
1588 NT_PRINTER_INFO_LEVEL *printer,
1589 TALLOC_CTX *mem_ctx)
1591 pstring temp;
1592 uint32 len;
1594 if (*printer->info_2->comment == '\0')
1595 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1596 sizeof(temp) - 2, True);
1597 else
1598 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1599 sizeof(temp) - 2, True);
1601 data->notify_data.data.length = len / 2 - 1;
1602 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1604 if (!data->notify_data.data.string) {
1605 data->notify_data.data.length = 0;
1606 return;
1609 memcpy(data->notify_data.data.string, temp, len);
1612 /*******************************************************************
1613 * fill a notify_info_data with the comment
1614 * jfm:xxxx incorrect, have to create a new smb.conf option
1615 * location = "Room 1, floor 2, building 3"
1616 ********************************************************************/
1617 static void spoolss_notify_location(int snum,
1618 SPOOL_NOTIFY_INFO_DATA *data,
1619 print_queue_struct *queue,
1620 NT_PRINTER_INFO_LEVEL *printer,
1621 TALLOC_CTX *mem_ctx)
1623 pstring temp;
1624 uint32 len;
1626 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1627 sizeof(temp) - 2, True);
1629 data->notify_data.data.length = len / 2 - 1;
1630 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1632 if (!data->notify_data.data.string) {
1633 data->notify_data.data.length = 0;
1634 return;
1637 memcpy(data->notify_data.data.string, temp, len);
1640 /*******************************************************************
1641 * fill a notify_info_data with the device mode
1642 * jfm:xxxx don't to it for know but that's a real problem !!!
1643 ********************************************************************/
1644 static void spoolss_notify_devmode(int snum,
1645 SPOOL_NOTIFY_INFO_DATA *data,
1646 print_queue_struct *queue,
1647 NT_PRINTER_INFO_LEVEL *printer,
1648 TALLOC_CTX *mem_ctx)
1652 /*******************************************************************
1653 * fill a notify_info_data with the separator file name
1654 * jfm:xxxx just return no file could add an option to smb.conf
1655 * separator file = "separator.txt"
1656 ********************************************************************/
1657 static void spoolss_notify_sepfile(int snum,
1658 SPOOL_NOTIFY_INFO_DATA *data,
1659 print_queue_struct *queue,
1660 NT_PRINTER_INFO_LEVEL *printer,
1661 TALLOC_CTX *mem_ctx)
1663 pstring temp;
1664 uint32 len;
1666 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1667 sizeof(temp) - 2, True);
1669 data->notify_data.data.length = len / 2 - 1;
1670 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1672 if (!data->notify_data.data.string) {
1673 data->notify_data.data.length = 0;
1674 return;
1677 memcpy(data->notify_data.data.string, temp, len);
1680 /*******************************************************************
1681 * fill a notify_info_data with the print processor
1682 * jfm:xxxx return always winprint to indicate we don't do anything to it
1683 ********************************************************************/
1684 static void spoolss_notify_print_processor(int snum,
1685 SPOOL_NOTIFY_INFO_DATA *data,
1686 print_queue_struct *queue,
1687 NT_PRINTER_INFO_LEVEL *printer,
1688 TALLOC_CTX *mem_ctx)
1690 pstring temp;
1691 uint32 len;
1693 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1694 sizeof(temp) - 2, True);
1696 data->notify_data.data.length = len / 2 - 1;
1697 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1699 if (!data->notify_data.data.string) {
1700 data->notify_data.data.length = 0;
1701 return;
1704 memcpy(data->notify_data.data.string, temp, len);
1707 /*******************************************************************
1708 * fill a notify_info_data with the print processor options
1709 * jfm:xxxx send an empty string
1710 ********************************************************************/
1711 static void spoolss_notify_parameters(int snum,
1712 SPOOL_NOTIFY_INFO_DATA *data,
1713 print_queue_struct *queue,
1714 NT_PRINTER_INFO_LEVEL *printer,
1715 TALLOC_CTX *mem_ctx)
1717 pstring temp;
1718 uint32 len;
1720 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1721 sizeof(temp) - 2, True);
1723 data->notify_data.data.length = len / 2 - 1;
1724 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1726 if (!data->notify_data.data.string) {
1727 data->notify_data.data.length = 0;
1728 return;
1731 memcpy(data->notify_data.data.string, temp, len);
1734 /*******************************************************************
1735 * fill a notify_info_data with the data type
1736 * jfm:xxxx always send RAW as data type
1737 ********************************************************************/
1738 static void spoolss_notify_datatype(int snum,
1739 SPOOL_NOTIFY_INFO_DATA *data,
1740 print_queue_struct *queue,
1741 NT_PRINTER_INFO_LEVEL *printer,
1742 TALLOC_CTX *mem_ctx)
1744 pstring temp;
1745 uint32 len;
1747 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1748 sizeof(pstring) - 2, True);
1750 data->notify_data.data.length = len / 2 - 1;
1751 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1753 if (!data->notify_data.data.string) {
1754 data->notify_data.data.length = 0;
1755 return;
1758 memcpy(data->notify_data.data.string, temp, len);
1761 /*******************************************************************
1762 * fill a notify_info_data with the security descriptor
1763 * jfm:xxxx send an null pointer to say no security desc
1764 * have to implement security before !
1765 ********************************************************************/
1766 static void spoolss_notify_security_desc(int snum,
1767 SPOOL_NOTIFY_INFO_DATA *data,
1768 print_queue_struct *queue,
1769 NT_PRINTER_INFO_LEVEL *printer,
1770 TALLOC_CTX *mem_ctx)
1772 data->notify_data.data.length=0;
1773 data->notify_data.data.string = NULL;
1776 /*******************************************************************
1777 * fill a notify_info_data with the attributes
1778 * jfm:xxxx a samba printer is always shared
1779 ********************************************************************/
1780 static void spoolss_notify_attributes(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->attributes;
1787 data->notify_data.value[1] = 0;
1790 /*******************************************************************
1791 * fill a notify_info_data with the priority
1792 ********************************************************************/
1793 static void spoolss_notify_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->priority;
1800 data->notify_data.value[1] = 0;
1803 /*******************************************************************
1804 * fill a notify_info_data with the default priority
1805 ********************************************************************/
1806 static void spoolss_notify_default_priority(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->default_priority;
1813 data->notify_data.value[1] = 0;
1816 /*******************************************************************
1817 * fill a notify_info_data with the start time
1818 ********************************************************************/
1819 static void spoolss_notify_start_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->starttime;
1826 data->notify_data.value[1] = 0;
1829 /*******************************************************************
1830 * fill a notify_info_data with the until time
1831 ********************************************************************/
1832 static void spoolss_notify_until_time(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 data->notify_data.value[0] = printer->info_2->untiltime;
1839 data->notify_data.value[1] = 0;
1842 /*******************************************************************
1843 * fill a notify_info_data with the status
1844 ********************************************************************/
1845 static void spoolss_notify_status(int snum,
1846 SPOOL_NOTIFY_INFO_DATA *data,
1847 print_queue_struct *queue,
1848 NT_PRINTER_INFO_LEVEL *printer,
1849 TALLOC_CTX *mem_ctx)
1851 print_status_struct status;
1853 print_queue_length(snum, &status);
1854 data->notify_data.value[0]=(uint32) status.status;
1855 data->notify_data.value[1] = 0;
1858 /*******************************************************************
1859 * fill a notify_info_data with the number of jobs queued
1860 ********************************************************************/
1861 static void spoolss_notify_cjobs(int snum,
1862 SPOOL_NOTIFY_INFO_DATA *data,
1863 print_queue_struct *queue,
1864 NT_PRINTER_INFO_LEVEL *printer,
1865 TALLOC_CTX *mem_ctx)
1867 data->notify_data.value[0] = print_queue_length(snum, NULL);
1868 data->notify_data.value[1] = 0;
1871 /*******************************************************************
1872 * fill a notify_info_data with the average ppm
1873 ********************************************************************/
1874 static void spoolss_notify_average_ppm(int snum,
1875 SPOOL_NOTIFY_INFO_DATA *data,
1876 print_queue_struct *queue,
1877 NT_PRINTER_INFO_LEVEL *printer,
1878 TALLOC_CTX *mem_ctx)
1880 /* always respond 8 pages per minutes */
1881 /* a little hard ! */
1882 data->notify_data.value[0] = printer->info_2->averageppm;
1883 data->notify_data.value[1] = 0;
1886 /*******************************************************************
1887 * fill a notify_info_data with username
1888 ********************************************************************/
1889 static void spoolss_notify_username(int snum,
1890 SPOOL_NOTIFY_INFO_DATA *data,
1891 print_queue_struct *queue,
1892 NT_PRINTER_INFO_LEVEL *printer,
1893 TALLOC_CTX *mem_ctx)
1895 pstring temp;
1896 uint32 len;
1898 len = (uint32)dos_PutUniCode(temp, queue->user,
1899 sizeof(temp) - 2, True);
1901 data->notify_data.data.length = len / 2 - 1;
1902 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1904 if (!data->notify_data.data.string) {
1905 data->notify_data.data.length = 0;
1906 return;
1909 memcpy(data->notify_data.data.string, temp, len);
1912 /*******************************************************************
1913 * fill a notify_info_data with job status
1914 ********************************************************************/
1915 static void spoolss_notify_job_status(int snum,
1916 SPOOL_NOTIFY_INFO_DATA *data,
1917 print_queue_struct *queue,
1918 NT_PRINTER_INFO_LEVEL *printer,
1919 TALLOC_CTX *mem_ctx)
1921 data->notify_data.value[0]=nt_printj_status(queue->status);
1922 data->notify_data.value[1] = 0;
1925 /*******************************************************************
1926 * fill a notify_info_data with job name
1927 ********************************************************************/
1928 static void spoolss_notify_job_name(int snum,
1929 SPOOL_NOTIFY_INFO_DATA *data,
1930 print_queue_struct *queue,
1931 NT_PRINTER_INFO_LEVEL *printer,
1932 TALLOC_CTX *mem_ctx)
1934 pstring temp;
1935 uint32 len;
1937 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1938 True);
1940 data->notify_data.data.length = len / 2 - 1;
1941 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1943 if (!data->notify_data.data.string) {
1944 data->notify_data.data.length = 0;
1945 return;
1948 memcpy(data->notify_data.data.string, temp, len);
1951 /*******************************************************************
1952 * fill a notify_info_data with job status
1953 ********************************************************************/
1954 static void spoolss_notify_job_status_string(int snum,
1955 SPOOL_NOTIFY_INFO_DATA *data,
1956 print_queue_struct *queue,
1957 NT_PRINTER_INFO_LEVEL *printer,
1958 TALLOC_CTX *mem_ctx)
1961 * Now we're returning job status codes we just return a "" here. JRA.
1964 char *p = "";
1965 pstring temp;
1966 uint32 len;
1968 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1969 p = "unknown";
1971 switch (queue->status) {
1972 case LPQ_QUEUED:
1973 p = "Queued";
1974 break;
1975 case LPQ_PAUSED:
1976 p = ""; /* NT provides the paused string */
1977 break;
1978 case LPQ_SPOOLING:
1979 p = "Spooling";
1980 break;
1981 case LPQ_PRINTING:
1982 p = "Printing";
1983 break;
1985 #endif /* NO LONGER NEEDED. */
1987 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1989 data->notify_data.data.length = len / 2 - 1;
1990 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1992 if (!data->notify_data.data.string) {
1993 data->notify_data.data.length = 0;
1994 return;
1997 memcpy(data->notify_data.data.string, temp, len);
2000 /*******************************************************************
2001 * fill a notify_info_data with job time
2002 ********************************************************************/
2003 static void spoolss_notify_job_time(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]=0x0;
2010 data->notify_data.value[1]=0;
2013 /*******************************************************************
2014 * fill a notify_info_data with job size
2015 ********************************************************************/
2016 static void spoolss_notify_job_size(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->size;
2023 data->notify_data.value[1]=0;
2026 /*******************************************************************
2027 * fill a notify_info_data with job position
2028 ********************************************************************/
2029 static void spoolss_notify_job_position(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 data->notify_data.value[0]=queue->job;
2036 data->notify_data.value[1]=0;
2039 /*******************************************************************
2040 * fill a notify_info_data with submitted time
2041 ********************************************************************/
2042 static void spoolss_notify_submitted_time(int snum,
2043 SPOOL_NOTIFY_INFO_DATA *data,
2044 print_queue_struct *queue,
2045 NT_PRINTER_INFO_LEVEL *printer,
2046 TALLOC_CTX *mem_ctx)
2048 struct tm *t;
2049 uint32 len;
2050 SYSTEMTIME st;
2052 t=gmtime(&queue->time);
2054 len = sizeof(SYSTEMTIME);
2056 data->notify_data.data.length = len/2 - 1;
2057 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2059 if (!data->notify_data.data.string) {
2060 data->notify_data.data.length = 0;
2061 return;
2064 make_systemtime(&st, t);
2065 memcpy(data->notify_data.data.string,&st,len);
2068 #define END 65535
2070 struct s_notify_info_data_table
2072 uint16 type;
2073 uint16 field;
2074 char *name;
2075 uint32 size;
2076 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2077 print_queue_struct *queue,
2078 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2081 struct s_notify_info_data_table notify_info_data_table[] =
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2095 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2096 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2097 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2098 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2099 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2100 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2101 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2102 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2103 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2104 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2105 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2106 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2107 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2108 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2118 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2119 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2120 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2121 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2122 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2123 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2124 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2125 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2126 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2127 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2128 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2129 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2130 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2131 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2132 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2133 { END, END, "", END, NULL }
2136 /*******************************************************************
2137 return the size of info_data structure
2138 ********************************************************************/
2139 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2141 int i=0;
2143 while (notify_info_data_table[i].type != END)
2145 if ( (notify_info_data_table[i].type == type ) &&
2146 (notify_info_data_table[i].field == field ) )
2148 return (notify_info_data_table[i].size);
2150 i++;
2152 return (65535);
2155 /*******************************************************************
2156 return the type of notify_info_data
2157 ********************************************************************/
2158 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2160 int i=0;
2162 while (notify_info_data_table[i].type != END)
2164 if ( (notify_info_data_table[i].type == type ) &&
2165 (notify_info_data_table[i].field == field ) )
2167 if (notify_info_data_table[i].size == POINTER)
2169 return (False);
2171 else
2173 return (True);
2176 i++;
2178 return (False);
2181 /****************************************************************************
2182 ****************************************************************************/
2183 static int search_notify(uint16 type, uint16 field, int *value)
2185 int j;
2186 BOOL found;
2188 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2190 if ( (notify_info_data_table[j].type == type ) &&
2191 (notify_info_data_table[j].field == field ) )
2192 found=True;
2194 *value=--j;
2196 if ( found && (notify_info_data_table[j].fn != NULL) )
2197 return True;
2198 else
2199 return False;
2202 /****************************************************************************
2203 ****************************************************************************/
2204 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2206 info_data->type = type;
2207 info_data->field = field;
2208 info_data->reserved = 0;
2209 info_data->id = id;
2210 info_data->size = size_of_notify_info_data(type, field);
2211 info_data->enc_type = type_of_notify_info_data(type, field);
2215 /*******************************************************************
2217 * fill a notify_info struct with info asked
2219 ********************************************************************/
2220 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2221 snum, SPOOL_NOTIFY_OPTION_TYPE
2222 *option_type, uint32 id,
2223 TALLOC_CTX *mem_ctx)
2225 int field_num,j;
2226 uint16 type;
2227 uint16 field;
2229 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2230 NT_PRINTER_INFO_LEVEL *printer = NULL;
2231 print_queue_struct *queue=NULL;
2233 type=option_type->type;
2235 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2236 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2237 option_type->count, lp_servicename(snum)));
2239 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2240 return False;
2242 for(field_num=0; field_num<option_type->count; field_num++) {
2243 field = option_type->fields[field_num];
2244 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2246 if (!search_notify(type, field, &j) )
2247 continue;
2249 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2250 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2251 return False;
2253 else info->data = tid;
2255 current_data=&info->data[info->count];
2257 construct_info_data(current_data, type, field, id);
2259 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2260 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2262 notify_info_data_table[j].fn(snum, current_data, queue,
2263 printer, mem_ctx);
2265 info->count++;
2268 free_a_printer(&printer, 2);
2269 return True;
2272 /*******************************************************************
2274 * fill a notify_info struct with info asked
2276 ********************************************************************/
2277 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2278 SPOOL_NOTIFY_INFO *info,
2279 NT_PRINTER_INFO_LEVEL *printer,
2280 int snum, SPOOL_NOTIFY_OPTION_TYPE
2281 *option_type, uint32 id,
2282 TALLOC_CTX *mem_ctx)
2284 int field_num,j;
2285 uint16 type;
2286 uint16 field;
2288 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2290 DEBUG(4,("construct_notify_jobs_info\n"));
2292 type = option_type->type;
2294 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2295 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2296 option_type->count));
2298 for(field_num=0; field_num<option_type->count; field_num++) {
2299 field = option_type->fields[field_num];
2301 if (!search_notify(type, field, &j) )
2302 continue;
2304 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2305 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2306 return False;
2308 else info->data = tid;
2310 current_data=&(info->data[info->count]);
2312 construct_info_data(current_data, type, field, id);
2313 notify_info_data_table[j].fn(snum, current_data, queue,
2314 printer, mem_ctx);
2315 info->count++;
2318 return True;
2322 * JFM: The enumeration is not that simple, it's even non obvious.
2324 * let's take an example: I want to monitor the PRINTER SERVER for
2325 * the printer's name and the number of jobs currently queued.
2326 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2327 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2329 * I have 3 printers on the back of my server.
2331 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2332 * structures.
2333 * Number Data Id
2334 * 1 printer 1 name 1
2335 * 2 printer 1 cjob 1
2336 * 3 printer 2 name 2
2337 * 4 printer 2 cjob 2
2338 * 5 printer 3 name 3
2339 * 6 printer 3 name 3
2341 * that's the print server case, the printer case is even worse.
2344 /*******************************************************************
2346 * enumerate all printers on the printserver
2347 * fill a notify_info struct with info asked
2349 ********************************************************************/
2351 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2352 SPOOL_NOTIFY_INFO *info,
2353 TALLOC_CTX *mem_ctx)
2355 int snum;
2356 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2357 int n_services=lp_numservices();
2358 int i;
2359 uint32 id;
2360 SPOOL_NOTIFY_OPTION *option;
2361 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2363 DEBUG(4,("printserver_notify_info\n"));
2365 option=Printer->notify.option;
2366 id=1;
2367 info->version=2;
2368 info->data=NULL;
2369 info->count=0;
2371 for (i=0; i<option->count; i++) {
2372 option_type=&(option->ctr.type[i]);
2374 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2375 continue;
2377 for (snum=0; snum<n_services; snum++)
2378 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2379 if (construct_notify_printer_info
2380 (info, snum, option_type, id, mem_ctx))
2381 id++;
2385 * Debugging information, don't delete.
2388 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2389 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2390 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2392 for (i=0; i<info->count; i++) {
2393 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2394 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2395 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2399 return WERR_OK;
2402 /*******************************************************************
2404 * fill a notify_info struct with info asked
2406 ********************************************************************/
2407 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2408 TALLOC_CTX *mem_ctx)
2410 int snum;
2411 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2412 int i;
2413 uint32 id;
2414 SPOOL_NOTIFY_OPTION *option;
2415 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2416 int count,j;
2417 print_queue_struct *queue=NULL;
2418 print_status_struct status;
2420 DEBUG(4,("printer_notify_info\n"));
2422 option=Printer->notify.option;
2423 id=0xffffffff;
2424 info->version=2;
2425 info->data=NULL;
2426 info->count=0;
2428 get_printer_snum(p, hnd, &snum);
2430 for (i=0; i<option->count; i++) {
2431 option_type=&option->ctr.type[i];
2433 switch ( option_type->type ) {
2434 case PRINTER_NOTIFY_TYPE:
2435 if(construct_notify_printer_info(info, snum,
2436 option_type, id,
2437 mem_ctx))
2438 id--;
2439 break;
2441 case JOB_NOTIFY_TYPE: {
2442 NT_PRINTER_INFO_LEVEL *printer = NULL;
2444 count = print_queue_status(snum, &queue, &status);
2446 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2447 lp_servicename(snum))))
2448 goto done;
2450 for (j=0; j<count; j++) {
2451 construct_notify_jobs_info(&queue[j], info,
2452 printer, snum,
2453 option_type,
2454 queue[j].job,
2455 mem_ctx);
2458 free_a_printer(&printer, 2);
2460 done:
2461 SAFE_FREE(queue);
2462 break;
2468 * Debugging information, don't delete.
2471 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2472 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2473 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2475 for (i=0; i<info->count; i++) {
2476 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2477 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2478 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2481 return WERR_OK;
2484 /********************************************************************
2485 * spoolss_rfnpcnex
2486 ********************************************************************/
2488 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2490 POLICY_HND *handle = &q_u->handle;
2491 /* uint32 change = q_u->change; - notused. */
2492 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2493 SPOOL_NOTIFY_INFO *info = &r_u->info;
2495 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2496 WERROR result = WERR_BADFID;
2498 /* we always have a NOTIFY_INFO struct */
2499 r_u->info_ptr=0x1;
2501 if (!Printer) {
2502 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2503 OUR_HANDLE(handle)));
2504 goto done;
2507 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2509 /* jfm: the change value isn't used right now.
2510 * we will honour it when
2511 * a) we'll be able to send notification to the client
2512 * b) we'll have a way to communicate between the spoolss process.
2514 * same thing for option->flags
2515 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2516 * I don't have a global notification system, I'm sending back all the
2517 * informations even when _NOTHING_ has changed.
2520 /* just ignore the SPOOL_NOTIFY_OPTION */
2522 switch (Printer->printer_type) {
2523 case PRINTER_HANDLE_IS_PRINTSERVER:
2524 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2525 break;
2527 case PRINTER_HANDLE_IS_PRINTER:
2528 result = printer_notify_info(p, handle, info, p->mem_ctx);
2529 break;
2532 done:
2533 return result;
2536 /********************************************************************
2537 * construct_printer_info_0
2538 * fill a printer_info_0 struct
2539 ********************************************************************/
2540 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2542 pstring chaine;
2543 int count;
2544 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2545 counter_printer_0 *session_counter;
2546 uint32 global_counter;
2547 struct tm *t;
2548 time_t setuptime;
2549 print_status_struct status;
2551 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2552 return False;
2554 count = print_queue_length(snum, &status);
2556 /* check if we already have a counter for this printer */
2557 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2559 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2560 if (session_counter->snum == snum)
2561 break;
2564 /* it's the first time, add it to the list */
2565 if (session_counter==NULL) {
2566 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2567 free_a_printer(&ntprinter, 2);
2568 return False;
2570 ZERO_STRUCTP(session_counter);
2571 session_counter->snum=snum;
2572 session_counter->counter=0;
2573 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2576 /* increment it */
2577 session_counter->counter++;
2579 /* JFM:
2580 * the global_counter should be stored in a TDB as it's common to all the clients
2581 * and should be zeroed on samba startup
2583 global_counter=session_counter->counter;
2585 pstrcpy(chaine,ntprinter->info_2->printername);
2587 init_unistr(&printer->printername, chaine);
2589 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2590 init_unistr(&printer->servername, chaine);
2592 printer->cjobs = count;
2593 printer->total_jobs = 0;
2594 printer->total_bytes = 0;
2596 setuptime = (time_t)ntprinter->info_2->setuptime;
2597 t=gmtime(&setuptime);
2599 printer->year = t->tm_year+1900;
2600 printer->month = t->tm_mon+1;
2601 printer->dayofweek = t->tm_wday;
2602 printer->day = t->tm_mday;
2603 printer->hour = t->tm_hour;
2604 printer->minute = t->tm_min;
2605 printer->second = t->tm_sec;
2606 printer->milliseconds = 0;
2608 printer->global_counter = global_counter;
2609 printer->total_pages = 0;
2610 printer->major_version = 0x0004; /* NT 4 */
2611 printer->build_version = 0x0565; /* build 1381 */
2612 printer->unknown7 = 0x1;
2613 printer->unknown8 = 0x0;
2614 printer->unknown9 = 0x0;
2615 printer->session_counter = session_counter->counter;
2616 printer->unknown11 = 0x0;
2617 printer->printer_errors = 0x0; /* number of print failure */
2618 printer->unknown13 = 0x0;
2619 printer->unknown14 = 0x1;
2620 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2621 printer->unknown16 = 0x0;
2622 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2623 printer->unknown18 = 0x0;
2624 printer->status = nt_printq_status(status.status);
2625 printer->unknown20 = 0x0;
2626 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2627 printer->unknown22 = 0x0;
2628 printer->unknown23 = 0x6; /* 6 ???*/
2629 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2630 printer->unknown25 = 0;
2631 printer->unknown26 = 0;
2632 printer->unknown27 = 0;
2633 printer->unknown28 = 0;
2634 printer->unknown29 = 0;
2636 free_a_printer(&ntprinter,2);
2637 return (True);
2640 /********************************************************************
2641 * construct_printer_info_1
2642 * fill a printer_info_1 struct
2643 ********************************************************************/
2644 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2646 pstring chaine;
2647 pstring chaine2;
2648 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2650 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2651 return False;
2653 printer->flags=flags;
2655 if (*ntprinter->info_2->comment == '\0') {
2656 init_unistr(&printer->comment, lp_comment(snum));
2657 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2658 ntprinter->info_2->drivername, lp_comment(snum));
2660 else {
2661 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2662 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2663 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2666 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2668 init_unistr(&printer->description, chaine);
2669 init_unistr(&printer->name, chaine2);
2671 free_a_printer(&ntprinter,2);
2673 return True;
2676 /****************************************************************************
2677 Free a DEVMODE struct.
2678 ****************************************************************************/
2680 static void free_dev_mode(DEVICEMODE *dev)
2682 if (dev == NULL)
2683 return;
2685 SAFE_FREE(dev->private);
2686 SAFE_FREE(dev);
2689 /****************************************************************************
2690 Create a DEVMODE struct. Returns malloced memory.
2691 ****************************************************************************/
2693 static DEVICEMODE *construct_dev_mode(int snum)
2695 char adevice[32];
2696 char aform[32];
2697 NT_PRINTER_INFO_LEVEL *printer = NULL;
2698 NT_DEVICEMODE *ntdevmode = NULL;
2699 DEVICEMODE *devmode = NULL;
2701 DEBUG(7,("construct_dev_mode\n"));
2703 DEBUGADD(8,("getting printer characteristics\n"));
2705 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2706 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2707 return NULL;
2710 ZERO_STRUCTP(devmode);
2712 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2713 goto fail;
2715 if (printer->info_2->devmode)
2716 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2718 if (ntdevmode == NULL)
2719 goto fail;
2721 DEBUGADD(8,("loading DEVICEMODE\n"));
2723 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2724 init_unistr(&devmode->devicename, adevice);
2726 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2727 init_unistr(&devmode->formname, aform);
2729 devmode->specversion = ntdevmode->specversion;
2730 devmode->driverversion = ntdevmode->driverversion;
2731 devmode->size = ntdevmode->size;
2732 devmode->driverextra = ntdevmode->driverextra;
2733 devmode->fields = ntdevmode->fields;
2735 devmode->orientation = ntdevmode->orientation;
2736 devmode->papersize = ntdevmode->papersize;
2737 devmode->paperlength = ntdevmode->paperlength;
2738 devmode->paperwidth = ntdevmode->paperwidth;
2739 devmode->scale = ntdevmode->scale;
2740 devmode->copies = ntdevmode->copies;
2741 devmode->defaultsource = ntdevmode->defaultsource;
2742 devmode->printquality = ntdevmode->printquality;
2743 devmode->color = ntdevmode->color;
2744 devmode->duplex = ntdevmode->duplex;
2745 devmode->yresolution = ntdevmode->yresolution;
2746 devmode->ttoption = ntdevmode->ttoption;
2747 devmode->collate = ntdevmode->collate;
2748 devmode->icmmethod = ntdevmode->icmmethod;
2749 devmode->icmintent = ntdevmode->icmintent;
2750 devmode->mediatype = ntdevmode->mediatype;
2751 devmode->dithertype = ntdevmode->dithertype;
2753 if (ntdevmode->private != NULL) {
2754 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2755 goto fail;
2758 free_nt_devicemode(&ntdevmode);
2759 free_a_printer(&printer,2);
2761 return devmode;
2763 fail:
2765 if (ntdevmode)
2766 free_nt_devicemode(&ntdevmode);
2767 if (printer)
2768 free_a_printer(&printer,2);
2769 free_dev_mode(devmode);
2771 return NULL;
2774 /********************************************************************
2775 * construct_printer_info_2
2776 * fill a printer_info_2 struct
2777 ********************************************************************/
2779 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2781 int count;
2782 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2784 print_status_struct status;
2786 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2787 return False;
2789 count = print_queue_length(snum, &status);
2791 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2792 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2793 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2794 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2795 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2797 if (*ntprinter->info_2->comment == '\0')
2798 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2799 else
2800 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2802 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2803 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2804 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2805 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2806 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2808 printer->attributes = ntprinter->info_2->attributes;
2810 printer->priority = ntprinter->info_2->priority; /* priority */
2811 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2812 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2813 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2814 printer->status = nt_printq_status(status.status); /* status */
2815 printer->cjobs = count; /* jobs */
2816 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2818 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2819 DEBUG(8, ("Returning NULL Devicemode!\n"));
2822 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2823 /* steal the printer info sec_desc structure. [badly done]. */
2824 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2825 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2826 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2827 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2829 else {
2830 printer->secdesc = NULL;
2833 free_a_printer(&ntprinter, 2);
2834 return True;
2837 /********************************************************************
2838 * construct_printer_info_3
2839 * fill a printer_info_3 struct
2840 ********************************************************************/
2841 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2843 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2844 PRINTER_INFO_3 *printer = NULL;
2846 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2847 return False;
2849 *pp_printer = NULL;
2850 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2851 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2852 return False;
2855 ZERO_STRUCTP(printer);
2857 printer->flags = 4; /* These are the components of the SD we are returning. */
2858 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2859 /* steal the printer info sec_desc structure. [badly done]. */
2860 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2862 #if 0
2864 * Set the flags for the components we are returning.
2867 if (printer->secdesc->owner_sid)
2868 printer->flags |= OWNER_SECURITY_INFORMATION;
2870 if (printer->secdesc->grp_sid)
2871 printer->flags |= GROUP_SECURITY_INFORMATION;
2873 if (printer->secdesc->dacl)
2874 printer->flags |= DACL_SECURITY_INFORMATION;
2876 if (printer->secdesc->sacl)
2877 printer->flags |= SACL_SECURITY_INFORMATION;
2878 #endif
2880 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2881 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2882 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2885 free_a_printer(&ntprinter, 2);
2887 *pp_printer = printer;
2888 return True;
2891 /********************************************************************
2892 Spoolss_enumprinters.
2893 ********************************************************************/
2894 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2896 int snum;
2897 int i;
2898 int n_services=lp_numservices();
2899 PRINTER_INFO_1 *tp, *printers=NULL;
2900 PRINTER_INFO_1 current_prt;
2902 DEBUG(4,("enum_all_printers_info_1\n"));
2904 for (snum=0; snum<n_services; snum++) {
2905 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2906 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2908 if (construct_printer_info_1(flags, &current_prt, snum)) {
2909 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2910 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2911 SAFE_FREE(printers);
2912 *returned=0;
2913 return WERR_NOMEM;
2915 else printers = tp;
2916 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2917 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2918 (*returned)++;
2923 /* check the required size. */
2924 for (i=0; i<*returned; i++)
2925 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2927 if (!alloc_buffer_size(buffer, *needed))
2928 return WERR_INSUFFICIENT_BUFFER;
2930 /* fill the buffer with the structures */
2931 for (i=0; i<*returned; i++)
2932 smb_io_printer_info_1("", buffer, &printers[i], 0);
2934 /* clear memory */
2935 SAFE_FREE(printers);
2937 if (*needed > offered) {
2938 *returned=0;
2939 return WERR_INSUFFICIENT_BUFFER;
2941 else
2942 return WERR_OK;
2945 /********************************************************************
2946 enum_all_printers_info_1_local.
2947 *********************************************************************/
2948 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2950 DEBUG(4,("enum_all_printers_info_1_local\n"));
2952 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2955 /********************************************************************
2956 enum_all_printers_info_1_name.
2957 *********************************************************************/
2958 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2960 char *s = name;
2962 DEBUG(4,("enum_all_printers_info_1_name\n"));
2964 if ((name[0] == '\\') && (name[1] == '\\'))
2965 s = name + 2;
2967 if (is_myname_or_ipaddr(s)) {
2968 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2970 else
2971 return WERR_INVALID_NAME;
2974 /********************************************************************
2975 enum_all_printers_info_1_remote.
2976 *********************************************************************/
2977 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2979 PRINTER_INFO_1 *printer;
2980 fstring printername;
2981 fstring desc;
2982 fstring comment;
2983 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2985 /* JFM: currently it's more a place holder than anything else.
2986 * In the spooler world there is a notion of server registration.
2987 * the print servers are registring (sp ?) on the PDC (in the same domain)
2989 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2992 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2993 return WERR_NOMEM;
2995 *returned=1;
2997 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2998 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2999 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3001 init_unistr(&printer->description, desc);
3002 init_unistr(&printer->name, printername);
3003 init_unistr(&printer->comment, comment);
3004 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3006 /* check the required size. */
3007 *needed += spoolss_size_printer_info_1(printer);
3009 if (!alloc_buffer_size(buffer, *needed)) {
3010 SAFE_FREE(printer);
3011 return WERR_INSUFFICIENT_BUFFER;
3014 /* fill the buffer with the structures */
3015 smb_io_printer_info_1("", buffer, printer, 0);
3017 /* clear memory */
3018 SAFE_FREE(printer);
3020 if (*needed > offered) {
3021 *returned=0;
3022 return WERR_INSUFFICIENT_BUFFER;
3024 else
3025 return WERR_OK;
3028 /********************************************************************
3029 enum_all_printers_info_1_network.
3030 *********************************************************************/
3032 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3034 DEBUG(4,("enum_all_printers_info_1_network\n"));
3036 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3039 /********************************************************************
3040 * api_spoolss_enumprinters
3042 * called from api_spoolss_enumprinters (see this to understand)
3043 ********************************************************************/
3045 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3047 int snum;
3048 int i;
3049 int n_services=lp_numservices();
3050 PRINTER_INFO_2 *tp, *printers=NULL;
3051 PRINTER_INFO_2 current_prt;
3053 for (snum=0; snum<n_services; snum++) {
3054 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3055 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3057 if (construct_printer_info_2(&current_prt, snum)) {
3058 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3059 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3060 SAFE_FREE(printers);
3061 *returned = 0;
3062 return WERR_NOMEM;
3064 else printers = tp;
3065 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3066 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3067 (*returned)++;
3072 /* check the required size. */
3073 for (i=0; i<*returned; i++)
3074 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3076 if (!alloc_buffer_size(buffer, *needed)) {
3077 for (i=0; i<*returned; i++) {
3078 free_devmode(printers[i].devmode);
3080 SAFE_FREE(printers);
3081 return WERR_INSUFFICIENT_BUFFER;
3084 /* fill the buffer with the structures */
3085 for (i=0; i<*returned; i++)
3086 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3088 /* clear memory */
3089 for (i=0; i<*returned; i++) {
3090 free_devmode(printers[i].devmode);
3092 SAFE_FREE(printers);
3094 if (*needed > offered) {
3095 *returned=0;
3096 return WERR_INSUFFICIENT_BUFFER;
3098 else
3099 return WERR_OK;
3102 /********************************************************************
3103 * handle enumeration of printers at level 1
3104 ********************************************************************/
3105 static WERROR enumprinters_level1( uint32 flags, fstring name,
3106 NEW_BUFFER *buffer, uint32 offered,
3107 uint32 *needed, uint32 *returned)
3109 /* Not all the flags are equals */
3111 if (flags & PRINTER_ENUM_LOCAL)
3112 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3114 if (flags & PRINTER_ENUM_NAME)
3115 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3117 if (flags & PRINTER_ENUM_REMOTE)
3118 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3120 if (flags & PRINTER_ENUM_NETWORK)
3121 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3123 return WERR_OK; /* NT4sp5 does that */
3126 /********************************************************************
3127 * handle enumeration of printers at level 2
3128 ********************************************************************/
3129 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3130 NEW_BUFFER *buffer, uint32 offered,
3131 uint32 *needed, uint32 *returned)
3133 char *s = servername;
3135 if (flags & PRINTER_ENUM_LOCAL) {
3136 return enum_all_printers_info_2(buffer, offered, needed, returned);
3139 if (flags & PRINTER_ENUM_NAME) {
3140 if ((servername[0] == '\\') && (servername[1] == '\\'))
3141 s = servername + 2;
3142 if (is_myname_or_ipaddr(s))
3143 return enum_all_printers_info_2(buffer, offered, needed, returned);
3144 else
3145 return WERR_INVALID_NAME;
3148 if (flags & PRINTER_ENUM_REMOTE)
3149 return WERR_UNKNOWN_LEVEL;
3151 return WERR_OK;
3154 /********************************************************************
3155 * handle enumeration of printers at level 5
3156 ********************************************************************/
3157 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3158 NEW_BUFFER *buffer, uint32 offered,
3159 uint32 *needed, uint32 *returned)
3161 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3162 return WERR_OK;
3165 /********************************************************************
3166 * api_spoolss_enumprinters
3168 * called from api_spoolss_enumprinters (see this to understand)
3169 ********************************************************************/
3171 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3173 uint32 flags = q_u->flags;
3174 UNISTR2 *servername = &q_u->servername;
3175 uint32 level = q_u->level;
3176 NEW_BUFFER *buffer = NULL;
3177 uint32 offered = q_u->offered;
3178 uint32 *needed = &r_u->needed;
3179 uint32 *returned = &r_u->returned;
3181 fstring name;
3183 /* that's an [in out] buffer */
3184 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3185 buffer = r_u->buffer;
3187 DEBUG(4,("_spoolss_enumprinters\n"));
3189 *needed=0;
3190 *returned=0;
3193 * Level 1:
3194 * flags==PRINTER_ENUM_NAME
3195 * if name=="" then enumerates all printers
3196 * if name!="" then enumerate the printer
3197 * flags==PRINTER_ENUM_REMOTE
3198 * name is NULL, enumerate printers
3199 * Level 2: name!="" enumerates printers, name can't be NULL
3200 * Level 3: doesn't exist
3201 * Level 4: does a local registry lookup
3202 * Level 5: same as Level 2
3205 unistr2_to_ascii(name, servername, sizeof(name)-1);
3206 strupper(name);
3208 switch (level) {
3209 case 1:
3210 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3211 case 2:
3212 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3213 case 5:
3214 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3215 case 3:
3216 case 4:
3217 break;
3219 return WERR_UNKNOWN_LEVEL;
3222 /****************************************************************************
3223 ****************************************************************************/
3224 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3226 PRINTER_INFO_0 *printer=NULL;
3228 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3229 return WERR_NOMEM;
3231 construct_printer_info_0(printer, snum);
3233 /* check the required size. */
3234 *needed += spoolss_size_printer_info_0(printer);
3236 if (!alloc_buffer_size(buffer, *needed)) {
3237 SAFE_FREE(printer);
3238 return WERR_INSUFFICIENT_BUFFER;
3241 /* fill the buffer with the structures */
3242 smb_io_printer_info_0("", buffer, printer, 0);
3244 /* clear memory */
3245 SAFE_FREE(printer);
3247 if (*needed > offered) {
3248 return WERR_INSUFFICIENT_BUFFER;
3251 return WERR_OK;
3254 /****************************************************************************
3255 ****************************************************************************/
3256 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3258 PRINTER_INFO_1 *printer=NULL;
3260 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3261 return WERR_NOMEM;
3263 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3265 /* check the required size. */
3266 *needed += spoolss_size_printer_info_1(printer);
3268 if (!alloc_buffer_size(buffer, *needed)) {
3269 SAFE_FREE(printer);
3270 return WERR_INSUFFICIENT_BUFFER;
3273 /* fill the buffer with the structures */
3274 smb_io_printer_info_1("", buffer, printer, 0);
3276 /* clear memory */
3277 SAFE_FREE(printer);
3279 if (*needed > offered) {
3280 return WERR_INSUFFICIENT_BUFFER;
3283 return WERR_OK;
3286 /****************************************************************************
3287 ****************************************************************************/
3288 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3290 PRINTER_INFO_2 *printer=NULL;
3292 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3293 return WERR_NOMEM;
3295 construct_printer_info_2(printer, snum);
3297 /* check the required size. */
3298 *needed += spoolss_size_printer_info_2(printer);
3300 if (!alloc_buffer_size(buffer, *needed)) {
3301 free_printer_info_2(printer);
3302 return WERR_INSUFFICIENT_BUFFER;
3305 /* fill the buffer with the structures */
3306 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3307 free_printer_info_2(printer);
3308 return WERR_NOMEM;
3311 /* clear memory */
3312 free_printer_info_2(printer);
3314 if (*needed > offered) {
3315 return WERR_INSUFFICIENT_BUFFER;
3318 return WERR_OK;
3321 /****************************************************************************
3322 ****************************************************************************/
3323 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3325 PRINTER_INFO_3 *printer=NULL;
3327 if (!construct_printer_info_3(&printer, snum))
3328 return WERR_NOMEM;
3330 /* check the required size. */
3331 *needed += spoolss_size_printer_info_3(printer);
3333 if (!alloc_buffer_size(buffer, *needed)) {
3334 free_printer_info_3(printer);
3335 return WERR_INSUFFICIENT_BUFFER;
3338 /* fill the buffer with the structures */
3339 smb_io_printer_info_3("", buffer, printer, 0);
3341 /* clear memory */
3342 free_printer_info_3(printer);
3344 if (*needed > offered) {
3345 return WERR_INSUFFICIENT_BUFFER;
3348 return WERR_OK;
3351 /****************************************************************************
3352 ****************************************************************************/
3354 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3356 POLICY_HND *handle = &q_u->handle;
3357 uint32 level = q_u->level;
3358 NEW_BUFFER *buffer = NULL;
3359 uint32 offered = q_u->offered;
3360 uint32 *needed = &r_u->needed;
3362 int snum;
3364 /* that's an [in out] buffer */
3365 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3366 buffer = r_u->buffer;
3368 *needed=0;
3370 if (!get_printer_snum(p, handle, &snum))
3371 return WERR_BADFID;
3373 switch (level) {
3374 case 0:
3375 return getprinter_level_0(snum, buffer, offered, needed);
3376 case 1:
3377 return getprinter_level_1(snum, buffer, offered, needed);
3378 case 2:
3379 return getprinter_level_2(snum, buffer, offered, needed);
3380 case 3:
3381 return getprinter_level_3(snum, buffer, offered, needed);
3383 return WERR_UNKNOWN_LEVEL;
3386 /********************************************************************
3387 * fill a DRIVER_INFO_1 struct
3388 ********************************************************************/
3389 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3391 init_unistr( &info->name, driver.info_3->name);
3394 /********************************************************************
3395 * construct_printer_driver_info_1
3396 ********************************************************************/
3397 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3399 NT_PRINTER_INFO_LEVEL *printer = NULL;
3400 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3402 ZERO_STRUCT(driver);
3404 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3405 return WERR_INVALID_PRINTER_NAME;
3407 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3408 return WERR_UNKNOWN_PRINTER_DRIVER;
3410 fill_printer_driver_info_1(info, driver, servername, architecture);
3412 free_a_printer(&printer,2);
3414 return WERR_OK;
3417 /********************************************************************
3418 * construct_printer_driver_info_2
3419 * fill a printer_info_2 struct
3420 ********************************************************************/
3421 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3423 pstring temp;
3425 info->version=driver.info_3->cversion;
3427 init_unistr( &info->name, driver.info_3->name );
3428 init_unistr( &info->architecture, driver.info_3->environment );
3431 if (strlen(driver.info_3->driverpath)) {
3432 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3433 init_unistr( &info->driverpath, temp );
3434 } else
3435 init_unistr( &info->driverpath, "" );
3437 if (strlen(driver.info_3->datafile)) {
3438 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3439 init_unistr( &info->datafile, temp );
3440 } else
3441 init_unistr( &info->datafile, "" );
3443 if (strlen(driver.info_3->configfile)) {
3444 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3445 init_unistr( &info->configfile, temp );
3446 } else
3447 init_unistr( &info->configfile, "" );
3450 /********************************************************************
3451 * construct_printer_driver_info_2
3452 * fill a printer_info_2 struct
3453 ********************************************************************/
3454 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3456 NT_PRINTER_INFO_LEVEL *printer = NULL;
3457 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3459 ZERO_STRUCT(printer);
3460 ZERO_STRUCT(driver);
3462 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3463 return WERR_INVALID_PRINTER_NAME;
3465 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3466 return WERR_UNKNOWN_PRINTER_DRIVER;
3468 fill_printer_driver_info_2(info, driver, servername);
3470 free_a_printer(&printer,2);
3472 return WERR_OK;
3475 /********************************************************************
3476 * copy a strings array and convert to UNICODE
3478 * convert an array of ascii string to a UNICODE string
3479 ********************************************************************/
3480 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3482 int i=0;
3483 int j=0;
3484 char *v;
3485 pstring line;
3486 uint16 *tuary;
3488 DEBUG(6,("init_unistr_array\n"));
3489 *uni_array=NULL;
3491 while (1) {
3492 if (char_array == NULL)
3493 v = "";
3494 else {
3495 v = char_array[i];
3496 if (!v) v = ""; /* hack to handle null lists */
3498 if (strlen(v) == 0) break;
3499 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3500 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3501 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3502 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3503 return;
3504 } else
3505 *uni_array = tuary;
3506 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3507 i++;
3510 if (*uni_array) {
3511 (*uni_array)[j]=0x0000;
3514 DEBUGADD(6,("last one:done\n"));
3517 /********************************************************************
3518 * construct_printer_info_3
3519 * fill a printer_info_3 struct
3520 ********************************************************************/
3521 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3523 pstring temp;
3525 ZERO_STRUCTP(info);
3527 info->version=driver.info_3->cversion;
3529 init_unistr( &info->name, driver.info_3->name );
3530 init_unistr( &info->architecture, driver.info_3->environment );
3532 if (strlen(driver.info_3->driverpath)) {
3533 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3534 init_unistr( &info->driverpath, temp );
3535 } else
3536 init_unistr( &info->driverpath, "" );
3538 if (strlen(driver.info_3->datafile)) {
3539 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3540 init_unistr( &info->datafile, temp );
3541 } else
3542 init_unistr( &info->datafile, "" );
3544 if (strlen(driver.info_3->configfile)) {
3545 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3546 init_unistr( &info->configfile, temp );
3547 } else
3548 init_unistr( &info->configfile, "" );
3550 if (strlen(driver.info_3->helpfile)) {
3551 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3552 init_unistr( &info->helpfile, temp );
3553 } else
3554 init_unistr( &info->helpfile, "" );
3556 init_unistr( &info->monitorname, driver.info_3->monitorname );
3557 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3559 info->dependentfiles=NULL;
3560 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3563 /********************************************************************
3564 * construct_printer_info_3
3565 * fill a printer_info_3 struct
3566 ********************************************************************/
3567 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3569 NT_PRINTER_INFO_LEVEL *printer = NULL;
3570 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3571 WERROR status;
3572 ZERO_STRUCT(driver);
3574 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3575 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3576 if (!W_ERROR_IS_OK(status))
3577 return WERR_INVALID_PRINTER_NAME;
3579 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3580 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3581 if (!W_ERROR_IS_OK(status)) {
3582 free_a_printer(&printer,2);
3583 return WERR_UNKNOWN_PRINTER_DRIVER;
3586 fill_printer_driver_info_3(info, driver, servername);
3588 free_a_printer(&printer,2);
3590 return WERR_OK;
3593 /********************************************************************
3594 * construct_printer_info_6
3595 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3596 ********************************************************************/
3598 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3600 pstring temp;
3601 fstring nullstr;
3603 ZERO_STRUCTP(info);
3604 memset(&nullstr, '\0', sizeof(fstring));
3606 info->version=driver.info_3->cversion;
3608 init_unistr( &info->name, driver.info_3->name );
3609 init_unistr( &info->architecture, driver.info_3->environment );
3611 if (strlen(driver.info_3->driverpath)) {
3612 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3613 init_unistr( &info->driverpath, temp );
3614 } else
3615 init_unistr( &info->driverpath, "" );
3617 if (strlen(driver.info_3->datafile)) {
3618 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3619 init_unistr( &info->datafile, temp );
3620 } else
3621 init_unistr( &info->datafile, "" );
3623 if (strlen(driver.info_3->configfile)) {
3624 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3625 init_unistr( &info->configfile, temp );
3626 } else
3627 init_unistr( &info->configfile, "" );
3629 if (strlen(driver.info_3->helpfile)) {
3630 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3631 init_unistr( &info->helpfile, temp );
3632 } else
3633 init_unistr( &info->helpfile, "" );
3635 init_unistr( &info->monitorname, driver.info_3->monitorname );
3636 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3638 info->dependentfiles=NULL;
3639 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3641 info->previousdrivernames=NULL;
3642 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3644 info->driver_date.low=0;
3645 info->driver_date.high=0;
3647 info->padding=0;
3648 info->driver_version_low=0;
3649 info->driver_version_high=0;
3651 init_unistr( &info->mfgname, "");
3652 init_unistr( &info->oem_url, "");
3653 init_unistr( &info->hardware_id, "");
3654 init_unistr( &info->provider, "");
3657 /********************************************************************
3658 * construct_printer_info_6
3659 * fill a printer_info_6 struct
3660 ********************************************************************/
3661 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3663 NT_PRINTER_INFO_LEVEL *printer = NULL;
3664 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3665 WERROR status;
3666 ZERO_STRUCT(driver);
3668 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3669 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3670 if (!W_ERROR_IS_OK(status))
3671 return WERR_INVALID_PRINTER_NAME;
3673 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3674 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3675 if (!W_ERROR_IS_OK(status)) {
3677 * Is this a W2k client ?
3680 if (version < 3) {
3681 free_a_printer(&printer,2);
3682 return WERR_UNKNOWN_PRINTER_DRIVER;
3685 /* Yes - try again with a WinNT driver. */
3686 version = 2;
3687 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3688 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3689 if (!W_ERROR_IS_OK(status)) {
3690 free_a_printer(&printer,2);
3691 return WERR_UNKNOWN_PRINTER_DRIVER;
3695 fill_printer_driver_info_6(info, driver, servername);
3697 free_a_printer(&printer,2);
3699 return WERR_OK;
3702 /****************************************************************************
3703 ****************************************************************************/
3705 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3707 SAFE_FREE(info->dependentfiles);
3710 /****************************************************************************
3711 ****************************************************************************/
3713 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3715 SAFE_FREE(info->dependentfiles);
3719 /****************************************************************************
3720 ****************************************************************************/
3721 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3723 DRIVER_INFO_1 *info=NULL;
3724 WERROR status;
3726 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3727 return WERR_NOMEM;
3729 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3730 if (!W_ERROR_IS_OK(status)) {
3731 SAFE_FREE(info);
3732 return status;
3735 /* check the required size. */
3736 *needed += spoolss_size_printer_driver_info_1(info);
3738 if (!alloc_buffer_size(buffer, *needed)) {
3739 SAFE_FREE(info);
3740 return WERR_INSUFFICIENT_BUFFER;
3743 /* fill the buffer with the structures */
3744 smb_io_printer_driver_info_1("", buffer, info, 0);
3746 /* clear memory */
3747 SAFE_FREE(info);
3749 if (*needed > offered)
3750 return WERR_INSUFFICIENT_BUFFER;
3752 return WERR_OK;
3755 /****************************************************************************
3756 ****************************************************************************/
3757 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3759 DRIVER_INFO_2 *info=NULL;
3760 WERROR status;
3762 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3763 return WERR_NOMEM;
3765 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3766 if (!W_ERROR_IS_OK(status)) {
3767 SAFE_FREE(info);
3768 return status;
3771 /* check the required size. */
3772 *needed += spoolss_size_printer_driver_info_2(info);
3774 if (!alloc_buffer_size(buffer, *needed)) {
3775 SAFE_FREE(info);
3776 return WERR_INSUFFICIENT_BUFFER;
3779 /* fill the buffer with the structures */
3780 smb_io_printer_driver_info_2("", buffer, info, 0);
3782 /* clear memory */
3783 SAFE_FREE(info);
3785 if (*needed > offered)
3786 return WERR_INSUFFICIENT_BUFFER;
3788 return WERR_OK;
3791 /****************************************************************************
3792 ****************************************************************************/
3793 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3795 DRIVER_INFO_3 info;
3796 WERROR status;
3798 ZERO_STRUCT(info);
3800 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3801 if (!W_ERROR_IS_OK(status)) {
3802 return status;
3805 /* check the required size. */
3806 *needed += spoolss_size_printer_driver_info_3(&info);
3808 if (!alloc_buffer_size(buffer, *needed)) {
3809 free_printer_driver_info_3(&info);
3810 return WERR_INSUFFICIENT_BUFFER;
3813 /* fill the buffer with the structures */
3814 smb_io_printer_driver_info_3("", buffer, &info, 0);
3816 free_printer_driver_info_3(&info);
3818 if (*needed > offered)
3819 return WERR_INSUFFICIENT_BUFFER;
3821 return WERR_OK;
3824 /****************************************************************************
3825 ****************************************************************************/
3826 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3828 DRIVER_INFO_6 info;
3829 WERROR status;
3831 ZERO_STRUCT(info);
3833 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3834 if (!W_ERROR_IS_OK(status)) {
3835 return status;
3838 /* check the required size. */
3839 *needed += spoolss_size_printer_driver_info_6(&info);
3841 if (!alloc_buffer_size(buffer, *needed)) {
3842 free_printer_driver_info_6(&info);
3843 return WERR_INSUFFICIENT_BUFFER;
3846 /* fill the buffer with the structures */
3847 smb_io_printer_driver_info_6("", buffer, &info, 0);
3849 free_printer_driver_info_6(&info);
3851 if (*needed > offered)
3852 return WERR_INSUFFICIENT_BUFFER;
3854 return WERR_OK;
3857 /****************************************************************************
3858 ****************************************************************************/
3860 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3862 POLICY_HND *handle = &q_u->handle;
3863 UNISTR2 *uni_arch = &q_u->architecture;
3864 uint32 level = q_u->level;
3865 uint32 clientmajorversion = q_u->clientmajorversion;
3866 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3867 NEW_BUFFER *buffer = NULL;
3868 uint32 offered = q_u->offered;
3869 uint32 *needed = &r_u->needed;
3870 uint32 *servermajorversion = &r_u->servermajorversion;
3871 uint32 *serverminorversion = &r_u->serverminorversion;
3873 fstring servername;
3874 fstring architecture;
3875 int snum;
3877 /* that's an [in out] buffer */
3878 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3879 buffer = r_u->buffer;
3881 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3883 *needed=0;
3884 *servermajorversion=0;
3885 *serverminorversion=0;
3887 pstrcpy(servername, global_myname);
3888 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3890 if (!get_printer_snum(p, handle, &snum))
3891 return WERR_BADFID;
3893 switch (level) {
3894 case 1:
3895 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3896 case 2:
3897 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3898 case 3:
3899 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3900 case 6:
3901 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3904 return WERR_UNKNOWN_LEVEL;
3907 /****************************************************************************
3908 ****************************************************************************/
3910 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3912 POLICY_HND *handle = &q_u->handle;
3914 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3916 if (Printer) {
3917 Printer->page_started=True;
3918 return WERR_OK;
3921 DEBUG(3,("Error in startpageprinter printer handle\n"));
3922 return WERR_BADFID;
3925 /****************************************************************************
3926 ****************************************************************************/
3928 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3930 POLICY_HND *handle = &q_u->handle;
3932 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3934 if (!Printer) {
3935 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3936 return WERR_BADFID;
3939 Printer->page_started=False;
3941 return WERR_OK;
3944 /********************************************************************
3945 * api_spoolss_getprinter
3946 * called from the spoolss dispatcher
3948 ********************************************************************/
3950 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3952 POLICY_HND *handle = &q_u->handle;
3953 /* uint32 level = q_u->doc_info_container.level; - notused. */
3954 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3955 uint32 *jobid = &r_u->jobid;
3957 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3958 int snum;
3959 pstring jobname;
3960 fstring datatype;
3961 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3962 struct current_user user;
3964 if (!Printer) {
3965 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3966 return WERR_BADFID;
3969 get_current_user(&user, p);
3972 * a nice thing with NT is it doesn't listen to what you tell it.
3973 * when asked to send _only_ RAW datas, it tries to send datas
3974 * in EMF format.
3976 * So I add checks like in NT Server ...
3978 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3979 * there's a bug in NT client-side code, so we'll fix it in the
3980 * server-side code. *nnnnnggggh!*
3983 if (info_1->p_datatype != 0) {
3984 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3985 if (strcmp(datatype, "RAW") != 0) {
3986 (*jobid)=0;
3987 return WERR_INVALID_DATATYPE;
3991 /* get the share number of the printer */
3992 if (!get_printer_snum(p, handle, &snum)) {
3993 return WERR_BADFID;
3996 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3998 Printer->jobid = print_job_start(&user, snum, jobname);
4000 /* An error occured in print_job_start() so return an appropriate
4001 NT error code. */
4003 if (Printer->jobid == -1) {
4004 return map_werror_from_unix(errno);
4007 Printer->document_started=True;
4008 (*jobid) = Printer->jobid;
4010 return WERR_OK;
4013 /********************************************************************
4014 * api_spoolss_getprinter
4015 * called from the spoolss dispatcher
4017 ********************************************************************/
4019 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4021 POLICY_HND *handle = &q_u->handle;
4023 return _spoolss_enddocprinter_internal(p, handle);
4026 /****************************************************************************
4027 ****************************************************************************/
4029 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4031 POLICY_HND *handle = &q_u->handle;
4032 uint32 buffer_size = q_u->buffer_size;
4033 uint8 *buffer = q_u->buffer;
4034 uint32 *buffer_written = &q_u->buffer_size2;
4036 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4038 if (!Printer) {
4039 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4040 r_u->buffer_written = q_u->buffer_size2;
4041 return WERR_BADFID;
4044 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4047 r_u->buffer_written = q_u->buffer_size2;
4049 return WERR_OK;
4052 /********************************************************************
4053 * api_spoolss_getprinter
4054 * called from the spoolss dispatcher
4056 ********************************************************************/
4057 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4058 pipes_struct *p)
4060 struct current_user user;
4061 int snum;
4062 WERROR errcode = WERR_BADFUNC;
4063 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4065 get_current_user(&user, p);
4067 if (!Printer) {
4068 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4069 return WERR_BADFID;
4072 if (!get_printer_snum(p, handle, &snum))
4073 return WERR_BADFID;
4075 switch (command) {
4076 case PRINTER_CONTROL_PAUSE:
4077 if (print_queue_pause(&user, snum, &errcode)) {
4078 errcode = WERR_OK;
4080 break;
4081 case PRINTER_CONTROL_RESUME:
4082 case PRINTER_CONTROL_UNPAUSE:
4083 if (print_queue_resume(&user, snum, &errcode)) {
4084 errcode = WERR_OK;
4086 break;
4087 case PRINTER_CONTROL_PURGE:
4088 if (print_queue_purge(&user, snum, &errcode)) {
4089 errcode = WERR_OK;
4091 break;
4092 default:
4093 return WERR_UNKNOWN_LEVEL;
4096 return errcode;
4099 /********************************************************************
4100 * api_spoolss_abortprinter
4101 ********************************************************************/
4103 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4105 POLICY_HND *handle = &q_u->handle;
4107 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4110 /********************************************************************
4111 * called by spoolss_api_setprinter
4112 * when updating a printer description
4113 ********************************************************************/
4114 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4115 const SPOOL_PRINTER_INFO_LEVEL *info,
4116 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4118 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4119 struct current_user user;
4120 WERROR result;
4121 int snum;
4123 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4125 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4126 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4127 OUR_HANDLE(handle)));
4129 result = WERR_BADFID;
4130 goto done;
4133 /* NT seems to like setting the security descriptor even though
4134 nothing may have actually changed. This causes annoying
4135 dialog boxes when the user doesn't have permission to change
4136 the security descriptor. */
4138 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4140 if (DEBUGLEVEL >= 10) {
4141 SEC_ACL *the_acl;
4142 int i;
4144 the_acl = old_secdesc_ctr->sec->dacl;
4145 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4146 PRINTERNAME(snum), the_acl->num_aces));
4148 for (i = 0; i < the_acl->num_aces; i++) {
4149 fstring sid_str;
4151 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4153 DEBUG(10, ("%s 0x%08x\n", sid_str,
4154 the_acl->ace[i].info.mask));
4157 the_acl = secdesc_ctr->sec->dacl;
4159 if (the_acl) {
4160 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4161 PRINTERNAME(snum), the_acl->num_aces));
4163 for (i = 0; i < the_acl->num_aces; i++) {
4164 fstring sid_str;
4166 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4168 DEBUG(10, ("%s 0x%08x\n", sid_str,
4169 the_acl->ace[i].info.mask));
4171 } else {
4172 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4176 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4178 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4179 result = WERR_OK;
4180 goto done;
4183 /* Work out which user is performing the operation */
4185 get_current_user(&user, p);
4187 /* Check the user has permissions to change the security
4188 descriptor. By experimentation with two NT machines, the user
4189 requires Full Access to the printer to change security
4190 information. */
4192 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4193 result = WERR_ACCESS_DENIED;
4194 goto done;
4197 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4199 done:
4201 return result;
4204 /********************************************************************
4205 Do Samba sanity checks on a printer info struct.
4206 this has changed purpose: it now "canonicalises" printer
4207 info from a client rather than just checking it is correct
4208 ********************************************************************/
4210 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4212 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4213 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4215 /* we force some elements to "correct" values */
4216 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4217 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4218 global_myname, lp_servicename(snum));
4219 fstrcpy(info->sharename, lp_servicename(snum));
4220 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4221 | PRINTER_ATTRIBUTE_LOCAL \
4222 | PRINTER_ATTRIBUTE_RAW_ONLY \
4223 | PRINTER_ATTRIBUTE_QUEUED ;
4225 return True;
4228 /****************************************************************************
4229 ****************************************************************************/
4230 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4232 char *cmd = lp_addprinter_cmd();
4233 char **qlines;
4234 pstring command;
4235 pstring driverlocation;
4236 int numlines;
4237 int ret;
4238 int fd;
4240 /* build driver path... only 9X architecture is needed for legacy reasons */
4241 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4242 global_myname);
4243 /* change \ to \\ for the shell */
4244 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4246 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4247 cmd, printer->info_2->printername, printer->info_2->sharename,
4248 printer->info_2->portname, printer->info_2->drivername,
4249 printer->info_2->location, driverlocation);
4251 /* Convert script args to unix-codepage */
4252 dos_to_unix(command, True);
4253 DEBUG(10,("Running [%s]\n", command));
4254 ret = smbrun(command, &fd);
4255 DEBUGADD(10,("returned [%d]\n", ret));
4257 if ( ret != 0 ) {
4258 if (fd != -1)
4259 close(fd);
4260 return False;
4263 numlines = 0;
4264 /* Get lines and convert them back to dos-codepage */
4265 qlines = fd_lines_load(fd, &numlines, True);
4266 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4267 close(fd);
4269 if(numlines) {
4270 /* Set the portname to what the script says the portname should be. */
4271 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4272 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4274 /* Send SIGHUP to process group... is there a better way? */
4275 kill(0, SIGHUP);
4276 add_all_printers();
4279 file_lines_free(qlines);
4280 return True;
4283 /* Return true if two devicemodes are equal */
4285 #define DEVMODE_CHECK_INT(field) \
4286 if (d1->field != d2->field) { \
4287 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4288 d1->field, d2->field)); \
4289 return False; \
4292 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4294 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4296 if (!d1 ^ !d2) {
4297 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4298 return False; /* if either is exclusively NULL are not equal */
4301 if (!strequal(d1->devicename, d2->devicename)) {
4302 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4303 return False;
4306 if (!strequal(d1->formname, d2->formname)) {
4307 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4308 return False;
4311 DEVMODE_CHECK_INT(specversion);
4312 DEVMODE_CHECK_INT(driverversion);
4313 DEVMODE_CHECK_INT(driverextra);
4314 DEVMODE_CHECK_INT(orientation);
4315 DEVMODE_CHECK_INT(papersize);
4316 DEVMODE_CHECK_INT(paperlength);
4317 DEVMODE_CHECK_INT(paperwidth);
4318 DEVMODE_CHECK_INT(scale);
4319 DEVMODE_CHECK_INT(copies);
4320 DEVMODE_CHECK_INT(defaultsource);
4321 DEVMODE_CHECK_INT(printquality);
4322 DEVMODE_CHECK_INT(color);
4323 DEVMODE_CHECK_INT(duplex);
4324 DEVMODE_CHECK_INT(yresolution);
4325 DEVMODE_CHECK_INT(ttoption);
4326 DEVMODE_CHECK_INT(collate);
4327 DEVMODE_CHECK_INT(logpixels);
4329 DEVMODE_CHECK_INT(fields);
4330 DEVMODE_CHECK_INT(bitsperpel);
4331 DEVMODE_CHECK_INT(pelswidth);
4332 DEVMODE_CHECK_INT(pelsheight);
4333 DEVMODE_CHECK_INT(displayflags);
4334 DEVMODE_CHECK_INT(displayfrequency);
4335 DEVMODE_CHECK_INT(icmmethod);
4336 DEVMODE_CHECK_INT(icmintent);
4337 DEVMODE_CHECK_INT(mediatype);
4338 DEVMODE_CHECK_INT(dithertype);
4339 DEVMODE_CHECK_INT(reserved1);
4340 DEVMODE_CHECK_INT(reserved2);
4341 DEVMODE_CHECK_INT(panningwidth);
4342 DEVMODE_CHECK_INT(panningheight);
4344 /* compare the private data if it exists */
4345 if (!d1->driverextra && !d2->driverextra) goto equal;
4348 DEVMODE_CHECK_INT(driverextra);
4350 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4351 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4352 return False;
4355 equal:
4356 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4357 return True;
4360 /* Return true if two NT_PRINTER_PARAM structures are equal */
4362 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4363 NT_PRINTER_PARAM *p2)
4365 if (!p1 && !p2) goto equal;
4367 if ((!p1 && p2) || (p1 && !p2)) {
4368 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4369 return False;
4372 /* Compare lists of printer parameters */
4374 while (p1) {
4375 BOOL found = False;
4376 NT_PRINTER_PARAM *q = p1;
4378 /* Find the parameter in the second structure */
4380 while(q) {
4382 if (strequal(p1->value, q->value)) {
4384 if (p1->type != q->type) {
4385 DEBUG(10, ("nt_printer_param_equal():"
4386 "types for %s differ (%d != %d)\n",
4387 p1->value, p1->type,
4388 q->type));
4389 break;
4392 if (p1->data_len != q->data_len) {
4393 DEBUG(10, ("nt_printer_param_equal():"
4394 "len for %s differs (%d != %d)\n",
4395 p1->value, p1->data_len,
4396 q->data_len));
4397 break;
4400 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4401 found = True;
4402 } else {
4403 DEBUG(10, ("nt_printer_param_equal():"
4404 "data for %s differs\n", p1->value));
4407 break;
4410 q = q->next;
4413 if (!found) {
4414 DEBUG(10, ("nt_printer_param_equal(): param %s "
4415 "does not exist\n", p1->value));
4416 return False;
4419 p1 = p1->next;
4422 equal:
4424 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4425 return True;
4428 /********************************************************************
4429 * Called by update_printer when trying to work out whether to
4430 * actually update printer info.
4431 ********************************************************************/
4433 #define PI_CHECK_INT(field) \
4434 if (pi1->field != pi2->field) { \
4435 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4436 pi1->field, pi2->field)); \
4437 return False; \
4440 #define PI_CHECK_STR(field) \
4441 if (!strequal(pi1->field, pi2->field)) { \
4442 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4443 pi1->field, pi2->field)); \
4444 return False; \
4447 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4448 NT_PRINTER_INFO_LEVEL *p2)
4450 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4452 /* Trivial conditions */
4454 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4455 goto equal;
4458 if ((!p1 && p2) || (p1 && !p2) ||
4459 (!p1->info_2 && p2->info_2) ||
4460 (p1->info_2 && !p2->info_2)) {
4461 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4462 "differ\n"));
4463 return False;
4466 /* Compare two nt_printer_info_level structures. Don't compare
4467 status or cjobs as they seem to have something to do with the
4468 printer queue. */
4470 pi1 = p1->info_2;
4471 pi2 = p2->info_2;
4473 /* Don't check the attributes as we stomp on the value in
4474 check_printer_ok() anyway. */
4476 #if 0
4477 PI_CHECK_INT(attributes);
4478 #endif
4480 PI_CHECK_INT(priority);
4481 PI_CHECK_INT(default_priority);
4482 PI_CHECK_INT(starttime);
4483 PI_CHECK_INT(untiltime);
4484 PI_CHECK_INT(averageppm);
4486 /* Yuck - don't check the printername or servername as the
4487 add_a_printer() code plays games with them. You can't
4488 change the printername or the sharename through this interface
4489 in Samba. */
4491 PI_CHECK_STR(sharename);
4492 PI_CHECK_STR(portname);
4493 PI_CHECK_STR(drivername);
4494 PI_CHECK_STR(comment);
4495 PI_CHECK_STR(location);
4497 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4498 return False;
4501 PI_CHECK_STR(sepfile);
4502 PI_CHECK_STR(printprocessor);
4503 PI_CHECK_STR(datatype);
4504 PI_CHECK_STR(parameters);
4506 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4507 return False;
4510 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4511 return False;
4514 PI_CHECK_INT(changeid);
4515 PI_CHECK_INT(c_setprinter);
4516 PI_CHECK_INT(setuptime);
4518 equal:
4519 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4520 return True;
4523 /********************************************************************
4524 * called by spoolss_api_setprinter
4525 * when updating a printer description
4526 ********************************************************************/
4528 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4529 const SPOOL_PRINTER_INFO_LEVEL *info,
4530 DEVICEMODE *devmode)
4532 int snum;
4533 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4534 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4535 WERROR result;
4537 DEBUG(8,("update_printer\n"));
4539 result = WERR_OK;
4541 if (level!=2) {
4542 DEBUG(0,("Send a mail to samba@samba.org\n"));
4543 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4544 result = WERR_UNKNOWN_LEVEL;
4545 goto done;
4548 if (!Printer) {
4549 result = WERR_BADFID;
4550 goto done;
4553 if (!get_printer_snum(p, handle, &snum)) {
4554 result = WERR_BADFID;
4555 goto done;
4558 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4559 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4560 result = WERR_BADFID;
4561 goto done;
4564 DEBUGADD(8,("Converting info_2 struct\n"));
4567 * convert_printer_info converts the incoming
4568 * info from the client and overwrites the info
4569 * just read from the tdb in the pointer 'printer'.
4572 if (!convert_printer_info(info, printer, level)) {
4573 result = WERR_NOMEM;
4574 goto done;
4577 if (info->info_2->devmode_ptr != 0) {
4578 /* we have a valid devmode
4579 convert it and link it*/
4581 DEBUGADD(8,("Converting the devicemode struct\n"));
4582 if (!convert_devicemode(printer->info_2->printername, devmode,
4583 &printer->info_2->devmode)) {
4584 result = WERR_NOMEM;
4585 goto done;
4589 /* Do sanity check on the requested changes for Samba */
4591 if (!check_printer_ok(printer->info_2, snum)) {
4592 result = WERR_INVALID_PARAM;
4593 goto done;
4596 /* NT likes to call this function even though nothing has actually
4597 changed. Check this so the user doesn't end up with an
4598 annoying permission denied dialog box. */
4600 if (nt_printer_info_level_equal(printer, old_printer)) {
4601 DEBUG(3, ("printer info has not changed\n"));
4602 result = WERR_OK;
4603 goto done;
4606 /* Check calling user has permission to update printer description */
4608 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4609 DEBUG(3, ("printer property change denied by security "
4610 "descriptor\n"));
4611 result = WERR_ACCESS_DENIED;
4612 goto done;
4615 /* Call addprinter hook */
4617 if (*lp_addprinter_cmd()) {
4618 if ( !add_printer_hook(printer) ) {
4619 result = WERR_ACCESS_DENIED;
4620 goto done;
4624 /* Update printer info */
4625 result = add_a_printer(*printer, 2);
4627 done:
4628 free_a_printer(&printer, 2);
4629 free_a_printer(&old_printer, 2);
4631 srv_spoolss_sendnotify(p, handle);
4633 return result;
4636 /****************************************************************************
4637 ****************************************************************************/
4639 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4641 POLICY_HND *handle = &q_u->handle;
4642 uint32 level = q_u->level;
4643 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4644 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4645 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4646 uint32 command = q_u->command;
4648 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4650 if (!Printer) {
4651 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4652 return WERR_BADFID;
4655 /* check the level */
4656 switch (level) {
4657 case 0:
4658 return control_printer(handle, command, p);
4659 case 2:
4660 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4661 case 3:
4662 return update_printer_sec(handle, level, info, p,
4663 secdesc_ctr);
4664 default:
4665 return WERR_UNKNOWN_LEVEL;
4669 /****************************************************************************
4670 ****************************************************************************/
4672 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4674 POLICY_HND *handle = &q_u->handle;
4676 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4678 if (!Printer) {
4679 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4680 return WERR_BADFID;
4683 if (Printer->notify.client_connected==True)
4684 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4686 Printer->notify.flags=0;
4687 Printer->notify.options=0;
4688 Printer->notify.localmachine[0]='\0';
4689 Printer->notify.printerlocal=0;
4690 if (Printer->notify.option)
4691 free_spool_notify_option(&Printer->notify.option);
4692 Printer->notify.client_connected=False;
4694 return WERR_OK;
4697 /****************************************************************************
4698 ****************************************************************************/
4700 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4702 /* that's an [in out] buffer (despite appearences to the contrary) */
4703 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4705 r_u->needed = 0;
4706 return WERR_INVALID_PARAM; /* this is what a NT server
4707 returns for AddJob. AddJob
4708 must fail on non-local
4709 printers */
4712 /****************************************************************************
4713 ****************************************************************************/
4714 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4715 int position, int snum)
4717 pstring temp_name;
4719 struct tm *t;
4721 t=gmtime(&queue->time);
4722 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4724 job_info->jobid=queue->job;
4725 init_unistr(&job_info->printername, lp_servicename(snum));
4726 init_unistr(&job_info->machinename, temp_name);
4727 init_unistr(&job_info->username, queue->user);
4728 init_unistr(&job_info->document, queue->file);
4729 init_unistr(&job_info->datatype, "RAW");
4730 init_unistr(&job_info->text_status, "");
4731 job_info->status=nt_printj_status(queue->status);
4732 job_info->priority=queue->priority;
4733 job_info->position=position;
4734 job_info->totalpages=0;
4735 job_info->pagesprinted=0;
4737 make_systemtime(&job_info->submitted, t);
4740 /****************************************************************************
4741 ****************************************************************************/
4742 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4743 int position, int snum,
4744 NT_PRINTER_INFO_LEVEL *ntprinter)
4746 pstring temp_name;
4747 pstring chaine;
4748 struct tm *t;
4750 t=gmtime(&queue->time);
4751 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4753 job_info->jobid=queue->job;
4755 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4757 init_unistr(&job_info->printername, chaine);
4759 init_unistr(&job_info->machinename, temp_name);
4760 init_unistr(&job_info->username, queue->user);
4761 init_unistr(&job_info->document, queue->file);
4762 init_unistr(&job_info->notifyname, queue->user);
4763 init_unistr(&job_info->datatype, "RAW");
4764 init_unistr(&job_info->printprocessor, "winprint");
4765 init_unistr(&job_info->parameters, "");
4766 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4767 init_unistr(&job_info->text_status, "");
4769 /* and here the security descriptor */
4771 job_info->status=nt_printj_status(queue->status);
4772 job_info->priority=queue->priority;
4773 job_info->position=position;
4774 job_info->starttime=0;
4775 job_info->untiltime=0;
4776 job_info->totalpages=0;
4777 job_info->size=queue->size;
4778 make_systemtime(&(job_info->submitted), t);
4779 job_info->timeelapsed=0;
4780 job_info->pagesprinted=0;
4782 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4783 return False;
4786 return (True);
4789 /****************************************************************************
4790 Enumjobs at level 1.
4791 ****************************************************************************/
4792 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4793 NEW_BUFFER *buffer, uint32 offered,
4794 uint32 *needed, uint32 *returned)
4796 JOB_INFO_1 *info;
4797 int i;
4799 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4800 if (info==NULL) {
4801 SAFE_FREE(queue);
4802 *returned=0;
4803 return WERR_NOMEM;
4806 for (i=0; i<*returned; i++)
4807 fill_job_info_1(&info[i], &queue[i], i, snum);
4809 SAFE_FREE(queue);
4811 /* check the required size. */
4812 for (i=0; i<*returned; i++)
4813 (*needed) += spoolss_size_job_info_1(&info[i]);
4815 if (!alloc_buffer_size(buffer, *needed)) {
4816 SAFE_FREE(info);
4817 return WERR_INSUFFICIENT_BUFFER;
4820 /* fill the buffer with the structures */
4821 for (i=0; i<*returned; i++)
4822 smb_io_job_info_1("", buffer, &info[i], 0);
4824 /* clear memory */
4825 SAFE_FREE(info);
4827 if (*needed > offered) {
4828 *returned=0;
4829 return WERR_INSUFFICIENT_BUFFER;
4832 return WERR_OK;
4835 /****************************************************************************
4836 Enumjobs at level 2.
4837 ****************************************************************************/
4838 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4839 NEW_BUFFER *buffer, uint32 offered,
4840 uint32 *needed, uint32 *returned)
4842 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4843 JOB_INFO_2 *info;
4844 int i;
4845 WERROR result;
4847 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4848 if (info==NULL) {
4849 *returned=0;
4850 return WERR_NOMEM;
4853 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4854 if (!W_ERROR_IS_OK(result)) {
4855 *returned = 0;
4856 return result;
4859 for (i=0; i<*returned; i++)
4860 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4862 free_a_printer(&ntprinter, 2);
4863 SAFE_FREE(queue);
4865 /* check the required size. */
4866 for (i=0; i<*returned; i++)
4867 (*needed) += spoolss_size_job_info_2(&info[i]);
4869 if (!alloc_buffer_size(buffer, *needed)) {
4870 SAFE_FREE(info);
4871 return WERR_INSUFFICIENT_BUFFER;
4874 /* fill the buffer with the structures */
4875 for (i=0; i<*returned; i++)
4876 smb_io_job_info_2("", buffer, &info[i], 0);
4878 /* clear memory */
4879 for (i = 0; i < *returned; i++)
4880 free_job_info_2(&info[i]);
4882 SAFE_FREE(info);
4884 if (*needed > offered) {
4885 *returned=0;
4886 return WERR_INSUFFICIENT_BUFFER;
4889 return WERR_OK;
4892 /****************************************************************************
4893 Enumjobs.
4894 ****************************************************************************/
4896 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4898 POLICY_HND *handle = &q_u->handle;
4899 /* uint32 firstjob = q_u->firstjob; - notused. */
4900 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4901 uint32 level = q_u->level;
4902 NEW_BUFFER *buffer = NULL;
4903 uint32 offered = q_u->offered;
4904 uint32 *needed = &r_u->needed;
4905 uint32 *returned = &r_u->returned;
4907 int snum;
4908 print_status_struct prt_status;
4909 print_queue_struct *queue=NULL;
4911 /* that's an [in out] buffer */
4912 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4913 buffer = r_u->buffer;
4915 DEBUG(4,("_spoolss_enumjobs\n"));
4917 *needed=0;
4918 *returned=0;
4920 if (!get_printer_snum(p, handle, &snum))
4921 return WERR_BADFID;
4923 *returned = print_queue_status(snum, &queue, &prt_status);
4924 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4926 if (*returned == 0) {
4927 SAFE_FREE(queue);
4928 return WERR_OK;
4931 switch (level) {
4932 case 1:
4933 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4934 case 2:
4935 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4936 default:
4937 SAFE_FREE(queue);
4938 *returned=0;
4939 return WERR_UNKNOWN_LEVEL;
4943 /****************************************************************************
4944 ****************************************************************************/
4946 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4948 return WERR_OK;
4951 /****************************************************************************
4952 ****************************************************************************/
4954 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4956 POLICY_HND *handle = &q_u->handle;
4957 uint32 jobid = q_u->jobid;
4958 /* uint32 level = q_u->level; - notused. */
4959 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4960 uint32 command = q_u->command;
4962 struct current_user user;
4963 int snum;
4964 WERROR errcode = WERR_BADFUNC;
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,True);
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,True);
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 = (uint32)dos_PutUniCode((char *)*out_value, "", in_value_len, True);
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 = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
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 *needed=0;
6756 if (!get_printer_snum(p, handle, &snum))
6757 return WERR_BADFID;
6759 count = print_queue_status(snum, &queue, &prt_status);
6761 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6762 count, prt_status.status, prt_status.message));
6764 switch (level) {
6765 case 1:
6766 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6767 case 2:
6768 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6769 default:
6770 SAFE_FREE(queue);
6771 return WERR_UNKNOWN_LEVEL;
6775 /********************************************************************
6776 * spoolss_getprinterdataex
6777 ********************************************************************/
6779 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6781 POLICY_HND *handle = &q_u->handle;
6782 uint32 in_size = q_u->size;
6783 uint32 *type = &r_u->type;
6784 uint32 *out_size = &r_u->size;
6785 uint8 **data = &r_u->data;
6786 uint32 *needed = &r_u->needed;
6788 fstring key, value;
6789 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6790 BOOL found = False;
6792 DEBUG(4,("_spoolss_getprinterdataex\n"));
6794 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6795 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6797 /* in case of problem, return some default values */
6798 *needed=0;
6799 *type=0;
6800 *out_size=0;
6803 if (!Printer) {
6804 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6805 return WERR_NOMEM;
6806 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6807 return WERR_BADFID;
6811 /* Is the handle to a printer or to the server? */
6813 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6815 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6816 return WERR_INVALID_PARAM;
6818 else
6821 * From MSDN documentation of GetPrinterDataEx: pass request
6822 * to GetPrinterData if key is "PrinterDriverData". This is
6823 * the only key we really support. Other keys to implement:
6824 * (a) DsDriver
6825 * (b) DsSpooler
6826 * (c) PnPData
6829 if (strcmp(key, "PrinterDriverData") != 0)
6830 return WERR_INVALID_PARAM;
6832 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6833 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
6834 type, data, needed, in_size);
6838 if (!found) {
6839 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6841 /* reply this param doesn't exist */
6842 if (*out_size) {
6843 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6844 return WERR_NOMEM;
6845 } else {
6846 *data = NULL;
6849 return WERR_INVALID_PARAM;
6852 if (*needed > *out_size)
6853 return WERR_MORE_DATA;
6854 else
6855 return WERR_OK;
6858 /********************************************************************
6859 * spoolss_setprinterdata
6860 ********************************************************************/
6862 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6864 SPOOL_Q_SETPRINTERDATA q_u_local;
6865 SPOOL_R_SETPRINTERDATA r_u_local;
6866 fstring key;
6868 DEBUG(4,("_spoolss_setprinterdataex\n"));
6870 /* From MSDN documentation of SetPrinterDataEx: pass request to
6871 SetPrinterData if key is "PrinterDriverData" */
6873 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6875 if (strcmp(key, "PrinterDriverData") == 0)
6876 return WERR_INVALID_PARAM;
6878 ZERO_STRUCT(q_u_local);
6879 ZERO_STRUCT(r_u_local);
6881 /* make a copy to call _spoolss_setprinterdata() */
6883 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
6884 copy_unistr2(&q_u_local.value, &q_u->value);
6885 q_u_local.type = q_u->type;
6886 q_u_local.max_len = q_u->max_len;
6887 q_u_local.data = q_u->data;
6888 q_u_local.real_len = q_u->real_len;
6889 q_u_local.numeric_data = q_u->numeric_data;
6891 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
6894 /********************************************************************
6895 * spoolss_enumprinterkey
6896 ********************************************************************/
6898 /* constants for EnumPrinterKey() */
6899 #define ENUMERATED_KEY_SIZE 19
6901 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
6903 fstring key;
6904 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
6905 char* ptr = NULL;
6906 int i;
6907 char *PrinterKey = "PrinterDriverData";
6909 DEBUG(4,("_spoolss_enumprinterkey\n"));
6911 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6914 * we only support enumating all keys (key == "")
6915 * Of course, the only key we support is the "PrinterDriverData"
6916 * key
6918 if (strlen(key) == 0)
6920 r_u->needed = ENUMERATED_KEY_SIZE *2;
6921 if (q_u->size < r_u->needed)
6922 return WERR_MORE_DATA;
6924 ptr = PrinterKey;
6925 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
6927 enumkeys[i] = (uint16)(*ptr);
6928 ptr++;
6931 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
6932 return WERR_BADFILE;
6934 return WERR_OK;
6937 /* The "PrinterDriverData" key should have no subkeys */
6938 if (strcmp(key, PrinterKey) == 0)
6940 r_u-> needed = 2;
6941 if (q_u->size < r_u->needed)
6942 return WERR_MORE_DATA;
6943 enumkeys[0] = 0x0;
6944 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
6945 return WERR_BADFILE;
6947 return WERR_OK;
6951 /* The return value for an unknown key is documented in MSDN
6952 EnumPrinterKey description */
6953 return WERR_BADFILE;
6956 /********************************************************************
6957 * spoolss_enumprinterdataex
6958 ********************************************************************/
6960 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
6962 POLICY_HND *handle = &q_u->handle;
6963 uint32 in_size = q_u->size;
6964 uint32 num_entries,
6965 needed;
6966 NT_PRINTER_INFO_LEVEL *printer = NULL;
6967 PRINTER_ENUM_VALUES *enum_values = NULL;
6968 fstring key, value;
6969 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6970 int snum;
6971 uint32 param_index,
6972 data_len,
6973 type;
6974 WERROR result;
6975 uint8 *data=NULL;
6978 DEBUG(4,("_spoolss_enumprinterdataex\n"));
6980 if (!Printer) {
6981 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6982 return WERR_BADFID;
6987 * The only key we support is "PrinterDriverData". This should return
6988 > an array of all the key/value pairs returned by EnumPrinterDataSee
6989 * _spoolss_getprinterdataex() for details --jerry
6992 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6993 if (strcmp(key, "PrinterDriverData") != 0)
6995 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
6996 return WERR_INVALID_PARAM;
7000 if (!get_printer_snum(p,handle, &snum))
7001 return WERR_BADFID;
7003 ZERO_STRUCT(printer);
7004 result = get_a_printer(&printer, 2, lp_servicename(snum));
7005 if (!W_ERROR_IS_OK(result))
7006 return result;
7010 * loop through all params and build the array to pass
7011 * back to the client
7013 result = WERR_OK;
7014 param_index = 0;
7015 needed = 0;
7016 num_entries = 0;
7018 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7020 PRINTER_ENUM_VALUES *ptr;
7021 uint32 add_len = 0;
7023 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7025 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7027 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7028 result = WERR_NOMEM;
7029 goto done;
7031 enum_values = ptr;
7033 /* copy the data */
7034 init_unistr(&enum_values[num_entries].valuename, value);
7035 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7036 enum_values[num_entries].type = type;
7039 * NULL terminate REG_SZ
7040 * FIXME!!! We should not be correctly problems in the way
7041 * we store PrinterData here. Need to investogate
7042 * SetPrinterData[Ex] --jerry
7045 if (type == REG_SZ) {
7046 /* fix alignment if the string was stored
7047 in a bizarre fashion */
7048 if ((data_len % 2) == 0)
7049 add_len = 2;
7050 else
7051 add_len = data_len % 2;
7054 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7055 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7056 result = WERR_NOMEM;
7057 goto done;
7059 memcpy(enum_values[num_entries].data, data, data_len);
7060 enum_values[num_entries].data_len = data_len + add_len;
7062 /* keep track of the size of the array in bytes */
7064 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7066 num_entries++;
7067 param_index++;
7070 r_u->needed = needed;
7071 r_u->returned = num_entries;
7073 if (needed > in_size) {
7074 result = WERR_MORE_DATA;
7075 goto done;
7078 /* copy data into the reply */
7080 r_u->ctr.size = r_u->needed;
7081 r_u->ctr.size_of_array = r_u->returned;
7082 r_u->ctr.values = enum_values;
7086 done:
7087 free_a_printer(&printer, 2);
7089 return result;