merge from appliance_head
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobcd47f6a1307c939ab096ae2bf1981b023e13bee1
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.
10 * Copyright (C) Tim Potter 2001.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "includes.h"
32 extern pstring global_myname;
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
36 #endif
38 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
39 #define PRINTER_HANDLE_IS_PRINTER 0
40 #define PRINTER_HANDLE_IS_PRINTSERVER 1
42 struct table_node {
43 char *long_archi;
44 char *short_archi;
45 int version;
49 /* structure to store the printer handles */
50 /* and a reference to what it's pointing to */
51 /* and the notify info asked about */
52 /* that's the central struct */
53 typedef struct _Printer{
54 BOOL document_started;
55 BOOL page_started;
56 int jobid; /* jobid in printing backend */
57 BOOL printer_type;
58 union {
59 fstring handlename;
60 fstring printerservername;
61 } dev;
62 uint32 type;
63 uint32 access;
64 struct {
65 uint32 flags;
66 uint32 options;
67 fstring localmachine;
68 uint32 printerlocal;
69 SPOOL_NOTIFY_OPTION *option;
70 POLICY_HND client_hnd;
71 uint32 client_connected;
72 } notify;
73 struct {
74 fstring machine;
75 fstring user;
76 } client;
77 } Printer_entry;
79 typedef struct _counter_printer_0 {
80 ubi_dlNode Next;
81 ubi_dlNode Prev;
83 int snum;
84 uint32 counter;
85 } counter_printer_0;
87 static ubi_dlList counter_list;
89 static struct cli_state cli;
90 static uint32 smb_connections=0;
92 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
94 /* translate between internal status numbers and NT status numbers */
95 static int nt_printj_status(int v)
97 switch (v) {
98 case LPQ_QUEUED:
99 return 0;
100 case LPQ_PAUSED:
101 return JOB_STATUS_PAUSED;
102 case LPQ_SPOOLING:
103 return JOB_STATUS_SPOOLING;
104 case LPQ_PRINTING:
105 return JOB_STATUS_PRINTING;
106 case LPQ_ERROR:
107 return JOB_STATUS_ERROR;
108 case LPQ_DELETING:
109 return JOB_STATUS_DELETING;
110 case LPQ_OFFLINE:
111 return JOB_STATUS_OFFLINE;
112 case LPQ_PAPEROUT:
113 return JOB_STATUS_PAPEROUT;
114 case LPQ_PRINTED:
115 return JOB_STATUS_PRINTED;
116 case LPQ_DELETED:
117 return JOB_STATUS_DELETED;
118 case LPQ_BLOCKED:
119 return JOB_STATUS_BLOCKED;
120 case LPQ_USER_INTERVENTION:
121 return JOB_STATUS_USER_INTERVENTION;
123 return 0;
126 static int nt_printq_status(int v)
128 switch (v) {
129 case LPQ_PAUSED:
130 return PRINTER_STATUS_PAUSED;
131 case LPQ_QUEUED:
132 case LPQ_SPOOLING:
133 case LPQ_PRINTING:
134 return 0;
136 return 0;
139 /****************************************************************************
140 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
141 ****************************************************************************/
143 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
145 if (*pp == NULL)
146 return;
148 SAFE_FREE((*pp)->ctr.type);
149 SAFE_FREE(*pp);
152 /***************************************************************************
153 Disconnect from the client
154 ****************************************************************************/
156 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
158 WERROR status;
160 /* weird if the test succeds !!! */
161 if (smb_connections==0) {
162 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163 return;
166 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
167 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
169 /* if it's the last connection, deconnect the IPC$ share */
170 if (smb_connections==1) {
171 if(!spoolss_disconnect_from_client(&cli))
172 return;
174 message_deregister(MSG_PRINTER_NOTIFY);
177 smb_connections--;
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True)
189 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
191 Printer->notify.flags=0;
192 Printer->notify.options=0;
193 Printer->notify.localmachine[0]='\0';
194 Printer->notify.printerlocal=0;
195 free_spool_notify_option(&Printer->notify.option);
196 Printer->notify.option=NULL;
197 Printer->notify.client_connected=False;
199 SAFE_FREE(Printer);
202 /****************************************************************************
203 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
204 ****************************************************************************/
206 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
208 SPOOL_NOTIFY_OPTION *new_sp = NULL;
210 if (!sp)
211 return NULL;
213 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
214 if (!new_sp)
215 return NULL;
217 *new_sp = *sp;
219 if (sp->ctr.count) {
220 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
222 if (!new_sp->ctr.type) {
223 SAFE_FREE(new_sp);
224 return NULL;
228 return new_sp;
231 /****************************************************************************
232 find printer index by handle
233 ****************************************************************************/
235 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
237 Printer_entry *find_printer = NULL;
239 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
240 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
241 return NULL;
244 return find_printer;
247 /****************************************************************************
248 close printer index by handle
249 ****************************************************************************/
251 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
253 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
255 if (!Printer) {
256 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
257 return False;
260 close_policy_hnd(p, hnd);
262 return True;
265 /****************************************************************************
266 delete a printer given a handle
267 ****************************************************************************/
268 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
270 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
272 if (!Printer) {
273 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
274 return WERR_BADFID;
277 if (del_a_printer(Printer->dev.handlename) != 0) {
278 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
279 return WERR_BADFID;
282 /* Check calling user has permission to delete printer. Note that
283 since we set the snum parameter to -1 only administrators can
284 delete the printer. This stops people with the Full Control
285 permission from deleting the printer. */
287 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
288 DEBUG(3, ("printer delete denied by security descriptor\n"));
289 return WERR_ACCESS_DENIED;
292 if (*lp_deleteprinter_cmd()) {
294 char *cmd = lp_deleteprinter_cmd();
295 pstring command;
296 int ret;
297 int i;
299 /* Printer->dev.handlename equals portname equals sharename */
300 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
301 Printer->dev.handlename);
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_m(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_m(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_m(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 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
965 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
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 */
1373 if(!spoolss_connect_to_client(&cli, unix_printer))
1374 return False;
1375 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1379 smb_connections++;
1381 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1382 return False;
1384 return True;
1387 /********************************************************************
1388 * _spoolss_rffpcnex
1389 * ReplyFindFirstPrinterChangeNotifyEx
1391 * jfmxxxx: before replying OK: status=0
1392 * should do a rpc call to the workstation asking ReplyOpenPrinter
1393 * have to code it, later.
1395 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1396 * called from api_spoolss_rffpcnex
1397 ********************************************************************/
1399 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1401 POLICY_HND *handle = &q_u->handle;
1402 uint32 flags = q_u->flags;
1403 uint32 options = q_u->options;
1404 UNISTR2 *localmachine = &q_u->localmachine;
1405 uint32 printerlocal = q_u->printerlocal;
1406 SPOOL_NOTIFY_OPTION *option = q_u->option;
1408 /* store the notify value in the printer struct */
1410 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1412 if (!Printer) {
1413 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1414 return WERR_BADFID;
1417 Printer->notify.flags=flags;
1418 Printer->notify.options=options;
1419 Printer->notify.printerlocal=printerlocal;
1421 if (Printer->notify.option)
1422 free_spool_notify_option(&Printer->notify.option);
1424 Printer->notify.option=dup_spool_notify_option(option);
1426 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1428 /* connect to the client machine and send a ReplyOpenPrinter */
1429 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1430 Printer->notify.printerlocal, 1,
1431 &Printer->notify.client_hnd))
1432 Printer->notify.client_connected=True;
1434 return WERR_OK;
1437 /*******************************************************************
1438 * fill a notify_info_data with the servername
1439 ********************************************************************/
1441 static void spoolss_notify_server_name(int snum,
1442 SPOOL_NOTIFY_INFO_DATA *data,
1443 print_queue_struct *queue,
1444 NT_PRINTER_INFO_LEVEL *printer,
1445 TALLOC_CTX *mem_ctx)
1447 pstring temp_name, temp;
1448 uint32 len;
1450 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1452 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1454 data->notify_data.data.length = len / 2;
1455 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1457 if (!data->notify_data.data.string) {
1458 data->notify_data.data.length = 0;
1459 return;
1462 memcpy(data->notify_data.data.string, temp, len);
1465 /*******************************************************************
1466 * fill a notify_info_data with the printername (not including the servername).
1467 ********************************************************************/
1468 static void spoolss_notify_printer_name(int snum,
1469 SPOOL_NOTIFY_INFO_DATA *data,
1470 print_queue_struct *queue,
1471 NT_PRINTER_INFO_LEVEL *printer,
1472 TALLOC_CTX *mem_ctx)
1474 pstring temp;
1475 uint32 len;
1477 /* the notify name should not contain the \\server\ part */
1478 char *p = strrchr_m(printer->info_2->printername, '\\');
1480 if (!p) {
1481 p = printer->info_2->printername;
1482 } else {
1483 p++;
1486 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1487 data->notify_data.data.length = len / 2;
1488 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1490 if (!data->notify_data.data.string) {
1491 data->notify_data.data.length = 0;
1492 return;
1495 memcpy(data->notify_data.data.string, temp, len);
1498 /*******************************************************************
1499 * fill a notify_info_data with the servicename
1500 ********************************************************************/
1501 static void spoolss_notify_share_name(int snum,
1502 SPOOL_NOTIFY_INFO_DATA *data,
1503 print_queue_struct *queue,
1504 NT_PRINTER_INFO_LEVEL *printer,
1505 TALLOC_CTX *mem_ctx)
1507 pstring temp;
1508 uint32 len;
1510 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1512 data->notify_data.data.length = len / 2;
1513 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1515 if (!data->notify_data.data.string) {
1516 data->notify_data.data.length = 0;
1517 return;
1520 memcpy(data->notify_data.data.string, temp, len);
1523 /*******************************************************************
1524 * fill a notify_info_data with the port name
1525 ********************************************************************/
1526 static void spoolss_notify_port_name(int snum,
1527 SPOOL_NOTIFY_INFO_DATA *data,
1528 print_queue_struct *queue,
1529 NT_PRINTER_INFO_LEVEL *printer,
1530 TALLOC_CTX *mem_ctx)
1532 pstring temp;
1533 uint32 len;
1535 /* even if it's strange, that's consistant in all the code */
1537 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1539 data->notify_data.data.length = len / 2;
1540 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1542 if (!data->notify_data.data.string) {
1543 data->notify_data.data.length = 0;
1544 return;
1547 memcpy(data->notify_data.data.string, temp, len);
1550 /*******************************************************************
1551 * fill a notify_info_data with the printername
1552 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1553 * but it doesn't exist, have to see what to do
1554 ********************************************************************/
1555 static void spoolss_notify_driver_name(int snum,
1556 SPOOL_NOTIFY_INFO_DATA *data,
1557 print_queue_struct *queue,
1558 NT_PRINTER_INFO_LEVEL *printer,
1559 TALLOC_CTX *mem_ctx)
1561 pstring temp;
1562 uint32 len;
1564 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1565 data->notify_data.data.length = len / 2;
1566 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1568 if (!data->notify_data.data.string) {
1569 data->notify_data.data.length = 0;
1570 return;
1573 memcpy(data->notify_data.data.string, temp, len);
1576 /*******************************************************************
1577 * fill a notify_info_data with the comment
1578 ********************************************************************/
1579 static void spoolss_notify_comment(int snum,
1580 SPOOL_NOTIFY_INFO_DATA *data,
1581 print_queue_struct *queue,
1582 NT_PRINTER_INFO_LEVEL *printer,
1583 TALLOC_CTX *mem_ctx)
1585 pstring temp;
1586 uint32 len;
1588 if (*printer->info_2->comment == '\0')
1589 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1591 else
1592 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1594 data->notify_data.data.length = len / 2;
1595 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1597 if (!data->notify_data.data.string) {
1598 data->notify_data.data.length = 0;
1599 return;
1602 memcpy(data->notify_data.data.string, temp, len);
1605 /*******************************************************************
1606 * fill a notify_info_data with the comment
1607 * jfm:xxxx incorrect, have to create a new smb.conf option
1608 * location = "Room 1, floor 2, building 3"
1609 ********************************************************************/
1610 static void spoolss_notify_location(int snum,
1611 SPOOL_NOTIFY_INFO_DATA *data,
1612 print_queue_struct *queue,
1613 NT_PRINTER_INFO_LEVEL *printer,
1614 TALLOC_CTX *mem_ctx)
1616 pstring temp;
1617 uint32 len;
1619 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1621 data->notify_data.data.length = len / 2;
1622 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1624 if (!data->notify_data.data.string) {
1625 data->notify_data.data.length = 0;
1626 return;
1629 memcpy(data->notify_data.data.string, temp, len);
1632 /*******************************************************************
1633 * fill a notify_info_data with the device mode
1634 * jfm:xxxx don't to it for know but that's a real problem !!!
1635 ********************************************************************/
1636 static void spoolss_notify_devmode(int snum,
1637 SPOOL_NOTIFY_INFO_DATA *data,
1638 print_queue_struct *queue,
1639 NT_PRINTER_INFO_LEVEL *printer,
1640 TALLOC_CTX *mem_ctx)
1644 /*******************************************************************
1645 * fill a notify_info_data with the separator file name
1646 * jfm:xxxx just return no file could add an option to smb.conf
1647 * separator file = "separator.txt"
1648 ********************************************************************/
1649 static void spoolss_notify_sepfile(int snum,
1650 SPOOL_NOTIFY_INFO_DATA *data,
1651 print_queue_struct *queue,
1652 NT_PRINTER_INFO_LEVEL *printer,
1653 TALLOC_CTX *mem_ctx)
1655 pstring temp;
1656 uint32 len;
1658 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1660 data->notify_data.data.length = len / 2;
1661 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1663 if (!data->notify_data.data.string) {
1664 data->notify_data.data.length = 0;
1665 return;
1668 memcpy(data->notify_data.data.string, temp, len);
1671 /*******************************************************************
1672 * fill a notify_info_data with the print processor
1673 * jfm:xxxx return always winprint to indicate we don't do anything to it
1674 ********************************************************************/
1675 static void spoolss_notify_print_processor(int snum,
1676 SPOOL_NOTIFY_INFO_DATA *data,
1677 print_queue_struct *queue,
1678 NT_PRINTER_INFO_LEVEL *printer,
1679 TALLOC_CTX *mem_ctx)
1681 pstring temp;
1682 uint32 len;
1684 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1686 data->notify_data.data.length = len / 2;
1687 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1689 if (!data->notify_data.data.string) {
1690 data->notify_data.data.length = 0;
1691 return;
1694 memcpy(data->notify_data.data.string, temp, len);
1697 /*******************************************************************
1698 * fill a notify_info_data with the print processor options
1699 * jfm:xxxx send an empty string
1700 ********************************************************************/
1701 static void spoolss_notify_parameters(int snum,
1702 SPOOL_NOTIFY_INFO_DATA *data,
1703 print_queue_struct *queue,
1704 NT_PRINTER_INFO_LEVEL *printer,
1705 TALLOC_CTX *mem_ctx)
1707 pstring temp;
1708 uint32 len;
1710 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1712 data->notify_data.data.length = len / 2;
1713 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1715 if (!data->notify_data.data.string) {
1716 data->notify_data.data.length = 0;
1717 return;
1720 memcpy(data->notify_data.data.string, temp, len);
1723 /*******************************************************************
1724 * fill a notify_info_data with the data type
1725 * jfm:xxxx always send RAW as data type
1726 ********************************************************************/
1727 static void spoolss_notify_datatype(int snum,
1728 SPOOL_NOTIFY_INFO_DATA *data,
1729 print_queue_struct *queue,
1730 NT_PRINTER_INFO_LEVEL *printer,
1731 TALLOC_CTX *mem_ctx)
1733 pstring temp;
1734 uint32 len;
1736 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
1738 data->notify_data.data.length = len / 2;
1739 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1741 if (!data->notify_data.data.string) {
1742 data->notify_data.data.length = 0;
1743 return;
1746 memcpy(data->notify_data.data.string, temp, len);
1749 /*******************************************************************
1750 * fill a notify_info_data with the security descriptor
1751 * jfm:xxxx send an null pointer to say no security desc
1752 * have to implement security before !
1753 ********************************************************************/
1754 static void spoolss_notify_security_desc(int snum,
1755 SPOOL_NOTIFY_INFO_DATA *data,
1756 print_queue_struct *queue,
1757 NT_PRINTER_INFO_LEVEL *printer,
1758 TALLOC_CTX *mem_ctx)
1760 data->notify_data.data.length=0;
1761 data->notify_data.data.string = NULL;
1764 /*******************************************************************
1765 * fill a notify_info_data with the attributes
1766 * jfm:xxxx a samba printer is always shared
1767 ********************************************************************/
1768 static void spoolss_notify_attributes(int snum,
1769 SPOOL_NOTIFY_INFO_DATA *data,
1770 print_queue_struct *queue,
1771 NT_PRINTER_INFO_LEVEL *printer,
1772 TALLOC_CTX *mem_ctx)
1774 data->notify_data.value[0] = printer->info_2->attributes;
1775 data->notify_data.value[1] = 0;
1778 /*******************************************************************
1779 * fill a notify_info_data with the priority
1780 ********************************************************************/
1781 static void spoolss_notify_priority(int snum,
1782 SPOOL_NOTIFY_INFO_DATA *data,
1783 print_queue_struct *queue,
1784 NT_PRINTER_INFO_LEVEL *printer,
1785 TALLOC_CTX *mem_ctx)
1787 data->notify_data.value[0] = printer->info_2->priority;
1788 data->notify_data.value[1] = 0;
1791 /*******************************************************************
1792 * fill a notify_info_data with the default priority
1793 ********************************************************************/
1794 static void spoolss_notify_default_priority(int snum,
1795 SPOOL_NOTIFY_INFO_DATA *data,
1796 print_queue_struct *queue,
1797 NT_PRINTER_INFO_LEVEL *printer,
1798 TALLOC_CTX *mem_ctx)
1800 data->notify_data.value[0] = printer->info_2->default_priority;
1801 data->notify_data.value[1] = 0;
1804 /*******************************************************************
1805 * fill a notify_info_data with the start time
1806 ********************************************************************/
1807 static void spoolss_notify_start_time(int snum,
1808 SPOOL_NOTIFY_INFO_DATA *data,
1809 print_queue_struct *queue,
1810 NT_PRINTER_INFO_LEVEL *printer,
1811 TALLOC_CTX *mem_ctx)
1813 data->notify_data.value[0] = printer->info_2->starttime;
1814 data->notify_data.value[1] = 0;
1817 /*******************************************************************
1818 * fill a notify_info_data with the until time
1819 ********************************************************************/
1820 static void spoolss_notify_until_time(int snum,
1821 SPOOL_NOTIFY_INFO_DATA *data,
1822 print_queue_struct *queue,
1823 NT_PRINTER_INFO_LEVEL *printer,
1824 TALLOC_CTX *mem_ctx)
1826 data->notify_data.value[0] = printer->info_2->untiltime;
1827 data->notify_data.value[1] = 0;
1830 /*******************************************************************
1831 * fill a notify_info_data with the status
1832 ********************************************************************/
1833 static void spoolss_notify_status(int snum,
1834 SPOOL_NOTIFY_INFO_DATA *data,
1835 print_queue_struct *queue,
1836 NT_PRINTER_INFO_LEVEL *printer,
1837 TALLOC_CTX *mem_ctx)
1839 print_status_struct status;
1841 print_queue_length(snum, &status);
1842 data->notify_data.value[0]=(uint32) status.status;
1843 data->notify_data.value[1] = 0;
1846 /*******************************************************************
1847 * fill a notify_info_data with the number of jobs queued
1848 ********************************************************************/
1849 static void spoolss_notify_cjobs(int snum,
1850 SPOOL_NOTIFY_INFO_DATA *data,
1851 print_queue_struct *queue,
1852 NT_PRINTER_INFO_LEVEL *printer,
1853 TALLOC_CTX *mem_ctx)
1855 data->notify_data.value[0] = print_queue_length(snum, NULL);
1856 data->notify_data.value[1] = 0;
1859 /*******************************************************************
1860 * fill a notify_info_data with the average ppm
1861 ********************************************************************/
1862 static void spoolss_notify_average_ppm(int snum,
1863 SPOOL_NOTIFY_INFO_DATA *data,
1864 print_queue_struct *queue,
1865 NT_PRINTER_INFO_LEVEL *printer,
1866 TALLOC_CTX *mem_ctx)
1868 /* always respond 8 pages per minutes */
1869 /* a little hard ! */
1870 data->notify_data.value[0] = printer->info_2->averageppm;
1871 data->notify_data.value[1] = 0;
1874 /*******************************************************************
1875 * fill a notify_info_data with username
1876 ********************************************************************/
1877 static void spoolss_notify_username(int snum,
1878 SPOOL_NOTIFY_INFO_DATA *data,
1879 print_queue_struct *queue,
1880 NT_PRINTER_INFO_LEVEL *printer,
1881 TALLOC_CTX *mem_ctx)
1883 pstring temp;
1884 uint32 len;
1886 len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
1889 data->notify_data.data.length = len / 2;
1890 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1892 if (!data->notify_data.data.string) {
1893 data->notify_data.data.length = 0;
1894 return;
1897 memcpy(data->notify_data.data.string, temp, len);
1900 /*******************************************************************
1901 * fill a notify_info_data with job status
1902 ********************************************************************/
1903 static void spoolss_notify_job_status(int snum,
1904 SPOOL_NOTIFY_INFO_DATA *data,
1905 print_queue_struct *queue,
1906 NT_PRINTER_INFO_LEVEL *printer,
1907 TALLOC_CTX *mem_ctx)
1909 data->notify_data.value[0]=nt_printj_status(queue->status);
1910 data->notify_data.value[1] = 0;
1913 /*******************************************************************
1914 * fill a notify_info_data with job name
1915 ********************************************************************/
1916 static void spoolss_notify_job_name(int snum,
1917 SPOOL_NOTIFY_INFO_DATA *data,
1918 print_queue_struct *queue,
1919 NT_PRINTER_INFO_LEVEL *printer,
1920 TALLOC_CTX *mem_ctx)
1922 pstring temp;
1923 uint32 len;
1925 len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
1927 data->notify_data.data.length = len / 2;
1928 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1930 if (!data->notify_data.data.string) {
1931 data->notify_data.data.length = 0;
1932 return;
1935 memcpy(data->notify_data.data.string, temp, len);
1938 /*******************************************************************
1939 * fill a notify_info_data with job status
1940 ********************************************************************/
1941 static void spoolss_notify_job_status_string(int snum,
1942 SPOOL_NOTIFY_INFO_DATA *data,
1943 print_queue_struct *queue,
1944 NT_PRINTER_INFO_LEVEL *printer,
1945 TALLOC_CTX *mem_ctx)
1948 * Now we're returning job status codes we just return a "" here. JRA.
1951 char *p = "";
1952 pstring temp;
1953 uint32 len;
1955 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1956 p = "unknown";
1958 switch (queue->status) {
1959 case LPQ_QUEUED:
1960 p = "Queued";
1961 break;
1962 case LPQ_PAUSED:
1963 p = ""; /* NT provides the paused string */
1964 break;
1965 case LPQ_SPOOLING:
1966 p = "Spooling";
1967 break;
1968 case LPQ_PRINTING:
1969 p = "Printing";
1970 break;
1972 #endif /* NO LONGER NEEDED. */
1974 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
1976 data->notify_data.data.length = len / 2;
1977 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1979 if (!data->notify_data.data.string) {
1980 data->notify_data.data.length = 0;
1981 return;
1984 memcpy(data->notify_data.data.string, temp, len);
1987 /*******************************************************************
1988 * fill a notify_info_data with job time
1989 ********************************************************************/
1990 static void spoolss_notify_job_time(int snum,
1991 SPOOL_NOTIFY_INFO_DATA *data,
1992 print_queue_struct *queue,
1993 NT_PRINTER_INFO_LEVEL *printer,
1994 TALLOC_CTX *mem_ctx)
1996 data->notify_data.value[0]=0x0;
1997 data->notify_data.value[1]=0;
2000 /*******************************************************************
2001 * fill a notify_info_data with job size
2002 ********************************************************************/
2003 static void spoolss_notify_job_size(int snum,
2004 SPOOL_NOTIFY_INFO_DATA *data,
2005 print_queue_struct *queue,
2006 NT_PRINTER_INFO_LEVEL *printer,
2007 TALLOC_CTX *mem_ctx)
2009 data->notify_data.value[0]=queue->size;
2010 data->notify_data.value[1]=0;
2013 /*******************************************************************
2014 * fill a notify_info_data with job position
2015 ********************************************************************/
2016 static void spoolss_notify_job_position(int snum,
2017 SPOOL_NOTIFY_INFO_DATA *data,
2018 print_queue_struct *queue,
2019 NT_PRINTER_INFO_LEVEL *printer,
2020 TALLOC_CTX *mem_ctx)
2022 data->notify_data.value[0]=queue->job;
2023 data->notify_data.value[1]=0;
2026 /*******************************************************************
2027 * fill a notify_info_data with submitted time
2028 ********************************************************************/
2029 static void spoolss_notify_submitted_time(int snum,
2030 SPOOL_NOTIFY_INFO_DATA *data,
2031 print_queue_struct *queue,
2032 NT_PRINTER_INFO_LEVEL *printer,
2033 TALLOC_CTX *mem_ctx)
2035 struct tm *t;
2036 uint32 len;
2037 SYSTEMTIME st;
2039 t=gmtime(&queue->time);
2041 len = sizeof(SYSTEMTIME);
2043 data->notify_data.data.length = len;
2044 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2046 if (!data->notify_data.data.string) {
2047 data->notify_data.data.length = 0;
2048 return;
2051 make_systemtime(&st, t);
2052 memcpy(data->notify_data.data.string,&st,len);
2055 #define END 65535
2057 struct s_notify_info_data_table
2059 uint16 type;
2060 uint16 field;
2061 char *name;
2062 uint32 size;
2063 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2064 print_queue_struct *queue,
2065 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2068 struct s_notify_info_data_table notify_info_data_table[] =
2070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2095 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2100 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2101 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2102 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2103 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2104 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2105 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2106 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2118 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2119 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2120 { END, END, "", END, NULL }
2123 /*******************************************************************
2124 return the size of info_data structure
2125 ********************************************************************/
2126 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2128 int i=0;
2130 while (notify_info_data_table[i].type != END)
2132 if ( (notify_info_data_table[i].type == type ) &&
2133 (notify_info_data_table[i].field == field ) )
2135 return (notify_info_data_table[i].size);
2137 i++;
2139 return (65535);
2142 /*******************************************************************
2143 return the type of notify_info_data
2144 ********************************************************************/
2145 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2147 int i=0;
2149 while (notify_info_data_table[i].type != END)
2151 if ( (notify_info_data_table[i].type == type ) &&
2152 (notify_info_data_table[i].field == field ) )
2154 if (notify_info_data_table[i].size == POINTER)
2156 return (False);
2158 else
2160 return (True);
2163 i++;
2165 return (False);
2168 /****************************************************************************
2169 ****************************************************************************/
2170 static int search_notify(uint16 type, uint16 field, int *value)
2172 int j;
2173 BOOL found;
2175 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2177 if ( (notify_info_data_table[j].type == type ) &&
2178 (notify_info_data_table[j].field == field ) )
2179 found=True;
2181 *value=--j;
2183 if ( found && (notify_info_data_table[j].fn != NULL) )
2184 return True;
2185 else
2186 return False;
2189 /****************************************************************************
2190 ****************************************************************************/
2191 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2193 info_data->type = type;
2194 info_data->field = field;
2195 info_data->reserved = 0;
2196 info_data->id = id;
2197 info_data->size = size_of_notify_info_data(type, field);
2198 info_data->enc_type = type_of_notify_info_data(type, field);
2202 /*******************************************************************
2204 * fill a notify_info struct with info asked
2206 ********************************************************************/
2207 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2208 snum, SPOOL_NOTIFY_OPTION_TYPE
2209 *option_type, uint32 id,
2210 TALLOC_CTX *mem_ctx)
2212 int field_num,j;
2213 uint16 type;
2214 uint16 field;
2216 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2217 NT_PRINTER_INFO_LEVEL *printer = NULL;
2218 print_queue_struct *queue=NULL;
2220 type=option_type->type;
2222 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2223 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2224 option_type->count, lp_servicename(snum)));
2226 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2227 return False;
2229 for(field_num=0; field_num<option_type->count; field_num++) {
2230 field = option_type->fields[field_num];
2231 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2233 if (!search_notify(type, field, &j) )
2234 continue;
2236 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2237 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2238 return False;
2240 else info->data = tid;
2242 current_data=&info->data[info->count];
2244 construct_info_data(current_data, type, field, id);
2246 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2247 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2249 notify_info_data_table[j].fn(snum, current_data, queue,
2250 printer, mem_ctx);
2252 info->count++;
2255 free_a_printer(&printer, 2);
2256 return True;
2259 /*******************************************************************
2261 * fill a notify_info struct with info asked
2263 ********************************************************************/
2264 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2265 SPOOL_NOTIFY_INFO *info,
2266 NT_PRINTER_INFO_LEVEL *printer,
2267 int snum, SPOOL_NOTIFY_OPTION_TYPE
2268 *option_type, uint32 id,
2269 TALLOC_CTX *mem_ctx)
2271 int field_num,j;
2272 uint16 type;
2273 uint16 field;
2275 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2277 DEBUG(4,("construct_notify_jobs_info\n"));
2279 type = option_type->type;
2281 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2282 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2283 option_type->count));
2285 for(field_num=0; field_num<option_type->count; field_num++) {
2286 field = option_type->fields[field_num];
2288 if (!search_notify(type, field, &j) )
2289 continue;
2291 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2292 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2293 return False;
2295 else info->data = tid;
2297 current_data=&(info->data[info->count]);
2299 construct_info_data(current_data, type, field, id);
2300 notify_info_data_table[j].fn(snum, current_data, queue,
2301 printer, mem_ctx);
2302 info->count++;
2305 return True;
2309 * JFM: The enumeration is not that simple, it's even non obvious.
2311 * let's take an example: I want to monitor the PRINTER SERVER for
2312 * the printer's name and the number of jobs currently queued.
2313 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2314 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2316 * I have 3 printers on the back of my server.
2318 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2319 * structures.
2320 * Number Data Id
2321 * 1 printer 1 name 1
2322 * 2 printer 1 cjob 1
2323 * 3 printer 2 name 2
2324 * 4 printer 2 cjob 2
2325 * 5 printer 3 name 3
2326 * 6 printer 3 name 3
2328 * that's the print server case, the printer case is even worse.
2331 /*******************************************************************
2333 * enumerate all printers on the printserver
2334 * fill a notify_info struct with info asked
2336 ********************************************************************/
2338 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2339 SPOOL_NOTIFY_INFO *info,
2340 TALLOC_CTX *mem_ctx)
2342 int snum;
2343 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2344 int n_services=lp_numservices();
2345 int i;
2346 uint32 id;
2347 SPOOL_NOTIFY_OPTION *option;
2348 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2350 DEBUG(4,("printserver_notify_info\n"));
2352 option=Printer->notify.option;
2353 id=1;
2354 info->version=2;
2355 info->data=NULL;
2356 info->count=0;
2358 for (i=0; i<option->count; i++) {
2359 option_type=&(option->ctr.type[i]);
2361 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2362 continue;
2364 for (snum=0; snum<n_services; snum++)
2365 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2366 if (construct_notify_printer_info
2367 (info, snum, option_type, id, mem_ctx))
2368 id++;
2372 * Debugging information, don't delete.
2375 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2376 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2377 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2379 for (i=0; i<info->count; i++) {
2380 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2381 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2382 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2386 return WERR_OK;
2389 /*******************************************************************
2391 * fill a notify_info struct with info asked
2393 ********************************************************************/
2394 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2395 TALLOC_CTX *mem_ctx)
2397 int snum;
2398 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2399 int i;
2400 uint32 id;
2401 SPOOL_NOTIFY_OPTION *option;
2402 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2403 int count,j;
2404 print_queue_struct *queue=NULL;
2405 print_status_struct status;
2407 DEBUG(4,("printer_notify_info\n"));
2409 option=Printer->notify.option;
2410 id=0xffffffff;
2411 info->version=2;
2412 info->data=NULL;
2413 info->count=0;
2415 get_printer_snum(p, hnd, &snum);
2417 for (i=0; i<option->count; i++) {
2418 option_type=&option->ctr.type[i];
2420 switch ( option_type->type ) {
2421 case PRINTER_NOTIFY_TYPE:
2422 if(construct_notify_printer_info(info, snum,
2423 option_type, id,
2424 mem_ctx))
2425 id--;
2426 break;
2428 case JOB_NOTIFY_TYPE: {
2429 NT_PRINTER_INFO_LEVEL *printer = NULL;
2431 count = print_queue_status(snum, &queue, &status);
2433 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2434 lp_servicename(snum))))
2435 goto done;
2437 for (j=0; j<count; j++) {
2438 construct_notify_jobs_info(&queue[j], info,
2439 printer, snum,
2440 option_type,
2441 queue[j].job,
2442 mem_ctx);
2445 free_a_printer(&printer, 2);
2447 done:
2448 SAFE_FREE(queue);
2449 break;
2455 * Debugging information, don't delete.
2458 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2459 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2460 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2462 for (i=0; i<info->count; i++) {
2463 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2464 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2465 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2468 return WERR_OK;
2471 /********************************************************************
2472 * spoolss_rfnpcnex
2473 ********************************************************************/
2475 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2477 POLICY_HND *handle = &q_u->handle;
2478 /* uint32 change = q_u->change; - notused. */
2479 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2480 SPOOL_NOTIFY_INFO *info = &r_u->info;
2482 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2483 WERROR result = WERR_BADFID;
2485 /* we always have a NOTIFY_INFO struct */
2486 r_u->info_ptr=0x1;
2488 if (!Printer) {
2489 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2490 OUR_HANDLE(handle)));
2491 goto done;
2494 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2496 /* jfm: the change value isn't used right now.
2497 * we will honour it when
2498 * a) we'll be able to send notification to the client
2499 * b) we'll have a way to communicate between the spoolss process.
2501 * same thing for option->flags
2502 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2503 * I don't have a global notification system, I'm sending back all the
2504 * informations even when _NOTHING_ has changed.
2507 /* just ignore the SPOOL_NOTIFY_OPTION */
2509 switch (Printer->printer_type) {
2510 case PRINTER_HANDLE_IS_PRINTSERVER:
2511 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2512 break;
2514 case PRINTER_HANDLE_IS_PRINTER:
2515 result = printer_notify_info(p, handle, info, p->mem_ctx);
2516 break;
2519 done:
2520 return result;
2523 /********************************************************************
2524 * construct_printer_info_0
2525 * fill a printer_info_0 struct
2526 ********************************************************************/
2527 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2529 pstring chaine;
2530 int count;
2531 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2532 counter_printer_0 *session_counter;
2533 uint32 global_counter;
2534 struct tm *t;
2535 time_t setuptime;
2536 print_status_struct status;
2538 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2539 return False;
2541 count = print_queue_length(snum, &status);
2543 /* check if we already have a counter for this printer */
2544 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2546 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2547 if (session_counter->snum == snum)
2548 break;
2551 /* it's the first time, add it to the list */
2552 if (session_counter==NULL) {
2553 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2554 free_a_printer(&ntprinter, 2);
2555 return False;
2557 ZERO_STRUCTP(session_counter);
2558 session_counter->snum=snum;
2559 session_counter->counter=0;
2560 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2563 /* increment it */
2564 session_counter->counter++;
2566 /* JFM:
2567 * the global_counter should be stored in a TDB as it's common to all the clients
2568 * and should be zeroed on samba startup
2570 global_counter=session_counter->counter;
2572 pstrcpy(chaine,ntprinter->info_2->printername);
2574 init_unistr(&printer->printername, chaine);
2576 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2577 init_unistr(&printer->servername, chaine);
2579 printer->cjobs = count;
2580 printer->total_jobs = 0;
2581 printer->total_bytes = 0;
2583 setuptime = (time_t)ntprinter->info_2->setuptime;
2584 t=gmtime(&setuptime);
2586 printer->year = t->tm_year+1900;
2587 printer->month = t->tm_mon+1;
2588 printer->dayofweek = t->tm_wday;
2589 printer->day = t->tm_mday;
2590 printer->hour = t->tm_hour;
2591 printer->minute = t->tm_min;
2592 printer->second = t->tm_sec;
2593 printer->milliseconds = 0;
2595 printer->global_counter = global_counter;
2596 printer->total_pages = 0;
2597 printer->major_version = 0x0004; /* NT 4 */
2598 printer->build_version = 0x0565; /* build 1381 */
2599 printer->unknown7 = 0x1;
2600 printer->unknown8 = 0x0;
2601 printer->unknown9 = 0x0;
2602 printer->session_counter = session_counter->counter;
2603 printer->unknown11 = 0x0;
2604 printer->printer_errors = 0x0; /* number of print failure */
2605 printer->unknown13 = 0x0;
2606 printer->unknown14 = 0x1;
2607 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2608 printer->unknown16 = 0x0;
2609 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2610 printer->unknown18 = 0x0;
2611 printer->status = nt_printq_status(status.status);
2612 printer->unknown20 = 0x0;
2613 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2614 printer->unknown22 = 0x0;
2615 printer->unknown23 = 0x6; /* 6 ???*/
2616 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2617 printer->unknown25 = 0;
2618 printer->unknown26 = 0;
2619 printer->unknown27 = 0;
2620 printer->unknown28 = 0;
2621 printer->unknown29 = 0;
2623 free_a_printer(&ntprinter,2);
2624 return (True);
2627 /********************************************************************
2628 * construct_printer_info_1
2629 * fill a printer_info_1 struct
2630 ********************************************************************/
2631 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2633 pstring chaine;
2634 pstring chaine2;
2635 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2637 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2638 return False;
2640 printer->flags=flags;
2642 if (*ntprinter->info_2->comment == '\0') {
2643 init_unistr(&printer->comment, lp_comment(snum));
2644 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2645 ntprinter->info_2->drivername, lp_comment(snum));
2647 else {
2648 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2649 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2650 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2653 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2655 init_unistr(&printer->description, chaine);
2656 init_unistr(&printer->name, chaine2);
2658 free_a_printer(&ntprinter,2);
2660 return True;
2663 /****************************************************************************
2664 Free a DEVMODE struct.
2665 ****************************************************************************/
2667 static void free_dev_mode(DEVICEMODE *dev)
2669 if (dev == NULL)
2670 return;
2672 SAFE_FREE(dev->private);
2673 SAFE_FREE(dev);
2676 /****************************************************************************
2677 Create a DEVMODE struct. Returns malloced memory.
2678 ****************************************************************************/
2680 static DEVICEMODE *construct_dev_mode(int snum)
2682 char adevice[32];
2683 char aform[32];
2684 NT_PRINTER_INFO_LEVEL *printer = NULL;
2685 NT_DEVICEMODE *ntdevmode = NULL;
2686 DEVICEMODE *devmode = NULL;
2688 DEBUG(7,("construct_dev_mode\n"));
2690 DEBUGADD(8,("getting printer characteristics\n"));
2692 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2693 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2694 return NULL;
2697 ZERO_STRUCTP(devmode);
2699 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2700 goto fail;
2702 if (printer->info_2->devmode)
2703 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2705 if (ntdevmode == NULL)
2706 goto fail;
2708 DEBUGADD(8,("loading DEVICEMODE\n"));
2710 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2711 init_unistr(&devmode->devicename, adevice);
2713 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2714 init_unistr(&devmode->formname, aform);
2716 devmode->specversion = ntdevmode->specversion;
2717 devmode->driverversion = ntdevmode->driverversion;
2718 devmode->size = ntdevmode->size;
2719 devmode->driverextra = ntdevmode->driverextra;
2720 devmode->fields = ntdevmode->fields;
2722 devmode->orientation = ntdevmode->orientation;
2723 devmode->papersize = ntdevmode->papersize;
2724 devmode->paperlength = ntdevmode->paperlength;
2725 devmode->paperwidth = ntdevmode->paperwidth;
2726 devmode->scale = ntdevmode->scale;
2727 devmode->copies = ntdevmode->copies;
2728 devmode->defaultsource = ntdevmode->defaultsource;
2729 devmode->printquality = ntdevmode->printquality;
2730 devmode->color = ntdevmode->color;
2731 devmode->duplex = ntdevmode->duplex;
2732 devmode->yresolution = ntdevmode->yresolution;
2733 devmode->ttoption = ntdevmode->ttoption;
2734 devmode->collate = ntdevmode->collate;
2735 devmode->icmmethod = ntdevmode->icmmethod;
2736 devmode->icmintent = ntdevmode->icmintent;
2737 devmode->mediatype = ntdevmode->mediatype;
2738 devmode->dithertype = ntdevmode->dithertype;
2740 if (ntdevmode->private != NULL) {
2741 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2742 goto fail;
2745 free_nt_devicemode(&ntdevmode);
2746 free_a_printer(&printer,2);
2748 return devmode;
2750 fail:
2752 if (ntdevmode)
2753 free_nt_devicemode(&ntdevmode);
2754 if (printer)
2755 free_a_printer(&printer,2);
2756 free_dev_mode(devmode);
2758 return NULL;
2761 /********************************************************************
2762 * construct_printer_info_2
2763 * fill a printer_info_2 struct
2764 ********************************************************************/
2766 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2768 int count;
2769 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2771 print_status_struct status;
2773 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2774 return False;
2776 count = print_queue_length(snum, &status);
2778 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2779 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2780 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2781 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2782 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2784 if (*ntprinter->info_2->comment == '\0')
2785 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2786 else
2787 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2789 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2790 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2791 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2792 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2793 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2795 printer->attributes = ntprinter->info_2->attributes;
2797 printer->priority = ntprinter->info_2->priority; /* priority */
2798 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2799 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2800 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2801 printer->status = nt_printq_status(status.status); /* status */
2802 printer->cjobs = count; /* jobs */
2803 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2805 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2806 DEBUG(8, ("Returning NULL Devicemode!\n"));
2809 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2810 /* steal the printer info sec_desc structure. [badly done]. */
2811 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2812 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2813 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2814 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2816 else {
2817 printer->secdesc = NULL;
2820 free_a_printer(&ntprinter, 2);
2821 return True;
2824 /********************************************************************
2825 * construct_printer_info_3
2826 * fill a printer_info_3 struct
2827 ********************************************************************/
2828 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2830 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2831 PRINTER_INFO_3 *printer = NULL;
2833 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2834 return False;
2836 *pp_printer = NULL;
2837 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2838 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2839 return False;
2842 ZERO_STRUCTP(printer);
2844 printer->flags = 4; /* These are the components of the SD we are returning. */
2845 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2846 /* steal the printer info sec_desc structure. [badly done]. */
2847 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2849 #if 0
2851 * Set the flags for the components we are returning.
2854 if (printer->secdesc->owner_sid)
2855 printer->flags |= OWNER_SECURITY_INFORMATION;
2857 if (printer->secdesc->grp_sid)
2858 printer->flags |= GROUP_SECURITY_INFORMATION;
2860 if (printer->secdesc->dacl)
2861 printer->flags |= DACL_SECURITY_INFORMATION;
2863 if (printer->secdesc->sacl)
2864 printer->flags |= SACL_SECURITY_INFORMATION;
2865 #endif
2867 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2868 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2869 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2872 free_a_printer(&ntprinter, 2);
2874 *pp_printer = printer;
2875 return True;
2878 /********************************************************************
2879 Spoolss_enumprinters.
2880 ********************************************************************/
2881 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2883 int snum;
2884 int i;
2885 int n_services=lp_numservices();
2886 PRINTER_INFO_1 *tp, *printers=NULL;
2887 PRINTER_INFO_1 current_prt;
2889 DEBUG(4,("enum_all_printers_info_1\n"));
2891 for (snum=0; snum<n_services; snum++) {
2892 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2893 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2895 if (construct_printer_info_1(flags, &current_prt, snum)) {
2896 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2897 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2898 SAFE_FREE(printers);
2899 *returned=0;
2900 return WERR_NOMEM;
2902 else printers = tp;
2903 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2904 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2905 (*returned)++;
2910 /* check the required size. */
2911 for (i=0; i<*returned; i++)
2912 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2914 if (!alloc_buffer_size(buffer, *needed))
2915 return WERR_INSUFFICIENT_BUFFER;
2917 /* fill the buffer with the structures */
2918 for (i=0; i<*returned; i++)
2919 smb_io_printer_info_1("", buffer, &printers[i], 0);
2921 /* clear memory */
2922 SAFE_FREE(printers);
2924 if (*needed > offered) {
2925 *returned=0;
2926 return WERR_INSUFFICIENT_BUFFER;
2928 else
2929 return WERR_OK;
2932 /********************************************************************
2933 enum_all_printers_info_1_local.
2934 *********************************************************************/
2935 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2937 DEBUG(4,("enum_all_printers_info_1_local\n"));
2939 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2942 /********************************************************************
2943 enum_all_printers_info_1_name.
2944 *********************************************************************/
2945 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2947 char *s = name;
2949 DEBUG(4,("enum_all_printers_info_1_name\n"));
2951 if ((name[0] == '\\') && (name[1] == '\\'))
2952 s = name + 2;
2954 if (is_myname_or_ipaddr(s)) {
2955 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2957 else
2958 return WERR_INVALID_NAME;
2961 /********************************************************************
2962 enum_all_printers_info_1_remote.
2963 *********************************************************************/
2964 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2966 PRINTER_INFO_1 *printer;
2967 fstring printername;
2968 fstring desc;
2969 fstring comment;
2970 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2972 /* JFM: currently it's more a place holder than anything else.
2973 * In the spooler world there is a notion of server registration.
2974 * the print servers are registring (sp ?) on the PDC (in the same domain)
2976 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2979 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2980 return WERR_NOMEM;
2982 *returned=1;
2984 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2985 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2986 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2988 init_unistr(&printer->description, desc);
2989 init_unistr(&printer->name, printername);
2990 init_unistr(&printer->comment, comment);
2991 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2993 /* check the required size. */
2994 *needed += spoolss_size_printer_info_1(printer);
2996 if (!alloc_buffer_size(buffer, *needed)) {
2997 SAFE_FREE(printer);
2998 return WERR_INSUFFICIENT_BUFFER;
3001 /* fill the buffer with the structures */
3002 smb_io_printer_info_1("", buffer, printer, 0);
3004 /* clear memory */
3005 SAFE_FREE(printer);
3007 if (*needed > offered) {
3008 *returned=0;
3009 return WERR_INSUFFICIENT_BUFFER;
3011 else
3012 return WERR_OK;
3015 /********************************************************************
3016 enum_all_printers_info_1_network.
3017 *********************************************************************/
3019 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3021 DEBUG(4,("enum_all_printers_info_1_network\n"));
3023 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3026 /********************************************************************
3027 * api_spoolss_enumprinters
3029 * called from api_spoolss_enumprinters (see this to understand)
3030 ********************************************************************/
3032 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3034 int snum;
3035 int i;
3036 int n_services=lp_numservices();
3037 PRINTER_INFO_2 *tp, *printers=NULL;
3038 PRINTER_INFO_2 current_prt;
3040 for (snum=0; snum<n_services; snum++) {
3041 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3042 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3044 if (construct_printer_info_2(&current_prt, snum)) {
3045 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3046 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3047 SAFE_FREE(printers);
3048 *returned = 0;
3049 return WERR_NOMEM;
3051 else printers = tp;
3052 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3053 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3054 (*returned)++;
3059 /* check the required size. */
3060 for (i=0; i<*returned; i++)
3061 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3063 if (!alloc_buffer_size(buffer, *needed)) {
3064 for (i=0; i<*returned; i++) {
3065 free_devmode(printers[i].devmode);
3067 SAFE_FREE(printers);
3068 return WERR_INSUFFICIENT_BUFFER;
3071 /* fill the buffer with the structures */
3072 for (i=0; i<*returned; i++)
3073 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3075 /* clear memory */
3076 for (i=0; i<*returned; i++) {
3077 free_devmode(printers[i].devmode);
3079 SAFE_FREE(printers);
3081 if (*needed > offered) {
3082 *returned=0;
3083 return WERR_INSUFFICIENT_BUFFER;
3085 else
3086 return WERR_OK;
3089 /********************************************************************
3090 * handle enumeration of printers at level 1
3091 ********************************************************************/
3092 static WERROR enumprinters_level1( uint32 flags, fstring name,
3093 NEW_BUFFER *buffer, uint32 offered,
3094 uint32 *needed, uint32 *returned)
3096 /* Not all the flags are equals */
3098 if (flags & PRINTER_ENUM_LOCAL)
3099 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3101 if (flags & PRINTER_ENUM_NAME)
3102 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3104 if (flags & PRINTER_ENUM_REMOTE)
3105 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3107 if (flags & PRINTER_ENUM_NETWORK)
3108 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3110 return WERR_OK; /* NT4sp5 does that */
3113 /********************************************************************
3114 * handle enumeration of printers at level 2
3115 ********************************************************************/
3116 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3117 NEW_BUFFER *buffer, uint32 offered,
3118 uint32 *needed, uint32 *returned)
3120 char *s = servername;
3122 if (flags & PRINTER_ENUM_LOCAL) {
3123 return enum_all_printers_info_2(buffer, offered, needed, returned);
3126 if (flags & PRINTER_ENUM_NAME) {
3127 if ((servername[0] == '\\') && (servername[1] == '\\'))
3128 s = servername + 2;
3129 if (is_myname_or_ipaddr(s))
3130 return enum_all_printers_info_2(buffer, offered, needed, returned);
3131 else
3132 return WERR_INVALID_NAME;
3135 if (flags & PRINTER_ENUM_REMOTE)
3136 return WERR_UNKNOWN_LEVEL;
3138 return WERR_OK;
3141 /********************************************************************
3142 * handle enumeration of printers at level 5
3143 ********************************************************************/
3144 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3145 NEW_BUFFER *buffer, uint32 offered,
3146 uint32 *needed, uint32 *returned)
3148 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3149 return WERR_OK;
3152 /********************************************************************
3153 * api_spoolss_enumprinters
3155 * called from api_spoolss_enumprinters (see this to understand)
3156 ********************************************************************/
3158 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3160 uint32 flags = q_u->flags;
3161 UNISTR2 *servername = &q_u->servername;
3162 uint32 level = q_u->level;
3163 NEW_BUFFER *buffer = NULL;
3164 uint32 offered = q_u->offered;
3165 uint32 *needed = &r_u->needed;
3166 uint32 *returned = &r_u->returned;
3168 fstring name;
3170 /* that's an [in out] buffer */
3171 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3172 buffer = r_u->buffer;
3174 DEBUG(4,("_spoolss_enumprinters\n"));
3176 *needed=0;
3177 *returned=0;
3180 * Level 1:
3181 * flags==PRINTER_ENUM_NAME
3182 * if name=="" then enumerates all printers
3183 * if name!="" then enumerate the printer
3184 * flags==PRINTER_ENUM_REMOTE
3185 * name is NULL, enumerate printers
3186 * Level 2: name!="" enumerates printers, name can't be NULL
3187 * Level 3: doesn't exist
3188 * Level 4: does a local registry lookup
3189 * Level 5: same as Level 2
3192 unistr2_to_ascii(name, servername, sizeof(name)-1);
3193 strupper(name);
3195 switch (level) {
3196 case 1:
3197 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3198 case 2:
3199 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3200 case 5:
3201 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3202 case 3:
3203 case 4:
3204 break;
3206 return WERR_UNKNOWN_LEVEL;
3209 /****************************************************************************
3210 ****************************************************************************/
3211 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3213 PRINTER_INFO_0 *printer=NULL;
3215 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3216 return WERR_NOMEM;
3218 construct_printer_info_0(printer, snum);
3220 /* check the required size. */
3221 *needed += spoolss_size_printer_info_0(printer);
3223 if (!alloc_buffer_size(buffer, *needed)) {
3224 SAFE_FREE(printer);
3225 return WERR_INSUFFICIENT_BUFFER;
3228 /* fill the buffer with the structures */
3229 smb_io_printer_info_0("", buffer, printer, 0);
3231 /* clear memory */
3232 SAFE_FREE(printer);
3234 if (*needed > offered) {
3235 return WERR_INSUFFICIENT_BUFFER;
3238 return WERR_OK;
3241 /****************************************************************************
3242 ****************************************************************************/
3243 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3245 PRINTER_INFO_1 *printer=NULL;
3247 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3248 return WERR_NOMEM;
3250 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3252 /* check the required size. */
3253 *needed += spoolss_size_printer_info_1(printer);
3255 if (!alloc_buffer_size(buffer, *needed)) {
3256 SAFE_FREE(printer);
3257 return WERR_INSUFFICIENT_BUFFER;
3260 /* fill the buffer with the structures */
3261 smb_io_printer_info_1("", buffer, printer, 0);
3263 /* clear memory */
3264 SAFE_FREE(printer);
3266 if (*needed > offered) {
3267 return WERR_INSUFFICIENT_BUFFER;
3270 return WERR_OK;
3273 /****************************************************************************
3274 ****************************************************************************/
3275 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3277 PRINTER_INFO_2 *printer=NULL;
3279 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3280 return WERR_NOMEM;
3282 construct_printer_info_2(printer, snum);
3284 /* check the required size. */
3285 *needed += spoolss_size_printer_info_2(printer);
3287 if (!alloc_buffer_size(buffer, *needed)) {
3288 free_printer_info_2(printer);
3289 return WERR_INSUFFICIENT_BUFFER;
3292 /* fill the buffer with the structures */
3293 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3294 free_printer_info_2(printer);
3295 return WERR_NOMEM;
3298 /* clear memory */
3299 free_printer_info_2(printer);
3301 if (*needed > offered) {
3302 return WERR_INSUFFICIENT_BUFFER;
3305 return WERR_OK;
3308 /****************************************************************************
3309 ****************************************************************************/
3310 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3312 PRINTER_INFO_3 *printer=NULL;
3314 if (!construct_printer_info_3(&printer, snum))
3315 return WERR_NOMEM;
3317 /* check the required size. */
3318 *needed += spoolss_size_printer_info_3(printer);
3320 if (!alloc_buffer_size(buffer, *needed)) {
3321 free_printer_info_3(printer);
3322 return WERR_INSUFFICIENT_BUFFER;
3325 /* fill the buffer with the structures */
3326 smb_io_printer_info_3("", buffer, printer, 0);
3328 /* clear memory */
3329 free_printer_info_3(printer);
3331 if (*needed > offered) {
3332 return WERR_INSUFFICIENT_BUFFER;
3335 return WERR_OK;
3338 /****************************************************************************
3339 ****************************************************************************/
3341 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3343 POLICY_HND *handle = &q_u->handle;
3344 uint32 level = q_u->level;
3345 NEW_BUFFER *buffer = NULL;
3346 uint32 offered = q_u->offered;
3347 uint32 *needed = &r_u->needed;
3349 int snum;
3351 /* that's an [in out] buffer */
3352 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3353 buffer = r_u->buffer;
3355 *needed=0;
3357 if (!get_printer_snum(p, handle, &snum))
3358 return WERR_BADFID;
3360 switch (level) {
3361 case 0:
3362 return getprinter_level_0(snum, buffer, offered, needed);
3363 case 1:
3364 return getprinter_level_1(snum, buffer, offered, needed);
3365 case 2:
3366 return getprinter_level_2(snum, buffer, offered, needed);
3367 case 3:
3368 return getprinter_level_3(snum, buffer, offered, needed);
3370 return WERR_UNKNOWN_LEVEL;
3373 /********************************************************************
3374 * fill a DRIVER_INFO_1 struct
3375 ********************************************************************/
3376 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3378 init_unistr( &info->name, driver.info_3->name);
3381 /********************************************************************
3382 * construct_printer_driver_info_1
3383 ********************************************************************/
3384 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3386 NT_PRINTER_INFO_LEVEL *printer = NULL;
3387 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3389 ZERO_STRUCT(driver);
3391 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3392 return WERR_INVALID_PRINTER_NAME;
3394 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3395 return WERR_UNKNOWN_PRINTER_DRIVER;
3397 fill_printer_driver_info_1(info, driver, servername, architecture);
3399 free_a_printer(&printer,2);
3401 return WERR_OK;
3404 /********************************************************************
3405 * construct_printer_driver_info_2
3406 * fill a printer_info_2 struct
3407 ********************************************************************/
3408 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3410 pstring temp;
3412 info->version=driver.info_3->cversion;
3414 init_unistr( &info->name, driver.info_3->name );
3415 init_unistr( &info->architecture, driver.info_3->environment );
3418 if (strlen(driver.info_3->driverpath)) {
3419 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3420 init_unistr( &info->driverpath, temp );
3421 } else
3422 init_unistr( &info->driverpath, "" );
3424 if (strlen(driver.info_3->datafile)) {
3425 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3426 init_unistr( &info->datafile, temp );
3427 } else
3428 init_unistr( &info->datafile, "" );
3430 if (strlen(driver.info_3->configfile)) {
3431 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3432 init_unistr( &info->configfile, temp );
3433 } else
3434 init_unistr( &info->configfile, "" );
3437 /********************************************************************
3438 * construct_printer_driver_info_2
3439 * fill a printer_info_2 struct
3440 ********************************************************************/
3441 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3443 NT_PRINTER_INFO_LEVEL *printer = NULL;
3444 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3446 ZERO_STRUCT(printer);
3447 ZERO_STRUCT(driver);
3449 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3450 return WERR_INVALID_PRINTER_NAME;
3452 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3453 return WERR_UNKNOWN_PRINTER_DRIVER;
3455 fill_printer_driver_info_2(info, driver, servername);
3457 free_a_printer(&printer,2);
3459 return WERR_OK;
3462 /********************************************************************
3463 * copy a strings array and convert to UNICODE
3465 * convert an array of ascii string to a UNICODE string
3466 ********************************************************************/
3467 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3469 int i=0;
3470 int j=0;
3471 char *v;
3472 pstring line;
3473 uint16 *tuary;
3475 DEBUG(6,("init_unistr_array\n"));
3476 *uni_array=NULL;
3478 while (1) {
3479 if (char_array == NULL)
3480 v = "";
3481 else {
3482 v = char_array[i];
3483 if (!v) v = ""; /* hack to handle null lists */
3485 if (strlen(v) == 0) break;
3486 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3487 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3488 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3489 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3490 return;
3492 else *uni_array = tuary;
3493 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3494 i++;
3497 if (*uni_array) {
3498 (*uni_array)[j]=0x0000;
3501 DEBUGADD(6,("last one:done\n"));
3504 /********************************************************************
3505 * construct_printer_info_3
3506 * fill a printer_info_3 struct
3507 ********************************************************************/
3508 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3510 pstring temp;
3512 ZERO_STRUCTP(info);
3514 info->version=driver.info_3->cversion;
3516 init_unistr( &info->name, driver.info_3->name );
3517 init_unistr( &info->architecture, driver.info_3->environment );
3519 if (strlen(driver.info_3->driverpath)) {
3520 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3521 init_unistr( &info->driverpath, temp );
3522 } else
3523 init_unistr( &info->driverpath, "" );
3525 if (strlen(driver.info_3->datafile)) {
3526 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3527 init_unistr( &info->datafile, temp );
3528 } else
3529 init_unistr( &info->datafile, "" );
3531 if (strlen(driver.info_3->configfile)) {
3532 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3533 init_unistr( &info->configfile, temp );
3534 } else
3535 init_unistr( &info->configfile, "" );
3537 if (strlen(driver.info_3->helpfile)) {
3538 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3539 init_unistr( &info->helpfile, temp );
3540 } else
3541 init_unistr( &info->helpfile, "" );
3543 init_unistr( &info->monitorname, driver.info_3->monitorname );
3544 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3546 info->dependentfiles=NULL;
3547 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3550 /********************************************************************
3551 * construct_printer_info_3
3552 * fill a printer_info_3 struct
3553 ********************************************************************/
3554 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3556 NT_PRINTER_INFO_LEVEL *printer = NULL;
3557 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3558 WERROR status;
3559 ZERO_STRUCT(driver);
3561 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3562 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3563 if (!W_ERROR_IS_OK(status))
3564 return WERR_INVALID_PRINTER_NAME;
3566 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3567 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3568 if (!W_ERROR_IS_OK(status)) {
3569 free_a_printer(&printer,2);
3570 return WERR_UNKNOWN_PRINTER_DRIVER;
3573 fill_printer_driver_info_3(info, driver, servername);
3575 free_a_printer(&printer,2);
3577 return WERR_OK;
3580 /********************************************************************
3581 * construct_printer_info_6
3582 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3583 ********************************************************************/
3585 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3587 pstring temp;
3588 fstring nullstr;
3590 ZERO_STRUCTP(info);
3591 memset(&nullstr, '\0', sizeof(fstring));
3593 info->version=driver.info_3->cversion;
3595 init_unistr( &info->name, driver.info_3->name );
3596 init_unistr( &info->architecture, driver.info_3->environment );
3598 if (strlen(driver.info_3->driverpath)) {
3599 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3600 init_unistr( &info->driverpath, temp );
3601 } else
3602 init_unistr( &info->driverpath, "" );
3604 if (strlen(driver.info_3->datafile)) {
3605 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3606 init_unistr( &info->datafile, temp );
3607 } else
3608 init_unistr( &info->datafile, "" );
3610 if (strlen(driver.info_3->configfile)) {
3611 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3612 init_unistr( &info->configfile, temp );
3613 } else
3614 init_unistr( &info->configfile, "" );
3616 if (strlen(driver.info_3->helpfile)) {
3617 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3618 init_unistr( &info->helpfile, temp );
3619 } else
3620 init_unistr( &info->helpfile, "" );
3622 init_unistr( &info->monitorname, driver.info_3->monitorname );
3623 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3625 info->dependentfiles=NULL;
3626 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3628 info->previousdrivernames=NULL;
3629 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3631 info->driver_date.low=0;
3632 info->driver_date.high=0;
3634 info->padding=0;
3635 info->driver_version_low=0;
3636 info->driver_version_high=0;
3638 init_unistr( &info->mfgname, "");
3639 init_unistr( &info->oem_url, "");
3640 init_unistr( &info->hardware_id, "");
3641 init_unistr( &info->provider, "");
3644 /********************************************************************
3645 * construct_printer_info_6
3646 * fill a printer_info_6 struct
3647 ********************************************************************/
3648 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3650 NT_PRINTER_INFO_LEVEL *printer = NULL;
3651 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3652 WERROR status;
3653 ZERO_STRUCT(driver);
3655 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3656 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3657 if (!W_ERROR_IS_OK(status))
3658 return WERR_INVALID_PRINTER_NAME;
3660 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3661 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3662 if (!W_ERROR_IS_OK(status)) {
3664 * Is this a W2k client ?
3667 if (version < 3) {
3668 free_a_printer(&printer,2);
3669 return WERR_UNKNOWN_PRINTER_DRIVER;
3672 /* Yes - try again with a WinNT driver. */
3673 version = 2;
3674 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3675 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3676 if (!W_ERROR_IS_OK(status)) {
3677 free_a_printer(&printer,2);
3678 return WERR_UNKNOWN_PRINTER_DRIVER;
3682 fill_printer_driver_info_6(info, driver, servername);
3684 free_a_printer(&printer,2);
3686 return WERR_OK;
3689 /****************************************************************************
3690 ****************************************************************************/
3692 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3694 SAFE_FREE(info->dependentfiles);
3697 /****************************************************************************
3698 ****************************************************************************/
3700 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3702 SAFE_FREE(info->dependentfiles);
3706 /****************************************************************************
3707 ****************************************************************************/
3708 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3710 DRIVER_INFO_1 *info=NULL;
3711 WERROR status;
3713 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3714 return WERR_NOMEM;
3716 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3717 if (!W_ERROR_IS_OK(status)) {
3718 SAFE_FREE(info);
3719 return status;
3722 /* check the required size. */
3723 *needed += spoolss_size_printer_driver_info_1(info);
3725 if (!alloc_buffer_size(buffer, *needed)) {
3726 SAFE_FREE(info);
3727 return WERR_INSUFFICIENT_BUFFER;
3730 /* fill the buffer with the structures */
3731 smb_io_printer_driver_info_1("", buffer, info, 0);
3733 /* clear memory */
3734 SAFE_FREE(info);
3736 if (*needed > offered)
3737 return WERR_INSUFFICIENT_BUFFER;
3739 return WERR_OK;
3742 /****************************************************************************
3743 ****************************************************************************/
3744 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3746 DRIVER_INFO_2 *info=NULL;
3747 WERROR status;
3749 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3750 return WERR_NOMEM;
3752 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3753 if (!W_ERROR_IS_OK(status)) {
3754 SAFE_FREE(info);
3755 return status;
3758 /* check the required size. */
3759 *needed += spoolss_size_printer_driver_info_2(info);
3761 if (!alloc_buffer_size(buffer, *needed)) {
3762 SAFE_FREE(info);
3763 return WERR_INSUFFICIENT_BUFFER;
3766 /* fill the buffer with the structures */
3767 smb_io_printer_driver_info_2("", buffer, info, 0);
3769 /* clear memory */
3770 SAFE_FREE(info);
3772 if (*needed > offered)
3773 return WERR_INSUFFICIENT_BUFFER;
3775 return WERR_OK;
3778 /****************************************************************************
3779 ****************************************************************************/
3780 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3782 DRIVER_INFO_3 info;
3783 WERROR status;
3785 ZERO_STRUCT(info);
3787 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3788 if (!W_ERROR_IS_OK(status)) {
3789 return status;
3792 /* check the required size. */
3793 *needed += spoolss_size_printer_driver_info_3(&info);
3795 if (!alloc_buffer_size(buffer, *needed)) {
3796 free_printer_driver_info_3(&info);
3797 return WERR_INSUFFICIENT_BUFFER;
3800 /* fill the buffer with the structures */
3801 smb_io_printer_driver_info_3("", buffer, &info, 0);
3803 free_printer_driver_info_3(&info);
3805 if (*needed > offered)
3806 return WERR_INSUFFICIENT_BUFFER;
3808 return WERR_OK;
3811 /****************************************************************************
3812 ****************************************************************************/
3813 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3815 DRIVER_INFO_6 info;
3816 WERROR status;
3818 ZERO_STRUCT(info);
3820 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3821 if (!W_ERROR_IS_OK(status)) {
3822 return status;
3825 /* check the required size. */
3826 *needed += spoolss_size_printer_driver_info_6(&info);
3828 if (!alloc_buffer_size(buffer, *needed)) {
3829 free_printer_driver_info_6(&info);
3830 return WERR_INSUFFICIENT_BUFFER;
3833 /* fill the buffer with the structures */
3834 smb_io_printer_driver_info_6("", buffer, &info, 0);
3836 free_printer_driver_info_6(&info);
3838 if (*needed > offered)
3839 return WERR_INSUFFICIENT_BUFFER;
3841 return WERR_OK;
3844 /****************************************************************************
3845 ****************************************************************************/
3847 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3849 POLICY_HND *handle = &q_u->handle;
3850 UNISTR2 *uni_arch = &q_u->architecture;
3851 uint32 level = q_u->level;
3852 uint32 clientmajorversion = q_u->clientmajorversion;
3853 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3854 NEW_BUFFER *buffer = NULL;
3855 uint32 offered = q_u->offered;
3856 uint32 *needed = &r_u->needed;
3857 uint32 *servermajorversion = &r_u->servermajorversion;
3858 uint32 *serverminorversion = &r_u->serverminorversion;
3860 fstring servername;
3861 fstring architecture;
3862 int snum;
3864 /* that's an [in out] buffer */
3865 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3866 buffer = r_u->buffer;
3868 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3870 *needed=0;
3871 *servermajorversion=0;
3872 *serverminorversion=0;
3874 pstrcpy(servername, global_myname);
3875 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3877 if (!get_printer_snum(p, handle, &snum))
3878 return WERR_BADFID;
3880 switch (level) {
3881 case 1:
3882 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3883 case 2:
3884 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3885 case 3:
3886 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3887 case 6:
3888 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3891 return WERR_UNKNOWN_LEVEL;
3894 /****************************************************************************
3895 ****************************************************************************/
3897 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3899 POLICY_HND *handle = &q_u->handle;
3901 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3903 if (Printer) {
3904 Printer->page_started=True;
3905 return WERR_OK;
3908 DEBUG(3,("Error in startpageprinter printer handle\n"));
3909 return WERR_BADFID;
3912 /****************************************************************************
3913 ****************************************************************************/
3915 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3917 POLICY_HND *handle = &q_u->handle;
3919 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3921 if (!Printer) {
3922 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3923 return WERR_BADFID;
3926 Printer->page_started=False;
3928 return WERR_OK;
3931 /********************************************************************
3932 * api_spoolss_getprinter
3933 * called from the spoolss dispatcher
3935 ********************************************************************/
3937 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3939 POLICY_HND *handle = &q_u->handle;
3940 /* uint32 level = q_u->doc_info_container.level; - notused. */
3941 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3942 uint32 *jobid = &r_u->jobid;
3944 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3945 int snum;
3946 pstring jobname;
3947 fstring datatype;
3948 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3949 struct current_user user;
3951 if (!Printer) {
3952 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3953 return WERR_BADFID;
3956 get_current_user(&user, p);
3959 * a nice thing with NT is it doesn't listen to what you tell it.
3960 * when asked to send _only_ RAW datas, it tries to send datas
3961 * in EMF format.
3963 * So I add checks like in NT Server ...
3965 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3966 * there's a bug in NT client-side code, so we'll fix it in the
3967 * server-side code. *nnnnnggggh!*
3970 if (info_1->p_datatype != 0) {
3971 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3972 if (strcmp(datatype, "RAW") != 0) {
3973 (*jobid)=0;
3974 return WERR_INVALID_DATATYPE;
3978 /* get the share number of the printer */
3979 if (!get_printer_snum(p, handle, &snum)) {
3980 return WERR_BADFID;
3983 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3985 Printer->jobid = print_job_start(&user, snum, jobname);
3987 /* An error occured in print_job_start() so return an appropriate
3988 NT error code. */
3990 if (Printer->jobid == -1) {
3991 return map_werror_from_unix(errno);
3994 Printer->document_started=True;
3995 (*jobid) = Printer->jobid;
3997 return WERR_OK;
4000 /********************************************************************
4001 * api_spoolss_getprinter
4002 * called from the spoolss dispatcher
4004 ********************************************************************/
4006 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4008 POLICY_HND *handle = &q_u->handle;
4010 return _spoolss_enddocprinter_internal(p, handle);
4013 /****************************************************************************
4014 ****************************************************************************/
4016 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4018 POLICY_HND *handle = &q_u->handle;
4019 uint32 buffer_size = q_u->buffer_size;
4020 uint8 *buffer = q_u->buffer;
4021 uint32 *buffer_written = &q_u->buffer_size2;
4023 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4025 if (!Printer) {
4026 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4027 r_u->buffer_written = q_u->buffer_size2;
4028 return WERR_BADFID;
4031 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4034 r_u->buffer_written = q_u->buffer_size2;
4036 return WERR_OK;
4039 /********************************************************************
4040 * api_spoolss_getprinter
4041 * called from the spoolss dispatcher
4043 ********************************************************************/
4044 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4045 pipes_struct *p)
4047 struct current_user user;
4048 int snum;
4049 WERROR errcode = WERR_BADFUNC;
4050 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4052 get_current_user(&user, p);
4054 if (!Printer) {
4055 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4056 return WERR_BADFID;
4059 if (!get_printer_snum(p, handle, &snum))
4060 return WERR_BADFID;
4062 switch (command) {
4063 case PRINTER_CONTROL_PAUSE:
4064 if (print_queue_pause(&user, snum, &errcode)) {
4065 errcode = WERR_OK;
4067 break;
4068 case PRINTER_CONTROL_RESUME:
4069 case PRINTER_CONTROL_UNPAUSE:
4070 if (print_queue_resume(&user, snum, &errcode)) {
4071 errcode = WERR_OK;
4073 break;
4074 case PRINTER_CONTROL_PURGE:
4075 if (print_queue_purge(&user, snum, &errcode)) {
4076 errcode = WERR_OK;
4078 break;
4079 default:
4080 return WERR_UNKNOWN_LEVEL;
4083 return errcode;
4086 /********************************************************************
4087 * api_spoolss_abortprinter
4088 ********************************************************************/
4090 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4092 POLICY_HND *handle = &q_u->handle;
4094 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4097 /********************************************************************
4098 * called by spoolss_api_setprinter
4099 * when updating a printer description
4100 ********************************************************************/
4101 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4102 const SPOOL_PRINTER_INFO_LEVEL *info,
4103 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4105 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4106 struct current_user user;
4107 WERROR result;
4108 int snum;
4110 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4112 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4113 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4114 OUR_HANDLE(handle)));
4116 result = WERR_BADFID;
4117 goto done;
4120 /* NT seems to like setting the security descriptor even though
4121 nothing may have actually changed. This causes annoying
4122 dialog boxes when the user doesn't have permission to change
4123 the security descriptor. */
4125 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4127 if (DEBUGLEVEL >= 10) {
4128 SEC_ACL *the_acl;
4129 int i;
4131 the_acl = old_secdesc_ctr->sec->dacl;
4132 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4133 PRINTERNAME(snum), the_acl->num_aces));
4135 for (i = 0; i < the_acl->num_aces; i++) {
4136 fstring sid_str;
4138 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4140 DEBUG(10, ("%s 0x%08x\n", sid_str,
4141 the_acl->ace[i].info.mask));
4144 the_acl = secdesc_ctr->sec->dacl;
4146 if (the_acl) {
4147 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4148 PRINTERNAME(snum), the_acl->num_aces));
4150 for (i = 0; i < the_acl->num_aces; i++) {
4151 fstring sid_str;
4153 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4155 DEBUG(10, ("%s 0x%08x\n", sid_str,
4156 the_acl->ace[i].info.mask));
4158 } else {
4159 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4163 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4165 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4166 result = WERR_OK;
4167 goto done;
4170 /* Work out which user is performing the operation */
4172 get_current_user(&user, p);
4174 /* Check the user has permissions to change the security
4175 descriptor. By experimentation with two NT machines, the user
4176 requires Full Access to the printer to change security
4177 information. */
4179 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4180 result = WERR_ACCESS_DENIED;
4181 goto done;
4184 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4186 done:
4188 return result;
4191 /********************************************************************
4192 Do Samba sanity checks on a printer info struct.
4193 this has changed purpose: it now "canonicalises" printer
4194 info from a client rather than just checking it is correct
4195 ********************************************************************/
4197 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4199 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4200 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4202 /* we force some elements to "correct" values */
4203 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4204 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4205 global_myname, lp_servicename(snum));
4206 fstrcpy(info->sharename, lp_servicename(snum));
4207 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4208 | PRINTER_ATTRIBUTE_LOCAL \
4209 | PRINTER_ATTRIBUTE_RAW_ONLY \
4210 | PRINTER_ATTRIBUTE_QUEUED ;
4212 return True;
4215 /****************************************************************************
4216 ****************************************************************************/
4217 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4219 char *cmd = lp_addprinter_cmd();
4220 char **qlines;
4221 pstring command;
4222 pstring driverlocation;
4223 int numlines;
4224 int ret;
4225 int fd;
4227 /* build driver path... only 9X architecture is needed for legacy reasons */
4228 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4229 global_myname);
4230 /* change \ to \\ for the shell */
4231 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4233 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4234 cmd, printer->info_2->printername, printer->info_2->sharename,
4235 printer->info_2->portname, printer->info_2->drivername,
4236 printer->info_2->location, driverlocation);
4238 DEBUG(10,("Running [%s]\n", command));
4239 ret = smbrun(command, &fd);
4240 DEBUGADD(10,("returned [%d]\n", ret));
4242 if ( ret != 0 ) {
4243 if (fd != -1)
4244 close(fd);
4245 return False;
4248 numlines = 0;
4249 /* Get lines and convert them back to dos-codepage */
4250 qlines = fd_lines_load(fd, &numlines);
4251 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4252 close(fd);
4254 if(numlines) {
4255 /* Set the portname to what the script says the portname should be. */
4256 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4257 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4259 /* Send SIGHUP to process group... is there a better way? */
4260 kill(0, SIGHUP);
4261 add_all_printers();
4264 file_lines_free(qlines);
4265 return True;
4268 /* Return true if two devicemodes are equal */
4270 #define DEVMODE_CHECK_INT(field) \
4271 if (d1->field != d2->field) { \
4272 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4273 d1->field, d2->field)); \
4274 return False; \
4277 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4279 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4281 if (!d1 ^ !d2) {
4282 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4283 return False; /* if either is exclusively NULL are not equal */
4286 if (!strequal(d1->devicename, d2->devicename)) {
4287 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4288 return False;
4291 if (!strequal(d1->formname, d2->formname)) {
4292 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4293 return False;
4296 DEVMODE_CHECK_INT(specversion);
4297 DEVMODE_CHECK_INT(driverversion);
4298 DEVMODE_CHECK_INT(driverextra);
4299 DEVMODE_CHECK_INT(orientation);
4300 DEVMODE_CHECK_INT(papersize);
4301 DEVMODE_CHECK_INT(paperlength);
4302 DEVMODE_CHECK_INT(paperwidth);
4303 DEVMODE_CHECK_INT(scale);
4304 DEVMODE_CHECK_INT(copies);
4305 DEVMODE_CHECK_INT(defaultsource);
4306 DEVMODE_CHECK_INT(printquality);
4307 DEVMODE_CHECK_INT(color);
4308 DEVMODE_CHECK_INT(duplex);
4309 DEVMODE_CHECK_INT(yresolution);
4310 DEVMODE_CHECK_INT(ttoption);
4311 DEVMODE_CHECK_INT(collate);
4312 DEVMODE_CHECK_INT(logpixels);
4314 DEVMODE_CHECK_INT(fields);
4315 DEVMODE_CHECK_INT(bitsperpel);
4316 DEVMODE_CHECK_INT(pelswidth);
4317 DEVMODE_CHECK_INT(pelsheight);
4318 DEVMODE_CHECK_INT(displayflags);
4319 DEVMODE_CHECK_INT(displayfrequency);
4320 DEVMODE_CHECK_INT(icmmethod);
4321 DEVMODE_CHECK_INT(icmintent);
4322 DEVMODE_CHECK_INT(mediatype);
4323 DEVMODE_CHECK_INT(dithertype);
4324 DEVMODE_CHECK_INT(reserved1);
4325 DEVMODE_CHECK_INT(reserved2);
4326 DEVMODE_CHECK_INT(panningwidth);
4327 DEVMODE_CHECK_INT(panningheight);
4329 /* compare the private data if it exists */
4330 if (!d1->driverextra && !d2->driverextra) goto equal;
4333 DEVMODE_CHECK_INT(driverextra);
4335 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4336 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4337 return False;
4340 equal:
4341 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4342 return True;
4345 /* Return true if two NT_PRINTER_PARAM structures are equal */
4347 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4348 NT_PRINTER_PARAM *p2)
4350 if (!p1 && !p2) goto equal;
4352 if ((!p1 && p2) || (p1 && !p2)) {
4353 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4354 return False;
4357 /* Compare lists of printer parameters */
4359 while (p1) {
4360 BOOL found = False;
4361 NT_PRINTER_PARAM *q = p1;
4363 /* Find the parameter in the second structure */
4365 while(q) {
4367 if (strequal(p1->value, q->value)) {
4369 if (p1->type != q->type) {
4370 DEBUG(10, ("nt_printer_param_equal():"
4371 "types for %s differ (%d != %d)\n",
4372 p1->value, p1->type,
4373 q->type));
4374 break;
4377 if (p1->data_len != q->data_len) {
4378 DEBUG(10, ("nt_printer_param_equal():"
4379 "len for %s differs (%d != %d)\n",
4380 p1->value, p1->data_len,
4381 q->data_len));
4382 break;
4385 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4386 found = True;
4387 } else {
4388 DEBUG(10, ("nt_printer_param_equal():"
4389 "data for %s differs\n", p1->value));
4392 break;
4395 q = q->next;
4398 if (!found) {
4399 DEBUG(10, ("nt_printer_param_equal(): param %s "
4400 "does not exist\n", p1->value));
4401 return False;
4404 p1 = p1->next;
4407 equal:
4409 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4410 return True;
4413 /********************************************************************
4414 * Called by update_printer when trying to work out whether to
4415 * actually update printer info.
4416 ********************************************************************/
4418 #define PI_CHECK_INT(field) \
4419 if (pi1->field != pi2->field) { \
4420 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4421 pi1->field, pi2->field)); \
4422 return False; \
4425 #define PI_CHECK_STR(field) \
4426 if (!strequal(pi1->field, pi2->field)) { \
4427 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4428 pi1->field, pi2->field)); \
4429 return False; \
4432 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4433 NT_PRINTER_INFO_LEVEL *p2)
4435 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4437 /* Trivial conditions */
4439 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4440 goto equal;
4443 if ((!p1 && p2) || (p1 && !p2) ||
4444 (!p1->info_2 && p2->info_2) ||
4445 (p1->info_2 && !p2->info_2)) {
4446 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4447 "differ\n"));
4448 return False;
4451 /* Compare two nt_printer_info_level structures. Don't compare
4452 status or cjobs as they seem to have something to do with the
4453 printer queue. */
4455 pi1 = p1->info_2;
4456 pi2 = p2->info_2;
4458 /* Don't check the attributes as we stomp on the value in
4459 check_printer_ok() anyway. */
4461 #if 0
4462 PI_CHECK_INT(attributes);
4463 #endif
4465 PI_CHECK_INT(priority);
4466 PI_CHECK_INT(default_priority);
4467 PI_CHECK_INT(starttime);
4468 PI_CHECK_INT(untiltime);
4469 PI_CHECK_INT(averageppm);
4471 /* Yuck - don't check the printername or servername as the
4472 add_a_printer() code plays games with them. You can't
4473 change the printername or the sharename through this interface
4474 in Samba. */
4476 PI_CHECK_STR(sharename);
4477 PI_CHECK_STR(portname);
4478 PI_CHECK_STR(drivername);
4479 PI_CHECK_STR(comment);
4480 PI_CHECK_STR(location);
4482 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4483 return False;
4486 PI_CHECK_STR(sepfile);
4487 PI_CHECK_STR(printprocessor);
4488 PI_CHECK_STR(datatype);
4489 PI_CHECK_STR(parameters);
4491 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4492 return False;
4495 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4496 return False;
4499 PI_CHECK_INT(changeid);
4500 PI_CHECK_INT(c_setprinter);
4501 PI_CHECK_INT(setuptime);
4503 equal:
4504 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4505 return True;
4508 /********************************************************************
4509 * called by spoolss_api_setprinter
4510 * when updating a printer description
4511 ********************************************************************/
4513 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4514 const SPOOL_PRINTER_INFO_LEVEL *info,
4515 DEVICEMODE *devmode)
4517 int snum;
4518 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4519 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4520 WERROR result;
4522 DEBUG(8,("update_printer\n"));
4524 result = WERR_OK;
4526 if (level!=2) {
4527 DEBUG(0,("Send a mail to samba@samba.org\n"));
4528 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4529 result = WERR_UNKNOWN_LEVEL;
4530 goto done;
4533 if (!Printer) {
4534 result = WERR_BADFID;
4535 goto done;
4538 if (!get_printer_snum(p, handle, &snum)) {
4539 result = WERR_BADFID;
4540 goto done;
4543 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4544 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4545 result = WERR_BADFID;
4546 goto done;
4549 DEBUGADD(8,("Converting info_2 struct\n"));
4552 * convert_printer_info converts the incoming
4553 * info from the client and overwrites the info
4554 * just read from the tdb in the pointer 'printer'.
4557 if (!convert_printer_info(info, printer, level)) {
4558 result = WERR_NOMEM;
4559 goto done;
4562 if (info->info_2->devmode_ptr != 0) {
4563 /* we have a valid devmode
4564 convert it and link it*/
4566 DEBUGADD(8,("Converting the devicemode struct\n"));
4567 if (!convert_devicemode(printer->info_2->printername, devmode,
4568 &printer->info_2->devmode)) {
4569 result = WERR_NOMEM;
4570 goto done;
4574 /* Do sanity check on the requested changes for Samba */
4576 if (!check_printer_ok(printer->info_2, snum)) {
4577 result = WERR_INVALID_PARAM;
4578 goto done;
4581 /* NT likes to call this function even though nothing has actually
4582 changed. Check this so the user doesn't end up with an
4583 annoying permission denied dialog box. */
4585 if (nt_printer_info_level_equal(printer, old_printer)) {
4586 DEBUG(3, ("printer info has not changed\n"));
4587 result = WERR_OK;
4588 goto done;
4591 /* Check calling user has permission to update printer description */
4593 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4594 DEBUG(3, ("printer property change denied by security "
4595 "descriptor\n"));
4596 result = WERR_ACCESS_DENIED;
4597 goto done;
4600 /* Call addprinter hook */
4602 if (*lp_addprinter_cmd()) {
4603 if (!add_printer_hook(printer)) {
4604 result = WERR_ACCESS_DENIED;
4605 goto done;
4609 /* Update printer info */
4610 result = add_a_printer(*printer, 2);
4612 done:
4613 free_a_printer(&printer, 2);
4614 free_a_printer(&old_printer, 2);
4616 srv_spoolss_sendnotify(p, handle);
4618 return result;
4621 /****************************************************************************
4622 ****************************************************************************/
4624 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4626 POLICY_HND *handle = &q_u->handle;
4627 uint32 level = q_u->level;
4628 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4629 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4630 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4631 uint32 command = q_u->command;
4633 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4635 if (!Printer) {
4636 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4637 return WERR_BADFID;
4640 /* check the level */
4641 switch (level) {
4642 case 0:
4643 return control_printer(handle, command, p);
4644 case 2:
4645 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4646 case 3:
4647 return update_printer_sec(handle, level, info, p,
4648 secdesc_ctr);
4649 default:
4650 return WERR_UNKNOWN_LEVEL;
4654 /****************************************************************************
4655 ****************************************************************************/
4657 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4659 POLICY_HND *handle = &q_u->handle;
4661 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4663 if (!Printer) {
4664 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4665 return WERR_BADFID;
4668 if (Printer->notify.client_connected==True)
4669 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4671 Printer->notify.flags=0;
4672 Printer->notify.options=0;
4673 Printer->notify.localmachine[0]='\0';
4674 Printer->notify.printerlocal=0;
4675 if (Printer->notify.option)
4676 free_spool_notify_option(&Printer->notify.option);
4677 Printer->notify.client_connected=False;
4679 return WERR_OK;
4682 /****************************************************************************
4683 ****************************************************************************/
4685 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4687 /* that's an [in out] buffer (despite appearences to the contrary) */
4688 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4690 r_u->needed = 0;
4691 return WERR_INVALID_PARAM; /* this is what a NT server
4692 returns for AddJob. AddJob
4693 must fail on non-local
4694 printers */
4697 /****************************************************************************
4698 ****************************************************************************/
4699 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4700 int position, int snum)
4702 pstring temp_name;
4704 struct tm *t;
4706 t=gmtime(&queue->time);
4707 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4709 job_info->jobid=queue->job;
4710 init_unistr(&job_info->printername, lp_servicename(snum));
4711 init_unistr(&job_info->machinename, temp_name);
4712 init_unistr(&job_info->username, queue->user);
4713 init_unistr(&job_info->document, queue->file);
4714 init_unistr(&job_info->datatype, "RAW");
4715 init_unistr(&job_info->text_status, "");
4716 job_info->status=nt_printj_status(queue->status);
4717 job_info->priority=queue->priority;
4718 job_info->position=position;
4719 job_info->totalpages=0;
4720 job_info->pagesprinted=0;
4722 make_systemtime(&job_info->submitted, t);
4725 /****************************************************************************
4726 ****************************************************************************/
4727 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4728 int position, int snum,
4729 NT_PRINTER_INFO_LEVEL *ntprinter)
4731 pstring temp_name;
4732 pstring chaine;
4733 struct tm *t;
4735 t=gmtime(&queue->time);
4736 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4738 job_info->jobid=queue->job;
4740 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4742 init_unistr(&job_info->printername, chaine);
4744 init_unistr(&job_info->machinename, temp_name);
4745 init_unistr(&job_info->username, queue->user);
4746 init_unistr(&job_info->document, queue->file);
4747 init_unistr(&job_info->notifyname, queue->user);
4748 init_unistr(&job_info->datatype, "RAW");
4749 init_unistr(&job_info->printprocessor, "winprint");
4750 init_unistr(&job_info->parameters, "");
4751 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4752 init_unistr(&job_info->text_status, "");
4754 /* and here the security descriptor */
4756 job_info->status=nt_printj_status(queue->status);
4757 job_info->priority=queue->priority;
4758 job_info->position=position;
4759 job_info->starttime=0;
4760 job_info->untiltime=0;
4761 job_info->totalpages=0;
4762 job_info->size=queue->size;
4763 make_systemtime(&(job_info->submitted), t);
4764 job_info->timeelapsed=0;
4765 job_info->pagesprinted=0;
4767 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4768 return False;
4771 return (True);
4774 /****************************************************************************
4775 Enumjobs at level 1.
4776 ****************************************************************************/
4777 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4778 NEW_BUFFER *buffer, uint32 offered,
4779 uint32 *needed, uint32 *returned)
4781 JOB_INFO_1 *info;
4782 int i;
4784 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4785 if (info==NULL) {
4786 SAFE_FREE(queue);
4787 *returned=0;
4788 return WERR_NOMEM;
4791 for (i=0; i<*returned; i++)
4792 fill_job_info_1(&info[i], &queue[i], i, snum);
4794 SAFE_FREE(queue);
4796 /* check the required size. */
4797 for (i=0; i<*returned; i++)
4798 (*needed) += spoolss_size_job_info_1(&info[i]);
4800 if (!alloc_buffer_size(buffer, *needed)) {
4801 SAFE_FREE(info);
4802 return WERR_INSUFFICIENT_BUFFER;
4805 /* fill the buffer with the structures */
4806 for (i=0; i<*returned; i++)
4807 smb_io_job_info_1("", buffer, &info[i], 0);
4809 /* clear memory */
4810 SAFE_FREE(info);
4812 if (*needed > offered) {
4813 *returned=0;
4814 return WERR_INSUFFICIENT_BUFFER;
4817 return WERR_OK;
4820 /****************************************************************************
4821 Enumjobs at level 2.
4822 ****************************************************************************/
4823 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4824 NEW_BUFFER *buffer, uint32 offered,
4825 uint32 *needed, uint32 *returned)
4827 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4828 JOB_INFO_2 *info;
4829 int i;
4830 WERROR result;
4832 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4833 if (info==NULL) {
4834 *returned=0;
4835 return WERR_NOMEM;
4838 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4839 if (!W_ERROR_IS_OK(result)) {
4840 *returned = 0;
4841 return result;
4844 for (i=0; i<*returned; i++)
4845 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4847 free_a_printer(&ntprinter, 2);
4848 SAFE_FREE(queue);
4850 /* check the required size. */
4851 for (i=0; i<*returned; i++)
4852 (*needed) += spoolss_size_job_info_2(&info[i]);
4854 if (!alloc_buffer_size(buffer, *needed)) {
4855 SAFE_FREE(info);
4856 return WERR_INSUFFICIENT_BUFFER;
4859 /* fill the buffer with the structures */
4860 for (i=0; i<*returned; i++)
4861 smb_io_job_info_2("", buffer, &info[i], 0);
4863 /* clear memory */
4864 for (i = 0; i < *returned; i++)
4865 free_job_info_2(&info[i]);
4867 SAFE_FREE(info);
4869 if (*needed > offered) {
4870 *returned=0;
4871 return WERR_INSUFFICIENT_BUFFER;
4874 return WERR_OK;
4877 /****************************************************************************
4878 Enumjobs.
4879 ****************************************************************************/
4881 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4883 POLICY_HND *handle = &q_u->handle;
4884 /* uint32 firstjob = q_u->firstjob; - notused. */
4885 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4886 uint32 level = q_u->level;
4887 NEW_BUFFER *buffer = NULL;
4888 uint32 offered = q_u->offered;
4889 uint32 *needed = &r_u->needed;
4890 uint32 *returned = &r_u->returned;
4892 int snum;
4893 print_status_struct prt_status;
4894 print_queue_struct *queue=NULL;
4896 /* that's an [in out] buffer */
4897 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4898 buffer = r_u->buffer;
4900 DEBUG(4,("_spoolss_enumjobs\n"));
4902 *needed=0;
4903 *returned=0;
4905 if (!get_printer_snum(p, handle, &snum))
4906 return WERR_BADFID;
4908 *returned = print_queue_status(snum, &queue, &prt_status);
4909 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4911 if (*returned == 0) {
4912 SAFE_FREE(queue);
4913 return WERR_OK;
4916 switch (level) {
4917 case 1:
4918 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4919 case 2:
4920 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4921 default:
4922 SAFE_FREE(queue);
4923 *returned=0;
4924 return WERR_UNKNOWN_LEVEL;
4928 /****************************************************************************
4929 ****************************************************************************/
4931 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4933 return WERR_OK;
4936 /****************************************************************************
4937 ****************************************************************************/
4939 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4941 POLICY_HND *handle = &q_u->handle;
4942 uint32 jobid = q_u->jobid;
4943 /* uint32 level = q_u->level; - notused. */
4944 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4945 uint32 command = q_u->command;
4947 struct current_user user;
4948 int snum;
4949 WERROR errcode = WERR_BADFUNC;
4951 if (!get_printer_snum(p, handle, &snum)) {
4952 return WERR_BADFID;
4955 if (!print_job_exists(jobid)) {
4956 return WERR_INVALID_PRINTER_NAME;
4959 get_current_user(&user, p);
4961 switch (command) {
4962 case JOB_CONTROL_CANCEL:
4963 case JOB_CONTROL_DELETE:
4964 if (print_job_delete(&user, jobid, &errcode)) {
4965 errcode = WERR_OK;
4967 break;
4968 case JOB_CONTROL_PAUSE:
4969 if (print_job_pause(&user, jobid, &errcode)) {
4970 errcode = WERR_OK;
4972 break;
4973 case JOB_CONTROL_RESTART:
4974 case JOB_CONTROL_RESUME:
4975 if (print_job_resume(&user, jobid, &errcode)) {
4976 errcode = WERR_OK;
4978 break;
4979 default:
4980 return WERR_UNKNOWN_LEVEL;
4983 return errcode;
4986 /****************************************************************************
4987 Enumerates all printer drivers at level 1.
4988 ****************************************************************************/
4989 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4991 int i;
4992 int ndrivers;
4993 uint32 version;
4994 fstring *list = NULL;
4996 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4997 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
4999 *returned=0;
5001 #define MAX_VERSION 4
5003 for (version=0; version<MAX_VERSION; version++) {
5004 list=NULL;
5005 ndrivers=get_ntdrivers(&list, architecture, version);
5006 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5008 if(ndrivers == -1)
5009 return WERR_NOMEM;
5011 if(ndrivers != 0) {
5012 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5013 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5014 SAFE_FREE(driver_info_1);
5015 SAFE_FREE(list);
5016 return WERR_NOMEM;
5018 else driver_info_1 = tdi1;
5021 for (i=0; i<ndrivers; i++) {
5022 WERROR status;
5023 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5024 ZERO_STRUCT(driver);
5025 status = get_a_printer_driver(&driver, 3, list[i],
5026 architecture, version);
5027 if (!W_ERROR_IS_OK(status)) {
5028 SAFE_FREE(list);
5029 return status;
5031 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5032 free_a_printer_driver(driver, 3);
5035 *returned+=ndrivers;
5036 SAFE_FREE(list);
5039 /* check the required size. */
5040 for (i=0; i<*returned; i++) {
5041 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5042 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5045 if (!alloc_buffer_size(buffer, *needed)) {
5046 SAFE_FREE(driver_info_1);
5047 return WERR_INSUFFICIENT_BUFFER;
5050 /* fill the buffer with the driver structures */
5051 for (i=0; i<*returned; i++) {
5052 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5053 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5056 SAFE_FREE(driver_info_1);
5058 if (*needed > offered) {
5059 *returned=0;
5060 return WERR_INSUFFICIENT_BUFFER;
5063 return WERR_OK;
5066 /****************************************************************************
5067 Enumerates all printer drivers at level 2.
5068 ****************************************************************************/
5069 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5071 int i;
5072 int ndrivers;
5073 uint32 version;
5074 fstring *list = NULL;
5076 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5077 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5079 *returned=0;
5081 #define MAX_VERSION 4
5083 for (version=0; version<MAX_VERSION; version++) {
5084 list=NULL;
5085 ndrivers=get_ntdrivers(&list, architecture, version);
5086 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5088 if(ndrivers == -1)
5089 return WERR_NOMEM;
5091 if(ndrivers != 0) {
5092 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5093 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5094 SAFE_FREE(driver_info_2);
5095 SAFE_FREE(list);
5096 return WERR_NOMEM;
5098 else driver_info_2 = tdi2;
5101 for (i=0; i<ndrivers; i++) {
5102 WERROR status;
5104 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5105 ZERO_STRUCT(driver);
5106 status = get_a_printer_driver(&driver, 3, list[i],
5107 architecture, version);
5108 if (!W_ERROR_IS_OK(status)) {
5109 SAFE_FREE(list);
5110 return status;
5112 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5113 free_a_printer_driver(driver, 3);
5116 *returned+=ndrivers;
5117 SAFE_FREE(list);
5120 /* check the required size. */
5121 for (i=0; i<*returned; i++) {
5122 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5123 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5126 if (!alloc_buffer_size(buffer, *needed)) {
5127 SAFE_FREE(driver_info_2);
5128 return WERR_INSUFFICIENT_BUFFER;
5131 /* fill the buffer with the form structures */
5132 for (i=0; i<*returned; i++) {
5133 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5134 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5137 SAFE_FREE(driver_info_2);
5139 if (*needed > offered) {
5140 *returned=0;
5141 return WERR_INSUFFICIENT_BUFFER;
5144 return WERR_OK;
5147 /****************************************************************************
5148 Enumerates all printer drivers at level 3.
5149 ****************************************************************************/
5150 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5152 int i;
5153 int ndrivers;
5154 uint32 version;
5155 fstring *list = NULL;
5157 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5158 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5160 *returned=0;
5162 #define MAX_VERSION 4
5164 for (version=0; version<MAX_VERSION; version++) {
5165 list=NULL;
5166 ndrivers=get_ntdrivers(&list, architecture, version);
5167 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5169 if(ndrivers == -1)
5170 return WERR_NOMEM;
5172 if(ndrivers != 0) {
5173 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5174 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5175 SAFE_FREE(driver_info_3);
5176 SAFE_FREE(list);
5177 return WERR_NOMEM;
5179 else driver_info_3 = tdi3;
5182 for (i=0; i<ndrivers; i++) {
5183 WERROR status;
5185 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5186 ZERO_STRUCT(driver);
5187 status = get_a_printer_driver(&driver, 3, list[i],
5188 architecture, version);
5189 if (!W_ERROR_IS_OK(status)) {
5190 SAFE_FREE(list);
5191 return status;
5193 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5194 free_a_printer_driver(driver, 3);
5197 *returned+=ndrivers;
5198 SAFE_FREE(list);
5201 /* check the required size. */
5202 for (i=0; i<*returned; i++) {
5203 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5204 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5207 if (!alloc_buffer_size(buffer, *needed)) {
5208 SAFE_FREE(driver_info_3);
5209 return WERR_INSUFFICIENT_BUFFER;
5212 /* fill the buffer with the driver structures */
5213 for (i=0; i<*returned; i++) {
5214 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5215 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5218 for (i=0; i<*returned; i++)
5219 SAFE_FREE(driver_info_3[i].dependentfiles);
5221 SAFE_FREE(driver_info_3);
5223 if (*needed > offered) {
5224 *returned=0;
5225 return WERR_INSUFFICIENT_BUFFER;
5228 return WERR_OK;
5231 /****************************************************************************
5232 Enumerates all printer drivers.
5233 ****************************************************************************/
5235 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5237 /* UNISTR2 *name = &q_u->name; - notused. */
5238 UNISTR2 *environment = &q_u->environment;
5239 uint32 level = q_u->level;
5240 NEW_BUFFER *buffer = NULL;
5241 uint32 offered = q_u->offered;
5242 uint32 *needed = &r_u->needed;
5243 uint32 *returned = &r_u->returned;
5245 fstring *list = NULL;
5246 fstring servername;
5247 fstring architecture;
5249 /* that's an [in out] buffer */
5250 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5251 buffer = r_u->buffer;
5253 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5254 fstrcpy(servername, global_myname);
5255 *needed=0;
5256 *returned=0;
5258 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5260 switch (level) {
5261 case 1:
5262 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5263 case 2:
5264 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5265 case 3:
5266 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5267 default:
5268 *returned=0;
5269 SAFE_FREE(list);
5270 return WERR_UNKNOWN_LEVEL;
5274 /****************************************************************************
5275 ****************************************************************************/
5277 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5279 form->flag=list->flag;
5280 init_unistr(&form->name, list->name);
5281 form->width=list->width;
5282 form->length=list->length;
5283 form->left=list->left;
5284 form->top=list->top;
5285 form->right=list->right;
5286 form->bottom=list->bottom;
5289 /****************************************************************************
5290 ****************************************************************************/
5292 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5294 /* POLICY_HND *handle = &q_u->handle; - notused. */
5295 uint32 level = q_u->level;
5296 NEW_BUFFER *buffer = NULL;
5297 uint32 offered = q_u->offered;
5298 uint32 *needed = &r_u->needed;
5299 uint32 *numofforms = &r_u->numofforms;
5300 uint32 numbuiltinforms;
5302 nt_forms_struct *list=NULL;
5303 nt_forms_struct *builtinlist=NULL;
5304 FORM_1 *forms_1;
5305 int buffer_size=0;
5306 int i;
5308 /* that's an [in out] buffer */
5309 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5310 buffer = r_u->buffer;
5312 DEBUG(4,("_spoolss_enumforms\n"));
5313 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5314 DEBUGADD(5,("Info level [%d]\n", level));
5316 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5317 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5318 *numofforms = get_ntforms(&list);
5319 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5320 *numofforms += numbuiltinforms;
5322 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5324 switch (level) {
5325 case 1:
5326 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5327 *numofforms=0;
5328 return WERR_NOMEM;
5331 /* construct the list of form structures */
5332 for (i=0; i<numbuiltinforms; i++) {
5333 DEBUGADD(6,("Filling form number [%d]\n",i));
5334 fill_form_1(&forms_1[i], &builtinlist[i]);
5337 SAFE_FREE(builtinlist);
5339 for (; i<*numofforms; i++) {
5340 DEBUGADD(6,("Filling form number [%d]\n",i));
5341 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5344 SAFE_FREE(list);
5346 /* check the required size. */
5347 for (i=0; i<numbuiltinforms; i++) {
5348 DEBUGADD(6,("adding form [%d]'s size\n",i));
5349 buffer_size += spoolss_size_form_1(&forms_1[i]);
5351 for (; i<*numofforms; i++) {
5352 DEBUGADD(6,("adding form [%d]'s size\n",i));
5353 buffer_size += spoolss_size_form_1(&forms_1[i]);
5356 *needed=buffer_size;
5358 if (!alloc_buffer_size(buffer, buffer_size)){
5359 SAFE_FREE(forms_1);
5360 return WERR_INSUFFICIENT_BUFFER;
5363 /* fill the buffer with the form structures */
5364 for (i=0; i<numbuiltinforms; i++) {
5365 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5366 smb_io_form_1("", buffer, &forms_1[i], 0);
5368 for (; i<*numofforms; i++) {
5369 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5370 smb_io_form_1("", buffer, &forms_1[i], 0);
5373 SAFE_FREE(forms_1);
5375 if (*needed > offered) {
5376 *numofforms=0;
5377 return WERR_INSUFFICIENT_BUFFER;
5379 else
5380 return WERR_OK;
5382 default:
5383 SAFE_FREE(list);
5384 SAFE_FREE(builtinlist);
5385 return WERR_UNKNOWN_LEVEL;
5390 /****************************************************************************
5391 ****************************************************************************/
5393 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5395 /* POLICY_HND *handle = &q_u->handle; - notused. */
5396 uint32 level = q_u->level;
5397 UNISTR2 *uni_formname = &q_u->formname;
5398 NEW_BUFFER *buffer = NULL;
5399 uint32 offered = q_u->offered;
5400 uint32 *needed = &r_u->needed;
5402 nt_forms_struct *list=NULL;
5403 nt_forms_struct builtin_form;
5404 BOOL foundBuiltin;
5405 FORM_1 form_1;
5406 fstring form_name;
5407 int buffer_size=0;
5408 int numofforms=0, i=0;
5410 /* that's an [in out] buffer */
5411 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5412 buffer = r_u->buffer;
5414 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5416 DEBUG(4,("_spoolss_getform\n"));
5417 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5418 DEBUGADD(5,("Info level [%d]\n", level));
5420 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5421 if (!foundBuiltin) {
5422 numofforms = get_ntforms(&list);
5423 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5425 if (numofforms == 0)
5426 return WERR_BADFID;
5429 switch (level) {
5430 case 1:
5431 if (foundBuiltin) {
5432 fill_form_1(&form_1, &builtin_form);
5433 } else {
5435 /* Check if the requested name is in the list of form structures */
5436 for (i=0; i<numofforms; i++) {
5438 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5440 if (strequal(form_name, list[i].name)) {
5441 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5442 fill_form_1(&form_1, &list[i]);
5443 break;
5447 SAFE_FREE(list);
5448 if (i == numofforms) {
5449 return WERR_BADFID;
5452 /* check the required size. */
5454 *needed=spoolss_size_form_1(&form_1);
5456 if (!alloc_buffer_size(buffer, buffer_size)){
5457 return WERR_INSUFFICIENT_BUFFER;
5460 if (*needed > offered) {
5461 return WERR_INSUFFICIENT_BUFFER;
5464 /* fill the buffer with the form structures */
5465 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5466 smb_io_form_1("", buffer, &form_1, 0);
5468 return WERR_OK;
5470 default:
5471 SAFE_FREE(list);
5472 return WERR_UNKNOWN_LEVEL;
5476 /****************************************************************************
5477 ****************************************************************************/
5478 static void fill_port_1(PORT_INFO_1 *port, char *name)
5480 init_unistr(&port->port_name, name);
5483 /****************************************************************************
5484 ****************************************************************************/
5485 static void fill_port_2(PORT_INFO_2 *port, char *name)
5487 init_unistr(&port->port_name, name);
5488 init_unistr(&port->monitor_name, "Local Monitor");
5489 init_unistr(&port->description, "Local Port");
5490 #define PORT_TYPE_WRITE 1
5491 port->port_type=PORT_TYPE_WRITE;
5492 port->reserved=0x0;
5495 /****************************************************************************
5496 enumports level 1.
5497 ****************************************************************************/
5498 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5500 PORT_INFO_1 *ports=NULL;
5501 int i=0;
5503 if (*lp_enumports_cmd()) {
5504 char *cmd = lp_enumports_cmd();
5505 char **qlines;
5506 pstring command;
5507 int numlines;
5508 int ret;
5509 int fd;
5511 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5513 DEBUG(10,("Running [%s]\n", command));
5514 ret = smbrun(command, &fd);
5515 DEBUG(10,("Returned [%d]\n", ret));
5516 if (ret != 0) {
5517 if (fd != -1)
5518 close(fd);
5519 /* Is this the best error to return here? */
5520 return WERR_ACCESS_DENIED;
5523 numlines = 0;
5524 qlines = fd_lines_load(fd, &numlines);
5525 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5526 close(fd);
5528 if(numlines) {
5529 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5530 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5531 werror_str(WERR_NOMEM)));
5532 file_lines_free(qlines);
5533 return WERR_NOMEM;
5536 for (i=0; i<numlines; i++) {
5537 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5538 fill_port_1(&ports[i], qlines[i]);
5541 file_lines_free(qlines);
5544 *returned = numlines;
5546 } else {
5547 *returned = 1; /* Sole Samba port returned. */
5549 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5550 return WERR_NOMEM;
5552 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5554 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5557 /* check the required size. */
5558 for (i=0; i<*returned; i++) {
5559 DEBUGADD(6,("adding port [%d]'s size\n", i));
5560 *needed += spoolss_size_port_info_1(&ports[i]);
5563 if (!alloc_buffer_size(buffer, *needed)) {
5564 SAFE_FREE(ports);
5565 return WERR_INSUFFICIENT_BUFFER;
5568 /* fill the buffer with the ports structures */
5569 for (i=0; i<*returned; i++) {
5570 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5571 smb_io_port_1("", buffer, &ports[i], 0);
5574 SAFE_FREE(ports);
5576 if (*needed > offered) {
5577 *returned=0;
5578 return WERR_INSUFFICIENT_BUFFER;
5581 return WERR_OK;
5584 /****************************************************************************
5585 enumports level 2.
5586 ****************************************************************************/
5588 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5590 PORT_INFO_2 *ports=NULL;
5591 int i=0;
5593 if (*lp_enumports_cmd()) {
5594 char *cmd = lp_enumports_cmd();
5595 char *path;
5596 char **qlines;
5597 pstring tmp_file;
5598 pstring command;
5599 int numlines;
5600 int ret;
5601 int fd;
5603 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5604 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5605 else
5606 path = lp_lockdir();
5608 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5609 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5611 unlink(tmp_file);
5612 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5613 ret = smbrun(command, &fd);
5614 DEBUGADD(10,("returned [%d]\n", ret));
5615 if (ret != 0) {
5616 if (fd != -1)
5617 close(fd);
5618 /* Is this the best error to return here? */
5619 return WERR_ACCESS_DENIED;
5622 numlines = 0;
5623 qlines = fd_lines_load(fd, &numlines);
5624 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5625 close(fd);
5627 if(numlines) {
5628 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5629 file_lines_free(qlines);
5630 return WERR_NOMEM;
5633 for (i=0; i<numlines; i++) {
5634 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5635 fill_port_2(&(ports[i]), qlines[i]);
5638 file_lines_free(qlines);
5641 *returned = numlines;
5643 } else {
5645 *returned = 1;
5647 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5648 return WERR_NOMEM;
5650 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5652 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5655 /* check the required size. */
5656 for (i=0; i<*returned; i++) {
5657 DEBUGADD(6,("adding port [%d]'s size\n", i));
5658 *needed += spoolss_size_port_info_2(&ports[i]);
5661 if (!alloc_buffer_size(buffer, *needed)) {
5662 SAFE_FREE(ports);
5663 return WERR_INSUFFICIENT_BUFFER;
5666 /* fill the buffer with the ports structures */
5667 for (i=0; i<*returned; i++) {
5668 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5669 smb_io_port_2("", buffer, &ports[i], 0);
5672 SAFE_FREE(ports);
5674 if (*needed > offered) {
5675 *returned=0;
5676 return WERR_INSUFFICIENT_BUFFER;
5679 return WERR_OK;
5682 /****************************************************************************
5683 enumports.
5684 ****************************************************************************/
5686 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5688 /* UNISTR2 *name = &q_u->name; - notused. */
5689 uint32 level = q_u->level;
5690 NEW_BUFFER *buffer = NULL;
5691 uint32 offered = q_u->offered;
5692 uint32 *needed = &r_u->needed;
5693 uint32 *returned = &r_u->returned;
5695 /* that's an [in out] buffer */
5696 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5697 buffer = r_u->buffer;
5699 DEBUG(4,("_spoolss_enumports\n"));
5701 *returned=0;
5702 *needed=0;
5704 switch (level) {
5705 case 1:
5706 return enumports_level_1(buffer, offered, needed, returned);
5707 case 2:
5708 return enumports_level_2(buffer, offered, needed, returned);
5709 default:
5710 return WERR_UNKNOWN_LEVEL;
5714 /****************************************************************************
5715 ****************************************************************************/
5716 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5717 const SPOOL_PRINTER_INFO_LEVEL *info,
5718 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5719 uint32 user_switch, const SPOOL_USER_CTR *user,
5720 POLICY_HND *handle)
5722 NT_PRINTER_INFO_LEVEL *printer = NULL;
5723 fstring name;
5724 int snum;
5725 WERROR err = WERR_OK;
5727 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5728 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5729 return WERR_NOMEM;
5732 ZERO_STRUCTP(printer);
5734 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5735 if (!convert_printer_info(info, printer, 2)) {
5736 free_a_printer(&printer, 2);
5737 return WERR_NOMEM;
5740 /* check to see if the printer already exists */
5742 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5743 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5744 printer->info_2->sharename));
5745 free_a_printer(&printer, 2);
5746 return WERR_PRINTER_ALREADY_EXISTS;
5749 if (*lp_addprinter_cmd() )
5750 if ( !add_printer_hook(printer) ) {
5751 free_a_printer(&printer,2);
5752 return WERR_ACCESS_DENIED;
5755 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5756 printer->info_2->sharename);
5758 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5759 free_a_printer(&printer,2);
5760 return WERR_ACCESS_DENIED;
5763 /* you must be a printer admin to add a new printer */
5764 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5765 free_a_printer(&printer,2);
5766 return WERR_ACCESS_DENIED;
5770 * Do sanity check on the requested changes for Samba.
5773 if (!check_printer_ok(printer->info_2, snum)) {
5774 free_a_printer(&printer,2);
5775 return WERR_INVALID_PARAM;
5779 * When a printer is created, the drivername bound to the printer is used
5780 * to lookup previously saved driver initialization info, which is then
5781 * bound to the new printer, simulating what happens in the Windows arch.
5783 set_driver_init(printer, 2);
5785 /* write the ASCII on disk */
5786 err = add_a_printer(*printer, 2);
5787 if (!W_ERROR_IS_OK(err)) {
5788 free_a_printer(&printer,2);
5789 return err;
5792 if (!open_printer_hnd(p, handle, name)) {
5793 /* Handle open failed - remove addition. */
5794 del_a_printer(printer->info_2->sharename);
5795 free_a_printer(&printer,2);
5796 return WERR_ACCESS_DENIED;
5799 free_a_printer(&printer,2);
5801 srv_spoolss_sendnotify(p, handle);
5803 return WERR_OK;
5806 /****************************************************************************
5807 ****************************************************************************/
5809 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5811 UNISTR2 *uni_srv_name = &q_u->server_name;
5812 uint32 level = q_u->level;
5813 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5814 uint32 unk0 = q_u->unk0;
5815 uint32 unk1 = q_u->unk1;
5816 uint32 unk2 = q_u->unk2;
5817 uint32 unk3 = q_u->unk3;
5818 uint32 user_switch = q_u->user_switch;
5819 SPOOL_USER_CTR *user = &q_u->user_ctr;
5820 POLICY_HND *handle = &r_u->handle;
5822 switch (level) {
5823 case 1:
5824 /* we don't handle yet */
5825 /* but I know what to do ... */
5826 return WERR_UNKNOWN_LEVEL;
5827 case 2:
5828 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5829 unk0, unk1, unk2, unk3,
5830 user_switch, user, handle);
5831 default:
5832 return WERR_UNKNOWN_LEVEL;
5836 /****************************************************************************
5837 ****************************************************************************/
5839 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5841 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5842 uint32 level = q_u->level;
5843 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5844 WERROR err = WERR_OK;
5845 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5846 struct current_user user;
5848 ZERO_STRUCT(driver);
5850 get_current_user(&user, p);
5852 if (!convert_printer_driver_info(info, &driver, level)) {
5853 err = WERR_NOMEM;
5854 goto done;
5857 DEBUG(5,("Cleaning driver's information\n"));
5858 err = clean_up_driver_struct(driver, level, &user);
5859 if (!W_ERROR_IS_OK(err))
5860 goto done;
5862 DEBUG(5,("Moving driver to final destination\n"));
5863 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5864 if (W_ERROR_IS_OK(err))
5865 err = WERR_ACCESS_DENIED;
5866 goto done;
5869 if (add_a_printer_driver(driver, level)!=0) {
5870 err = WERR_ACCESS_DENIED;
5871 goto done;
5874 done:
5875 free_a_printer_driver(driver, level);
5876 return err;
5879 /****************************************************************************
5880 ****************************************************************************/
5881 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5883 init_unistr(&info->name, name);
5886 /****************************************************************************
5887 ****************************************************************************/
5888 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5890 pstring path;
5891 pstring long_archi;
5892 pstring short_archi;
5893 DRIVER_DIRECTORY_1 *info=NULL;
5895 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5897 if (get_short_archi(short_archi, long_archi)==False)
5898 return WERR_INVALID_ENVIRONMENT;
5900 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5901 return WERR_NOMEM;
5903 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5905 DEBUG(4,("printer driver directory: [%s]\n", path));
5907 fill_driverdir_1(info, path);
5909 *needed += spoolss_size_driverdir_info_1(info);
5911 if (!alloc_buffer_size(buffer, *needed)) {
5912 SAFE_FREE(info);
5913 return WERR_INSUFFICIENT_BUFFER;
5916 smb_io_driverdir_1("", buffer, info, 0);
5918 SAFE_FREE(info);
5920 if (*needed > offered)
5921 return WERR_INSUFFICIENT_BUFFER;
5923 return WERR_OK;
5926 /****************************************************************************
5927 ****************************************************************************/
5929 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5931 UNISTR2 *name = &q_u->name;
5932 UNISTR2 *uni_environment = &q_u->environment;
5933 uint32 level = q_u->level;
5934 NEW_BUFFER *buffer = NULL;
5935 uint32 offered = q_u->offered;
5936 uint32 *needed = &r_u->needed;
5938 /* that's an [in out] buffer */
5939 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5940 buffer = r_u->buffer;
5942 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5944 *needed=0;
5946 switch(level) {
5947 case 1:
5948 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5949 default:
5950 return WERR_UNKNOWN_LEVEL;
5954 /****************************************************************************
5955 ****************************************************************************/
5957 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5959 POLICY_HND *handle = &q_u->handle;
5960 uint32 idx = q_u->index;
5961 uint32 in_value_len = q_u->valuesize;
5962 uint32 in_data_len = q_u->datasize;
5963 uint32 *out_max_value_len = &r_u->valuesize;
5964 uint16 **out_value = &r_u->value;
5965 uint32 *out_value_len = &r_u->realvaluesize;
5966 uint32 *out_type = &r_u->type;
5967 uint32 *out_max_data_len = &r_u->datasize;
5968 uint8 **data_out = &r_u->data;
5969 uint32 *out_data_len = &r_u->realdatasize;
5971 NT_PRINTER_INFO_LEVEL *printer = NULL;
5973 fstring value;
5975 uint32 param_index;
5976 uint32 biggest_valuesize;
5977 uint32 biggest_datasize;
5978 uint32 data_len;
5979 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5980 int snum;
5981 uint8 *data=NULL;
5982 uint32 type;
5983 WERROR result;
5985 ZERO_STRUCT(printer);
5987 *out_type=0;
5989 *out_max_data_len=0;
5990 *data_out=NULL;
5991 *out_data_len=0;
5993 DEBUG(5,("spoolss_enumprinterdata\n"));
5995 if (!Printer) {
5996 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5997 return WERR_BADFID;
6000 if (!get_printer_snum(p,handle, &snum))
6001 return WERR_BADFID;
6003 result = get_a_printer(&printer, 2, lp_servicename(snum));
6004 if (!W_ERROR_IS_OK(result))
6005 return result;
6008 * The NT machine wants to know the biggest size of value and data
6010 * cf: MSDN EnumPrinterData remark section
6012 if ( (in_value_len==0) && (in_data_len==0) ) {
6013 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6015 #if 0
6017 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6018 * if this parameter size doesn't exist.
6019 * Ok - my opinion here is that the client is not asking for the greatest
6020 * possible size of all the parameters, but is asking specifically for the size needed
6021 * for this specific parameter. In that case we can remove the loop below and
6022 * simplify this lookup code considerably. JF - comments welcome. JRA.
6025 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6026 SAFE_FREE(data);
6027 free_a_printer(&printer, 2);
6028 return WERR_NO_MORE_ITEMS;
6030 #endif
6032 SAFE_FREE(data);
6034 param_index=0;
6035 biggest_valuesize=0;
6036 biggest_datasize=0;
6038 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6039 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6040 if (data_len > biggest_datasize) biggest_datasize=data_len;
6042 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6044 SAFE_FREE(data);
6045 param_index++;
6048 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6049 *out_value_len=2*(1+biggest_valuesize);
6050 *out_data_len=biggest_datasize;
6052 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6054 free_a_printer(&printer, 2);
6055 return WERR_OK;
6059 * the value len is wrong in NT sp3
6060 * that's the number of bytes not the number of unicode chars
6063 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6065 SAFE_FREE(data);
6066 free_a_printer(&printer, 2);
6068 /* out_value should default to "" or else NT4 has
6069 problems unmarshalling the response */
6071 *out_max_value_len=(in_value_len/sizeof(uint16));
6072 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
6073 return WERR_NOMEM;
6075 ZERO_STRUCTP(*out_value);
6076 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6078 /* the data is counted in bytes */
6079 *out_max_data_len = in_data_len;
6080 *out_data_len = in_data_len;
6081 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
6082 return WERR_NOMEM;
6084 memset(*data_out,'\0',in_data_len);
6086 return WERR_NO_MORE_ITEMS;
6089 free_a_printer(&printer, 2);
6092 * the value is:
6093 * - counted in bytes in the request
6094 * - counted in UNICODE chars in the max reply
6095 * - counted in bytes in the real size
6097 * take a pause *before* coding not *during* coding
6100 *out_max_value_len=(in_value_len/sizeof(uint16));
6101 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6102 SAFE_FREE(data);
6103 return WERR_NOMEM;
6106 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6108 *out_type=type;
6110 /* the data is counted in bytes */
6111 *out_max_data_len=in_data_len;
6112 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6113 SAFE_FREE(data);
6114 return WERR_NOMEM;
6117 memcpy(*data_out, data, (size_t)data_len);
6118 *out_data_len=data_len;
6120 SAFE_FREE(data);
6122 return WERR_OK;
6125 /****************************************************************************
6126 ****************************************************************************/
6128 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6130 POLICY_HND *handle = &q_u->handle;
6131 UNISTR2 *value = &q_u->value;
6132 uint32 type = q_u->type;
6133 /* uint32 max_len = q_u->max_len; - notused. */
6134 uint8 *data = q_u->data;
6135 uint32 real_len = q_u->real_len;
6136 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6138 NT_PRINTER_INFO_LEVEL *printer = NULL;
6139 NT_PRINTER_PARAM *param = NULL, old_param;
6140 int snum=0;
6141 WERROR status = WERR_OK;
6142 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6144 DEBUG(5,("spoolss_setprinterdata\n"));
6146 if (!Printer) {
6147 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6148 return WERR_BADFID;
6151 if (!get_printer_snum(p,handle, &snum))
6152 return WERR_BADFID;
6154 ZERO_STRUCT(old_param);
6157 * Access check : NT returns "access denied" if you make a
6158 * SetPrinterData call without the necessary privildge.
6159 * we were originally returning OK if nothing changed
6160 * which made Win2k issue **a lot** of SetPrinterData
6161 * when connecting to a printer --jerry
6164 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6165 DEBUG(3, ("security descriptor change denied by existing "
6166 "security descriptor\n"));
6167 status = WERR_ACCESS_DENIED;
6168 goto done;
6171 /* Check if we are making any changes or not. Return true if
6172 nothing is actually changing. This is not needed anymore but
6173 has been left in as an optimization to keep from from
6174 writing to disk as often --jerry */
6176 status = get_a_printer(&printer, 2, lp_servicename(snum));
6177 if (!W_ERROR_IS_OK(status))
6178 return status;
6180 convert_specific_param(&param, value , type, data, real_len);
6183 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6184 &old_param.type, (uint32 *)&old_param.data_len)) {
6186 if (param->type == old_param.type &&
6187 param->data_len == old_param.data_len &&
6188 memcmp(param->data, old_param.data,
6189 old_param.data_len) == 0) {
6191 DEBUG(3, ("setprinterdata hasn't changed\n"));
6192 status = WERR_OK;
6193 goto done;
6197 unlink_specific_param_if_exist(printer->info_2, param);
6200 * When client side code sets a magic printer data key, detect it and save
6201 * the current printer data and the magic key's data (its the DEVMODE) for
6202 * future printer/driver initializations.
6204 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6206 * Set devmode and printer initialization info
6208 status = save_driver_init(printer, 2, param);
6210 else {
6211 add_a_specific_param(printer->info_2, &param);
6212 status = mod_a_printer(*printer, 2);
6215 done:
6216 free_a_printer(&printer, 2);
6217 if (param)
6218 free_nt_printer_param(&param);
6219 SAFE_FREE(old_param.data);
6221 return status;
6224 /****************************************************************************
6225 ****************************************************************************/
6227 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6229 POLICY_HND *handle = &q_u->handle;
6230 UNISTR2 *value = &q_u->valuename;
6232 NT_PRINTER_INFO_LEVEL *printer = NULL;
6233 NT_PRINTER_PARAM param;
6234 int snum=0;
6235 WERROR status = WERR_OK;
6236 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6238 DEBUG(5,("spoolss_deleteprinterdata\n"));
6240 if (!Printer) {
6241 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6242 return WERR_BADFID;
6245 if (!get_printer_snum(p, handle, &snum))
6246 return WERR_BADFID;
6248 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6249 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6250 "change denied by existing security descriptor\n"));
6251 return WERR_ACCESS_DENIED;
6254 status = get_a_printer(&printer, 2, lp_servicename(snum));
6255 if (!W_ERROR_IS_OK(status))
6256 return status;
6258 ZERO_STRUCTP(&param);
6259 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6261 if(!unlink_specific_param_if_exist(printer->info_2, &param))
6262 status = WERR_INVALID_PARAM;
6263 else
6264 status = mod_a_printer(*printer, 2);
6266 free_a_printer(&printer, 2);
6267 return status;
6270 /****************************************************************************
6271 ****************************************************************************/
6273 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6275 POLICY_HND *handle = &q_u->handle;
6276 /* uint32 level = q_u->level; - notused. */
6277 FORM *form = &q_u->form;
6278 nt_forms_struct tmpForm;
6280 int count=0;
6281 nt_forms_struct *list=NULL;
6282 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6284 DEBUG(5,("spoolss_addform\n"));
6286 if (!Printer) {
6287 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6288 return WERR_BADFID;
6291 /* can't add if builtin */
6292 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6293 return WERR_INVALID_PARAM;
6296 count=get_ntforms(&list);
6297 if(!add_a_form(&list, form, &count))
6298 return WERR_NOMEM;
6299 write_ntforms(&list, count);
6301 SAFE_FREE(list);
6303 return WERR_OK;
6306 /****************************************************************************
6307 ****************************************************************************/
6309 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6311 POLICY_HND *handle = &q_u->handle;
6312 UNISTR2 *form_name = &q_u->name;
6313 nt_forms_struct tmpForm;
6314 int count=0;
6315 WERROR ret = WERR_OK;
6316 nt_forms_struct *list=NULL;
6317 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6319 DEBUG(5,("spoolss_deleteform\n"));
6321 if (!Printer) {
6322 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6323 return WERR_BADFID;
6326 /* can't delete if builtin */
6327 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6328 return WERR_INVALID_PARAM;
6331 count = get_ntforms(&list);
6332 if(!delete_a_form(&list, form_name, &count, &ret))
6333 return WERR_INVALID_PARAM;
6335 SAFE_FREE(list);
6337 return ret;
6340 /****************************************************************************
6341 ****************************************************************************/
6343 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6345 POLICY_HND *handle = &q_u->handle;
6346 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6347 /* uint32 level = q_u->level; - notused. */
6348 FORM *form = &q_u->form;
6349 nt_forms_struct tmpForm;
6351 int count=0;
6352 nt_forms_struct *list=NULL;
6353 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6355 DEBUG(5,("spoolss_setform\n"));
6357 if (!Printer) {
6358 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6359 return WERR_BADFID;
6361 /* can't set if builtin */
6362 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6363 return WERR_INVALID_PARAM;
6366 count=get_ntforms(&list);
6367 update_a_form(&list, form, count);
6368 write_ntforms(&list, count);
6370 SAFE_FREE(list);
6372 return WERR_OK;
6375 /****************************************************************************
6376 enumprintprocessors level 1.
6377 ****************************************************************************/
6378 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6380 PRINTPROCESSOR_1 *info_1=NULL;
6382 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6383 return WERR_NOMEM;
6385 (*returned) = 0x1;
6387 init_unistr(&info_1->name, "winprint");
6389 *needed += spoolss_size_printprocessor_info_1(info_1);
6391 if (!alloc_buffer_size(buffer, *needed))
6392 return WERR_INSUFFICIENT_BUFFER;
6394 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6396 SAFE_FREE(info_1);
6398 if (*needed > offered) {
6399 *returned=0;
6400 return WERR_INSUFFICIENT_BUFFER;
6403 return WERR_OK;
6406 /****************************************************************************
6407 ****************************************************************************/
6409 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6411 /* UNISTR2 *name = &q_u->name; - notused. */
6412 /* UNISTR2 *environment = &q_u->environment; - notused. */
6413 uint32 level = q_u->level;
6414 NEW_BUFFER *buffer = NULL;
6415 uint32 offered = q_u->offered;
6416 uint32 *needed = &r_u->needed;
6417 uint32 *returned = &r_u->returned;
6419 /* that's an [in out] buffer */
6420 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6421 buffer = r_u->buffer;
6423 DEBUG(5,("spoolss_enumprintprocessors\n"));
6426 * Enumerate the print processors ...
6428 * Just reply with "winprint", to keep NT happy
6429 * and I can use my nice printer checker.
6432 *returned=0;
6433 *needed=0;
6435 switch (level) {
6436 case 1:
6437 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6438 default:
6439 return WERR_UNKNOWN_LEVEL;
6443 /****************************************************************************
6444 enumprintprocdatatypes level 1.
6445 ****************************************************************************/
6446 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6448 PRINTPROCDATATYPE_1 *info_1=NULL;
6450 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6451 return WERR_NOMEM;
6453 (*returned) = 0x1;
6455 init_unistr(&info_1->name, "RAW");
6457 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6459 if (!alloc_buffer_size(buffer, *needed))
6460 return WERR_INSUFFICIENT_BUFFER;
6462 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6464 SAFE_FREE(info_1);
6466 if (*needed > offered) {
6467 *returned=0;
6468 return WERR_INSUFFICIENT_BUFFER;
6471 return WERR_OK;
6474 /****************************************************************************
6475 ****************************************************************************/
6477 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6479 /* UNISTR2 *name = &q_u->name; - notused. */
6480 /* UNISTR2 *processor = &q_u->processor; - notused. */
6481 uint32 level = q_u->level;
6482 NEW_BUFFER *buffer = NULL;
6483 uint32 offered = q_u->offered;
6484 uint32 *needed = &r_u->needed;
6485 uint32 *returned = &r_u->returned;
6487 /* that's an [in out] buffer */
6488 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6489 buffer = r_u->buffer;
6491 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6493 *returned=0;
6494 *needed=0;
6496 switch (level) {
6497 case 1:
6498 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6499 default:
6500 return WERR_UNKNOWN_LEVEL;
6504 /****************************************************************************
6505 enumprintmonitors level 1.
6506 ****************************************************************************/
6508 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6510 PRINTMONITOR_1 *info_1=NULL;
6512 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6513 return WERR_NOMEM;
6515 (*returned) = 0x1;
6517 init_unistr(&info_1->name, "Local Port");
6519 *needed += spoolss_size_printmonitor_info_1(info_1);
6521 if (!alloc_buffer_size(buffer, *needed))
6522 return WERR_INSUFFICIENT_BUFFER;
6524 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6526 SAFE_FREE(info_1);
6528 if (*needed > offered) {
6529 *returned=0;
6530 return WERR_INSUFFICIENT_BUFFER;
6533 return WERR_OK;
6536 /****************************************************************************
6537 enumprintmonitors level 2.
6538 ****************************************************************************/
6539 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6541 PRINTMONITOR_2 *info_2=NULL;
6543 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6544 return WERR_NOMEM;
6546 (*returned) = 0x1;
6548 init_unistr(&info_2->name, "Local Port");
6549 init_unistr(&info_2->environment, "Windows NT X86");
6550 init_unistr(&info_2->dll_name, "localmon.dll");
6552 *needed += spoolss_size_printmonitor_info_2(info_2);
6554 if (!alloc_buffer_size(buffer, *needed))
6555 return WERR_INSUFFICIENT_BUFFER;
6557 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6559 SAFE_FREE(info_2);
6561 if (*needed > offered) {
6562 *returned=0;
6563 return WERR_INSUFFICIENT_BUFFER;
6566 return WERR_OK;
6569 /****************************************************************************
6570 ****************************************************************************/
6572 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6574 /* UNISTR2 *name = &q_u->name; - notused. */
6575 uint32 level = q_u->level;
6576 NEW_BUFFER *buffer = NULL;
6577 uint32 offered = q_u->offered;
6578 uint32 *needed = &r_u->needed;
6579 uint32 *returned = &r_u->returned;
6581 /* that's an [in out] buffer */
6582 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6583 buffer = r_u->buffer;
6585 DEBUG(5,("spoolss_enumprintmonitors\n"));
6588 * Enumerate the print monitors ...
6590 * Just reply with "Local Port", to keep NT happy
6591 * and I can use my nice printer checker.
6594 *returned=0;
6595 *needed=0;
6597 switch (level) {
6598 case 1:
6599 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6600 case 2:
6601 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6602 default:
6603 return WERR_UNKNOWN_LEVEL;
6607 /****************************************************************************
6608 ****************************************************************************/
6609 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6611 int i=0;
6612 BOOL found=False;
6613 JOB_INFO_1 *info_1=NULL;
6615 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6617 if (info_1 == NULL) {
6618 SAFE_FREE(queue);
6619 return WERR_NOMEM;
6622 for (i=0; i<count && found==False; i++) {
6623 if (queue[i].job==(int)jobid)
6624 found=True;
6627 if (found==False) {
6628 SAFE_FREE(queue);
6629 SAFE_FREE(info_1);
6630 /* NT treats not found as bad param... yet another bad choice */
6631 return WERR_INVALID_PARAM;
6634 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6636 SAFE_FREE(queue);
6638 *needed += spoolss_size_job_info_1(info_1);
6640 if (!alloc_buffer_size(buffer, *needed)) {
6641 SAFE_FREE(info_1);
6642 return WERR_INSUFFICIENT_BUFFER;
6645 smb_io_job_info_1("", buffer, info_1, 0);
6647 SAFE_FREE(info_1);
6649 if (*needed > offered)
6650 return WERR_INSUFFICIENT_BUFFER;
6652 return WERR_OK;
6656 /****************************************************************************
6657 ****************************************************************************/
6658 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6660 int i=0;
6661 BOOL found=False;
6662 JOB_INFO_2 *info_2;
6663 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6664 WERROR ret;
6666 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6668 ZERO_STRUCTP(info_2);
6670 if (info_2 == NULL) {
6671 SAFE_FREE(queue);
6672 return WERR_NOMEM;
6675 for (i=0; i<count && found==False; i++) {
6676 if (queue[i].job==(int)jobid)
6677 found=True;
6680 if (found==False) {
6681 SAFE_FREE(queue);
6682 SAFE_FREE(info_2);
6683 /* NT treats not found as bad param... yet another bad choice */
6684 return WERR_INVALID_PARAM;
6687 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6688 if (!W_ERROR_IS_OK(ret)) {
6689 SAFE_FREE(queue);
6690 return ret;
6693 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6695 free_a_printer(&ntprinter, 2);
6696 SAFE_FREE(queue);
6698 *needed += spoolss_size_job_info_2(info_2);
6700 if (!alloc_buffer_size(buffer, *needed)) {
6701 SAFE_FREE(info_2);
6702 return WERR_INSUFFICIENT_BUFFER;
6705 smb_io_job_info_2("", buffer, info_2, 0);
6707 free_job_info_2(info_2);
6708 SAFE_FREE(info_2);
6710 if (*needed > offered)
6711 return WERR_INSUFFICIENT_BUFFER;
6713 return WERR_OK;
6716 /****************************************************************************
6717 ****************************************************************************/
6719 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6721 POLICY_HND *handle = &q_u->handle;
6722 uint32 jobid = q_u->jobid;
6723 uint32 level = q_u->level;
6724 NEW_BUFFER *buffer = NULL;
6725 uint32 offered = q_u->offered;
6726 uint32 *needed = &r_u->needed;
6728 int snum;
6729 int count;
6730 print_queue_struct *queue=NULL;
6731 print_status_struct prt_status;
6733 /* that's an [in out] buffer */
6734 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6735 buffer = r_u->buffer;
6737 DEBUG(5,("spoolss_getjob\n"));
6739 *needed=0;
6741 if (!get_printer_snum(p, handle, &snum))
6742 return WERR_BADFID;
6744 count = print_queue_status(snum, &queue, &prt_status);
6746 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6747 count, prt_status.status, prt_status.message));
6749 switch (level) {
6750 case 1:
6751 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6752 case 2:
6753 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6754 default:
6755 SAFE_FREE(queue);
6756 return WERR_UNKNOWN_LEVEL;
6760 /********************************************************************
6761 * spoolss_getprinterdataex
6762 ********************************************************************/
6764 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6766 POLICY_HND *handle = &q_u->handle;
6767 uint32 in_size = q_u->size;
6768 uint32 *type = &r_u->type;
6769 uint32 *out_size = &r_u->size;
6770 uint8 **data = &r_u->data;
6771 uint32 *needed = &r_u->needed;
6773 fstring key, value;
6774 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6775 BOOL found = False;
6777 DEBUG(4,("_spoolss_getprinterdataex\n"));
6779 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6780 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6782 /* in case of problem, return some default values */
6783 *needed=0;
6784 *type=0;
6785 *out_size=0;
6788 if (!Printer) {
6789 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6790 return WERR_NOMEM;
6791 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6792 return WERR_BADFID;
6796 /* Is the handle to a printer or to the server? */
6798 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6800 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6801 return WERR_INVALID_PARAM;
6803 else
6806 * From MSDN documentation of GetPrinterDataEx: pass request
6807 * to GetPrinterData if key is "PrinterDriverData". This is
6808 * the only key we really support. Other keys to implement:
6809 * (a) DsDriver
6810 * (b) DsSpooler
6811 * (c) PnPData
6814 if (strcmp(key, "PrinterDriverData") != 0)
6815 return WERR_INVALID_PARAM;
6817 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6818 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
6819 type, data, needed, in_size);
6823 if (!found) {
6824 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6826 /* reply this param doesn't exist */
6827 if (*out_size) {
6828 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6829 return WERR_NOMEM;
6830 } else {
6831 *data = NULL;
6834 return WERR_INVALID_PARAM;
6837 if (*needed > *out_size)
6838 return WERR_MORE_DATA;
6839 else
6840 return WERR_OK;
6843 /********************************************************************
6844 * spoolss_setprinterdata
6845 ********************************************************************/
6847 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6849 SPOOL_Q_SETPRINTERDATA q_u_local;
6850 SPOOL_R_SETPRINTERDATA r_u_local;
6851 fstring key;
6853 DEBUG(4,("_spoolss_setprinterdataex\n"));
6855 /* From MSDN documentation of SetPrinterDataEx: pass request to
6856 SetPrinterData if key is "PrinterDriverData" */
6858 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6860 if (strcmp(key, "PrinterDriverData") == 0)
6861 return WERR_INVALID_PARAM;
6863 ZERO_STRUCT(q_u_local);
6864 ZERO_STRUCT(r_u_local);
6866 /* make a copy to call _spoolss_setprinterdata() */
6868 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
6869 copy_unistr2(&q_u_local.value, &q_u->value);
6870 q_u_local.type = q_u->type;
6871 q_u_local.max_len = q_u->max_len;
6872 q_u_local.data = q_u->data;
6873 q_u_local.real_len = q_u->real_len;
6874 q_u_local.numeric_data = q_u->numeric_data;
6876 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
6879 /********************************************************************
6880 * spoolss_enumprinterkey
6881 ********************************************************************/
6883 /* constants for EnumPrinterKey() */
6884 #define ENUMERATED_KEY_SIZE 19
6886 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
6888 fstring key;
6889 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
6890 char* ptr = NULL;
6891 int i;
6892 char *PrinterKey = "PrinterDriverData";
6894 DEBUG(4,("_spoolss_enumprinterkey\n"));
6896 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6899 * we only support enumating all keys (key == "")
6900 * Of course, the only key we support is the "PrinterDriverData"
6901 * key
6903 if (strlen(key) == 0)
6905 r_u->needed = ENUMERATED_KEY_SIZE *2;
6906 if (q_u->size < r_u->needed)
6907 return WERR_MORE_DATA;
6909 ptr = PrinterKey;
6910 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
6912 enumkeys[i] = (uint16)(*ptr);
6913 ptr++;
6916 /* tag of with 2 '\0's */
6917 enumkeys[i++] = '\0';
6918 enumkeys[i] = '\0';
6920 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
6921 return WERR_BADFILE;
6923 return WERR_OK;
6926 /* The "PrinterDriverData" key should have no subkeys */
6927 if (strcmp(key, PrinterKey) == 0)
6929 r_u-> needed = 2;
6930 if (q_u->size < r_u->needed)
6931 return WERR_MORE_DATA;
6932 enumkeys[0] = 0x0;
6933 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
6934 return WERR_BADFILE;
6936 return WERR_OK;
6940 /* The return value for an unknown key is documented in MSDN
6941 EnumPrinterKey description */
6942 return WERR_BADFILE;
6945 /********************************************************************
6946 * spoolss_enumprinterdataex
6947 ********************************************************************/
6949 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
6951 POLICY_HND *handle = &q_u->handle;
6952 uint32 in_size = q_u->size;
6953 uint32 num_entries,
6954 needed;
6955 NT_PRINTER_INFO_LEVEL *printer = NULL;
6956 PRINTER_ENUM_VALUES *enum_values = NULL;
6957 fstring key, value;
6958 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6959 int snum;
6960 uint32 param_index,
6961 data_len,
6962 type;
6963 WERROR result;
6964 uint8 *data=NULL;
6967 DEBUG(4,("_spoolss_enumprinterdataex\n"));
6969 if (!Printer) {
6970 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6971 return WERR_BADFID;
6976 * The only key we support is "PrinterDriverData". This should return
6977 > an array of all the key/value pairs returned by EnumPrinterDataSee
6978 * _spoolss_getprinterdataex() for details --jerry
6981 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6982 if (strcmp(key, "PrinterDriverData") != 0)
6984 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
6985 return WERR_INVALID_PARAM;
6989 if (!get_printer_snum(p,handle, &snum))
6990 return WERR_BADFID;
6992 ZERO_STRUCT(printer);
6993 result = get_a_printer(&printer, 2, lp_servicename(snum));
6994 if (!W_ERROR_IS_OK(result))
6995 return result;
6999 * loop through all params and build the array to pass
7000 * back to the client
7002 result = WERR_OK;
7003 param_index = 0;
7004 needed = 0;
7005 num_entries = 0;
7007 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7009 PRINTER_ENUM_VALUES *ptr;
7010 uint32 add_len = 0;
7012 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7014 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7016 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7017 result = WERR_NOMEM;
7018 goto done;
7020 enum_values = ptr;
7022 /* copy the data */
7023 init_unistr(&enum_values[num_entries].valuename, value);
7024 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7025 enum_values[num_entries].type = type;
7028 * NULL terminate REG_SZ
7029 * FIXME!!! We should not be correctly problems in the way
7030 * we store PrinterData here. Need to investogate
7031 * SetPrinterData[Ex] --jerry
7034 if (type == REG_SZ) {
7035 /* fix alignment if the string was stored
7036 in a bizarre fashion */
7037 if ((data_len % 2) == 0)
7038 add_len = 2;
7039 else
7040 add_len = data_len % 2;
7043 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7044 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7045 result = WERR_NOMEM;
7046 goto done;
7048 memcpy(enum_values[num_entries].data, data, data_len);
7049 enum_values[num_entries].data_len = data_len + add_len;
7051 /* keep track of the size of the array in bytes */
7053 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7055 num_entries++;
7056 param_index++;
7059 r_u->needed = needed;
7060 r_u->returned = num_entries;
7062 if (needed > in_size) {
7063 result = WERR_MORE_DATA;
7064 goto done;
7067 /* copy data into the reply */
7069 r_u->ctr.size = r_u->needed;
7070 r_u->ctr.size_of_array = r_u->returned;
7071 r_u->ctr.values = enum_values;
7075 done:
7076 free_a_printer(&printer, 2);
7078 return result;
7081 /****************************************************************************
7082 ****************************************************************************/
7084 /* Disabled because it doesn't fix the bug I am looking at but it would be
7085 a shame to throw away the code. -tpot */
7087 #if 0
7089 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7091 init_unistr(&info->name, name);
7094 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
7095 UNISTR2 *environment,
7096 NEW_BUFFER *buffer,
7097 uint32 offered,
7098 uint32 *needed)
7100 pstring path;
7101 pstring long_archi;
7102 pstring short_archi;
7103 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7105 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7107 if (get_short_archi(short_archi, long_archi)==FALSE)
7108 return WERR_INVALID_ENVIRONMENT;
7110 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7111 return WERR_NOMEM;
7113 /* Not sure what to return here - are UNC names valid here?.
7114 Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7115 which is pretty bogus for a RPC. */
7117 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
7119 DEBUG(4,("print processor directory: [%s]\n", path));
7121 fill_printprocessordirectory_1(info, path);
7123 *needed += spoolss_size_printprocessordirectory_info_1(info);
7125 if (!alloc_buffer_size(buffer, *needed)) {
7126 safe_free(info);
7127 return WERR_INSUFFICIENT_BUFFER;
7130 smb_io_printprocessordirectory_1("", buffer, info, 0);
7132 safe_free(info);
7134 if (*needed > offered)
7135 return WERR_INSUFFICIENT_BUFFER;
7136 else
7137 return WERR_OK;
7140 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7142 uint32 level = q_u->level;
7143 NEW_BUFFER *buffer = NULL;
7144 uint32 offered = q_u->offered;
7145 uint32 *needed = &r_u->needed;
7147 /* that's an [in out] buffer */
7148 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7149 buffer = r_u->buffer;
7151 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7153 *needed=0;
7155 switch(level) {
7156 case 1:
7157 return getprintprocessordirectory_level_1
7158 (&q_u->name, &q_u->environment, buffer, offered, needed);
7159 default:
7160 return WERR_UNKNOWN_LEVEL;
7163 return WERR_ACCESS_DENIED;
7166 #endif