merge from SAMBA_2_2
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobd6ce06554845089ef50987e62629cc5401c3486a
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001,
8 * Copyright (C) Gerald Carter 2000-2001,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
33 #endif
35 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
36 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
37 #define PRINTER_HANDLE_IS_PRINTER 0
38 #define PRINTER_HANDLE_IS_PRINTSERVER 1
40 struct table_node {
41 char *long_archi;
42 char *short_archi;
43 int version;
47 /* structure to store the printer handles */
48 /* and a reference to what it's pointing to */
49 /* and the notify info asked about */
50 /* that's the central struct */
51 typedef struct _Printer{
52 struct _Printer *prev, *next;
53 BOOL document_started;
54 BOOL page_started;
55 int jobid; /* jobid in printing backend */
56 BOOL printer_type;
57 union {
58 fstring handlename;
59 fstring printerservername;
60 } dev;
61 uint32 type;
62 uint32 access_granted;
63 struct {
64 uint32 flags;
65 uint32 options;
66 fstring localmachine;
67 uint32 printerlocal;
68 SPOOL_NOTIFY_OPTION *option;
69 POLICY_HND client_hnd;
70 uint32 client_connected;
71 } notify;
72 struct {
73 fstring machine;
74 fstring user;
75 } client;
76 } Printer_entry;
78 static Printer_entry *printers_list;
80 typedef struct _counter_printer_0 {
81 ubi_dlNode Next;
82 ubi_dlNode Prev;
84 int snum;
85 uint32 counter;
86 } counter_printer_0;
88 static ubi_dlList counter_list;
90 static struct cli_state cli;
91 static uint32 smb_connections=0;
94 /* in printing/nt_printing.c */
96 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
98 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
99 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v)
104 switch (v) {
105 case LPQ_QUEUED:
106 return 0;
107 case LPQ_PAUSED:
108 return JOB_STATUS_PAUSED;
109 case LPQ_SPOOLING:
110 return JOB_STATUS_SPOOLING;
111 case LPQ_PRINTING:
112 return JOB_STATUS_PRINTING;
113 case LPQ_ERROR:
114 return JOB_STATUS_ERROR;
115 case LPQ_DELETING:
116 return JOB_STATUS_DELETING;
117 case LPQ_OFFLINE:
118 return JOB_STATUS_OFFLINE;
119 case LPQ_PAPEROUT:
120 return JOB_STATUS_PAPEROUT;
121 case LPQ_PRINTED:
122 return JOB_STATUS_PRINTED;
123 case LPQ_DELETED:
124 return JOB_STATUS_DELETED;
125 case LPQ_BLOCKED:
126 return JOB_STATUS_BLOCKED;
127 case LPQ_USER_INTERVENTION:
128 return JOB_STATUS_USER_INTERVENTION;
130 return 0;
133 static int nt_printq_status(int v)
135 switch (v) {
136 case LPQ_PAUSED:
137 return PRINTER_STATUS_PAUSED;
138 case LPQ_QUEUED:
139 case LPQ_SPOOLING:
140 case LPQ_PRINTING:
141 return 0;
143 return 0;
146 /****************************************************************************
147 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
148 ****************************************************************************/
150 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
152 if (*pp == NULL)
153 return;
155 SAFE_FREE((*pp)->ctr.type);
156 SAFE_FREE(*pp);
159 /***************************************************************************
160 Disconnect from the client
161 ****************************************************************************/
163 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
165 WERROR result;
167 /* weird if the test succeds !!! */
168 if (smb_connections==0) {
169 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
170 return;
173 result = cli_spoolss_reply_close_printer(&cli, cli.mem_ctx, handle);
175 if (!W_ERROR_IS_OK(result))
176 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
177 dos_errstr(result)));
179 /* if it's the last connection, deconnect the IPC$ share */
180 if (smb_connections==1) {
181 if(!spoolss_disconnect_from_client(&cli))
182 return;
184 message_deregister(MSG_PRINTER_NOTIFY);
187 smb_connections--;
190 /****************************************************************************
191 Functions to free a printer entry datastruct.
192 ****************************************************************************/
194 static void free_printer_entry(void *ptr)
196 Printer_entry *Printer = (Printer_entry *)ptr;
198 if (Printer->notify.client_connected==True)
199 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
201 Printer->notify.flags=0;
202 Printer->notify.options=0;
203 Printer->notify.localmachine[0]='\0';
204 Printer->notify.printerlocal=0;
205 free_spool_notify_option(&Printer->notify.option);
206 Printer->notify.option=NULL;
207 Printer->notify.client_connected=False;
209 /* Remove from the internal list. */
210 DLIST_REMOVE(printers_list, Printer);
212 SAFE_FREE(Printer);
215 /****************************************************************************
216 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
217 ****************************************************************************/
219 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
221 SPOOL_NOTIFY_OPTION *new_sp = NULL;
223 if (!sp)
224 return NULL;
226 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
227 if (!new_sp)
228 return NULL;
230 *new_sp = *sp;
232 if (sp->ctr.count) {
233 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
235 if (!new_sp->ctr.type) {
236 SAFE_FREE(new_sp);
237 return NULL;
241 return new_sp;
244 /****************************************************************************
245 find printer index by handle
246 ****************************************************************************/
248 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
250 Printer_entry *find_printer = NULL;
252 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
253 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
254 return NULL;
257 return find_printer;
260 /****************************************************************************
261 Close printer index by handle.
262 ****************************************************************************/
264 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
266 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
268 if (!Printer) {
269 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
270 return False;
273 close_policy_hnd(p, hnd);
275 return True;
278 /****************************************************************************
279 Delete a printer given a handle.
280 ****************************************************************************/
282 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
284 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
286 if (!Printer) {
287 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
288 return WERR_BADFID;
291 if (del_a_printer(Printer->dev.handlename) != 0) {
292 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
293 return WERR_BADFID;
296 /* Check calling user has permission to delete printer. Note that
297 since we set the snum parameter to -1 only administrators can
298 delete the printer. This stops people with the Full Control
299 permission from deleting the printer. */
301 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
302 DEBUG(3, ("printer delete denied by security descriptor\n"));
303 return WERR_ACCESS_DENIED;
306 if (*lp_deleteprinter_cmd()) {
308 char *cmd = lp_deleteprinter_cmd();
309 pstring command;
310 int ret;
311 int i;
313 /* Printer->dev.handlename equals portname equals sharename */
314 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
315 Printer->dev.handlename);
317 DEBUG(10,("Running [%s]\n", command));
318 ret = smbrun(command, NULL);
319 if (ret != 0) {
320 return WERR_BADFID; /* What to return here? */
322 DEBUGADD(10,("returned [%d]\n", ret));
324 /* Send SIGHUP to process group... is there a better way? */
325 kill(0, SIGHUP);
327 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
328 lp_killservice( i );
329 return WERR_OK;
330 } else
331 return WERR_ACCESS_DENIED;
334 return WERR_OK;
337 /****************************************************************************
338 Return the snum of a printer corresponding to an handle.
339 ****************************************************************************/
341 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
343 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
345 if (!Printer) {
346 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
347 return False;
350 switch (Printer->printer_type) {
351 case PRINTER_HANDLE_IS_PRINTER:
352 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
353 *number = print_queue_snum(Printer->dev.handlename);
354 return (*number != -1);
355 case PRINTER_HANDLE_IS_PRINTSERVER:
356 return False;
357 default:
358 return False;
362 /****************************************************************************
363 Set printer handle type.
364 Check if it's \\server or \\server\printer
365 ****************************************************************************/
367 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
369 DEBUG(3,("Setting printer type=%s\n", handlename));
371 if ( strlen(handlename) < 3 ) {
372 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
373 return False;
376 /* it's a print server */
377 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
378 DEBUGADD(4,("Printer is a print server\n"));
379 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
381 /* it's a printer */
382 else {
383 DEBUGADD(4,("Printer is a printer\n"));
384 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
387 return True;
390 /****************************************************************************
391 Set printer handle name.
392 ****************************************************************************/
394 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
396 int snum;
397 int n_services=lp_numservices();
398 char *aprinter;
399 fstring sname;
400 BOOL found=False;
402 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
404 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
405 ZERO_STRUCT(Printer->dev.printerservername);
406 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
407 return True;
410 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
411 return False;
413 if (*handlename=='\\') {
414 aprinter=strchr_m(handlename+2, '\\');
415 aprinter++;
417 else {
418 aprinter=handlename;
421 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
424 * The original code allowed smbd to store a printer name that
425 * was different from the share name. This is not possible
426 * anymore, so I've simplified this loop greatly. Here
427 * we are just verifying that the printer name is a valid
428 * printer service defined in smb.conf
429 * --jerry [Fri Feb 15 11:17:46 CST 2002]
432 for (snum=0; snum<n_services; snum++) {
434 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
435 continue;
437 fstrcpy(sname, lp_servicename(snum));
439 DEBUGADD(5,("share:%s\n",sname));
441 if (! StrCaseCmp(sname, aprinter)) {
442 found = True;
443 break;
449 if (!found) {
450 DEBUGADD(4,("Printer not found\n"));
451 return False;
454 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
456 ZERO_STRUCT(Printer->dev.handlename);
457 fstrcpy(Printer->dev.handlename, sname);
459 return True;
462 /****************************************************************************
463 Find first available printer slot. creates a printer handle for you.
464 ****************************************************************************/
466 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
468 Printer_entry *new_printer;
470 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
472 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
473 return False;
475 ZERO_STRUCTP(new_printer);
477 new_printer->notify.option=NULL;
479 /* Add to the internal list. */
480 DLIST_ADD(printers_list, new_printer);
482 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
483 SAFE_FREE(new_printer);
484 return False;
487 if (!set_printer_hnd_printertype(new_printer, name)) {
488 close_printer_handle(p, hnd);
489 return False;
492 if (!set_printer_hnd_name(new_printer, name)) {
493 close_printer_handle(p, hnd);
494 return False;
497 new_printer->access_granted = access_granted;
499 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
501 return True;
504 /****************************************************************************
505 Allocate more memory for a BUFFER.
506 ****************************************************************************/
508 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
510 prs_struct *ps;
511 uint32 extra_space;
512 uint32 old_offset;
514 ps= &buffer->prs;
516 /* damn, I'm doing the reverse operation of prs_grow() :) */
517 if (buffer_size < prs_data_size(ps))
518 extra_space=0;
519 else
520 extra_space = buffer_size - prs_data_size(ps);
523 * save the offset and move to the end of the buffer
524 * prs_grow() checks the extra_space against the offset
526 old_offset=prs_offset(ps);
527 prs_set_offset(ps, prs_data_size(ps));
529 if (!prs_grow(ps, extra_space))
530 return False;
532 prs_set_offset(ps, old_offset);
534 buffer->string_at_end=prs_data_size(ps);
536 return True;
538 /***************************************************************************
539 Always give preference Printer_entry.notify.option over
540 Printer_entry.notify.flags. Return True if we should send notification
541 events using SPOOLSS_RRPCN. False means that we should use
542 SPOOLSS_ROUTERREPLYPRINTER.
543 **************************************************************************/
544 static BOOL valid_notify_options(Printer_entry *printer)
546 if (printer->notify.option == NULL)
547 return False;
549 return True;
552 /***************************************************************************
553 Simple check to see if the client motify handle is set to watch for events
554 represented by 'flags'
556 FIXME!!!! only a stub right now --jerry
557 **************************************************************************/
559 static BOOL is_client_monitoring_event(Printer_entry *p, uint32 flags)
562 return True;
565 /***************************************************************************
566 Server wrapper for cli_spoolss_routerreplyprinter() since the client
567 function can only send a single change notification at a time.
569 FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
570 --jerry
571 **************************************************************************/
573 static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
574 POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
575 NT_PRINTER_INFO_LEVEL *printer)
577 WERROR result;
578 uint32 condition = 0x0;
580 if (info->flags & PRINTER_MESSAGE_DRIVER)
581 condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
583 result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
584 printer->info_2->changeid);
586 return result;
589 /***********************************************************************
590 Wrapper around the decision of which RPC use to in the change
591 notification
592 **********************************************************************/
594 static WERROR srv_spoolss_send_event_to_client(Printer_entry* Printer,
595 struct cli_state *send_cli, PRINTER_MESSAGE_INFO *msg,
596 NT_PRINTER_INFO_LEVEL *info)
598 WERROR result;
600 if (valid_notify_options(Printer)) {
601 /* This is a single call that can send information about multiple changes */
602 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
603 msg->flags |= PRINTER_MESSAGE_ATTRIBUTES;
605 result = cli_spoolss_reply_rrpcn(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
606 msg, info);
608 else {
609 /* This requires that the server send an individual event notification for each change */
610 result = srv_spoolss_routerreplyprinter(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
611 msg, info);
614 return result;
618 /***********************************************************************
619 Send a change notication message on all handles which have a call
620 back registered
621 **********************************************************************/
623 static void send_spoolss_event_notification(PRINTER_MESSAGE_INFO *msg)
625 Printer_entry *find_printer;
626 WERROR result;
627 NT_PRINTER_INFO_LEVEL *printer = NULL;
629 if (!msg) {
630 DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n"));
631 return;
634 for(find_printer = printers_list; find_printer; find_printer = find_printer->next) {
637 * If the entry has a connected client we send the message. There should
638 * only be one of these normally when dealing with the NT/2k spooler.
639 * However, iterate over all to make sure we deal with user applications
640 * in addition to spooler service.
642 * While we are only maintaining a single connection to the client,
643 * the FindFirstPrinterChangeNotification() call is made on a printer
644 * handle, so "client_connected" represents the whether or not the
645 * client asked for change notication on this handle.
647 * --jerry
650 if (find_printer->notify.client_connected==True) {
652 /* does the client care about what changed? */
654 if (msg->flags && !is_client_monitoring_event(find_printer, msg->flags)) {
655 DEBUG(10,("send_spoolss_event_notification: Client [%s] not monitoring these events\n",
656 find_printer->client.machine));
657 continue;
660 if (find_printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
661 DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer->dev.printerservername ));
662 else
663 DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer->dev.handlename));
666 * if handle is a printer, only send if the printer_name matches.
667 * ...else if handle is a printerserver, send to all
670 if (*msg->printer_name && (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
671 && !strequal(msg->printer_name, find_printer->dev.handlename))
673 DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n",
674 msg->printer_name, find_printer->dev.handlename ));
675 continue;
679 /* lookup the printer if we have a name if we don't already have a
680 valid NT_PRINTER_INFO_LEVEL structure. And yes I'm assuming we
681 will always have a non-empty msg.printer_name */
683 if (!printer || !printer->info_2 || strcmp(msg->printer_name, printer->info_2->printername))
686 if (printer) {
687 free_a_printer(&printer, 2);
688 printer = NULL;
691 result = get_a_printer(&printer, 2, msg->printer_name);
692 if (!W_ERROR_IS_OK(result))
693 continue;
696 /* issue the client call */
698 result = srv_spoolss_send_event_to_client(find_printer, &cli, msg, printer);
700 if (!W_ERROR_IS_OK(result)) {
701 DEBUG(5,("send_spoolss_event_notification: Event notification failed [%s]\n",
702 dos_errstr(result)));
707 return;
709 /***************************************************************************
710 Receive the notify message and decode the message. Do not send
711 notification if we sent this originally as that would result in
712 duplicates.
713 ****************************************************************************/
715 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
717 PRINTER_MESSAGE_INFO msg;
719 if (len < sizeof(msg)) {
720 DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len));
721 return;
724 memcpy(&msg, buf, sizeof(PRINTER_MESSAGE_INFO));
726 DEBUG(10,("srv_spoolss_receive_message: Got message printer change [queue = %s] low=0x%x high=0x%x flags=0x%x\n",
727 msg.printer_name, (unsigned int)msg.low, (unsigned int)msg.high, msg.flags ));
729 /* Iterate the printer list */
731 send_spoolss_event_notification(&msg);
735 /***************************************************************************
736 Send a notify event.
737 ****************************************************************************/
739 static BOOL srv_spoolss_sendnotify(char* printer_name, uint32 high, uint32 low, uint32 flags)
741 char msg[sizeof(PRINTER_MESSAGE_INFO)];
742 PRINTER_MESSAGE_INFO info;
744 ZERO_STRUCT(info);
746 info.low = low;
747 info.high = high;
748 info.flags = flags;
749 fstrcpy(info.printer_name, printer_name);
751 memcpy(msg, &info, sizeof(PRINTER_MESSAGE_INFO));
753 DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x [%s], flags=0x%x\n",
754 low, high, printer_name, flags));
756 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(PRINTER_MESSAGE_INFO),
757 False, NULL);
759 return True;
762 /********************************************************************
763 Copy routines used by convert_to_openprinterex()
764 *******************************************************************/
766 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
768 DEVICEMODE *d;
769 int len;
771 if (!devmode)
772 return NULL;
774 DEBUG (8,("dup_devmode\n"));
776 /* bulk copy first */
778 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
779 if (!d)
780 return NULL;
782 /* dup the pointer members separately */
784 len = unistrlen(devmode->devicename.buffer);
785 if (len != -1) {
786 d->devicename.buffer = talloc(ctx, len*2);
787 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
788 return NULL;
792 len = unistrlen(devmode->formname.buffer);
793 if (len != -1) {
794 d->devicename.buffer = talloc(ctx, len*2);
795 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
796 return NULL;
799 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
801 return d;
804 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
806 if (!new_ctr || !ctr)
807 return;
809 DEBUG(8,("copy_devmode_ctr\n"));
811 new_ctr->size = ctr->size;
812 new_ctr->devmode_ptr = ctr->devmode_ptr;
814 if(ctr->devmode_ptr)
815 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
818 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
820 if (!new_def || !def)
821 return;
823 DEBUG(8,("copy_printer_defaults\n"));
825 new_def->datatype_ptr = def->datatype_ptr;
827 if (def->datatype_ptr)
828 copy_unistr2(&new_def->datatype, &def->datatype);
830 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
832 new_def->access_required = def->access_required;
835 /********************************************************************
836 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
837 * SPOOL_Q_OPEN_PRINTER_EX structure
838 ********************************************************************/
840 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
842 if (!q_u_ex || !q_u)
843 return;
845 DEBUG(8,("convert_to_openprinterex\n"));
847 q_u_ex->printername_ptr = q_u->printername_ptr;
849 if (q_u->printername_ptr)
850 copy_unistr2(&q_u_ex->printername, &q_u->printername);
852 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
855 /********************************************************************
856 * spoolss_open_printer
858 * called from the spoolss dispatcher
859 ********************************************************************/
861 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
863 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
864 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
866 if (!q_u || !r_u)
867 return WERR_NOMEM;
869 ZERO_STRUCT(q_u_ex);
870 ZERO_STRUCT(r_u_ex);
872 /* convert the OpenPrinter() call to OpenPrinterEx() */
874 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
876 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
878 /* convert back to OpenPrinter() */
880 memcpy(r_u, &r_u_ex, sizeof(*r_u));
882 return r_u->status;
885 /********************************************************************
886 * spoolss_open_printer
888 * called from the spoolss dispatcher
889 ********************************************************************/
891 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
893 UNISTR2 *printername = NULL;
894 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
895 /* uint32 user_switch = q_u->user_switch; - notused */
896 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
897 POLICY_HND *handle = &r_u->handle;
899 fstring name;
900 int snum;
901 struct current_user user;
902 Printer_entry *Printer=NULL;
904 if (q_u->printername_ptr != 0)
905 printername = &q_u->printername;
907 if (printername == NULL)
908 return WERR_INVALID_PRINTER_NAME;
910 /* some sanity check because you can open a printer or a print server */
911 /* aka: \\server\printer or \\server */
912 unistr2_to_ascii(name, printername, sizeof(name)-1);
914 DEBUGADD(3,("checking name: %s\n",name));
916 if (!open_printer_hnd(p, handle, name, 0))
917 return WERR_INVALID_PRINTER_NAME;
919 Printer=find_printer_index_by_hnd(p, handle);
920 if (!Printer) {
921 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
922 Can't find printer handle we created for printer %s\n", name ));
923 close_printer_handle(p,handle);
924 return WERR_INVALID_PRINTER_NAME;
928 if (printer_default->datatype_ptr != NULL)
930 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
931 set_printer_hnd_datatype(handle, datatype);
933 else
934 set_printer_hnd_datatype(handle, "");
938 First case: the user is opening the print server:
940 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
941 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
943 Then both Win2k and WinNT clients try an OpenPrinterEx with
944 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
945 or if the user is listed in the smb.conf printer admin parameter.
947 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
948 client view printer folder, but does not show the MSAPW.
950 Note: this test needs code to check access rights here too. Jeremy
951 could you look at this?
954 Second case: the user is opening a printer:
955 NT doesn't let us connect to a printer if the connecting user
956 doesn't have print permission.
960 get_current_user(&user, p);
962 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
964 /* Printserver handles use global struct... */
966 snum = -1;
968 /* Map standard access rights to object specific access
969 rights */
971 se_map_standard(&printer_default->access_required,
972 &printserver_std_mapping);
974 /* Deny any object specific bits that don't apply to print
975 servers (i.e printer and job specific bits) */
977 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
979 if (printer_default->access_required &
980 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
981 DEBUG(3, ("access DENIED for non-printserver bits"));
982 close_printer_handle(p, handle);
983 return WERR_ACCESS_DENIED;
986 /* Allow admin access */
988 if (printer_default->access_required &
989 SERVER_ACCESS_ADMINISTER) {
991 if (!lp_ms_add_printer_wizard()) {
992 close_printer_handle(p, handle);
993 return WERR_ACCESS_DENIED;
996 if (user.uid == 0 ||
997 user_in_list(uidtoname(user.uid),
998 lp_printer_admin(snum)))
999 return WERR_OK;
1001 close_printer_handle(p, handle);
1002 return WERR_ACCESS_DENIED;
1005 /* We fall through to return WERR_OK */
1008 else
1010 /* NT doesn't let us connect to a printer if the connecting user
1011 doesn't have print permission. */
1013 if (!get_printer_snum(p, handle, &snum))
1014 return WERR_BADFID;
1016 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1018 /* map an empty access mask to the minimum access mask */
1019 if (printer_default->access_required == 0x0)
1020 printer_default->access_required = PRINTER_ACCESS_USE;
1023 * If we are not serving the printer driver for this printer,
1024 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1025 * will keep NT clients happy --jerry
1028 if (lp_use_client_driver(snum)
1029 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1031 printer_default->access_required = PRINTER_ACCESS_USE;
1034 if (!print_access_check(&user, snum, printer_default->access_required)) {
1035 DEBUG(3, ("access DENIED for printer open\n"));
1036 close_printer_handle(p, handle);
1037 return WERR_ACCESS_DENIED;
1040 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1041 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1042 close_printer_handle(p, handle);
1043 return WERR_ACCESS_DENIED;
1046 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1047 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1048 else
1049 printer_default->access_required = PRINTER_ACCESS_USE;
1051 DEBUG(4,("Setting printer access=%x\n", printer_default->access_required));
1052 Printer->access_granted = printer_default->access_required;
1055 * If we have a default device pointer in the
1056 * printer_default struct, then we need to get
1057 * the printer info from the tdb and if there is
1058 * no default devicemode there then we do a *SET*
1059 * here ! This is insanity.... JRA.
1063 * If the openprinterex rpc call contains a devmode,
1064 * it's a per-user one. This per-user devmode is derivated
1065 * from the global devmode. Openprinterex() contains a per-user
1066 * devmode for when you do EMF printing and spooling.
1067 * In the EMF case, the NT workstation is only doing half the job
1068 * of rendering the page. The other half is done by running the printer
1069 * driver on the server.
1070 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1071 * The EMF file only contains what is to be printed on the page.
1072 * So in order for the server to know how to print, the NT client sends
1073 * a devicemode attached to the openprinterex call.
1074 * But this devicemode is short lived, it's only valid for the current print job.
1076 * If Samba would have supported EMF spooling, this devicemode would
1077 * have been attached to the handle, to sent it to the driver to correctly
1078 * rasterize the EMF file.
1080 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1081 * we just act as a pass-thru between windows and the printer.
1083 * In order to know that Samba supports only RAW spooling, NT has to call
1084 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1085 * and until NT sends a RAW job, we refuse it.
1087 * But to call getprinter() or startdoc(), you first need a valid handle,
1088 * and to get an handle you have to call openprintex(). Hence why you have
1089 * a devicemode in the openprinterex() call.
1092 * Differences between NT4 and NT 2000.
1093 * NT4:
1094 * ---
1095 * On NT4, you only have a global devicemode. This global devicemode can be changed
1096 * by the administrator (or by a user with enough privs). Everytime a user
1097 * wants to print, the devicemode is resetted to the default. In Word, everytime
1098 * you print, the printer's characteristics are always reset to the global devicemode.
1100 * NT 2000:
1101 * -------
1102 * In W2K, there is the notion of per-user devicemode. The first time you use
1103 * a printer, a per-user devicemode is build from the global devicemode.
1104 * If you change your per-user devicemode, it is saved in the registry, under the
1105 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1106 * printer preferences available.
1108 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1109 * on the General Tab of the printer properties windows.
1111 * To change the global devicemode: it's the "Printing Defaults..." button
1112 * on the Advanced Tab of the printer properties window.
1114 * JFM.
1119 #if 0
1120 if (printer_default->devmode_cont.devmode != NULL) {
1121 result = printer_write_default_dev( snum, printer_default);
1122 if (result != 0) {
1123 close_printer_handle(p, handle);
1124 return result;
1127 #endif
1130 return WERR_OK;
1133 /****************************************************************************
1134 ****************************************************************************/
1136 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1137 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1139 BOOL ret = True;
1141 switch (level) {
1142 case 2:
1143 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1144 break;
1145 default:
1146 break;
1149 return ret;
1152 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1153 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1155 BOOL result = True;
1157 switch (level) {
1158 case 3:
1159 printer->info_3=NULL;
1160 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1161 result = False;
1162 break;
1163 case 6:
1164 printer->info_6=NULL;
1165 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1166 result = False;
1167 break;
1168 default:
1169 break;
1172 return result;
1175 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1176 NT_DEVICEMODE **pp_nt_devmode)
1178 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1181 * Ensure nt_devmode is a valid pointer
1182 * as we will be overwriting it.
1185 if (nt_devmode == NULL) {
1186 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1187 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1188 return False;
1191 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1192 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1194 nt_devmode->specversion=devmode->specversion;
1195 nt_devmode->driverversion=devmode->driverversion;
1196 nt_devmode->size=devmode->size;
1197 nt_devmode->fields=devmode->fields;
1198 nt_devmode->orientation=devmode->orientation;
1199 nt_devmode->papersize=devmode->papersize;
1200 nt_devmode->paperlength=devmode->paperlength;
1201 nt_devmode->paperwidth=devmode->paperwidth;
1202 nt_devmode->scale=devmode->scale;
1203 nt_devmode->copies=devmode->copies;
1204 nt_devmode->defaultsource=devmode->defaultsource;
1205 nt_devmode->printquality=devmode->printquality;
1206 nt_devmode->color=devmode->color;
1207 nt_devmode->duplex=devmode->duplex;
1208 nt_devmode->yresolution=devmode->yresolution;
1209 nt_devmode->ttoption=devmode->ttoption;
1210 nt_devmode->collate=devmode->collate;
1212 nt_devmode->logpixels=devmode->logpixels;
1213 nt_devmode->bitsperpel=devmode->bitsperpel;
1214 nt_devmode->pelswidth=devmode->pelswidth;
1215 nt_devmode->pelsheight=devmode->pelsheight;
1216 nt_devmode->displayflags=devmode->displayflags;
1217 nt_devmode->displayfrequency=devmode->displayfrequency;
1218 nt_devmode->icmmethod=devmode->icmmethod;
1219 nt_devmode->icmintent=devmode->icmintent;
1220 nt_devmode->mediatype=devmode->mediatype;
1221 nt_devmode->dithertype=devmode->dithertype;
1222 nt_devmode->reserved1=devmode->reserved1;
1223 nt_devmode->reserved2=devmode->reserved2;
1224 nt_devmode->panningwidth=devmode->panningwidth;
1225 nt_devmode->panningheight=devmode->panningheight;
1228 * Only change private and driverextra if the incoming devmode
1229 * has a new one. JRA.
1232 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1233 SAFE_FREE(nt_devmode->private);
1234 nt_devmode->driverextra=devmode->driverextra;
1235 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1236 return False;
1237 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1240 *pp_nt_devmode = nt_devmode;
1242 return True;
1245 /********************************************************************
1246 * _spoolss_enddocprinter_internal.
1247 ********************************************************************/
1249 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1251 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1253 if (!Printer) {
1254 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1255 return WERR_BADFID;
1258 Printer->document_started=False;
1259 print_job_end(Printer->jobid,True);
1260 /* error codes unhandled so far ... */
1262 return WERR_OK;
1265 /********************************************************************
1266 * api_spoolss_closeprinter
1267 ********************************************************************/
1269 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1271 POLICY_HND *handle = &q_u->handle;
1273 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1275 if (Printer && Printer->document_started)
1276 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1278 if (!close_printer_handle(p, handle))
1279 return WERR_BADFID;
1281 /* clear the returned printer handle. Observed behavior
1282 from Win2k server. Don't think this really matters.
1283 Previous code just copied the value of the closed
1284 handle. --jerry */
1286 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1288 return WERR_OK;
1291 /********************************************************************
1292 * api_spoolss_deleteprinter
1294 ********************************************************************/
1296 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1298 POLICY_HND *handle = &q_u->handle;
1299 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1300 WERROR result;
1302 if (Printer && Printer->document_started)
1303 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1305 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1307 result = delete_printer_handle(p, handle);
1309 update_c_setprinter(False);
1311 if (W_ERROR_IS_OK(result)) {
1312 srv_spoolss_sendnotify(Printer->dev.handlename, 0, PRINTER_CHANGE_DELETE_PRINTER, 0x0);
1315 return result;
1318 /*******************************************************************
1319 * static function to lookup the version id corresponding to an
1320 * long architecture string
1321 ******************************************************************/
1323 static int get_version_id (char * arch)
1325 int i;
1326 struct table_node archi_table[]= {
1328 {"Windows 4.0", "WIN40", 0 },
1329 {"Windows NT x86", "W32X86", 2 },
1330 {"Windows NT R4000", "W32MIPS", 2 },
1331 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1332 {"Windows NT PowerPC", "W32PPC", 2 },
1333 {NULL, "", -1 }
1336 for (i=0; archi_table[i].long_archi != NULL; i++)
1338 if (strcmp(arch, archi_table[i].long_archi) == 0)
1339 return (archi_table[i].version);
1342 return -1;
1345 /********************************************************************
1346 * _spoolss_deleteprinterdriver
1348 * We currently delete the driver for the architecture only.
1349 * This can leave the driver for other archtectures. However,
1350 * since every printer associates a "Windows NT x86" driver name
1351 * and we cannot delete that one while it is in use, **and** since
1352 * it is impossible to assign a driver to a Samba printer without
1353 * having the "Windows NT x86" driver installed,...
1355 * ....we should not get into trouble here.
1357 * --jerry
1358 ********************************************************************/
1360 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1361 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1363 fstring driver;
1364 fstring arch;
1365 NT_PRINTER_DRIVER_INFO_LEVEL info;
1366 int version;
1368 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1369 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1371 /* check that we have a valid driver name first */
1372 if ((version=get_version_id(arch)) == -1) {
1373 /* this is what NT returns */
1374 return WERR_INVALID_ENVIRONMENT;
1377 ZERO_STRUCT(info);
1378 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1379 return WERR_UNKNOWN_PRINTER_DRIVER;
1383 if (printer_driver_in_use(arch, driver))
1385 return WERR_PRINTER_DRIVER_IN_USE;
1388 return delete_printer_driver(info.info_3);
1391 /********************************************************************
1392 GetPrinterData on a printer server Handle.
1393 ********************************************************************/
1395 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1397 int i;
1399 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1401 if (!strcmp(value, "W3SvcInstalled")) {
1402 *type = 0x4;
1403 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1404 return False;
1405 *needed = 0x4;
1406 return True;
1409 if (!strcmp(value, "BeepEnabled")) {
1410 *type = 0x4;
1411 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1412 return False;
1413 SIVAL(*data, 0, 0x00);
1414 *needed = 0x4;
1415 return True;
1418 if (!strcmp(value, "EventLog")) {
1419 *type = 0x4;
1420 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1421 return False;
1422 /* formally was 0x1b */
1423 SIVAL(*data, 0, 0x0);
1424 *needed = 0x4;
1425 return True;
1428 if (!strcmp(value, "NetPopup")) {
1429 *type = 0x4;
1430 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1431 return False;
1432 SIVAL(*data, 0, 0x00);
1433 *needed = 0x4;
1434 return True;
1437 if (!strcmp(value, "MajorVersion")) {
1438 *type = 0x4;
1439 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1440 return False;
1441 SIVAL(*data, 0, 2);
1442 *needed = 0x4;
1443 return True;
1446 if (!strcmp(value, "DefaultSpoolDirectory")) {
1447 fstring string;
1449 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1450 *type = 0x1;
1451 *needed = 2*(strlen(string)+1);
1452 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1453 return False;
1454 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1456 /* it's done by hand ready to go on the wire */
1457 for (i=0; i<strlen(string); i++) {
1458 (*data)[2*i]=string[i];
1459 (*data)[2*i+1]='\0';
1461 return True;
1464 if (!strcmp(value, "Architecture")) {
1465 pstring string="Windows NT x86";
1466 *type = 0x1;
1467 *needed = 2*(strlen(string)+1);
1468 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1469 return False;
1470 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1471 for (i=0; i<strlen(string); i++) {
1472 (*data)[2*i]=string[i];
1473 (*data)[2*i+1]='\0';
1475 return True;
1478 return False;
1481 /********************************************************************
1482 GetPrinterData on a printer Handle.
1483 ********************************************************************/
1485 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1486 fstring value, uint32 *type,
1487 uint8 **data, uint32 *needed, uint32 in_size )
1489 NT_PRINTER_INFO_LEVEL *printer = NULL;
1490 int snum=0;
1491 uint8 *idata=NULL;
1492 uint32 len;
1493 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1495 DEBUG(5,("getprinterdata_printer\n"));
1497 if (!Printer) {
1498 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1499 return False;
1502 if(!get_printer_snum(p, handle, &snum))
1503 return False;
1505 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1506 return False;
1508 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1509 free_a_printer(&printer, 2);
1510 return False;
1513 free_a_printer(&printer, 2);
1515 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1517 if (in_size) {
1518 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1519 return False;
1522 memset(*data, 0, in_size *sizeof(uint8));
1523 /* copy the min(in_size, len) */
1524 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1525 } else {
1526 *data = NULL;
1529 *needed = len;
1531 DEBUG(5,("getprinterdata_printer:copy done\n"));
1533 SAFE_FREE(idata);
1535 return True;
1538 /********************************************************************
1539 * spoolss_getprinterdata
1540 ********************************************************************/
1542 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1544 POLICY_HND *handle = &q_u->handle;
1545 UNISTR2 *valuename = &q_u->valuename;
1546 uint32 in_size = q_u->size;
1547 uint32 *type = &r_u->type;
1548 uint32 *out_size = &r_u->size;
1549 uint8 **data = &r_u->data;
1550 uint32 *needed = &r_u->needed;
1552 fstring value;
1553 BOOL found=False;
1554 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1557 * Reminder: when it's a string, the length is in BYTES
1558 * even if UNICODE is negociated.
1560 * JFM, 4/19/1999
1563 *out_size=in_size;
1565 /* in case of problem, return some default values */
1566 *needed=0;
1567 *type=0;
1569 DEBUG(4,("_spoolss_getprinterdata\n"));
1571 if (!Printer) {
1572 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1573 return WERR_NOMEM;
1574 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1575 return WERR_BADFID;
1578 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1580 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1581 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1582 else
1583 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1585 if (found==False) {
1586 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1587 /* reply this param doesn't exist */
1588 if (*out_size) {
1589 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1590 return WERR_NOMEM;
1591 } else {
1592 *data = NULL;
1595 /* error depends on handle type */
1597 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1598 return WERR_INVALID_PARAM;
1599 else
1600 return WERR_BADFILE;
1603 if (*needed > *out_size)
1604 return WERR_MORE_DATA;
1605 else
1606 return WERR_OK;
1609 /***************************************************************************
1610 Connect to the client.
1611 ****************************************************************************/
1613 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1615 WERROR result;
1618 * If it's the first connection, contact the client
1619 * and connect to the IPC$ share anonumously
1621 if (smb_connections==0) {
1622 fstring unix_printer;
1624 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1626 if(!spoolss_connect_to_client(&cli, unix_printer))
1627 return False;
1629 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1633 smb_connections++;
1635 result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
1636 type, handle);
1638 if (!W_ERROR_IS_OK(result))
1639 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1640 dos_errstr(result)));
1642 return (W_ERROR_IS_OK(result));
1645 /********************************************************************
1646 * _spoolss_rffpcnex
1647 * ReplyFindFirstPrinterChangeNotifyEx
1649 * jfmxxxx: before replying OK: status=0
1650 * should do a rpc call to the workstation asking ReplyOpenPrinter
1651 * have to code it, later.
1653 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1654 * called from api_spoolss_rffpcnex
1655 ********************************************************************/
1657 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1659 POLICY_HND *handle = &q_u->handle;
1660 uint32 flags = q_u->flags;
1661 uint32 options = q_u->options;
1662 UNISTR2 *localmachine = &q_u->localmachine;
1663 uint32 printerlocal = q_u->printerlocal;
1664 SPOOL_NOTIFY_OPTION *option = q_u->option;
1666 /* store the notify value in the printer struct */
1668 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1670 if (!Printer) {
1671 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1672 return WERR_BADFID;
1675 Printer->notify.flags=flags;
1676 Printer->notify.options=options;
1677 Printer->notify.printerlocal=printerlocal;
1679 if (Printer->notify.option)
1680 free_spool_notify_option(&Printer->notify.option);
1682 Printer->notify.option=dup_spool_notify_option(option);
1684 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1686 /* connect to the client machine and send a ReplyOpenPrinter */
1687 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1688 Printer->notify.printerlocal, 1,
1689 &Printer->notify.client_hnd))
1691 Printer->notify.client_connected=True;
1694 return WERR_OK;
1697 /*******************************************************************
1698 * fill a notify_info_data with the servername
1699 ********************************************************************/
1701 void spoolss_notify_server_name(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_name, temp;
1708 uint32 len;
1710 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1712 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1714 data->notify_data.data.length = len / 2 - 1;
1715 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1717 if (!data->notify_data.data.string) {
1718 data->notify_data.data.length = 0;
1719 return;
1722 memcpy(data->notify_data.data.string, temp, len);
1725 /*******************************************************************
1726 * fill a notify_info_data with the printername (not including the servername).
1727 ********************************************************************/
1729 void spoolss_notify_printer_name(int snum,
1730 SPOOL_NOTIFY_INFO_DATA *data,
1731 print_queue_struct *queue,
1732 NT_PRINTER_INFO_LEVEL *printer,
1733 TALLOC_CTX *mem_ctx)
1735 pstring temp;
1736 uint32 len;
1738 /* the notify name should not contain the \\server\ part */
1739 char *p = strrchr(printer->info_2->printername, '\\');
1741 if (!p) {
1742 p = printer->info_2->printername;
1743 } else {
1744 p++;
1747 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1749 data->notify_data.data.length = len / 2 - 1;
1750 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1752 if (!data->notify_data.data.string) {
1753 data->notify_data.data.length = 0;
1754 return;
1757 memcpy(data->notify_data.data.string, temp, len);
1760 /*******************************************************************
1761 * fill a notify_info_data with the servicename
1762 ********************************************************************/
1764 void spoolss_notify_share_name(int snum,
1765 SPOOL_NOTIFY_INFO_DATA *data,
1766 print_queue_struct *queue,
1767 NT_PRINTER_INFO_LEVEL *printer,
1768 TALLOC_CTX *mem_ctx)
1770 pstring temp;
1771 uint32 len;
1773 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1775 data->notify_data.data.length = len / 2 - 1;
1776 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1778 if (!data->notify_data.data.string) {
1779 data->notify_data.data.length = 0;
1780 return;
1783 memcpy(data->notify_data.data.string, temp, len);
1786 /*******************************************************************
1787 * fill a notify_info_data with the port name
1788 ********************************************************************/
1790 void spoolss_notify_port_name(int snum,
1791 SPOOL_NOTIFY_INFO_DATA *data,
1792 print_queue_struct *queue,
1793 NT_PRINTER_INFO_LEVEL *printer,
1794 TALLOC_CTX *mem_ctx)
1796 pstring temp;
1797 uint32 len;
1799 /* even if it's strange, that's consistant in all the code */
1801 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1803 data->notify_data.data.length = len / 2 - 1;
1804 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1806 if (!data->notify_data.data.string) {
1807 data->notify_data.data.length = 0;
1808 return;
1811 memcpy(data->notify_data.data.string, temp, len);
1814 /*******************************************************************
1815 * fill a notify_info_data with the printername
1816 * but it doesn't exist, have to see what to do
1817 ********************************************************************/
1819 void spoolss_notify_driver_name(int snum,
1820 SPOOL_NOTIFY_INFO_DATA *data,
1821 print_queue_struct *queue,
1822 NT_PRINTER_INFO_LEVEL *printer,
1823 TALLOC_CTX *mem_ctx)
1825 pstring temp;
1826 uint32 len;
1828 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1829 data->notify_data.data.length = len / 2 - 1;
1830 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1832 if (!data->notify_data.data.string) {
1833 data->notify_data.data.length = 0;
1834 return;
1837 memcpy(data->notify_data.data.string, temp, len);
1840 /*******************************************************************
1841 * fill a notify_info_data with the comment
1842 ********************************************************************/
1844 void spoolss_notify_comment(int snum,
1845 SPOOL_NOTIFY_INFO_DATA *data,
1846 print_queue_struct *queue,
1847 NT_PRINTER_INFO_LEVEL *printer,
1848 TALLOC_CTX *mem_ctx)
1850 pstring temp;
1851 uint32 len;
1853 if (*printer->info_2->comment == '\0')
1854 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1855 else
1856 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1858 data->notify_data.data.length = len / 2 - 1;
1859 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1861 if (!data->notify_data.data.string) {
1862 data->notify_data.data.length = 0;
1863 return;
1866 memcpy(data->notify_data.data.string, temp, len);
1869 /*******************************************************************
1870 * fill a notify_info_data with the comment
1871 * location = "Room 1, floor 2, building 3"
1872 ********************************************************************/
1874 void spoolss_notify_location(int snum,
1875 SPOOL_NOTIFY_INFO_DATA *data,
1876 print_queue_struct *queue,
1877 NT_PRINTER_INFO_LEVEL *printer,
1878 TALLOC_CTX *mem_ctx)
1880 pstring temp;
1881 uint32 len;
1883 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1885 data->notify_data.data.length = len / 2 - 1;
1886 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1888 if (!data->notify_data.data.string) {
1889 data->notify_data.data.length = 0;
1890 return;
1893 memcpy(data->notify_data.data.string, temp, len);
1896 /*******************************************************************
1897 * fill a notify_info_data with the device mode
1898 * jfm:xxxx don't to it for know but that's a real problem !!!
1899 ********************************************************************/
1901 static void spoolss_notify_devmode(int snum,
1902 SPOOL_NOTIFY_INFO_DATA *data,
1903 print_queue_struct *queue,
1904 NT_PRINTER_INFO_LEVEL *printer,
1905 TALLOC_CTX *mem_ctx)
1909 /*******************************************************************
1910 * fill a notify_info_data with the separator file name
1911 ********************************************************************/
1913 void spoolss_notify_sepfile(int snum,
1914 SPOOL_NOTIFY_INFO_DATA *data,
1915 print_queue_struct *queue,
1916 NT_PRINTER_INFO_LEVEL *printer,
1917 TALLOC_CTX *mem_ctx)
1919 pstring temp;
1920 uint32 len;
1922 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1924 data->notify_data.data.length = len / 2 - 1;
1925 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1927 if (!data->notify_data.data.string) {
1928 data->notify_data.data.length = 0;
1929 return;
1932 memcpy(data->notify_data.data.string, temp, len);
1935 /*******************************************************************
1936 * fill a notify_info_data with the print processor
1937 * jfm:xxxx return always winprint to indicate we don't do anything to it
1938 ********************************************************************/
1940 void spoolss_notify_print_processor(int snum,
1941 SPOOL_NOTIFY_INFO_DATA *data,
1942 print_queue_struct *queue,
1943 NT_PRINTER_INFO_LEVEL *printer,
1944 TALLOC_CTX *mem_ctx)
1946 pstring temp;
1947 uint32 len;
1949 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1951 data->notify_data.data.length = len / 2 - 1;
1952 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1954 if (!data->notify_data.data.string) {
1955 data->notify_data.data.length = 0;
1956 return;
1959 memcpy(data->notify_data.data.string, temp, len);
1962 /*******************************************************************
1963 * fill a notify_info_data with the print processor options
1964 * jfm:xxxx send an empty string
1965 ********************************************************************/
1967 void spoolss_notify_parameters(int snum,
1968 SPOOL_NOTIFY_INFO_DATA *data,
1969 print_queue_struct *queue,
1970 NT_PRINTER_INFO_LEVEL *printer,
1971 TALLOC_CTX *mem_ctx)
1973 pstring temp;
1974 uint32 len;
1976 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1978 data->notify_data.data.length = len / 2 - 1;
1979 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1981 if (!data->notify_data.data.string) {
1982 data->notify_data.data.length = 0;
1983 return;
1986 memcpy(data->notify_data.data.string, temp, len);
1989 /*******************************************************************
1990 * fill a notify_info_data with the data type
1991 * jfm:xxxx always send RAW as data type
1992 ********************************************************************/
1994 void spoolss_notify_datatype(int snum,
1995 SPOOL_NOTIFY_INFO_DATA *data,
1996 print_queue_struct *queue,
1997 NT_PRINTER_INFO_LEVEL *printer,
1998 TALLOC_CTX *mem_ctx)
2000 pstring temp;
2001 uint32 len;
2003 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2005 data->notify_data.data.length = len / 2 - 1;
2006 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2008 if (!data->notify_data.data.string) {
2009 data->notify_data.data.length = 0;
2010 return;
2013 memcpy(data->notify_data.data.string, temp, len);
2016 /*******************************************************************
2017 * fill a notify_info_data with the security descriptor
2018 * jfm:xxxx send an null pointer to say no security desc
2019 * have to implement security before !
2020 ********************************************************************/
2022 static void spoolss_notify_security_desc(int snum,
2023 SPOOL_NOTIFY_INFO_DATA *data,
2024 print_queue_struct *queue,
2025 NT_PRINTER_INFO_LEVEL *printer,
2026 TALLOC_CTX *mem_ctx)
2028 data->notify_data.data.length=0;
2029 data->notify_data.data.string = NULL;
2032 /*******************************************************************
2033 * fill a notify_info_data with the attributes
2034 * jfm:xxxx a samba printer is always shared
2035 ********************************************************************/
2037 void spoolss_notify_attributes(int snum,
2038 SPOOL_NOTIFY_INFO_DATA *data,
2039 print_queue_struct *queue,
2040 NT_PRINTER_INFO_LEVEL *printer,
2041 TALLOC_CTX *mem_ctx)
2043 data->notify_data.value[0] = printer->info_2->attributes;
2044 data->notify_data.value[1] = 0;
2047 /*******************************************************************
2048 * fill a notify_info_data with the priority
2049 ********************************************************************/
2051 static void spoolss_notify_priority(int snum,
2052 SPOOL_NOTIFY_INFO_DATA *data,
2053 print_queue_struct *queue,
2054 NT_PRINTER_INFO_LEVEL *printer,
2055 TALLOC_CTX *mem_ctx)
2057 data->notify_data.value[0] = printer->info_2->priority;
2058 data->notify_data.value[1] = 0;
2061 /*******************************************************************
2062 * fill a notify_info_data with the default priority
2063 ********************************************************************/
2065 static void spoolss_notify_default_priority(int snum,
2066 SPOOL_NOTIFY_INFO_DATA *data,
2067 print_queue_struct *queue,
2068 NT_PRINTER_INFO_LEVEL *printer,
2069 TALLOC_CTX *mem_ctx)
2071 data->notify_data.value[0] = printer->info_2->default_priority;
2072 data->notify_data.value[1] = 0;
2075 /*******************************************************************
2076 * fill a notify_info_data with the start time
2077 ********************************************************************/
2079 static void spoolss_notify_start_time(int snum,
2080 SPOOL_NOTIFY_INFO_DATA *data,
2081 print_queue_struct *queue,
2082 NT_PRINTER_INFO_LEVEL *printer,
2083 TALLOC_CTX *mem_ctx)
2085 data->notify_data.value[0] = printer->info_2->starttime;
2086 data->notify_data.value[1] = 0;
2089 /*******************************************************************
2090 * fill a notify_info_data with the until time
2091 ********************************************************************/
2093 static void spoolss_notify_until_time(int snum,
2094 SPOOL_NOTIFY_INFO_DATA *data,
2095 print_queue_struct *queue,
2096 NT_PRINTER_INFO_LEVEL *printer,
2097 TALLOC_CTX *mem_ctx)
2099 data->notify_data.value[0] = printer->info_2->untiltime;
2100 data->notify_data.value[1] = 0;
2103 /*******************************************************************
2104 * fill a notify_info_data with the status
2105 ********************************************************************/
2107 static void spoolss_notify_status(int snum,
2108 SPOOL_NOTIFY_INFO_DATA *data,
2109 print_queue_struct *queue,
2110 NT_PRINTER_INFO_LEVEL *printer,
2111 TALLOC_CTX *mem_ctx)
2113 print_status_struct status;
2115 print_queue_length(snum, &status);
2116 data->notify_data.value[0]=(uint32) status.status;
2117 data->notify_data.value[1] = 0;
2120 /*******************************************************************
2121 * fill a notify_info_data with the number of jobs queued
2122 ********************************************************************/
2124 void spoolss_notify_cjobs(int snum,
2125 SPOOL_NOTIFY_INFO_DATA *data,
2126 print_queue_struct *queue,
2127 NT_PRINTER_INFO_LEVEL *printer,
2128 TALLOC_CTX *mem_ctx)
2130 data->notify_data.value[0] = print_queue_length(snum, NULL);
2131 data->notify_data.value[1] = 0;
2134 /*******************************************************************
2135 * fill a notify_info_data with the average ppm
2136 ********************************************************************/
2138 static void spoolss_notify_average_ppm(int snum,
2139 SPOOL_NOTIFY_INFO_DATA *data,
2140 print_queue_struct *queue,
2141 NT_PRINTER_INFO_LEVEL *printer,
2142 TALLOC_CTX *mem_ctx)
2144 /* always respond 8 pages per minutes */
2145 /* a little hard ! */
2146 data->notify_data.value[0] = printer->info_2->averageppm;
2147 data->notify_data.value[1] = 0;
2150 /*******************************************************************
2151 * fill a notify_info_data with username
2152 ********************************************************************/
2154 static void spoolss_notify_username(int snum,
2155 SPOOL_NOTIFY_INFO_DATA *data,
2156 print_queue_struct *queue,
2157 NT_PRINTER_INFO_LEVEL *printer,
2158 TALLOC_CTX *mem_ctx)
2160 pstring temp;
2161 uint32 len;
2163 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2165 data->notify_data.data.length = len / 2 - 1;
2166 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2168 if (!data->notify_data.data.string) {
2169 data->notify_data.data.length = 0;
2170 return;
2173 memcpy(data->notify_data.data.string, temp, len);
2176 /*******************************************************************
2177 * fill a notify_info_data with job status
2178 ********************************************************************/
2180 static void spoolss_notify_job_status(int snum,
2181 SPOOL_NOTIFY_INFO_DATA *data,
2182 print_queue_struct *queue,
2183 NT_PRINTER_INFO_LEVEL *printer,
2184 TALLOC_CTX *mem_ctx)
2186 data->notify_data.value[0]=nt_printj_status(queue->status);
2187 data->notify_data.value[1] = 0;
2190 /*******************************************************************
2191 * fill a notify_info_data with job name
2192 ********************************************************************/
2194 static void spoolss_notify_job_name(int snum,
2195 SPOOL_NOTIFY_INFO_DATA *data,
2196 print_queue_struct *queue,
2197 NT_PRINTER_INFO_LEVEL *printer,
2198 TALLOC_CTX *mem_ctx)
2200 pstring temp;
2201 uint32 len;
2203 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2205 data->notify_data.data.length = len / 2 - 1;
2206 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2208 if (!data->notify_data.data.string) {
2209 data->notify_data.data.length = 0;
2210 return;
2213 memcpy(data->notify_data.data.string, temp, len);
2216 /*******************************************************************
2217 * fill a notify_info_data with job status
2218 ********************************************************************/
2220 static void spoolss_notify_job_status_string(int snum,
2221 SPOOL_NOTIFY_INFO_DATA *data,
2222 print_queue_struct *queue,
2223 NT_PRINTER_INFO_LEVEL *printer,
2224 TALLOC_CTX *mem_ctx)
2227 * Now we're returning job status codes we just return a "" here. JRA.
2230 char *p = "";
2231 pstring temp;
2232 uint32 len;
2234 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2235 p = "unknown";
2237 switch (queue->status) {
2238 case LPQ_QUEUED:
2239 p = "Queued";
2240 break;
2241 case LPQ_PAUSED:
2242 p = ""; /* NT provides the paused string */
2243 break;
2244 case LPQ_SPOOLING:
2245 p = "Spooling";
2246 break;
2247 case LPQ_PRINTING:
2248 p = "Printing";
2249 break;
2251 #endif /* NO LONGER NEEDED. */
2253 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2255 data->notify_data.data.length = len / 2 - 1;
2256 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2258 if (!data->notify_data.data.string) {
2259 data->notify_data.data.length = 0;
2260 return;
2263 memcpy(data->notify_data.data.string, temp, len);
2266 /*******************************************************************
2267 * fill a notify_info_data with job time
2268 ********************************************************************/
2270 static void spoolss_notify_job_time(int snum,
2271 SPOOL_NOTIFY_INFO_DATA *data,
2272 print_queue_struct *queue,
2273 NT_PRINTER_INFO_LEVEL *printer,
2274 TALLOC_CTX *mem_ctx)
2276 data->notify_data.value[0]=0x0;
2277 data->notify_data.value[1]=0;
2280 /*******************************************************************
2281 * fill a notify_info_data with job size
2282 ********************************************************************/
2284 static void spoolss_notify_job_size(int snum,
2285 SPOOL_NOTIFY_INFO_DATA *data,
2286 print_queue_struct *queue,
2287 NT_PRINTER_INFO_LEVEL *printer,
2288 TALLOC_CTX *mem_ctx)
2290 data->notify_data.value[0]=queue->size;
2291 data->notify_data.value[1]=0;
2294 /*******************************************************************
2295 * fill a notify_info_data with page info
2296 ********************************************************************/
2297 static void spoolss_notify_total_pages(int snum,
2298 SPOOL_NOTIFY_INFO_DATA *data,
2299 print_queue_struct *queue,
2300 NT_PRINTER_INFO_LEVEL *printer,
2301 TALLOC_CTX *mem_ctx)
2303 data->notify_data.value[0]=queue->page_count;
2304 data->notify_data.value[1]=0;
2307 /*******************************************************************
2308 * fill a notify_info_data with pages printed info.
2309 ********************************************************************/
2310 static void spoolss_notify_pages_printed(int snum,
2311 SPOOL_NOTIFY_INFO_DATA *data,
2312 print_queue_struct *queue,
2313 NT_PRINTER_INFO_LEVEL *printer,
2314 TALLOC_CTX *mem_ctx)
2316 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2317 data->notify_data.value[1]=0;
2320 /*******************************************************************
2321 Fill a notify_info_data with job position.
2322 ********************************************************************/
2324 static void spoolss_notify_job_position(int snum,
2325 SPOOL_NOTIFY_INFO_DATA *data,
2326 print_queue_struct *queue,
2327 NT_PRINTER_INFO_LEVEL *printer,
2328 TALLOC_CTX *mem_ctx)
2330 data->notify_data.value[0]=queue->job;
2331 data->notify_data.value[1]=0;
2334 /*******************************************************************
2335 Fill a notify_info_data with submitted time.
2336 ********************************************************************/
2338 static void spoolss_notify_submitted_time(int snum,
2339 SPOOL_NOTIFY_INFO_DATA *data,
2340 print_queue_struct *queue,
2341 NT_PRINTER_INFO_LEVEL *printer,
2342 TALLOC_CTX *mem_ctx)
2344 struct tm *t;
2345 uint32 len;
2346 SYSTEMTIME st;
2347 char *p;
2349 t=gmtime(&queue->time);
2351 len = sizeof(SYSTEMTIME);
2353 data->notify_data.data.length = len;
2354 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2356 if (!data->notify_data.data.string) {
2357 data->notify_data.data.length = 0;
2358 return;
2361 make_systemtime(&st, t);
2364 * Systemtime must be linearized as a set of UINT16's.
2365 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2368 p = (char *)data->notify_data.data.string;
2369 SSVAL(p, 0, st.year);
2370 SSVAL(p, 2, st.month);
2371 SSVAL(p, 4, st.dayofweek);
2372 SSVAL(p, 6, st.day);
2373 SSVAL(p, 8, st.hour);
2374 SSVAL(p, 10, st.minute);
2375 SSVAL(p, 12, st.second);
2376 SSVAL(p, 14, st.milliseconds);
2379 #define END 65535
2381 struct s_notify_info_data_table
2383 uint16 type;
2384 uint16 field;
2385 char *name;
2386 uint32 size;
2387 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2388 print_queue_struct *queue,
2389 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2392 struct s_notify_info_data_table notify_info_data_table[] =
2394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, spoolss_notify_total_pages },
2441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, spoolss_notify_pages_printed },
2442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2444 { END, END, "", END, NULL }
2447 /*******************************************************************
2448 Return the size of info_data structure.
2449 ********************************************************************/
2451 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2453 int i=0;
2455 while (notify_info_data_table[i].type != END)
2457 if ( (notify_info_data_table[i].type == type ) &&
2458 (notify_info_data_table[i].field == field ) )
2460 return (notify_info_data_table[i].size);
2462 i++;
2464 return (65535);
2467 /*******************************************************************
2468 Return the type of notify_info_data.
2469 ********************************************************************/
2471 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2473 int i=0;
2475 while (notify_info_data_table[i].type != END)
2477 if ( (notify_info_data_table[i].type == type ) &&
2478 (notify_info_data_table[i].field == field ) )
2480 if (notify_info_data_table[i].size == POINTER)
2482 return (False);
2484 else
2486 return (True);
2489 i++;
2491 return (False);
2494 /****************************************************************************
2495 ****************************************************************************/
2497 static int search_notify(uint16 type, uint16 field, int *value)
2499 int j;
2500 BOOL found;
2502 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2504 if ( (notify_info_data_table[j].type == type ) &&
2505 (notify_info_data_table[j].field == field ) )
2506 found=True;
2508 *value=--j;
2510 if ( found && (notify_info_data_table[j].fn != NULL) )
2511 return True;
2512 else
2513 return False;
2516 /****************************************************************************
2517 ****************************************************************************/
2519 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2521 info_data->type = type;
2522 info_data->field = field;
2523 info_data->reserved = 0;
2524 info_data->id = id;
2525 info_data->size = size_of_notify_info_data(type, field);
2526 info_data->enc_type = type_of_notify_info_data(type, field);
2530 /*******************************************************************
2532 * fill a notify_info struct with info asked
2534 ********************************************************************/
2536 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2537 snum, SPOOL_NOTIFY_OPTION_TYPE
2538 *option_type, uint32 id,
2539 TALLOC_CTX *mem_ctx)
2541 int field_num,j;
2542 uint16 type;
2543 uint16 field;
2545 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2546 NT_PRINTER_INFO_LEVEL *printer = NULL;
2547 print_queue_struct *queue=NULL;
2549 type=option_type->type;
2551 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2552 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2553 option_type->count, lp_servicename(snum)));
2555 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2556 return False;
2558 for(field_num=0; field_num<option_type->count; field_num++) {
2559 field = option_type->fields[field_num];
2560 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2562 if (!search_notify(type, field, &j) )
2563 continue;
2565 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2566 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2567 return False;
2569 else info->data = tid;
2571 current_data=&info->data[info->count];
2573 construct_info_data(current_data, type, field, id);
2575 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2576 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2578 notify_info_data_table[j].fn(snum, current_data, queue,
2579 printer, mem_ctx);
2581 info->count++;
2584 free_a_printer(&printer, 2);
2585 return True;
2588 /*******************************************************************
2590 * fill a notify_info struct with info asked
2592 ********************************************************************/
2594 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2595 SPOOL_NOTIFY_INFO *info,
2596 NT_PRINTER_INFO_LEVEL *printer,
2597 int snum, SPOOL_NOTIFY_OPTION_TYPE
2598 *option_type, uint32 id,
2599 TALLOC_CTX *mem_ctx)
2601 int field_num,j;
2602 uint16 type;
2603 uint16 field;
2605 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2607 DEBUG(4,("construct_notify_jobs_info\n"));
2609 type = option_type->type;
2611 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2612 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2613 option_type->count));
2615 for(field_num=0; field_num<option_type->count; field_num++) {
2616 field = option_type->fields[field_num];
2618 if (!search_notify(type, field, &j) )
2619 continue;
2621 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2622 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2623 return False;
2625 else info->data = tid;
2627 current_data=&(info->data[info->count]);
2629 construct_info_data(current_data, type, field, id);
2630 notify_info_data_table[j].fn(snum, current_data, queue,
2631 printer, mem_ctx);
2632 info->count++;
2635 return True;
2639 * JFM: The enumeration is not that simple, it's even non obvious.
2641 * let's take an example: I want to monitor the PRINTER SERVER for
2642 * the printer's name and the number of jobs currently queued.
2643 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2644 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2646 * I have 3 printers on the back of my server.
2648 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2649 * structures.
2650 * Number Data Id
2651 * 1 printer 1 name 1
2652 * 2 printer 1 cjob 1
2653 * 3 printer 2 name 2
2654 * 4 printer 2 cjob 2
2655 * 5 printer 3 name 3
2656 * 6 printer 3 name 3
2658 * that's the print server case, the printer case is even worse.
2661 /*******************************************************************
2663 * enumerate all printers on the printserver
2664 * fill a notify_info struct with info asked
2666 ********************************************************************/
2668 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2669 SPOOL_NOTIFY_INFO *info,
2670 TALLOC_CTX *mem_ctx)
2672 int snum;
2673 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2674 int n_services=lp_numservices();
2675 int i;
2676 uint32 id;
2677 SPOOL_NOTIFY_OPTION *option;
2678 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2680 DEBUG(4,("printserver_notify_info\n"));
2682 if (!Printer)
2683 return WERR_BADFID;
2685 option=Printer->notify.option;
2686 id=1;
2687 info->version=2;
2688 info->data=NULL;
2689 info->count=0;
2691 for (i=0; i<option->count; i++) {
2692 option_type=&(option->ctr.type[i]);
2694 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2695 continue;
2697 for (snum=0; snum<n_services; snum++)
2698 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2699 if (construct_notify_printer_info
2700 (info, snum, option_type, id, mem_ctx))
2701 id++;
2705 * Debugging information, don't delete.
2708 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2709 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2710 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2712 for (i=0; i<info->count; i++) {
2713 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2714 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2715 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2719 return WERR_OK;
2722 /*******************************************************************
2724 * fill a notify_info struct with info asked
2726 ********************************************************************/
2728 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2729 TALLOC_CTX *mem_ctx)
2731 int snum;
2732 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2733 int i;
2734 uint32 id;
2735 SPOOL_NOTIFY_OPTION *option;
2736 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2737 int count,j;
2738 print_queue_struct *queue=NULL;
2739 print_status_struct status;
2741 DEBUG(4,("printer_notify_info\n"));
2743 if (!Printer)
2744 return WERR_BADFID;
2746 option=Printer->notify.option;
2747 id = 0x0;
2748 info->version=2;
2749 info->data=NULL;
2750 info->count=0;
2752 get_printer_snum(p, hnd, &snum);
2754 for (i=0; i<option->count; i++) {
2755 option_type=&option->ctr.type[i];
2757 switch ( option_type->type ) {
2758 case PRINTER_NOTIFY_TYPE:
2759 if(construct_notify_printer_info(info, snum,
2760 option_type, id,
2761 mem_ctx))
2762 id--;
2763 break;
2765 case JOB_NOTIFY_TYPE: {
2766 NT_PRINTER_INFO_LEVEL *printer = NULL;
2768 count = print_queue_status(snum, &queue, &status);
2770 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2771 lp_servicename(snum))))
2772 goto done;
2774 for (j=0; j<count; j++) {
2775 construct_notify_jobs_info(&queue[j], info,
2776 printer, snum,
2777 option_type,
2778 queue[j].job,
2779 mem_ctx);
2782 free_a_printer(&printer, 2);
2784 done:
2785 SAFE_FREE(queue);
2786 break;
2792 * Debugging information, don't delete.
2795 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2796 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2797 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2799 for (i=0; i<info->count; i++) {
2800 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2801 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2802 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2805 return WERR_OK;
2808 /********************************************************************
2809 * spoolss_rfnpcnex
2810 ********************************************************************/
2812 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2814 POLICY_HND *handle = &q_u->handle;
2815 /* uint32 change = q_u->change; - notused. */
2816 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2817 SPOOL_NOTIFY_INFO *info = &r_u->info;
2819 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2820 WERROR result = WERR_BADFID;
2822 /* we always have a NOTIFY_INFO struct */
2823 r_u->info_ptr=0x1;
2825 if (!Printer) {
2826 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
2827 OUR_HANDLE(handle)));
2828 goto done;
2831 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2833 /* jfm: the change value isn't used right now.
2834 * we will honour it when
2835 * a) we'll be able to send notification to the client
2836 * b) we'll have a way to communicate between the spoolss process.
2838 * same thing for option->flags
2839 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2840 * I don't have a global notification system, I'm sending back all the
2841 * informations even when _NOTHING_ has changed.
2844 /* just ignore the SPOOL_NOTIFY_OPTION */
2846 switch (Printer->printer_type) {
2847 case PRINTER_HANDLE_IS_PRINTSERVER:
2848 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2849 break;
2851 case PRINTER_HANDLE_IS_PRINTER:
2852 result = printer_notify_info(p, handle, info, p->mem_ctx);
2853 break;
2856 done:
2857 return result;
2860 /********************************************************************
2861 * construct_printer_info_0
2862 * fill a printer_info_0 struct
2863 ********************************************************************/
2865 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2867 pstring chaine;
2868 int count;
2869 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2870 counter_printer_0 *session_counter;
2871 uint32 global_counter;
2872 struct tm *t;
2873 time_t setuptime;
2874 print_status_struct status;
2876 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2877 return False;
2879 count = print_queue_length(snum, &status);
2881 /* check if we already have a counter for this printer */
2882 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2884 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2885 if (session_counter->snum == snum)
2886 break;
2889 /* it's the first time, add it to the list */
2890 if (session_counter==NULL) {
2891 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2892 free_a_printer(&ntprinter, 2);
2893 return False;
2895 ZERO_STRUCTP(session_counter);
2896 session_counter->snum=snum;
2897 session_counter->counter=0;
2898 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2901 /* increment it */
2902 session_counter->counter++;
2904 /* JFM:
2905 * the global_counter should be stored in a TDB as it's common to all the clients
2906 * and should be zeroed on samba startup
2908 global_counter=session_counter->counter;
2910 pstrcpy(chaine,ntprinter->info_2->printername);
2912 init_unistr(&printer->printername, chaine);
2914 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2915 init_unistr(&printer->servername, chaine);
2917 printer->cjobs = count;
2918 printer->total_jobs = 0;
2919 printer->total_bytes = 0;
2921 setuptime = (time_t)ntprinter->info_2->setuptime;
2922 t=gmtime(&setuptime);
2924 printer->year = t->tm_year+1900;
2925 printer->month = t->tm_mon+1;
2926 printer->dayofweek = t->tm_wday;
2927 printer->day = t->tm_mday;
2928 printer->hour = t->tm_hour;
2929 printer->minute = t->tm_min;
2930 printer->second = t->tm_sec;
2931 printer->milliseconds = 0;
2933 printer->global_counter = global_counter;
2934 printer->total_pages = 0;
2935 #if 0 /* JERRY */
2936 printer->major_version = 0x0004; /* NT 4 */
2937 printer->build_version = 0x0565; /* build 1381 */
2938 #else
2939 printer->major_version = 0x0005; /* NT 5 */
2940 printer->build_version = 0x0893; /* build 2195 */
2941 #endif
2942 printer->unknown7 = 0x1;
2943 printer->unknown8 = 0x0;
2944 printer->unknown9 = 0x0;
2945 printer->session_counter = session_counter->counter;
2946 printer->unknown11 = 0x0;
2947 printer->printer_errors = 0x0; /* number of print failure */
2948 printer->unknown13 = 0x0;
2949 printer->unknown14 = 0x1;
2950 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2951 printer->unknown16 = 0x0;
2952 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2953 printer->unknown18 = 0x0;
2954 printer->status = nt_printq_status(status.status);
2955 printer->unknown20 = 0x0;
2956 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
2957 printer->unknown22 = 0x0;
2958 printer->unknown23 = 0x6; /* 6 ???*/
2959 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2960 printer->unknown25 = 0;
2961 printer->unknown26 = 0;
2962 printer->unknown27 = 0;
2963 printer->unknown28 = 0;
2964 printer->unknown29 = 0;
2966 free_a_printer(&ntprinter,2);
2967 return (True);
2970 /********************************************************************
2971 * construct_printer_info_1
2972 * fill a printer_info_1 struct
2973 ********************************************************************/
2975 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2977 pstring chaine;
2978 pstring chaine2;
2979 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2981 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2982 return False;
2984 printer->flags=flags;
2986 if (*ntprinter->info_2->comment == '\0') {
2987 init_unistr(&printer->comment, lp_comment(snum));
2988 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
2989 ntprinter->info_2->drivername, lp_comment(snum));
2991 else {
2992 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2993 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
2994 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2997 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2999 init_unistr(&printer->description, chaine);
3000 init_unistr(&printer->name, chaine2);
3002 free_a_printer(&ntprinter,2);
3004 return True;
3007 /****************************************************************************
3008 Free a DEVMODE struct.
3009 ****************************************************************************/
3011 static void free_dev_mode(DEVICEMODE *dev)
3013 if (dev == NULL)
3014 return;
3016 SAFE_FREE(dev->private);
3017 SAFE_FREE(dev);
3020 /****************************************************************************
3021 Create a DEVMODE struct. Returns malloced memory.
3022 ****************************************************************************/
3024 static DEVICEMODE *construct_dev_mode(int snum)
3026 char adevice[32];
3027 char aform[32];
3028 NT_PRINTER_INFO_LEVEL *printer = NULL;
3029 NT_DEVICEMODE *ntdevmode = NULL;
3030 DEVICEMODE *devmode = NULL;
3032 DEBUG(7,("construct_dev_mode\n"));
3034 DEBUGADD(8,("getting printer characteristics\n"));
3036 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3037 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3038 return NULL;
3041 ZERO_STRUCTP(devmode);
3043 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3044 goto fail;
3046 if (printer->info_2->devmode)
3047 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3049 if (ntdevmode == NULL)
3050 goto fail;
3052 DEBUGADD(8,("loading DEVICEMODE\n"));
3054 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3055 init_unistr(&devmode->devicename, adevice);
3057 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3058 init_unistr(&devmode->formname, aform);
3060 devmode->specversion = ntdevmode->specversion;
3061 devmode->driverversion = ntdevmode->driverversion;
3062 devmode->size = ntdevmode->size;
3063 devmode->driverextra = ntdevmode->driverextra;
3064 devmode->fields = ntdevmode->fields;
3066 devmode->orientation = ntdevmode->orientation;
3067 devmode->papersize = ntdevmode->papersize;
3068 devmode->paperlength = ntdevmode->paperlength;
3069 devmode->paperwidth = ntdevmode->paperwidth;
3070 devmode->scale = ntdevmode->scale;
3071 devmode->copies = ntdevmode->copies;
3072 devmode->defaultsource = ntdevmode->defaultsource;
3073 devmode->printquality = ntdevmode->printquality;
3074 devmode->color = ntdevmode->color;
3075 devmode->duplex = ntdevmode->duplex;
3076 devmode->yresolution = ntdevmode->yresolution;
3077 devmode->ttoption = ntdevmode->ttoption;
3078 devmode->collate = ntdevmode->collate;
3079 devmode->icmmethod = ntdevmode->icmmethod;
3080 devmode->icmintent = ntdevmode->icmintent;
3081 devmode->mediatype = ntdevmode->mediatype;
3082 devmode->dithertype = ntdevmode->dithertype;
3084 if (ntdevmode->private != NULL) {
3085 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3086 goto fail;
3089 free_nt_devicemode(&ntdevmode);
3090 free_a_printer(&printer,2);
3092 return devmode;
3094 fail:
3096 if (ntdevmode)
3097 free_nt_devicemode(&ntdevmode);
3098 if (printer)
3099 free_a_printer(&printer,2);
3100 free_dev_mode(devmode);
3102 return NULL;
3105 /********************************************************************
3106 * construct_printer_info_2
3107 * fill a printer_info_2 struct
3108 ********************************************************************/
3110 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3112 int count;
3113 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3115 print_status_struct status;
3117 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3118 return False;
3120 count = print_queue_length(snum, &status);
3122 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3123 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3124 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3125 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3126 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3128 if (*ntprinter->info_2->comment == '\0')
3129 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3130 else
3131 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3133 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3134 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3135 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3136 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3137 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3139 printer->attributes = ntprinter->info_2->attributes;
3141 printer->priority = ntprinter->info_2->priority; /* priority */
3142 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3143 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3144 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3145 printer->status = nt_printq_status(status.status); /* status */
3146 printer->cjobs = count; /* jobs */
3147 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3149 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3150 DEBUG(8, ("Returning NULL Devicemode!\n"));
3153 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3154 /* steal the printer info sec_desc structure. [badly done]. */
3155 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3156 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3157 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3158 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3160 else {
3161 printer->secdesc = NULL;
3164 free_a_printer(&ntprinter, 2);
3165 return True;
3168 /********************************************************************
3169 * construct_printer_info_3
3170 * fill a printer_info_3 struct
3171 ********************************************************************/
3173 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3175 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3176 PRINTER_INFO_3 *printer = NULL;
3178 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3179 return False;
3181 *pp_printer = NULL;
3182 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3183 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3184 return False;
3187 ZERO_STRUCTP(printer);
3189 printer->flags = 4; /* These are the components of the SD we are returning. */
3190 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3191 /* steal the printer info sec_desc structure. [badly done]. */
3192 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3194 #if 0
3196 * Set the flags for the components we are returning.
3199 if (printer->secdesc->owner_sid)
3200 printer->flags |= OWNER_SECURITY_INFORMATION;
3202 if (printer->secdesc->grp_sid)
3203 printer->flags |= GROUP_SECURITY_INFORMATION;
3205 if (printer->secdesc->dacl)
3206 printer->flags |= DACL_SECURITY_INFORMATION;
3208 if (printer->secdesc->sacl)
3209 printer->flags |= SACL_SECURITY_INFORMATION;
3210 #endif
3212 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3213 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3214 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3217 free_a_printer(&ntprinter, 2);
3219 *pp_printer = printer;
3220 return True;
3223 /********************************************************************
3224 * construct_printer_info_4
3225 * fill a printer_info_4 struct
3226 ********************************************************************/
3228 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3230 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3232 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3233 return False;
3235 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3236 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3237 printer->attributes = ntprinter->info_2->attributes;
3239 free_a_printer(&ntprinter, 2);
3240 return True;
3243 /********************************************************************
3244 * construct_printer_info_5
3245 * fill a printer_info_5 struct
3246 ********************************************************************/
3248 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3250 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3252 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3253 return False;
3255 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3256 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3257 printer->attributes = ntprinter->info_2->attributes;
3258 printer->device_not_selected_timeout = 0x3a98;
3259 printer->transmission_retry_timeout = 0xafc8;
3261 free_a_printer(&ntprinter, 2);
3262 return True;
3265 /********************************************************************
3266 Spoolss_enumprinters.
3267 ********************************************************************/
3269 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3271 int snum;
3272 int i;
3273 int n_services=lp_numservices();
3274 PRINTER_INFO_1 *tp, *printers=NULL;
3275 PRINTER_INFO_1 current_prt;
3277 DEBUG(4,("enum_all_printers_info_1\n"));
3279 for (snum=0; snum<n_services; snum++) {
3280 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3281 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3283 if (construct_printer_info_1(flags, &current_prt, snum)) {
3284 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3285 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3286 SAFE_FREE(printers);
3287 *returned=0;
3288 return WERR_NOMEM;
3290 else printers = tp;
3291 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3293 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
3294 (*returned)++;
3299 /* check the required size. */
3300 for (i=0; i<*returned; i++)
3301 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3303 if (!alloc_buffer_size(buffer, *needed))
3304 return WERR_INSUFFICIENT_BUFFER;
3306 /* fill the buffer with the structures */
3307 for (i=0; i<*returned; i++)
3308 smb_io_printer_info_1("", buffer, &printers[i], 0);
3310 /* clear memory */
3311 SAFE_FREE(printers);
3313 if (*needed > offered) {
3314 *returned=0;
3315 return WERR_INSUFFICIENT_BUFFER;
3317 else
3318 return WERR_OK;
3321 /********************************************************************
3322 enum_all_printers_info_1_local.
3323 *********************************************************************/
3325 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3327 DEBUG(4,("enum_all_printers_info_1_local\n"));
3329 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3332 /********************************************************************
3333 enum_all_printers_info_1_name.
3334 *********************************************************************/
3336 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3338 char *s = name;
3340 DEBUG(4,("enum_all_printers_info_1_name\n"));
3342 if ((name[0] == '\\') && (name[1] == '\\'))
3343 s = name + 2;
3345 if (is_myname_or_ipaddr(s)) {
3346 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3348 else
3349 return WERR_INVALID_NAME;
3352 /********************************************************************
3353 enum_all_printers_info_1_remote.
3354 *********************************************************************/
3356 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3358 PRINTER_INFO_1 *printer;
3359 fstring printername;
3360 fstring desc;
3361 fstring comment;
3362 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3364 /* JFM: currently it's more a place holder than anything else.
3365 * In the spooler world there is a notion of server registration.
3366 * the print servers are registring (sp ?) on the PDC (in the same domain)
3368 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3371 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3372 return WERR_NOMEM;
3374 *returned=1;
3376 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3377 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3378 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3380 init_unistr(&printer->description, desc);
3381 init_unistr(&printer->name, printername);
3382 init_unistr(&printer->comment, comment);
3383 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3385 /* check the required size. */
3386 *needed += spoolss_size_printer_info_1(printer);
3388 if (!alloc_buffer_size(buffer, *needed)) {
3389 SAFE_FREE(printer);
3390 return WERR_INSUFFICIENT_BUFFER;
3393 /* fill the buffer with the structures */
3394 smb_io_printer_info_1("", buffer, printer, 0);
3396 /* clear memory */
3397 SAFE_FREE(printer);
3399 if (*needed > offered) {
3400 *returned=0;
3401 return WERR_INSUFFICIENT_BUFFER;
3403 else
3404 return WERR_OK;
3407 /********************************************************************
3408 enum_all_printers_info_1_network.
3409 *********************************************************************/
3411 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3413 DEBUG(4,("enum_all_printers_info_1_network\n"));
3415 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3418 /********************************************************************
3419 * api_spoolss_enumprinters
3421 * called from api_spoolss_enumprinters (see this to understand)
3422 ********************************************************************/
3424 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3426 int snum;
3427 int i;
3428 int n_services=lp_numservices();
3429 PRINTER_INFO_2 *tp, *printers=NULL;
3430 PRINTER_INFO_2 current_prt;
3432 for (snum=0; snum<n_services; snum++) {
3433 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3434 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3436 if (construct_printer_info_2(&current_prt, snum)) {
3437 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3438 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3439 SAFE_FREE(printers);
3440 *returned = 0;
3441 return WERR_NOMEM;
3443 else printers = tp;
3444 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3445 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3446 (*returned)++;
3451 /* check the required size. */
3452 for (i=0; i<*returned; i++)
3453 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3455 if (!alloc_buffer_size(buffer, *needed)) {
3456 for (i=0; i<*returned; i++) {
3457 free_devmode(printers[i].devmode);
3459 SAFE_FREE(printers);
3460 return WERR_INSUFFICIENT_BUFFER;
3463 /* fill the buffer with the structures */
3464 for (i=0; i<*returned; i++)
3465 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3467 /* clear memory */
3468 for (i=0; i<*returned; i++) {
3469 free_devmode(printers[i].devmode);
3471 SAFE_FREE(printers);
3473 if (*needed > offered) {
3474 *returned=0;
3475 return WERR_INSUFFICIENT_BUFFER;
3477 else
3478 return WERR_OK;
3481 /********************************************************************
3482 * handle enumeration of printers at level 1
3483 ********************************************************************/
3485 static WERROR enumprinters_level1( uint32 flags, fstring name,
3486 NEW_BUFFER *buffer, uint32 offered,
3487 uint32 *needed, uint32 *returned)
3489 /* Not all the flags are equals */
3491 if (flags & PRINTER_ENUM_LOCAL)
3492 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3494 if (flags & PRINTER_ENUM_NAME)
3495 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3497 if (flags & PRINTER_ENUM_REMOTE)
3498 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3500 if (flags & PRINTER_ENUM_NETWORK)
3501 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3503 return WERR_OK; /* NT4sp5 does that */
3506 /********************************************************************
3507 * handle enumeration of printers at level 2
3508 ********************************************************************/
3510 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3511 NEW_BUFFER *buffer, uint32 offered,
3512 uint32 *needed, uint32 *returned)
3514 char *s = servername;
3516 if (flags & PRINTER_ENUM_LOCAL) {
3517 return enum_all_printers_info_2(buffer, offered, needed, returned);
3520 if (flags & PRINTER_ENUM_NAME) {
3521 if ((servername[0] == '\\') && (servername[1] == '\\'))
3522 s = servername + 2;
3523 if (is_myname_or_ipaddr(s))
3524 return enum_all_printers_info_2(buffer, offered, needed, returned);
3525 else
3526 return WERR_INVALID_NAME;
3529 if (flags & PRINTER_ENUM_REMOTE)
3530 return WERR_UNKNOWN_LEVEL;
3532 return WERR_OK;
3535 /********************************************************************
3536 * handle enumeration of printers at level 5
3537 ********************************************************************/
3539 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3540 NEW_BUFFER *buffer, uint32 offered,
3541 uint32 *needed, uint32 *returned)
3543 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3544 return WERR_OK;
3547 /********************************************************************
3548 * api_spoolss_enumprinters
3550 * called from api_spoolss_enumprinters (see this to understand)
3551 ********************************************************************/
3553 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3555 uint32 flags = q_u->flags;
3556 UNISTR2 *servername = &q_u->servername;
3557 uint32 level = q_u->level;
3558 NEW_BUFFER *buffer = NULL;
3559 uint32 offered = q_u->offered;
3560 uint32 *needed = &r_u->needed;
3561 uint32 *returned = &r_u->returned;
3563 fstring name;
3565 /* that's an [in out] buffer */
3566 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3567 buffer = r_u->buffer;
3569 DEBUG(4,("_spoolss_enumprinters\n"));
3571 *needed=0;
3572 *returned=0;
3575 * Level 1:
3576 * flags==PRINTER_ENUM_NAME
3577 * if name=="" then enumerates all printers
3578 * if name!="" then enumerate the printer
3579 * flags==PRINTER_ENUM_REMOTE
3580 * name is NULL, enumerate printers
3581 * Level 2: name!="" enumerates printers, name can't be NULL
3582 * Level 3: doesn't exist
3583 * Level 4: does a local registry lookup
3584 * Level 5: same as Level 2
3587 unistr2_to_ascii(name, servername, sizeof(name)-1);
3588 strupper(name);
3590 switch (level) {
3591 case 1:
3592 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3593 case 2:
3594 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3595 case 5:
3596 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3597 case 3:
3598 case 4:
3599 break;
3601 return WERR_UNKNOWN_LEVEL;
3604 /****************************************************************************
3605 ****************************************************************************/
3607 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3609 PRINTER_INFO_0 *printer=NULL;
3611 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3612 return WERR_NOMEM;
3614 construct_printer_info_0(printer, snum);
3616 /* check the required size. */
3617 *needed += spoolss_size_printer_info_0(printer);
3619 if (!alloc_buffer_size(buffer, *needed)) {
3620 SAFE_FREE(printer);
3621 return WERR_INSUFFICIENT_BUFFER;
3624 /* fill the buffer with the structures */
3625 smb_io_printer_info_0("", buffer, printer, 0);
3627 /* clear memory */
3628 SAFE_FREE(printer);
3630 if (*needed > offered) {
3631 return WERR_INSUFFICIENT_BUFFER;
3634 return WERR_OK;
3637 /****************************************************************************
3638 ****************************************************************************/
3640 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3642 PRINTER_INFO_1 *printer=NULL;
3644 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3645 return WERR_NOMEM;
3647 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3649 /* check the required size. */
3650 *needed += spoolss_size_printer_info_1(printer);
3652 if (!alloc_buffer_size(buffer, *needed)) {
3653 SAFE_FREE(printer);
3654 return WERR_INSUFFICIENT_BUFFER;
3657 /* fill the buffer with the structures */
3658 smb_io_printer_info_1("", buffer, printer, 0);
3660 /* clear memory */
3661 SAFE_FREE(printer);
3663 if (*needed > offered) {
3664 return WERR_INSUFFICIENT_BUFFER;
3667 return WERR_OK;
3670 /****************************************************************************
3671 ****************************************************************************/
3673 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3675 PRINTER_INFO_2 *printer=NULL;
3677 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3678 return WERR_NOMEM;
3680 construct_printer_info_2(printer, snum);
3682 /* check the required size. */
3683 *needed += spoolss_size_printer_info_2(printer);
3685 if (!alloc_buffer_size(buffer, *needed)) {
3686 free_printer_info_2(printer);
3687 return WERR_INSUFFICIENT_BUFFER;
3690 /* fill the buffer with the structures */
3691 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3692 free_printer_info_2(printer);
3693 return WERR_NOMEM;
3696 /* clear memory */
3697 free_printer_info_2(printer);
3699 if (*needed > offered) {
3700 return WERR_INSUFFICIENT_BUFFER;
3703 return WERR_OK;
3706 /****************************************************************************
3707 ****************************************************************************/
3709 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3711 PRINTER_INFO_3 *printer=NULL;
3713 if (!construct_printer_info_3(&printer, snum))
3714 return WERR_NOMEM;
3716 /* check the required size. */
3717 *needed += spoolss_size_printer_info_3(printer);
3719 if (!alloc_buffer_size(buffer, *needed)) {
3720 free_printer_info_3(printer);
3721 return WERR_INSUFFICIENT_BUFFER;
3724 /* fill the buffer with the structures */
3725 smb_io_printer_info_3("", buffer, printer, 0);
3727 /* clear memory */
3728 free_printer_info_3(printer);
3730 if (*needed > offered) {
3731 return WERR_INSUFFICIENT_BUFFER;
3734 return WERR_OK;
3737 /****************************************************************************
3738 ****************************************************************************/
3740 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3742 PRINTER_INFO_4 *printer=NULL;
3744 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3745 return WERR_NOMEM;
3747 if (!construct_printer_info_4(printer, snum))
3748 return WERR_NOMEM;
3750 /* check the required size. */
3751 *needed += spoolss_size_printer_info_4(printer);
3753 if (!alloc_buffer_size(buffer, *needed)) {
3754 free_printer_info_4(printer);
3755 return WERR_INSUFFICIENT_BUFFER;
3758 /* fill the buffer with the structures */
3759 smb_io_printer_info_4("", buffer, printer, 0);
3761 /* clear memory */
3762 free_printer_info_4(printer);
3764 if (*needed > offered) {
3765 return WERR_INSUFFICIENT_BUFFER;
3768 return WERR_OK;
3771 /****************************************************************************
3772 ****************************************************************************/
3774 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3776 PRINTER_INFO_5 *printer=NULL;
3778 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3779 return WERR_NOMEM;
3781 if (!construct_printer_info_5(printer, snum))
3782 return WERR_NOMEM;
3784 /* check the required size. */
3785 *needed += spoolss_size_printer_info_5(printer);
3787 if (!alloc_buffer_size(buffer, *needed)) {
3788 free_printer_info_5(printer);
3789 return WERR_INSUFFICIENT_BUFFER;
3792 /* fill the buffer with the structures */
3793 smb_io_printer_info_5("", buffer, printer, 0);
3795 /* clear memory */
3796 free_printer_info_5(printer);
3798 if (*needed > offered) {
3799 return WERR_INSUFFICIENT_BUFFER;
3802 return WERR_OK;
3805 /****************************************************************************
3806 ****************************************************************************/
3808 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3810 POLICY_HND *handle = &q_u->handle;
3811 uint32 level = q_u->level;
3812 NEW_BUFFER *buffer = NULL;
3813 uint32 offered = q_u->offered;
3814 uint32 *needed = &r_u->needed;
3816 int snum;
3818 /* that's an [in out] buffer */
3819 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3820 buffer = r_u->buffer;
3822 *needed=0;
3824 if (!get_printer_snum(p, handle, &snum))
3825 return WERR_BADFID;
3827 switch (level) {
3828 case 0:
3829 return getprinter_level_0(snum, buffer, offered, needed);
3830 case 1:
3831 return getprinter_level_1(snum, buffer, offered, needed);
3832 case 2:
3833 return getprinter_level_2(snum, buffer, offered, needed);
3834 case 3:
3835 return getprinter_level_3(snum, buffer, offered, needed);
3836 case 4:
3837 return getprinter_level_4(snum, buffer, offered, needed);
3838 case 5:
3839 return getprinter_level_5(snum, buffer, offered, needed);
3841 return WERR_UNKNOWN_LEVEL;
3844 /********************************************************************
3845 * fill a DRIVER_INFO_1 struct
3846 ********************************************************************/
3848 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3850 init_unistr( &info->name, driver.info_3->name);
3853 /********************************************************************
3854 * construct_printer_driver_info_1
3855 ********************************************************************/
3857 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3859 NT_PRINTER_INFO_LEVEL *printer = NULL;
3860 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3862 ZERO_STRUCT(driver);
3864 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3865 return WERR_INVALID_PRINTER_NAME;
3867 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3868 return WERR_UNKNOWN_PRINTER_DRIVER;
3870 fill_printer_driver_info_1(info, driver, servername, architecture);
3872 free_a_printer(&printer,2);
3874 return WERR_OK;
3877 /********************************************************************
3878 * construct_printer_driver_info_2
3879 * fill a printer_info_2 struct
3880 ********************************************************************/
3882 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3884 pstring temp;
3886 info->version=driver.info_3->cversion;
3888 init_unistr( &info->name, driver.info_3->name );
3889 init_unistr( &info->architecture, driver.info_3->environment );
3892 if (strlen(driver.info_3->driverpath)) {
3893 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3894 init_unistr( &info->driverpath, temp );
3895 } else
3896 init_unistr( &info->driverpath, "" );
3898 if (strlen(driver.info_3->datafile)) {
3899 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3900 init_unistr( &info->datafile, temp );
3901 } else
3902 init_unistr( &info->datafile, "" );
3904 if (strlen(driver.info_3->configfile)) {
3905 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3906 init_unistr( &info->configfile, temp );
3907 } else
3908 init_unistr( &info->configfile, "" );
3911 /********************************************************************
3912 * construct_printer_driver_info_2
3913 * fill a printer_info_2 struct
3914 ********************************************************************/
3916 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3918 NT_PRINTER_INFO_LEVEL *printer = NULL;
3919 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3921 ZERO_STRUCT(printer);
3922 ZERO_STRUCT(driver);
3924 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3925 return WERR_INVALID_PRINTER_NAME;
3927 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3928 return WERR_UNKNOWN_PRINTER_DRIVER;
3930 fill_printer_driver_info_2(info, driver, servername);
3932 free_a_printer(&printer,2);
3934 return WERR_OK;
3937 /********************************************************************
3938 * copy a strings array and convert to UNICODE
3940 * convert an array of ascii string to a UNICODE string
3941 ********************************************************************/
3943 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3945 int i=0;
3946 int j=0;
3947 char *v;
3948 pstring line;
3949 uint16 *tuary;
3951 DEBUG(6,("init_unistr_array\n"));
3952 *uni_array=NULL;
3954 while (1) {
3955 if (char_array == NULL)
3956 v = "";
3957 else {
3958 v = char_array[i];
3959 if (!v) v = ""; /* hack to handle null lists */
3961 if (strlen(v) == 0) break;
3962 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3963 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3964 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3965 DEBUG(2,("init_unistr_array: Realloc error\n" ));
3966 return;
3967 } else
3968 *uni_array = tuary;
3969 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3970 i++;
3973 if (*uni_array) {
3974 (*uni_array)[j]=0x0000;
3977 DEBUGADD(6,("last one:done\n"));
3980 /********************************************************************
3981 * construct_printer_info_3
3982 * fill a printer_info_3 struct
3983 ********************************************************************/
3985 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3987 pstring temp;
3989 ZERO_STRUCTP(info);
3991 info->version=driver.info_3->cversion;
3993 init_unistr( &info->name, driver.info_3->name );
3994 init_unistr( &info->architecture, driver.info_3->environment );
3996 if (strlen(driver.info_3->driverpath)) {
3997 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3998 init_unistr( &info->driverpath, temp );
3999 } else
4000 init_unistr( &info->driverpath, "" );
4002 if (strlen(driver.info_3->datafile)) {
4003 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4004 init_unistr( &info->datafile, temp );
4005 } else
4006 init_unistr( &info->datafile, "" );
4008 if (strlen(driver.info_3->configfile)) {
4009 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4010 init_unistr( &info->configfile, temp );
4011 } else
4012 init_unistr( &info->configfile, "" );
4014 if (strlen(driver.info_3->helpfile)) {
4015 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4016 init_unistr( &info->helpfile, temp );
4017 } else
4018 init_unistr( &info->helpfile, "" );
4020 init_unistr( &info->monitorname, driver.info_3->monitorname );
4021 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4023 info->dependentfiles=NULL;
4024 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4027 /********************************************************************
4028 * construct_printer_info_3
4029 * fill a printer_info_3 struct
4030 ********************************************************************/
4032 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4034 NT_PRINTER_INFO_LEVEL *printer = NULL;
4035 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4036 WERROR status;
4037 ZERO_STRUCT(driver);
4039 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4040 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4041 if (!W_ERROR_IS_OK(status))
4042 return WERR_INVALID_PRINTER_NAME;
4044 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4045 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4047 #if 0 /* JERRY */
4050 * I put this code in during testing. Helpful when commenting out the
4051 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4052 * as win2k always queries the driver using an infor level of 6.
4053 * I've left it in (but ifdef'd out) because I'll probably
4054 * use it in experimentation again in the future. --jerry 22/01/2002
4057 if (!W_ERROR_IS_OK(status)) {
4059 * Is this a W2k client ?
4061 if (version == 3) {
4062 /* Yes - try again with a WinNT driver. */
4063 version = 2;
4064 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4065 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4067 #endif
4069 if (!W_ERROR_IS_OK(status)) {
4070 free_a_printer(&printer,2);
4071 return WERR_UNKNOWN_PRINTER_DRIVER;
4074 #if 0 /* JERRY */
4076 #endif
4079 fill_printer_driver_info_3(info, driver, servername);
4081 free_a_printer(&printer,2);
4083 return WERR_OK;
4086 /********************************************************************
4087 * construct_printer_info_6
4088 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4089 ********************************************************************/
4091 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4093 pstring temp;
4094 fstring nullstr;
4096 ZERO_STRUCTP(info);
4097 memset(&nullstr, '\0', sizeof(fstring));
4099 info->version=driver.info_3->cversion;
4101 init_unistr( &info->name, driver.info_3->name );
4102 init_unistr( &info->architecture, driver.info_3->environment );
4104 if (strlen(driver.info_3->driverpath)) {
4105 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4106 init_unistr( &info->driverpath, temp );
4107 } else
4108 init_unistr( &info->driverpath, "" );
4110 if (strlen(driver.info_3->datafile)) {
4111 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4112 init_unistr( &info->datafile, temp );
4113 } else
4114 init_unistr( &info->datafile, "" );
4116 if (strlen(driver.info_3->configfile)) {
4117 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4118 init_unistr( &info->configfile, temp );
4119 } else
4120 init_unistr( &info->configfile, "" );
4122 if (strlen(driver.info_3->helpfile)) {
4123 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4124 init_unistr( &info->helpfile, temp );
4125 } else
4126 init_unistr( &info->helpfile, "" );
4128 init_unistr( &info->monitorname, driver.info_3->monitorname );
4129 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4131 info->dependentfiles=NULL;
4132 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4134 info->previousdrivernames=NULL;
4135 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4137 info->driver_date.low=0;
4138 info->driver_date.high=0;
4140 info->padding=0;
4141 info->driver_version_low=0;
4142 info->driver_version_high=0;
4144 init_unistr( &info->mfgname, "");
4145 init_unistr( &info->oem_url, "");
4146 init_unistr( &info->hardware_id, "");
4147 init_unistr( &info->provider, "");
4150 /********************************************************************
4151 * construct_printer_info_6
4152 * fill a printer_info_6 struct
4153 ********************************************************************/
4155 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4157 NT_PRINTER_INFO_LEVEL *printer = NULL;
4158 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4159 WERROR status;
4160 ZERO_STRUCT(driver);
4162 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4163 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4164 if (!W_ERROR_IS_OK(status))
4165 return WERR_INVALID_PRINTER_NAME;
4167 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4168 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4169 if (!W_ERROR_IS_OK(status)) {
4171 * Is this a W2k client ?
4174 if (version < 3) {
4175 free_a_printer(&printer,2);
4176 return WERR_UNKNOWN_PRINTER_DRIVER;
4179 /* Yes - try again with a WinNT driver. */
4180 version = 2;
4181 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4182 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4183 if (!W_ERROR_IS_OK(status)) {
4184 free_a_printer(&printer,2);
4185 return WERR_UNKNOWN_PRINTER_DRIVER;
4189 fill_printer_driver_info_6(info, driver, servername);
4191 free_a_printer(&printer,2);
4193 return WERR_OK;
4196 /****************************************************************************
4197 ****************************************************************************/
4199 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4201 SAFE_FREE(info->dependentfiles);
4204 /****************************************************************************
4205 ****************************************************************************/
4207 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4209 SAFE_FREE(info->dependentfiles);
4213 /****************************************************************************
4214 ****************************************************************************/
4216 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4218 DRIVER_INFO_1 *info=NULL;
4219 WERROR status;
4221 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4222 return WERR_NOMEM;
4224 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4225 if (!W_ERROR_IS_OK(status)) {
4226 SAFE_FREE(info);
4227 return status;
4230 /* check the required size. */
4231 *needed += spoolss_size_printer_driver_info_1(info);
4233 if (!alloc_buffer_size(buffer, *needed)) {
4234 SAFE_FREE(info);
4235 return WERR_INSUFFICIENT_BUFFER;
4238 /* fill the buffer with the structures */
4239 smb_io_printer_driver_info_1("", buffer, info, 0);
4241 /* clear memory */
4242 SAFE_FREE(info);
4244 if (*needed > offered)
4245 return WERR_INSUFFICIENT_BUFFER;
4247 return WERR_OK;
4250 /****************************************************************************
4251 ****************************************************************************/
4253 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4255 DRIVER_INFO_2 *info=NULL;
4256 WERROR status;
4258 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4259 return WERR_NOMEM;
4261 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4262 if (!W_ERROR_IS_OK(status)) {
4263 SAFE_FREE(info);
4264 return status;
4267 /* check the required size. */
4268 *needed += spoolss_size_printer_driver_info_2(info);
4270 if (!alloc_buffer_size(buffer, *needed)) {
4271 SAFE_FREE(info);
4272 return WERR_INSUFFICIENT_BUFFER;
4275 /* fill the buffer with the structures */
4276 smb_io_printer_driver_info_2("", buffer, info, 0);
4278 /* clear memory */
4279 SAFE_FREE(info);
4281 if (*needed > offered)
4282 return WERR_INSUFFICIENT_BUFFER;
4284 return WERR_OK;
4287 /****************************************************************************
4288 ****************************************************************************/
4290 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4292 DRIVER_INFO_3 info;
4293 WERROR status;
4295 ZERO_STRUCT(info);
4297 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4298 if (!W_ERROR_IS_OK(status)) {
4299 return status;
4302 /* check the required size. */
4303 *needed += spoolss_size_printer_driver_info_3(&info);
4305 if (!alloc_buffer_size(buffer, *needed)) {
4306 free_printer_driver_info_3(&info);
4307 return WERR_INSUFFICIENT_BUFFER;
4310 /* fill the buffer with the structures */
4311 smb_io_printer_driver_info_3("", buffer, &info, 0);
4313 free_printer_driver_info_3(&info);
4315 if (*needed > offered)
4316 return WERR_INSUFFICIENT_BUFFER;
4318 return WERR_OK;
4321 /****************************************************************************
4322 ****************************************************************************/
4324 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4326 DRIVER_INFO_6 info;
4327 WERROR status;
4329 ZERO_STRUCT(info);
4331 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4332 if (!W_ERROR_IS_OK(status)) {
4333 return status;
4336 /* check the required size. */
4337 *needed += spoolss_size_printer_driver_info_6(&info);
4339 if (!alloc_buffer_size(buffer, *needed)) {
4340 free_printer_driver_info_6(&info);
4341 return WERR_INSUFFICIENT_BUFFER;
4344 /* fill the buffer with the structures */
4345 smb_io_printer_driver_info_6("", buffer, &info, 0);
4347 free_printer_driver_info_6(&info);
4349 if (*needed > offered)
4350 return WERR_INSUFFICIENT_BUFFER;
4352 return WERR_OK;
4355 /****************************************************************************
4356 ****************************************************************************/
4358 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4360 POLICY_HND *handle = &q_u->handle;
4361 UNISTR2 *uni_arch = &q_u->architecture;
4362 uint32 level = q_u->level;
4363 uint32 clientmajorversion = q_u->clientmajorversion;
4364 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4365 NEW_BUFFER *buffer = NULL;
4366 uint32 offered = q_u->offered;
4367 uint32 *needed = &r_u->needed;
4368 uint32 *servermajorversion = &r_u->servermajorversion;
4369 uint32 *serverminorversion = &r_u->serverminorversion;
4371 fstring servername;
4372 fstring architecture;
4373 int snum;
4375 /* that's an [in out] buffer */
4376 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4377 buffer = r_u->buffer;
4379 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4381 *needed=0;
4382 *servermajorversion=0;
4383 *serverminorversion=0;
4385 pstrcpy(servername, get_called_name());
4386 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4388 if (!get_printer_snum(p, handle, &snum))
4389 return WERR_BADFID;
4391 switch (level) {
4392 case 1:
4393 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4394 case 2:
4395 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4396 case 3:
4397 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4398 case 6:
4399 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4402 return WERR_UNKNOWN_LEVEL;
4405 /****************************************************************************
4406 ****************************************************************************/
4408 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4410 POLICY_HND *handle = &q_u->handle;
4412 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4414 if (!Printer) {
4415 DEBUG(3,("Error in startpageprinter printer handle\n"));
4416 return WERR_BADFID;
4419 Printer->page_started=True;
4420 return WERR_OK;
4423 /****************************************************************************
4424 ****************************************************************************/
4426 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4428 POLICY_HND *handle = &q_u->handle;
4430 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4432 if (!Printer) {
4433 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4434 return WERR_BADFID;
4437 Printer->page_started=False;
4438 print_job_endpage(Printer->jobid);
4440 return WERR_OK;
4443 /********************************************************************
4444 * api_spoolss_getprinter
4445 * called from the spoolss dispatcher
4447 ********************************************************************/
4449 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4451 POLICY_HND *handle = &q_u->handle;
4452 /* uint32 level = q_u->doc_info_container.level; - notused. */
4453 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4454 uint32 *jobid = &r_u->jobid;
4456 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4457 int snum;
4458 pstring jobname;
4459 fstring datatype;
4460 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4461 struct current_user user;
4463 if (!Printer) {
4464 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4465 return WERR_BADFID;
4468 get_current_user(&user, p);
4471 * a nice thing with NT is it doesn't listen to what you tell it.
4472 * when asked to send _only_ RAW datas, it tries to send datas
4473 * in EMF format.
4475 * So I add checks like in NT Server ...
4477 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4478 * there's a bug in NT client-side code, so we'll fix it in the
4479 * server-side code. *nnnnnggggh!*
4482 if (info_1->p_datatype != 0) {
4483 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4484 if (strcmp(datatype, "RAW") != 0) {
4485 (*jobid)=0;
4486 return WERR_INVALID_DATATYPE;
4490 /* get the share number of the printer */
4491 if (!get_printer_snum(p, handle, &snum)) {
4492 return WERR_BADFID;
4495 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4497 Printer->jobid = print_job_start(&user, snum, jobname);
4499 /* An error occured in print_job_start() so return an appropriate
4500 NT error code. */
4502 if (Printer->jobid == -1) {
4503 return map_werror_from_unix(errno);
4506 Printer->document_started=True;
4507 (*jobid) = Printer->jobid;
4509 return WERR_OK;
4512 /********************************************************************
4513 * api_spoolss_getprinter
4514 * called from the spoolss dispatcher
4516 ********************************************************************/
4518 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4520 POLICY_HND *handle = &q_u->handle;
4522 return _spoolss_enddocprinter_internal(p, handle);
4525 /****************************************************************************
4526 ****************************************************************************/
4528 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4530 POLICY_HND *handle = &q_u->handle;
4531 uint32 buffer_size = q_u->buffer_size;
4532 uint8 *buffer = q_u->buffer;
4533 uint32 *buffer_written = &q_u->buffer_size2;
4535 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4537 if (!Printer) {
4538 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4539 r_u->buffer_written = q_u->buffer_size2;
4540 return WERR_BADFID;
4543 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4546 r_u->buffer_written = q_u->buffer_size2;
4548 return WERR_OK;
4551 /********************************************************************
4552 * api_spoolss_getprinter
4553 * called from the spoolss dispatcher
4555 ********************************************************************/
4557 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4558 pipes_struct *p)
4560 struct current_user user;
4561 int snum;
4562 WERROR errcode = WERR_BADFUNC;
4563 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4565 get_current_user(&user, p);
4567 if (!Printer) {
4568 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4569 return WERR_BADFID;
4572 if (!get_printer_snum(p, handle, &snum))
4573 return WERR_BADFID;
4575 switch (command) {
4576 case PRINTER_CONTROL_PAUSE:
4577 if (print_queue_pause(&user, snum, &errcode)) {
4578 errcode = WERR_OK;
4580 break;
4581 case PRINTER_CONTROL_RESUME:
4582 case PRINTER_CONTROL_UNPAUSE:
4583 if (print_queue_resume(&user, snum, &errcode)) {
4584 errcode = WERR_OK;
4586 break;
4587 case PRINTER_CONTROL_PURGE:
4588 if (print_queue_purge(&user, snum, &errcode)) {
4589 errcode = WERR_OK;
4591 break;
4592 default:
4593 return WERR_UNKNOWN_LEVEL;
4596 return errcode;
4599 /********************************************************************
4600 * api_spoolss_abortprinter
4601 ********************************************************************/
4603 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4605 POLICY_HND *handle = &q_u->handle;
4607 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4610 /********************************************************************
4611 * called by spoolss_api_setprinter
4612 * when updating a printer description
4613 ********************************************************************/
4615 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4616 const SPOOL_PRINTER_INFO_LEVEL *info,
4617 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4619 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4620 struct current_user user;
4621 WERROR result;
4622 int snum;
4624 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4626 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4627 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4628 OUR_HANDLE(handle)));
4630 result = WERR_BADFID;
4631 goto done;
4634 /* NT seems to like setting the security descriptor even though
4635 nothing may have actually changed. This causes annoying
4636 dialog boxes when the user doesn't have permission to change
4637 the security descriptor. */
4639 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4641 if (DEBUGLEVEL >= 10) {
4642 SEC_ACL *the_acl;
4643 int i;
4645 the_acl = old_secdesc_ctr->sec->dacl;
4646 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4647 PRINTERNAME(snum), the_acl->num_aces));
4649 for (i = 0; i < the_acl->num_aces; i++) {
4650 fstring sid_str;
4652 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4654 DEBUG(10, ("%s 0x%08x\n", sid_str,
4655 the_acl->ace[i].info.mask));
4658 the_acl = secdesc_ctr->sec->dacl;
4660 if (the_acl) {
4661 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4662 PRINTERNAME(snum), the_acl->num_aces));
4664 for (i = 0; i < the_acl->num_aces; i++) {
4665 fstring sid_str;
4667 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4669 DEBUG(10, ("%s 0x%08x\n", sid_str,
4670 the_acl->ace[i].info.mask));
4672 } else {
4673 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4677 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4679 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4680 result = WERR_OK;
4681 goto done;
4684 /* Work out which user is performing the operation */
4686 get_current_user(&user, p);
4688 /* Check the user has permissions to change the security
4689 descriptor. By experimentation with two NT machines, the user
4690 requires Full Access to the printer to change security
4691 information. */
4693 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4694 result = WERR_ACCESS_DENIED;
4695 goto done;
4698 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4700 done:
4702 return result;
4705 /********************************************************************
4706 Do Samba sanity checks on a printer info struct.
4707 this has changed purpose: it now "canonicalises" printer
4708 info from a client rather than just checking it is correct
4709 ********************************************************************/
4711 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4713 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4714 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4716 /* we force some elements to "correct" values */
4717 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4718 fstrcpy(info->sharename, lp_servicename(snum));
4719 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4720 get_called_name(), info->sharename);
4721 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
4723 return True;
4726 /****************************************************************************
4727 ****************************************************************************/
4729 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4731 char *cmd = lp_addprinter_cmd();
4732 char **qlines;
4733 pstring command;
4734 pstring driverlocation;
4735 int numlines;
4736 int ret;
4737 int fd;
4738 fstring remote_machine = "%m";
4740 /* build driver path... only 9X architecture is needed for legacy reasons */
4741 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4742 get_called_name());
4743 /* change \ to \\ for the shell */
4744 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4746 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4747 cmd, printer->info_2->printername, printer->info_2->sharename,
4748 printer->info_2->portname, printer->info_2->drivername,
4749 printer->info_2->location, driverlocation, remote_machine);
4751 /* Convert script args to unix-codepage */
4752 DEBUG(10,("Running [%s]\n", command));
4753 ret = smbrun(command, &fd);
4754 DEBUGADD(10,("returned [%d]\n", ret));
4756 if ( ret != 0 ) {
4757 if (fd != -1)
4758 close(fd);
4759 return False;
4762 numlines = 0;
4763 /* Get lines and convert them back to dos-codepage */
4764 qlines = fd_lines_load(fd, &numlines);
4765 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4766 close(fd);
4768 if(numlines) {
4769 /* Set the portname to what the script says the portname should be. */
4770 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4771 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4773 /* Send SIGHUP to process group... is there a better way? */
4774 kill(0, SIGHUP);
4775 add_all_printers();
4778 file_lines_free(qlines);
4779 return True;
4782 #if 0 /* JERRY */
4784 /* Return true if two devicemodes are equal */
4786 #define DEVMODE_CHECK_INT(field) \
4787 if (d1->field != d2->field) { \
4788 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4789 d1->field, d2->field)); \
4790 return False; \
4793 /************************************************************************
4794 Handy, but currently unused functions
4795 ***********************************************************************/
4797 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4799 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4801 if (!d1 ^ !d2) {
4802 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4803 return False; /* if either is exclusively NULL are not equal */
4806 if (!strequal(d1->devicename, d2->devicename)) {
4807 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4808 return False;
4811 if (!strequal(d1->formname, d2->formname)) {
4812 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4813 return False;
4816 DEVMODE_CHECK_INT(specversion);
4817 DEVMODE_CHECK_INT(driverversion);
4818 DEVMODE_CHECK_INT(driverextra);
4819 DEVMODE_CHECK_INT(orientation);
4820 DEVMODE_CHECK_INT(papersize);
4821 DEVMODE_CHECK_INT(paperlength);
4822 DEVMODE_CHECK_INT(paperwidth);
4823 DEVMODE_CHECK_INT(scale);
4824 DEVMODE_CHECK_INT(copies);
4825 DEVMODE_CHECK_INT(defaultsource);
4826 DEVMODE_CHECK_INT(printquality);
4827 DEVMODE_CHECK_INT(color);
4828 DEVMODE_CHECK_INT(duplex);
4829 DEVMODE_CHECK_INT(yresolution);
4830 DEVMODE_CHECK_INT(ttoption);
4831 DEVMODE_CHECK_INT(collate);
4832 DEVMODE_CHECK_INT(logpixels);
4834 DEVMODE_CHECK_INT(fields);
4835 DEVMODE_CHECK_INT(bitsperpel);
4836 DEVMODE_CHECK_INT(pelswidth);
4837 DEVMODE_CHECK_INT(pelsheight);
4838 DEVMODE_CHECK_INT(displayflags);
4839 DEVMODE_CHECK_INT(displayfrequency);
4840 DEVMODE_CHECK_INT(icmmethod);
4841 DEVMODE_CHECK_INT(icmintent);
4842 DEVMODE_CHECK_INT(mediatype);
4843 DEVMODE_CHECK_INT(dithertype);
4844 DEVMODE_CHECK_INT(reserved1);
4845 DEVMODE_CHECK_INT(reserved2);
4846 DEVMODE_CHECK_INT(panningwidth);
4847 DEVMODE_CHECK_INT(panningheight);
4849 /* compare the private data if it exists */
4850 if (!d1->driverextra && !d2->driverextra) goto equal;
4853 DEVMODE_CHECK_INT(driverextra);
4855 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4856 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4857 return False;
4860 equal:
4861 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4862 return True;
4865 /* Return true if two NT_PRINTER_PARAM structures are equal */
4867 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4868 NT_PRINTER_PARAM *p2)
4870 if (!p1 && !p2) goto equal;
4872 if ((!p1 && p2) || (p1 && !p2)) {
4873 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4874 return False;
4877 /* Compare lists of printer parameters */
4879 while (p1) {
4880 BOOL found = False;
4881 NT_PRINTER_PARAM *q = p1;
4883 /* Find the parameter in the second structure */
4885 while(q) {
4887 if (strequal(p1->value, q->value)) {
4889 if (p1->type != q->type) {
4890 DEBUG(10, ("nt_printer_param_equal():"
4891 "types for %s differ (%d != %d)\n",
4892 p1->value, p1->type,
4893 q->type));
4894 break;
4897 if (p1->data_len != q->data_len) {
4898 DEBUG(10, ("nt_printer_param_equal():"
4899 "len for %s differs (%d != %d)\n",
4900 p1->value, p1->data_len,
4901 q->data_len));
4902 break;
4905 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4906 found = True;
4907 } else {
4908 DEBUG(10, ("nt_printer_param_equal():"
4909 "data for %s differs\n", p1->value));
4912 break;
4915 q = q->next;
4918 if (!found) {
4919 DEBUG(10, ("nt_printer_param_equal(): param %s "
4920 "does not exist\n", p1->value));
4921 return False;
4924 p1 = p1->next;
4927 equal:
4929 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4930 return True;
4933 /********************************************************************
4934 * Called by update_printer when trying to work out whether to
4935 * actually update printer info.
4936 ********************************************************************/
4938 #define PI_CHECK_INT(field) \
4939 if (pi1->field != pi2->field) { \
4940 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4941 pi1->field, pi2->field)); \
4942 return False; \
4945 #define PI_CHECK_STR(field) \
4946 if (!strequal(pi1->field, pi2->field)) { \
4947 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4948 pi1->field, pi2->field)); \
4949 return False; \
4952 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4953 NT_PRINTER_INFO_LEVEL *p2)
4955 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4957 /* Trivial conditions */
4959 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4960 goto equal;
4963 if ((!p1 && p2) || (p1 && !p2) ||
4964 (!p1->info_2 && p2->info_2) ||
4965 (p1->info_2 && !p2->info_2)) {
4966 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4967 "differ\n"));
4968 return False;
4971 /* Compare two nt_printer_info_level structures. Don't compare
4972 status or cjobs as they seem to have something to do with the
4973 printer queue. */
4975 pi1 = p1->info_2;
4976 pi2 = p2->info_2;
4978 /* Don't check the attributes as we stomp on the value in
4979 check_printer_ok() anyway. */
4981 #if 0
4982 PI_CHECK_INT(attributes);
4983 #endif
4985 PI_CHECK_INT(priority);
4986 PI_CHECK_INT(default_priority);
4987 PI_CHECK_INT(starttime);
4988 PI_CHECK_INT(untiltime);
4989 PI_CHECK_INT(averageppm);
4991 /* Yuck - don't check the printername or servername as the
4992 mod_a_printer() code plays games with them. You can't
4993 change the printername or the sharename through this interface
4994 in Samba. */
4996 PI_CHECK_STR(sharename);
4997 PI_CHECK_STR(portname);
4998 PI_CHECK_STR(drivername);
4999 PI_CHECK_STR(comment);
5000 PI_CHECK_STR(location);
5002 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
5003 return False;
5006 PI_CHECK_STR(sepfile);
5007 PI_CHECK_STR(printprocessor);
5008 PI_CHECK_STR(datatype);
5009 PI_CHECK_STR(parameters);
5011 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
5012 return False;
5015 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
5016 return False;
5019 PI_CHECK_INT(changeid);
5020 PI_CHECK_INT(c_setprinter);
5021 PI_CHECK_INT(setuptime);
5023 equal:
5024 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5025 return True;
5028 #endif
5030 /********************************************************************
5031 * Called by spoolss_api_setprinter
5032 * when updating a printer description.
5033 ********************************************************************/
5035 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5036 const SPOOL_PRINTER_INFO_LEVEL *info,
5037 DEVICEMODE *devmode)
5039 int snum;
5040 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5041 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5042 PRINTER_MESSAGE_INFO msg;
5043 WERROR result;
5045 DEBUG(8,("update_printer\n"));
5047 ZERO_STRUCT(msg);
5049 result = WERR_OK;
5051 if (level!=2) {
5052 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5053 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5054 result = WERR_UNKNOWN_LEVEL;
5055 goto done;
5058 if (!Printer) {
5059 result = WERR_BADFID;
5060 goto done;
5063 if (!get_printer_snum(p, handle, &snum)) {
5064 result = WERR_BADFID;
5065 goto done;
5068 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5069 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5070 result = WERR_BADFID;
5071 goto done;
5074 DEBUGADD(8,("Converting info_2 struct\n"));
5077 * convert_printer_info converts the incoming
5078 * info from the client and overwrites the info
5079 * just read from the tdb in the pointer 'printer'.
5082 if (!convert_printer_info(info, printer, level)) {
5083 result = WERR_NOMEM;
5084 goto done;
5087 if (devmode) {
5088 /* we have a valid devmode
5089 convert it and link it*/
5091 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5092 if (!convert_devicemode(printer->info_2->printername, devmode,
5093 &printer->info_2->devmode)) {
5094 result = WERR_NOMEM;
5095 goto done;
5099 /* Do sanity check on the requested changes for Samba */
5101 if (!check_printer_ok(printer->info_2, snum)) {
5102 result = WERR_INVALID_PARAM;
5103 goto done;
5106 #if 0 /* JERRY */
5109 * Another one of those historical misunderstandings...
5110 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5111 * I'm leaving it here as a reminder. --jerry
5114 if (nt_printer_info_level_equal(printer, old_printer)) {
5115 DEBUG(3, ("update_printer: printer info has not changed\n"));
5116 result = WERR_OK;
5117 goto done;
5120 #endif
5122 /* Check calling user has permission to update printer description */
5124 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5125 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5126 result = WERR_ACCESS_DENIED;
5127 goto done;
5130 /* Call addprinter hook */
5132 if (*lp_addprinter_cmd()) {
5133 if ( !add_printer_hook(printer) ) {
5134 result = WERR_ACCESS_DENIED;
5135 goto done;
5140 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5141 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5142 * requires Win32 client code (see other notes elsewhere in the code).
5144 if (printer->info_2->devmode &&
5145 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5147 DEBUG(10,("update_printer: Save printer driver init data\n"));
5148 printer->info_2->devmode->displayfrequency = 0;
5150 if (update_driver_init(*printer, 2)!=0) {
5151 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5152 result = WERR_ACCESS_DENIED;
5153 goto done;
5155 } else {
5157 * When a *new* driver is bound to a printer, the drivername is used to
5158 * lookup previously saved driver initialization info, which is then
5159 * bound to the printer, simulating what happens in the Windows arch.
5161 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5162 set_driver_init(printer, 2);
5163 msg.flags |= PRINTER_MESSAGE_DRIVER;
5167 /* Update printer info */
5168 result = mod_a_printer(*printer, 2);
5170 /* flag which changes actually occured. This is a small subset of
5171 all the possible changes */
5173 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5174 msg.flags |= PRINTER_MESSAGE_COMMENT;
5176 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5177 msg.flags |= PRINTER_MESSAGE_SHARENAME;
5179 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5180 msg.flags |= PRINTER_MESSAGE_PORT;
5182 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5183 msg.flags |= PRINTER_MESSAGE_LOCATION;
5185 ZERO_STRUCT(msg);
5187 msg.low = PRINTER_CHANGE_ADD_PRINTER;
5188 fstrcpy(msg.printer_name, printer->info_2->printername);
5190 /* only send a notify if something changed */
5191 if (msg.flags) {
5192 srv_spoolss_sendnotify(msg.printer_name, 0, PRINTER_CHANGE_ADD_PRINTER, msg.flags);
5195 done:
5196 free_a_printer(&printer, 2);
5197 free_a_printer(&old_printer, 2);
5200 return result;
5203 /****************************************************************************
5204 ****************************************************************************/
5206 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5208 POLICY_HND *handle = &q_u->handle;
5209 uint32 level = q_u->level;
5210 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5211 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5212 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5213 uint32 command = q_u->command;
5215 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5217 if (!Printer) {
5218 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5219 return WERR_BADFID;
5222 /* check the level */
5223 switch (level) {
5224 case 0:
5225 return control_printer(handle, command, p);
5226 case 2:
5227 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5228 case 3:
5229 return update_printer_sec(handle, level, info, p,
5230 secdesc_ctr);
5231 default:
5232 return WERR_UNKNOWN_LEVEL;
5236 /****************************************************************************
5237 ****************************************************************************/
5239 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5241 POLICY_HND *handle = &q_u->handle;
5243 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5245 if (!Printer) {
5246 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5247 return WERR_BADFID;
5250 if (Printer->notify.client_connected==True)
5251 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5253 Printer->notify.flags=0;
5254 Printer->notify.options=0;
5255 Printer->notify.localmachine[0]='\0';
5256 Printer->notify.printerlocal=0;
5257 if (Printer->notify.option)
5258 free_spool_notify_option(&Printer->notify.option);
5259 Printer->notify.client_connected=False;
5261 return WERR_OK;
5264 /****************************************************************************
5265 ****************************************************************************/
5267 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5269 /* that's an [in out] buffer (despite appearences to the contrary) */
5270 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5272 r_u->needed = 0;
5273 return WERR_INVALID_PARAM; /* this is what a NT server
5274 returns for AddJob. AddJob
5275 must fail on non-local
5276 printers */
5279 /****************************************************************************
5280 ****************************************************************************/
5282 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5283 int position, int snum)
5285 pstring temp_name;
5287 struct tm *t;
5289 t=gmtime(&queue->time);
5290 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5292 job_info->jobid=queue->job;
5293 init_unistr(&job_info->printername, lp_servicename(snum));
5294 init_unistr(&job_info->machinename, temp_name);
5295 init_unistr(&job_info->username, queue->fs_user);
5296 init_unistr(&job_info->document, queue->fs_file);
5297 init_unistr(&job_info->datatype, "RAW");
5298 init_unistr(&job_info->text_status, "");
5299 job_info->status=nt_printj_status(queue->status);
5300 job_info->priority=queue->priority;
5301 job_info->position=position;
5302 job_info->totalpages=queue->page_count;
5303 job_info->pagesprinted=0;
5305 make_systemtime(&job_info->submitted, t);
5308 /****************************************************************************
5309 ****************************************************************************/
5311 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5312 int position, int snum,
5313 NT_PRINTER_INFO_LEVEL *ntprinter,
5314 DEVICEMODE *devmode)
5316 pstring temp_name;
5317 pstring chaine;
5318 struct tm *t;
5320 t=gmtime(&queue->time);
5321 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5323 job_info->jobid=queue->job;
5325 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5327 init_unistr(&job_info->printername, chaine);
5329 init_unistr(&job_info->machinename, temp_name);
5330 init_unistr(&job_info->username, queue->fs_user);
5331 init_unistr(&job_info->document, queue->fs_file);
5332 init_unistr(&job_info->notifyname, queue->fs_user);
5333 init_unistr(&job_info->datatype, "RAW");
5334 init_unistr(&job_info->printprocessor, "winprint");
5335 init_unistr(&job_info->parameters, "");
5336 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5337 init_unistr(&job_info->text_status, "");
5339 /* and here the security descriptor */
5341 job_info->status=nt_printj_status(queue->status);
5342 job_info->priority=queue->priority;
5343 job_info->position=position;
5344 job_info->starttime=0;
5345 job_info->untiltime=0;
5346 job_info->totalpages=queue->page_count;
5347 job_info->size=queue->size;
5348 make_systemtime(&(job_info->submitted), t);
5349 job_info->timeelapsed=0;
5350 job_info->pagesprinted=0;
5352 job_info->devmode = devmode;
5354 return (True);
5357 /****************************************************************************
5358 Enumjobs at level 1.
5359 ****************************************************************************/
5361 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5362 NEW_BUFFER *buffer, uint32 offered,
5363 uint32 *needed, uint32 *returned)
5365 JOB_INFO_1 *info;
5366 int i;
5368 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5369 if (info==NULL) {
5370 SAFE_FREE(queue);
5371 *returned=0;
5372 return WERR_NOMEM;
5375 for (i=0; i<*returned; i++)
5376 fill_job_info_1(&info[i], &queue[i], i, snum);
5378 SAFE_FREE(queue);
5380 /* check the required size. */
5381 for (i=0; i<*returned; i++)
5382 (*needed) += spoolss_size_job_info_1(&info[i]);
5384 if (!alloc_buffer_size(buffer, *needed)) {
5385 SAFE_FREE(info);
5386 return WERR_INSUFFICIENT_BUFFER;
5389 /* fill the buffer with the structures */
5390 for (i=0; i<*returned; i++)
5391 smb_io_job_info_1("", buffer, &info[i], 0);
5393 /* clear memory */
5394 SAFE_FREE(info);
5396 if (*needed > offered) {
5397 *returned=0;
5398 return WERR_INSUFFICIENT_BUFFER;
5401 return WERR_OK;
5404 /****************************************************************************
5405 Enumjobs at level 2.
5406 ****************************************************************************/
5408 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5409 NEW_BUFFER *buffer, uint32 offered,
5410 uint32 *needed, uint32 *returned)
5412 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5413 JOB_INFO_2 *info = NULL;
5414 int i;
5415 WERROR result;
5416 DEVICEMODE *devmode = NULL;
5418 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5419 if (info==NULL) {
5420 *returned=0;
5421 result = WERR_NOMEM;
5422 goto done;
5425 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5426 if (!W_ERROR_IS_OK(result)) {
5427 *returned = 0;
5428 goto done;
5431 if (!(devmode = construct_dev_mode(snum))) {
5432 *returned = 0;
5433 result = WERR_NOMEM;
5434 goto done;
5437 for (i=0; i<*returned; i++)
5438 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5439 devmode);
5441 free_a_printer(&ntprinter, 2);
5442 SAFE_FREE(queue);
5444 /* check the required size. */
5445 for (i=0; i<*returned; i++)
5446 (*needed) += spoolss_size_job_info_2(&info[i]);
5448 if (*needed > offered) {
5449 *returned=0;
5450 result = WERR_INSUFFICIENT_BUFFER;
5451 goto done;
5454 if (!alloc_buffer_size(buffer, *needed)) {
5455 SAFE_FREE(info);
5456 result = WERR_INSUFFICIENT_BUFFER;
5457 goto done;
5460 /* fill the buffer with the structures */
5461 for (i=0; i<*returned; i++)
5462 smb_io_job_info_2("", buffer, &info[i], 0);
5464 result = WERR_OK;
5466 done:
5467 free_a_printer(&ntprinter, 2);
5468 free_devmode(devmode);
5469 SAFE_FREE(queue);
5470 SAFE_FREE(info);
5472 return result;
5475 /****************************************************************************
5476 Enumjobs.
5477 ****************************************************************************/
5479 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5481 POLICY_HND *handle = &q_u->handle;
5482 /* uint32 firstjob = q_u->firstjob; - notused. */
5483 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5484 uint32 level = q_u->level;
5485 NEW_BUFFER *buffer = NULL;
5486 uint32 offered = q_u->offered;
5487 uint32 *needed = &r_u->needed;
5488 uint32 *returned = &r_u->returned;
5490 int snum;
5491 print_status_struct prt_status;
5492 print_queue_struct *queue=NULL;
5494 /* that's an [in out] buffer */
5495 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5496 buffer = r_u->buffer;
5498 DEBUG(4,("_spoolss_enumjobs\n"));
5500 *needed=0;
5501 *returned=0;
5503 if (!get_printer_snum(p, handle, &snum))
5504 return WERR_BADFID;
5506 *returned = print_queue_status(snum, &queue, &prt_status);
5507 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5509 if (*returned == 0) {
5510 SAFE_FREE(queue);
5511 return WERR_OK;
5514 switch (level) {
5515 case 1:
5516 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5517 case 2:
5518 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5519 default:
5520 SAFE_FREE(queue);
5521 *returned=0;
5522 return WERR_UNKNOWN_LEVEL;
5526 /****************************************************************************
5527 ****************************************************************************/
5529 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5531 return WERR_OK;
5534 /****************************************************************************
5535 ****************************************************************************/
5537 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5539 POLICY_HND *handle = &q_u->handle;
5540 uint32 jobid = q_u->jobid;
5541 /* uint32 level = q_u->level; - notused. */
5542 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5543 uint32 command = q_u->command;
5545 struct current_user user;
5546 int snum;
5547 WERROR errcode = WERR_BADFUNC;
5549 if (!get_printer_snum(p, handle, &snum)) {
5550 return WERR_BADFID;
5553 if (!print_job_exists(jobid)) {
5554 return WERR_INVALID_PRINTER_NAME;
5557 get_current_user(&user, p);
5559 switch (command) {
5560 case JOB_CONTROL_CANCEL:
5561 case JOB_CONTROL_DELETE:
5562 if (print_job_delete(&user, jobid, &errcode)) {
5563 errcode = WERR_OK;
5565 break;
5566 case JOB_CONTROL_PAUSE:
5567 if (print_job_pause(&user, jobid, &errcode)) {
5568 errcode = WERR_OK;
5570 break;
5571 case JOB_CONTROL_RESTART:
5572 case JOB_CONTROL_RESUME:
5573 if (print_job_resume(&user, jobid, &errcode)) {
5574 errcode = WERR_OK;
5576 break;
5577 default:
5578 return WERR_UNKNOWN_LEVEL;
5581 return errcode;
5584 /****************************************************************************
5585 Enumerates all printer drivers at level 1.
5586 ****************************************************************************/
5588 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5590 int i;
5591 int ndrivers;
5592 uint32 version;
5593 fstring *list = NULL;
5595 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5596 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5598 *returned=0;
5600 #define MAX_VERSION 4
5602 for (version=0; version<MAX_VERSION; version++) {
5603 list=NULL;
5604 ndrivers=get_ntdrivers(&list, architecture, version);
5605 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5607 if(ndrivers == -1)
5608 return WERR_NOMEM;
5610 if(ndrivers != 0) {
5611 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5612 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5613 SAFE_FREE(driver_info_1);
5614 SAFE_FREE(list);
5615 return WERR_NOMEM;
5617 else driver_info_1 = tdi1;
5620 for (i=0; i<ndrivers; i++) {
5621 WERROR status;
5622 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5623 ZERO_STRUCT(driver);
5624 status = get_a_printer_driver(&driver, 3, list[i],
5625 architecture, version);
5626 if (!W_ERROR_IS_OK(status)) {
5627 SAFE_FREE(list);
5628 return status;
5630 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5631 free_a_printer_driver(driver, 3);
5634 *returned+=ndrivers;
5635 SAFE_FREE(list);
5638 /* check the required size. */
5639 for (i=0; i<*returned; i++) {
5640 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5641 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5644 if (!alloc_buffer_size(buffer, *needed)) {
5645 SAFE_FREE(driver_info_1);
5646 return WERR_INSUFFICIENT_BUFFER;
5649 /* fill the buffer with the driver structures */
5650 for (i=0; i<*returned; i++) {
5651 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5652 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5655 SAFE_FREE(driver_info_1);
5657 if (*needed > offered) {
5658 *returned=0;
5659 return WERR_INSUFFICIENT_BUFFER;
5662 return WERR_OK;
5665 /****************************************************************************
5666 Enumerates all printer drivers at level 2.
5667 ****************************************************************************/
5669 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5671 int i;
5672 int ndrivers;
5673 uint32 version;
5674 fstring *list = NULL;
5676 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5677 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5679 *returned=0;
5681 #define MAX_VERSION 4
5683 for (version=0; version<MAX_VERSION; version++) {
5684 list=NULL;
5685 ndrivers=get_ntdrivers(&list, architecture, version);
5686 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5688 if(ndrivers == -1)
5689 return WERR_NOMEM;
5691 if(ndrivers != 0) {
5692 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5693 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5694 SAFE_FREE(driver_info_2);
5695 SAFE_FREE(list);
5696 return WERR_NOMEM;
5698 else driver_info_2 = tdi2;
5701 for (i=0; i<ndrivers; i++) {
5702 WERROR status;
5704 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5705 ZERO_STRUCT(driver);
5706 status = get_a_printer_driver(&driver, 3, list[i],
5707 architecture, version);
5708 if (!W_ERROR_IS_OK(status)) {
5709 SAFE_FREE(list);
5710 return status;
5712 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5713 free_a_printer_driver(driver, 3);
5716 *returned+=ndrivers;
5717 SAFE_FREE(list);
5720 /* check the required size. */
5721 for (i=0; i<*returned; i++) {
5722 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5723 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5726 if (!alloc_buffer_size(buffer, *needed)) {
5727 SAFE_FREE(driver_info_2);
5728 return WERR_INSUFFICIENT_BUFFER;
5731 /* fill the buffer with the form structures */
5732 for (i=0; i<*returned; i++) {
5733 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5734 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5737 SAFE_FREE(driver_info_2);
5739 if (*needed > offered) {
5740 *returned=0;
5741 return WERR_INSUFFICIENT_BUFFER;
5744 return WERR_OK;
5747 /****************************************************************************
5748 Enumerates all printer drivers at level 3.
5749 ****************************************************************************/
5751 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5753 int i;
5754 int ndrivers;
5755 uint32 version;
5756 fstring *list = NULL;
5758 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5759 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5761 *returned=0;
5763 #define MAX_VERSION 4
5765 for (version=0; version<MAX_VERSION; version++) {
5766 list=NULL;
5767 ndrivers=get_ntdrivers(&list, architecture, version);
5768 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5770 if(ndrivers == -1)
5771 return WERR_NOMEM;
5773 if(ndrivers != 0) {
5774 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5775 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5776 SAFE_FREE(driver_info_3);
5777 SAFE_FREE(list);
5778 return WERR_NOMEM;
5780 else driver_info_3 = tdi3;
5783 for (i=0; i<ndrivers; i++) {
5784 WERROR status;
5786 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5787 ZERO_STRUCT(driver);
5788 status = get_a_printer_driver(&driver, 3, list[i],
5789 architecture, version);
5790 if (!W_ERROR_IS_OK(status)) {
5791 SAFE_FREE(list);
5792 return status;
5794 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5795 free_a_printer_driver(driver, 3);
5798 *returned+=ndrivers;
5799 SAFE_FREE(list);
5802 /* check the required size. */
5803 for (i=0; i<*returned; i++) {
5804 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5805 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5808 if (!alloc_buffer_size(buffer, *needed)) {
5809 SAFE_FREE(driver_info_3);
5810 return WERR_INSUFFICIENT_BUFFER;
5813 /* fill the buffer with the driver structures */
5814 for (i=0; i<*returned; i++) {
5815 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5816 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5819 for (i=0; i<*returned; i++)
5820 SAFE_FREE(driver_info_3[i].dependentfiles);
5822 SAFE_FREE(driver_info_3);
5824 if (*needed > offered) {
5825 *returned=0;
5826 return WERR_INSUFFICIENT_BUFFER;
5829 return WERR_OK;
5832 /****************************************************************************
5833 Enumerates all printer drivers.
5834 ****************************************************************************/
5836 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5838 /* UNISTR2 *name = &q_u->name; - notused. */
5839 UNISTR2 *environment = &q_u->environment;
5840 uint32 level = q_u->level;
5841 NEW_BUFFER *buffer = NULL;
5842 uint32 offered = q_u->offered;
5843 uint32 *needed = &r_u->needed;
5844 uint32 *returned = &r_u->returned;
5846 fstring *list = NULL;
5847 fstring servername;
5848 fstring architecture;
5850 /* that's an [in out] buffer */
5851 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5852 buffer = r_u->buffer;
5854 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5855 fstrcpy(servername, get_called_name());
5856 *needed=0;
5857 *returned=0;
5859 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5861 switch (level) {
5862 case 1:
5863 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5864 case 2:
5865 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5866 case 3:
5867 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5868 default:
5869 *returned=0;
5870 SAFE_FREE(list);
5871 return WERR_UNKNOWN_LEVEL;
5875 /****************************************************************************
5876 ****************************************************************************/
5878 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5880 form->flag=list->flag;
5881 init_unistr(&form->name, list->name);
5882 form->width=list->width;
5883 form->length=list->length;
5884 form->left=list->left;
5885 form->top=list->top;
5886 form->right=list->right;
5887 form->bottom=list->bottom;
5890 /****************************************************************************
5891 ****************************************************************************/
5893 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5895 /* POLICY_HND *handle = &q_u->handle; - notused. */
5896 uint32 level = q_u->level;
5897 NEW_BUFFER *buffer = NULL;
5898 uint32 offered = q_u->offered;
5899 uint32 *needed = &r_u->needed;
5900 uint32 *numofforms = &r_u->numofforms;
5901 uint32 numbuiltinforms;
5903 nt_forms_struct *list=NULL;
5904 nt_forms_struct *builtinlist=NULL;
5905 FORM_1 *forms_1;
5906 int buffer_size=0;
5907 int i;
5909 /* that's an [in out] buffer */
5910 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5911 buffer = r_u->buffer;
5913 DEBUG(4,("_spoolss_enumforms\n"));
5914 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5915 DEBUGADD(5,("Info level [%d]\n", level));
5917 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5918 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5919 *numofforms = get_ntforms(&list);
5920 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5921 *numofforms += numbuiltinforms;
5923 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5925 switch (level) {
5926 case 1:
5927 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5928 *numofforms=0;
5929 return WERR_NOMEM;
5932 /* construct the list of form structures */
5933 for (i=0; i<numbuiltinforms; i++) {
5934 DEBUGADD(6,("Filling form number [%d]\n",i));
5935 fill_form_1(&forms_1[i], &builtinlist[i]);
5938 SAFE_FREE(builtinlist);
5940 for (; i<*numofforms; i++) {
5941 DEBUGADD(6,("Filling form number [%d]\n",i));
5942 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5945 SAFE_FREE(list);
5947 /* check the required size. */
5948 for (i=0; i<numbuiltinforms; i++) {
5949 DEBUGADD(6,("adding form [%d]'s size\n",i));
5950 buffer_size += spoolss_size_form_1(&forms_1[i]);
5952 for (; i<*numofforms; i++) {
5953 DEBUGADD(6,("adding form [%d]'s size\n",i));
5954 buffer_size += spoolss_size_form_1(&forms_1[i]);
5957 *needed=buffer_size;
5959 if (!alloc_buffer_size(buffer, buffer_size)){
5960 SAFE_FREE(forms_1);
5961 return WERR_INSUFFICIENT_BUFFER;
5964 /* fill the buffer with the form structures */
5965 for (i=0; i<numbuiltinforms; i++) {
5966 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5967 smb_io_form_1("", buffer, &forms_1[i], 0);
5969 for (; i<*numofforms; i++) {
5970 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5971 smb_io_form_1("", buffer, &forms_1[i], 0);
5974 SAFE_FREE(forms_1);
5976 if (*needed > offered) {
5977 *numofforms=0;
5978 return WERR_INSUFFICIENT_BUFFER;
5980 else
5981 return WERR_OK;
5983 default:
5984 SAFE_FREE(list);
5985 SAFE_FREE(builtinlist);
5986 return WERR_UNKNOWN_LEVEL;
5991 /****************************************************************************
5992 ****************************************************************************/
5994 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5996 /* POLICY_HND *handle = &q_u->handle; - notused. */
5997 uint32 level = q_u->level;
5998 UNISTR2 *uni_formname = &q_u->formname;
5999 NEW_BUFFER *buffer = NULL;
6000 uint32 offered = q_u->offered;
6001 uint32 *needed = &r_u->needed;
6003 nt_forms_struct *list=NULL;
6004 nt_forms_struct builtin_form;
6005 BOOL foundBuiltin;
6006 FORM_1 form_1;
6007 fstring form_name;
6008 int buffer_size=0;
6009 int numofforms=0, i=0;
6011 /* that's an [in out] buffer */
6012 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6013 buffer = r_u->buffer;
6015 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6017 DEBUG(4,("_spoolss_getform\n"));
6018 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6019 DEBUGADD(5,("Info level [%d]\n", level));
6021 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6022 if (!foundBuiltin) {
6023 numofforms = get_ntforms(&list);
6024 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6026 if (numofforms == 0)
6027 return WERR_BADFID;
6030 switch (level) {
6031 case 1:
6032 if (foundBuiltin) {
6033 fill_form_1(&form_1, &builtin_form);
6034 } else {
6036 /* Check if the requested name is in the list of form structures */
6037 for (i=0; i<numofforms; i++) {
6039 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6041 if (strequal(form_name, list[i].name)) {
6042 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6043 fill_form_1(&form_1, &list[i]);
6044 break;
6048 SAFE_FREE(list);
6049 if (i == numofforms) {
6050 return WERR_BADFID;
6053 /* check the required size. */
6055 *needed=spoolss_size_form_1(&form_1);
6057 if (!alloc_buffer_size(buffer, buffer_size)){
6058 return WERR_INSUFFICIENT_BUFFER;
6061 if (*needed > offered) {
6062 return WERR_INSUFFICIENT_BUFFER;
6065 /* fill the buffer with the form structures */
6066 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6067 smb_io_form_1("", buffer, &form_1, 0);
6069 return WERR_OK;
6071 default:
6072 SAFE_FREE(list);
6073 return WERR_UNKNOWN_LEVEL;
6077 /****************************************************************************
6078 ****************************************************************************/
6080 static void fill_port_1(PORT_INFO_1 *port, char *name)
6082 init_unistr(&port->port_name, name);
6085 /****************************************************************************
6086 ****************************************************************************/
6088 static void fill_port_2(PORT_INFO_2 *port, char *name)
6090 init_unistr(&port->port_name, name);
6091 init_unistr(&port->monitor_name, "Local Monitor");
6092 init_unistr(&port->description, "Local Port");
6093 #define PORT_TYPE_WRITE 1
6094 port->port_type=PORT_TYPE_WRITE;
6095 port->reserved=0x0;
6098 /****************************************************************************
6099 enumports level 1.
6100 ****************************************************************************/
6102 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6104 PORT_INFO_1 *ports=NULL;
6105 int i=0;
6107 if (*lp_enumports_cmd()) {
6108 char *cmd = lp_enumports_cmd();
6109 char **qlines;
6110 pstring command;
6111 int numlines;
6112 int ret;
6113 int fd;
6115 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6117 DEBUG(10,("Running [%s]\n", command));
6118 ret = smbrun(command, &fd);
6119 DEBUG(10,("Returned [%d]\n", ret));
6120 if (ret != 0) {
6121 if (fd != -1)
6122 close(fd);
6123 /* Is this the best error to return here? */
6124 return WERR_ACCESS_DENIED;
6127 numlines = 0;
6128 qlines = fd_lines_load(fd, &numlines);
6129 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6130 close(fd);
6132 if(numlines) {
6133 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6134 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6135 dos_errstr(WERR_NOMEM)));
6136 file_lines_free(qlines);
6137 return WERR_NOMEM;
6140 for (i=0; i<numlines; i++) {
6141 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6142 fill_port_1(&ports[i], qlines[i]);
6145 file_lines_free(qlines);
6148 *returned = numlines;
6150 } else {
6151 *returned = 1; /* Sole Samba port returned. */
6153 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6154 return WERR_NOMEM;
6156 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6158 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6161 /* check the required size. */
6162 for (i=0; i<*returned; i++) {
6163 DEBUGADD(6,("adding port [%d]'s size\n", i));
6164 *needed += spoolss_size_port_info_1(&ports[i]);
6167 if (!alloc_buffer_size(buffer, *needed)) {
6168 SAFE_FREE(ports);
6169 return WERR_INSUFFICIENT_BUFFER;
6172 /* fill the buffer with the ports structures */
6173 for (i=0; i<*returned; i++) {
6174 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6175 smb_io_port_1("", buffer, &ports[i], 0);
6178 SAFE_FREE(ports);
6180 if (*needed > offered) {
6181 *returned=0;
6182 return WERR_INSUFFICIENT_BUFFER;
6185 return WERR_OK;
6188 /****************************************************************************
6189 enumports level 2.
6190 ****************************************************************************/
6192 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6194 PORT_INFO_2 *ports=NULL;
6195 int i=0;
6197 if (*lp_enumports_cmd()) {
6198 char *cmd = lp_enumports_cmd();
6199 char *path;
6200 char **qlines;
6201 pstring tmp_file;
6202 pstring command;
6203 int numlines;
6204 int ret;
6205 int fd;
6207 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6208 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6209 else
6210 path = lp_lockdir();
6212 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6213 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6215 unlink(tmp_file);
6216 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6217 ret = smbrun(command, &fd);
6218 DEBUGADD(10,("returned [%d]\n", ret));
6219 if (ret != 0) {
6220 if (fd != -1)
6221 close(fd);
6222 /* Is this the best error to return here? */
6223 return WERR_ACCESS_DENIED;
6226 numlines = 0;
6227 qlines = fd_lines_load(fd, &numlines);
6228 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6229 close(fd);
6231 if(numlines) {
6232 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6233 file_lines_free(qlines);
6234 return WERR_NOMEM;
6237 for (i=0; i<numlines; i++) {
6238 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6239 fill_port_2(&(ports[i]), qlines[i]);
6242 file_lines_free(qlines);
6245 *returned = numlines;
6247 } else {
6249 *returned = 1;
6251 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6252 return WERR_NOMEM;
6254 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6256 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6259 /* check the required size. */
6260 for (i=0; i<*returned; i++) {
6261 DEBUGADD(6,("adding port [%d]'s size\n", i));
6262 *needed += spoolss_size_port_info_2(&ports[i]);
6265 if (!alloc_buffer_size(buffer, *needed)) {
6266 SAFE_FREE(ports);
6267 return WERR_INSUFFICIENT_BUFFER;
6270 /* fill the buffer with the ports structures */
6271 for (i=0; i<*returned; i++) {
6272 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6273 smb_io_port_2("", buffer, &ports[i], 0);
6276 SAFE_FREE(ports);
6278 if (*needed > offered) {
6279 *returned=0;
6280 return WERR_INSUFFICIENT_BUFFER;
6283 return WERR_OK;
6286 /****************************************************************************
6287 enumports.
6288 ****************************************************************************/
6290 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6292 /* UNISTR2 *name = &q_u->name; - notused. */
6293 uint32 level = q_u->level;
6294 NEW_BUFFER *buffer = NULL;
6295 uint32 offered = q_u->offered;
6296 uint32 *needed = &r_u->needed;
6297 uint32 *returned = &r_u->returned;
6299 /* that's an [in out] buffer */
6300 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6301 buffer = r_u->buffer;
6303 DEBUG(4,("_spoolss_enumports\n"));
6305 *returned=0;
6306 *needed=0;
6308 switch (level) {
6309 case 1:
6310 return enumports_level_1(buffer, offered, needed, returned);
6311 case 2:
6312 return enumports_level_2(buffer, offered, needed, returned);
6313 default:
6314 return WERR_UNKNOWN_LEVEL;
6318 /****************************************************************************
6319 ****************************************************************************/
6321 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6322 const SPOOL_PRINTER_INFO_LEVEL *info,
6323 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6324 uint32 user_switch, const SPOOL_USER_CTR *user,
6325 POLICY_HND *handle)
6327 NT_PRINTER_INFO_LEVEL *printer = NULL;
6328 fstring name;
6329 int snum;
6330 WERROR err = WERR_OK;
6332 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6333 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6334 return WERR_NOMEM;
6337 ZERO_STRUCTP(printer);
6339 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6340 if (!convert_printer_info(info, printer, 2)) {
6341 free_a_printer(&printer, 2);
6342 return WERR_NOMEM;
6345 /* check to see if the printer already exists */
6347 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6348 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6349 printer->info_2->sharename));
6350 free_a_printer(&printer, 2);
6351 return WERR_PRINTER_ALREADY_EXISTS;
6354 if (*lp_addprinter_cmd() )
6355 if ( !add_printer_hook(printer) ) {
6356 free_a_printer(&printer,2);
6357 return WERR_ACCESS_DENIED;
6360 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6361 printer->info_2->sharename);
6363 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6364 free_a_printer(&printer,2);
6365 return WERR_ACCESS_DENIED;
6368 /* you must be a printer admin to add a new printer */
6369 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6370 free_a_printer(&printer,2);
6371 return WERR_ACCESS_DENIED;
6375 * Do sanity check on the requested changes for Samba.
6378 if (!check_printer_ok(printer->info_2, snum)) {
6379 free_a_printer(&printer,2);
6380 return WERR_INVALID_PARAM;
6384 * When a printer is created, the drivername bound to the printer is used
6385 * to lookup previously saved driver initialization info, which is then
6386 * bound to the new printer, simulating what happens in the Windows arch.
6389 if (!devmode)
6390 set_driver_init(printer, 2);
6391 else {
6392 /* A valid devmode was included, convert and link it
6394 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6396 if (!convert_devicemode(printer->info_2->printername, devmode,
6397 &printer->info_2->devmode))
6398 return WERR_NOMEM;
6401 set_driver_init(printer, 2);
6403 /* write the ASCII on disk */
6404 err = mod_a_printer(*printer, 2);
6405 if (!W_ERROR_IS_OK(err)) {
6406 free_a_printer(&printer,2);
6407 return err;
6410 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6411 /* Handle open failed - remove addition. */
6412 del_a_printer(printer->info_2->sharename);
6413 free_a_printer(&printer,2);
6414 return WERR_ACCESS_DENIED;
6417 update_c_setprinter(False);
6419 srv_spoolss_sendnotify(printer->info_2->printername, 0, PRINTER_CHANGE_ADD_PRINTER, 0x0);
6421 free_a_printer(&printer,2);
6423 return WERR_OK;
6426 /****************************************************************************
6427 ****************************************************************************/
6429 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6431 UNISTR2 *uni_srv_name = &q_u->server_name;
6432 uint32 level = q_u->level;
6433 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6434 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6435 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6436 uint32 user_switch = q_u->user_switch;
6437 SPOOL_USER_CTR *user = &q_u->user_ctr;
6438 POLICY_HND *handle = &r_u->handle;
6440 switch (level) {
6441 case 1:
6442 /* we don't handle yet */
6443 /* but I know what to do ... */
6444 return WERR_UNKNOWN_LEVEL;
6445 case 2:
6446 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6447 devmode, sdb,
6448 user_switch, user, handle);
6449 default:
6450 return WERR_UNKNOWN_LEVEL;
6454 /****************************************************************************
6455 ****************************************************************************/
6457 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6459 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6460 uint32 level = q_u->level;
6461 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6462 WERROR err = WERR_OK;
6463 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6464 struct current_user user;
6466 ZERO_STRUCT(driver);
6468 get_current_user(&user, p);
6470 if (!convert_printer_driver_info(info, &driver, level)) {
6471 err = WERR_NOMEM;
6472 goto done;
6475 DEBUG(5,("Cleaning driver's information\n"));
6476 err = clean_up_driver_struct(driver, level, &user);
6477 if (!W_ERROR_IS_OK(err))
6478 goto done;
6480 DEBUG(5,("Moving driver to final destination\n"));
6481 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6482 if (W_ERROR_IS_OK(err))
6483 err = WERR_ACCESS_DENIED;
6484 goto done;
6487 if (add_a_printer_driver(driver, level)!=0) {
6488 err = WERR_ACCESS_DENIED;
6489 goto done;
6492 done:
6493 free_a_printer_driver(driver, level);
6494 return err;
6497 /****************************************************************************
6498 ****************************************************************************/
6500 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6502 init_unistr(&info->name, name);
6505 /****************************************************************************
6506 ****************************************************************************/
6508 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6510 pstring path;
6511 pstring long_archi;
6512 pstring short_archi;
6513 DRIVER_DIRECTORY_1 *info=NULL;
6515 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6517 if (get_short_archi(short_archi, long_archi)==False)
6518 return WERR_INVALID_ENVIRONMENT;
6520 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6521 return WERR_NOMEM;
6523 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6525 DEBUG(4,("printer driver directory: [%s]\n", path));
6527 fill_driverdir_1(info, path);
6529 *needed += spoolss_size_driverdir_info_1(info);
6531 if (!alloc_buffer_size(buffer, *needed)) {
6532 SAFE_FREE(info);
6533 return WERR_INSUFFICIENT_BUFFER;
6536 smb_io_driverdir_1("", buffer, info, 0);
6538 SAFE_FREE(info);
6540 if (*needed > offered)
6541 return WERR_INSUFFICIENT_BUFFER;
6543 return WERR_OK;
6546 /****************************************************************************
6547 ****************************************************************************/
6549 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6551 UNISTR2 *name = &q_u->name;
6552 UNISTR2 *uni_environment = &q_u->environment;
6553 uint32 level = q_u->level;
6554 NEW_BUFFER *buffer = NULL;
6555 uint32 offered = q_u->offered;
6556 uint32 *needed = &r_u->needed;
6558 /* that's an [in out] buffer */
6559 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6560 buffer = r_u->buffer;
6562 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6564 *needed=0;
6566 switch(level) {
6567 case 1:
6568 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6569 default:
6570 return WERR_UNKNOWN_LEVEL;
6574 /****************************************************************************
6575 ****************************************************************************/
6577 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6579 POLICY_HND *handle = &q_u->handle;
6580 uint32 idx = q_u->index;
6581 uint32 in_value_len = q_u->valuesize;
6582 uint32 in_data_len = q_u->datasize;
6583 uint32 *out_max_value_len = &r_u->valuesize;
6584 uint16 **out_value = &r_u->value;
6585 uint32 *out_value_len = &r_u->realvaluesize;
6586 uint32 *out_type = &r_u->type;
6587 uint32 *out_max_data_len = &r_u->datasize;
6588 uint8 **data_out = &r_u->data;
6589 uint32 *out_data_len = &r_u->realdatasize;
6591 NT_PRINTER_INFO_LEVEL *printer = NULL;
6593 fstring value;
6595 uint32 param_index;
6596 uint32 biggest_valuesize;
6597 uint32 biggest_datasize;
6598 uint32 data_len;
6599 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6600 int snum;
6601 uint8 *data=NULL;
6602 uint32 type;
6603 WERROR result;
6605 ZERO_STRUCT(printer);
6607 *out_type=0;
6609 *out_max_data_len=0;
6610 *data_out=NULL;
6611 *out_data_len=0;
6613 DEBUG(5,("spoolss_enumprinterdata\n"));
6615 if (!Printer) {
6616 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6617 return WERR_BADFID;
6620 if (!get_printer_snum(p,handle, &snum))
6621 return WERR_BADFID;
6623 result = get_a_printer(&printer, 2, lp_servicename(snum));
6624 if (!W_ERROR_IS_OK(result))
6625 return result;
6628 * The NT machine wants to know the biggest size of value and data
6630 * cf: MSDN EnumPrinterData remark section
6632 if ( (in_value_len==0) && (in_data_len==0) ) {
6633 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6635 #if 0
6637 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6638 * if this parameter size doesn't exist.
6639 * Ok - my opinion here is that the client is not asking for the greatest
6640 * possible size of all the parameters, but is asking specifically for the size needed
6641 * for this specific parameter. In that case we can remove the loop below and
6642 * simplify this lookup code considerably. JF - comments welcome. JRA.
6645 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6646 SAFE_FREE(data);
6647 free_a_printer(&printer, 2);
6648 return WERR_NO_MORE_ITEMS;
6650 #endif
6652 SAFE_FREE(data);
6654 param_index=0;
6655 biggest_valuesize=0;
6656 biggest_datasize=0;
6658 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6659 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6660 if (data_len > biggest_datasize) biggest_datasize=data_len;
6662 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6664 SAFE_FREE(data);
6665 param_index++;
6668 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6669 *out_value_len=2*(1+biggest_valuesize);
6670 *out_data_len=biggest_datasize;
6672 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6674 free_a_printer(&printer, 2);
6675 return WERR_OK;
6679 * the value len is wrong in NT sp3
6680 * that's the number of bytes not the number of unicode chars
6683 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6685 SAFE_FREE(data);
6686 free_a_printer(&printer, 2);
6688 /* out_value should default to "" or else NT4 has
6689 problems unmarshalling the response */
6691 *out_max_value_len=(in_value_len/sizeof(uint16));
6692 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
6693 return WERR_NOMEM;
6695 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6697 /* the data is counted in bytes */
6698 *out_max_data_len = in_data_len;
6699 *out_data_len = in_data_len;
6700 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
6701 return WERR_NOMEM;
6703 return WERR_NO_MORE_ITEMS;
6706 free_a_printer(&printer, 2);
6709 * the value is:
6710 * - counted in bytes in the request
6711 * - counted in UNICODE chars in the max reply
6712 * - counted in bytes in the real size
6714 * take a pause *before* coding not *during* coding
6717 *out_max_value_len=(in_value_len/sizeof(uint16));
6718 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6719 SAFE_FREE(data);
6720 return WERR_NOMEM;
6723 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6725 *out_type=type;
6727 /* the data is counted in bytes */
6728 *out_max_data_len=in_data_len;
6729 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6730 SAFE_FREE(data);
6731 return WERR_NOMEM;
6734 memcpy(*data_out, data, (size_t)data_len);
6735 *out_data_len=data_len;
6737 SAFE_FREE(data);
6739 return WERR_OK;
6742 /****************************************************************************
6743 ****************************************************************************/
6745 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6747 POLICY_HND *handle = &q_u->handle;
6748 UNISTR2 *value = &q_u->value;
6749 uint32 type = q_u->type;
6750 /* uint32 max_len = q_u->max_len; - notused. */
6751 uint8 *data = q_u->data;
6752 uint32 real_len = q_u->real_len;
6753 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6755 NT_PRINTER_INFO_LEVEL *printer = NULL;
6756 NT_PRINTER_PARAM *param = NULL, old_param;
6757 int snum=0;
6758 WERROR status = WERR_OK;
6759 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6761 DEBUG(5,("spoolss_setprinterdata\n"));
6763 if (!Printer) {
6764 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6765 return WERR_BADFID;
6768 if (!get_printer_snum(p,handle, &snum))
6769 return WERR_BADFID;
6771 ZERO_STRUCT(old_param);
6774 * Access check : NT returns "access denied" if you make a
6775 * SetPrinterData call without the necessary privildge.
6776 * we were originally returning OK if nothing changed
6777 * which made Win2k issue **a lot** of SetPrinterData
6778 * when connecting to a printer --jerry
6781 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6782 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
6783 status = WERR_ACCESS_DENIED;
6784 goto done;
6787 /* Check if we are making any changes or not. Return true if
6788 nothing is actually changing. This is not needed anymore but
6789 has been left in as an optimization to keep from from
6790 writing to disk as often --jerry */
6792 status = get_a_printer(&printer, 2, lp_servicename(snum));
6793 if (!W_ERROR_IS_OK(status))
6794 return status;
6796 convert_specific_param(&param, value , type, data, real_len);
6798 unlink_specific_param_if_exist(printer->info_2, param);
6801 * When client side code sets a magic printer data key, detect it and save
6802 * the current printer data and the magic key's data (its the DEVMODE) for
6803 * future printer/driver initializations.
6805 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6807 * Set devmode and printer initialization info
6809 status = save_driver_init(printer, 2, param);
6811 else {
6812 add_a_specific_param(printer->info_2, &param);
6813 status = mod_a_printer(*printer, 2);
6816 done:
6817 free_a_printer(&printer, 2);
6818 if (param)
6819 free_nt_printer_param(&param);
6820 SAFE_FREE(old_param.data);
6822 return status;
6825 /****************************************************************************
6826 ****************************************************************************/
6828 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
6830 POLICY_HND *handle = &q_u->handle;
6831 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6832 int snum;
6834 DEBUG(5,("_spoolss_resetprinter\n"));
6837 * All we do is to check to see if the handle and queue is valid.
6838 * This call really doesn't mean anything to us because we only
6839 * support RAW printing. --jerry
6842 if (!Printer) {
6843 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6844 return WERR_BADFID;
6847 if (!get_printer_snum(p,handle, &snum))
6848 return WERR_BADFID;
6851 /* blindly return success */
6852 return WERR_OK;
6856 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6858 POLICY_HND *handle = &q_u->handle;
6859 UNISTR2 *value = &q_u->valuename;
6861 NT_PRINTER_INFO_LEVEL *printer = NULL;
6862 NT_PRINTER_PARAM param;
6863 int snum=0;
6864 WERROR status = WERR_OK;
6865 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6867 DEBUG(5,("spoolss_deleteprinterdata\n"));
6869 if (!Printer) {
6870 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6871 return WERR_BADFID;
6874 if (!get_printer_snum(p, handle, &snum))
6875 return WERR_BADFID;
6877 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6878 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
6879 return WERR_ACCESS_DENIED;
6882 status = get_a_printer(&printer, 2, lp_servicename(snum));
6883 if (!W_ERROR_IS_OK(status))
6884 return status;
6886 ZERO_STRUCTP(&param);
6887 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6889 if(!unlink_specific_param_if_exist(printer->info_2, &param))
6890 status = WERR_INVALID_PARAM;
6891 else
6892 status = mod_a_printer(*printer, 2);
6894 free_a_printer(&printer, 2);
6895 return status;
6898 /****************************************************************************
6899 ****************************************************************************/
6901 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6903 POLICY_HND *handle = &q_u->handle;
6904 /* uint32 level = q_u->level; - notused. */
6905 FORM *form = &q_u->form;
6906 nt_forms_struct tmpForm;
6907 int snum;
6908 WERROR status = WERR_OK;
6909 NT_PRINTER_INFO_LEVEL *printer = NULL;
6911 int count=0;
6912 nt_forms_struct *list=NULL;
6913 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6915 DEBUG(5,("spoolss_addform\n"));
6917 if (!Printer) {
6918 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6919 return WERR_BADFID;
6922 if (!get_printer_snum(p,handle, &snum))
6923 return WERR_BADFID;
6925 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6926 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
6927 status = WERR_ACCESS_DENIED;
6928 goto done;
6931 /* can't add if builtin */
6932 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6933 return WERR_ALREADY_EXISTS;
6936 count=get_ntforms(&list);
6937 if(!add_a_form(&list, form, &count))
6938 return WERR_NOMEM;
6939 write_ntforms(&list, count);
6942 * ChangeID must always be set
6945 status = get_a_printer(&printer, 2, lp_servicename(snum));
6946 if (!W_ERROR_IS_OK(status))
6947 goto done;
6949 status = mod_a_printer(*printer, 2);
6950 if (!W_ERROR_IS_OK(status))
6951 goto done;
6953 done:
6954 free_a_printer(&printer, 2);
6955 SAFE_FREE(list);
6957 return status;
6960 /****************************************************************************
6961 ****************************************************************************/
6963 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6965 POLICY_HND *handle = &q_u->handle;
6966 UNISTR2 *form_name = &q_u->name;
6967 nt_forms_struct tmpForm;
6968 int count=0;
6969 WERROR ret = WERR_OK;
6970 nt_forms_struct *list=NULL;
6971 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6972 int snum;
6973 WERROR status = WERR_OK;
6974 NT_PRINTER_INFO_LEVEL *printer = NULL;
6976 DEBUG(5,("spoolss_deleteform\n"));
6978 if (!Printer) {
6979 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6980 return WERR_BADFID;
6983 if (!get_printer_snum(p, handle, &snum))
6984 return WERR_BADFID;
6986 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6987 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
6988 return WERR_ACCESS_DENIED;
6991 /* can't delete if builtin */
6992 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6993 return WERR_INVALID_PARAM;
6996 count = get_ntforms(&list);
6997 if(!delete_a_form(&list, form_name, &count, &ret))
6998 return WERR_INVALID_PARAM;
7001 * ChangeID must always be set
7004 status = get_a_printer(&printer, 2, lp_servicename(snum));
7005 if (!W_ERROR_IS_OK(status))
7006 goto done;
7008 status = mod_a_printer(*printer, 2);
7009 if (!W_ERROR_IS_OK(status))
7010 goto done;
7012 done:
7013 free_a_printer(&printer, 2);
7014 SAFE_FREE(list);
7016 return ret;
7019 /****************************************************************************
7020 ****************************************************************************/
7022 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7024 POLICY_HND *handle = &q_u->handle;
7025 /* UNISTR2 *uni_name = &q_u->name; - notused. */
7026 /* uint32 level = q_u->level; - notused. */
7027 FORM *form = &q_u->form;
7028 nt_forms_struct tmpForm;
7029 int snum;
7030 WERROR status = WERR_OK;
7031 NT_PRINTER_INFO_LEVEL *printer = NULL;
7033 int count=0;
7034 nt_forms_struct *list=NULL;
7035 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7037 DEBUG(5,("spoolss_setform\n"));
7039 if (!Printer) {
7040 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7041 return WERR_BADFID;
7044 if (!get_printer_snum(p, handle, &snum))
7045 return WERR_BADFID;
7047 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7048 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7049 return WERR_ACCESS_DENIED;
7052 /* can't set if builtin */
7053 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7054 return WERR_INVALID_PARAM;
7057 count=get_ntforms(&list);
7058 update_a_form(&list, form, count);
7059 write_ntforms(&list, count);
7062 * ChangeID must always be set
7065 status = get_a_printer(&printer, 2, lp_servicename(snum));
7066 if (!W_ERROR_IS_OK(status))
7067 goto done;
7069 status = mod_a_printer(*printer, 2);
7070 if (!W_ERROR_IS_OK(status))
7071 goto done;
7073 done:
7074 free_a_printer(&printer, 2);
7075 SAFE_FREE(list);
7077 return WERR_OK;
7080 /****************************************************************************
7081 enumprintprocessors level 1.
7082 ****************************************************************************/
7084 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7086 PRINTPROCESSOR_1 *info_1=NULL;
7088 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7089 return WERR_NOMEM;
7091 (*returned) = 0x1;
7093 init_unistr(&info_1->name, "winprint");
7095 *needed += spoolss_size_printprocessor_info_1(info_1);
7097 if (!alloc_buffer_size(buffer, *needed))
7098 return WERR_INSUFFICIENT_BUFFER;
7100 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7102 SAFE_FREE(info_1);
7104 if (*needed > offered) {
7105 *returned=0;
7106 return WERR_INSUFFICIENT_BUFFER;
7109 return WERR_OK;
7112 /****************************************************************************
7113 ****************************************************************************/
7115 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7117 /* UNISTR2 *name = &q_u->name; - notused. */
7118 /* UNISTR2 *environment = &q_u->environment; - notused. */
7119 uint32 level = q_u->level;
7120 NEW_BUFFER *buffer = NULL;
7121 uint32 offered = q_u->offered;
7122 uint32 *needed = &r_u->needed;
7123 uint32 *returned = &r_u->returned;
7125 /* that's an [in out] buffer */
7126 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7127 buffer = r_u->buffer;
7129 DEBUG(5,("spoolss_enumprintprocessors\n"));
7132 * Enumerate the print processors ...
7134 * Just reply with "winprint", to keep NT happy
7135 * and I can use my nice printer checker.
7138 *returned=0;
7139 *needed=0;
7141 switch (level) {
7142 case 1:
7143 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7144 default:
7145 return WERR_UNKNOWN_LEVEL;
7149 /****************************************************************************
7150 enumprintprocdatatypes level 1.
7151 ****************************************************************************/
7153 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7155 PRINTPROCDATATYPE_1 *info_1=NULL;
7157 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7158 return WERR_NOMEM;
7160 (*returned) = 0x1;
7162 init_unistr(&info_1->name, "RAW");
7164 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7166 if (!alloc_buffer_size(buffer, *needed))
7167 return WERR_INSUFFICIENT_BUFFER;
7169 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7171 SAFE_FREE(info_1);
7173 if (*needed > offered) {
7174 *returned=0;
7175 return WERR_INSUFFICIENT_BUFFER;
7178 return WERR_OK;
7181 /****************************************************************************
7182 ****************************************************************************/
7184 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7186 /* UNISTR2 *name = &q_u->name; - notused. */
7187 /* UNISTR2 *processor = &q_u->processor; - notused. */
7188 uint32 level = q_u->level;
7189 NEW_BUFFER *buffer = NULL;
7190 uint32 offered = q_u->offered;
7191 uint32 *needed = &r_u->needed;
7192 uint32 *returned = &r_u->returned;
7194 /* that's an [in out] buffer */
7195 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7196 buffer = r_u->buffer;
7198 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7200 *returned=0;
7201 *needed=0;
7203 switch (level) {
7204 case 1:
7205 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7206 default:
7207 return WERR_UNKNOWN_LEVEL;
7211 /****************************************************************************
7212 enumprintmonitors level 1.
7213 ****************************************************************************/
7215 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7217 PRINTMONITOR_1 *info_1=NULL;
7219 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7220 return WERR_NOMEM;
7222 (*returned) = 0x1;
7224 init_unistr(&info_1->name, "Local Port");
7226 *needed += spoolss_size_printmonitor_info_1(info_1);
7228 if (!alloc_buffer_size(buffer, *needed))
7229 return WERR_INSUFFICIENT_BUFFER;
7231 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7233 SAFE_FREE(info_1);
7235 if (*needed > offered) {
7236 *returned=0;
7237 return WERR_INSUFFICIENT_BUFFER;
7240 return WERR_OK;
7243 /****************************************************************************
7244 enumprintmonitors level 2.
7245 ****************************************************************************/
7247 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7249 PRINTMONITOR_2 *info_2=NULL;
7251 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7252 return WERR_NOMEM;
7254 (*returned) = 0x1;
7256 init_unistr(&info_2->name, "Local Port");
7257 init_unistr(&info_2->environment, "Windows NT X86");
7258 init_unistr(&info_2->dll_name, "localmon.dll");
7260 *needed += spoolss_size_printmonitor_info_2(info_2);
7262 if (!alloc_buffer_size(buffer, *needed))
7263 return WERR_INSUFFICIENT_BUFFER;
7265 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7267 SAFE_FREE(info_2);
7269 if (*needed > offered) {
7270 *returned=0;
7271 return WERR_INSUFFICIENT_BUFFER;
7274 return WERR_OK;
7277 /****************************************************************************
7278 ****************************************************************************/
7280 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7282 /* UNISTR2 *name = &q_u->name; - notused. */
7283 uint32 level = q_u->level;
7284 NEW_BUFFER *buffer = NULL;
7285 uint32 offered = q_u->offered;
7286 uint32 *needed = &r_u->needed;
7287 uint32 *returned = &r_u->returned;
7289 /* that's an [in out] buffer */
7290 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7291 buffer = r_u->buffer;
7293 DEBUG(5,("spoolss_enumprintmonitors\n"));
7296 * Enumerate the print monitors ...
7298 * Just reply with "Local Port", to keep NT happy
7299 * and I can use my nice printer checker.
7302 *returned=0;
7303 *needed=0;
7305 switch (level) {
7306 case 1:
7307 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7308 case 2:
7309 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7310 default:
7311 return WERR_UNKNOWN_LEVEL;
7315 /****************************************************************************
7316 ****************************************************************************/
7318 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7320 int i=0;
7321 BOOL found=False;
7322 JOB_INFO_1 *info_1=NULL;
7324 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7326 if (info_1 == NULL) {
7327 SAFE_FREE(queue);
7328 return WERR_NOMEM;
7331 for (i=0; i<count && found==False; i++) {
7332 if (queue[i].job==(int)jobid)
7333 found=True;
7336 if (found==False) {
7337 SAFE_FREE(queue);
7338 SAFE_FREE(info_1);
7339 /* NT treats not found as bad param... yet another bad choice */
7340 return WERR_INVALID_PARAM;
7343 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7345 SAFE_FREE(queue);
7347 *needed += spoolss_size_job_info_1(info_1);
7349 if (!alloc_buffer_size(buffer, *needed)) {
7350 SAFE_FREE(info_1);
7351 return WERR_INSUFFICIENT_BUFFER;
7354 smb_io_job_info_1("", buffer, info_1, 0);
7356 SAFE_FREE(info_1);
7358 if (*needed > offered)
7359 return WERR_INSUFFICIENT_BUFFER;
7361 return WERR_OK;
7364 /****************************************************************************
7365 ****************************************************************************/
7367 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7369 int i=0;
7370 BOOL found=False;
7371 JOB_INFO_2 *info_2;
7372 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7373 WERROR ret;
7374 DEVICEMODE *devmode = NULL;
7376 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7378 ZERO_STRUCTP(info_2);
7380 if (info_2 == NULL) {
7381 ret = WERR_NOMEM;
7382 goto done;
7385 for (i=0; i<count && found==False; i++) {
7386 if (queue[i].job==(int)jobid)
7387 found=True;
7390 if (found==False) {
7391 /* NT treats not found as bad param... yet another bad
7392 choice */
7393 ret = WERR_INVALID_PARAM;
7394 goto done;
7397 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7398 if (!W_ERROR_IS_OK(ret))
7399 goto done;
7400 if (construct_dev_mode(snum) == NULL) {
7401 ret = WERR_NOMEM;
7402 goto done;
7405 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7407 *needed += spoolss_size_job_info_2(info_2);
7409 if (!alloc_buffer_size(buffer, *needed)) {
7410 ret = WERR_INSUFFICIENT_BUFFER;
7411 goto done;
7414 smb_io_job_info_2("", buffer, info_2, 0);
7416 if (*needed > offered) {
7417 ret = WERR_INSUFFICIENT_BUFFER;
7418 goto done;
7421 ret = WERR_OK;
7423 done:
7424 /* Cleanup allocated memory */
7426 SAFE_FREE(queue);
7427 free_job_info_2(info_2); /* Also frees devmode */
7428 SAFE_FREE(info_2);
7429 free_a_printer(&ntprinter, 2);
7431 return ret;
7434 /****************************************************************************
7435 ****************************************************************************/
7437 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7439 POLICY_HND *handle = &q_u->handle;
7440 uint32 jobid = q_u->jobid;
7441 uint32 level = q_u->level;
7442 NEW_BUFFER *buffer = NULL;
7443 uint32 offered = q_u->offered;
7444 uint32 *needed = &r_u->needed;
7446 int snum;
7447 int count;
7448 print_queue_struct *queue=NULL;
7449 print_status_struct prt_status;
7451 /* that's an [in out] buffer */
7452 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7453 buffer = r_u->buffer;
7455 DEBUG(5,("spoolss_getjob\n"));
7457 *needed=0;
7459 if (!get_printer_snum(p, handle, &snum))
7460 return WERR_BADFID;
7462 count = print_queue_status(snum, &queue, &prt_status);
7464 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7465 count, prt_status.status, prt_status.message));
7467 switch (level) {
7468 case 1:
7469 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7470 case 2:
7471 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7472 default:
7473 SAFE_FREE(queue);
7474 return WERR_UNKNOWN_LEVEL;
7478 /********************************************************************
7479 * spoolss_getprinterdataex
7480 ********************************************************************/
7482 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7484 POLICY_HND *handle = &q_u->handle;
7485 uint32 in_size = q_u->size;
7486 uint32 *type = &r_u->type;
7487 uint32 *out_size = &r_u->size;
7488 uint8 **data = &r_u->data;
7489 uint32 *needed = &r_u->needed;
7491 fstring key, value;
7492 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7493 BOOL found = False;
7495 DEBUG(4,("_spoolss_getprinterdataex\n"));
7497 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7498 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7500 /* in case of problem, return some default values */
7501 *needed=0;
7502 *type=0;
7503 *out_size=0;
7506 if (!Printer) {
7507 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7508 return WERR_NOMEM;
7509 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7510 return WERR_BADFID;
7514 /* Is the handle to a printer or to the server? */
7516 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7518 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7519 return WERR_INVALID_PARAM;
7521 else
7524 * From MSDN documentation of GetPrinterDataEx: pass request
7525 * to GetPrinterData if key is "PrinterDriverData". This is
7526 * the only key we really support. Other keys to implement:
7527 * (a) DsDriver
7528 * (b) DsSpooler
7529 * (c) PnPData
7532 if (strcmp(key, "PrinterDriverData") != 0)
7533 return WERR_BADFILE;
7535 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7536 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7537 type, data, needed, in_size);
7541 if (!found) {
7542 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7544 /* reply this param doesn't exist */
7545 if (*out_size) {
7546 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7547 return WERR_NOMEM;
7548 } else {
7549 *data = NULL;
7552 return WERR_INVALID_PARAM;
7555 if (*needed > *out_size)
7556 return WERR_MORE_DATA;
7557 else
7558 return WERR_OK;
7561 /********************************************************************
7562 * spoolss_setprinterdata
7563 ********************************************************************/
7565 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7567 SPOOL_Q_SETPRINTERDATA q_u_local;
7568 SPOOL_R_SETPRINTERDATA r_u_local;
7569 fstring key;
7571 DEBUG(4,("_spoolss_setprinterdataex\n"));
7573 /* From MSDN documentation of SetPrinterDataEx: pass request to
7574 SetPrinterData if key is "PrinterDriverData" */
7576 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7578 if (strcmp(key, "PrinterDriverData") != 0)
7579 return WERR_INVALID_PARAM;
7581 ZERO_STRUCT(q_u_local);
7582 ZERO_STRUCT(r_u_local);
7584 /* make a copy to call _spoolss_setprinterdata() */
7586 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7587 copy_unistr2(&q_u_local.value, &q_u->value);
7588 q_u_local.type = q_u->type;
7589 q_u_local.max_len = q_u->max_len;
7590 q_u_local.data = q_u->data;
7591 q_u_local.real_len = q_u->real_len;
7592 q_u_local.numeric_data = q_u->numeric_data;
7594 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7597 /********************************************************************
7598 * spoolss_enumprinterkey
7599 ********************************************************************/
7601 /* constants for EnumPrinterKey() */
7602 #define ENUMERATED_KEY_SIZE 19
7604 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7606 fstring key;
7607 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
7608 char* ptr = NULL;
7609 int i;
7610 char *PrinterKey = "PrinterDriverData";
7612 DEBUG(4,("_spoolss_enumprinterkey\n"));
7614 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7617 * we only support enumating all keys (key == "")
7618 * Of course, the only key we support is the "PrinterDriverData"
7619 * key
7621 if (strlen(key) == 0)
7623 r_u->needed = ENUMERATED_KEY_SIZE *2;
7624 if (q_u->size < r_u->needed)
7625 return WERR_MORE_DATA;
7627 ptr = PrinterKey;
7628 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7630 enumkeys[i] = (uint16)(*ptr);
7631 ptr++;
7634 /* tag of with 2 '\0's */
7635 enumkeys[i++] = '\0';
7636 enumkeys[i] = '\0';
7638 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7639 return WERR_BADFILE;
7641 return WERR_OK;
7644 /* The "PrinterDriverData" key should have no subkeys */
7645 if (strcmp(key, PrinterKey) == 0)
7647 r_u-> needed = 2;
7648 if (q_u->size < r_u->needed)
7649 return WERR_MORE_DATA;
7650 enumkeys[0] = 0x0;
7651 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7652 return WERR_BADFILE;
7654 return WERR_OK;
7658 /* The return value for an unknown key is documented in MSDN
7659 EnumPrinterKey description */
7660 return WERR_BADFILE;
7663 /********************************************************************
7664 * spoolss_enumprinterdataex
7665 ********************************************************************/
7667 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7669 POLICY_HND *handle = &q_u->handle;
7670 uint32 in_size = q_u->size;
7671 uint32 num_entries,
7672 needed;
7673 NT_PRINTER_INFO_LEVEL *printer = NULL;
7674 PRINTER_ENUM_VALUES *enum_values = NULL;
7675 fstring key, value;
7676 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7677 int snum;
7678 uint32 param_index,
7679 data_len,
7680 type;
7681 WERROR result;
7682 uint8 *data=NULL;
7685 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7687 if (!Printer) {
7688 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
7689 return WERR_BADFID;
7694 * The only key we support is "PrinterDriverData". This should return
7695 > an array of all the key/value pairs returned by EnumPrinterDataSee
7696 * _spoolss_getprinterdataex() for details --jerry
7699 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7700 if (strcmp(key, "PrinterDriverData") != 0)
7702 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7703 return WERR_INVALID_PARAM;
7707 if (!get_printer_snum(p,handle, &snum))
7708 return WERR_BADFID;
7710 ZERO_STRUCT(printer);
7711 result = get_a_printer(&printer, 2, lp_servicename(snum));
7712 if (!W_ERROR_IS_OK(result))
7713 return result;
7717 * loop through all params and build the array to pass
7718 * back to the client
7720 result = WERR_OK;
7721 param_index = 0;
7722 needed = 0;
7723 num_entries = 0;
7725 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7727 PRINTER_ENUM_VALUES *ptr;
7728 uint32 add_len = 0;
7730 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7732 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7734 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7735 result = WERR_NOMEM;
7736 goto done;
7738 enum_values = ptr;
7740 /* copy the data */
7741 init_unistr(&enum_values[num_entries].valuename, value);
7742 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7743 enum_values[num_entries].type = type;
7745 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7746 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7747 result = WERR_NOMEM;
7748 goto done;
7750 memcpy(enum_values[num_entries].data, data, data_len);
7751 enum_values[num_entries].data_len = data_len + add_len;
7753 /* keep track of the size of the array in bytes */
7755 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7757 num_entries++;
7758 param_index++;
7761 r_u->needed = needed;
7762 r_u->returned = num_entries;
7764 if (needed > in_size) {
7765 result = WERR_MORE_DATA;
7766 goto done;
7769 /* copy data into the reply */
7771 r_u->ctr.size = r_u->needed;
7772 r_u->ctr.size_of_array = r_u->returned;
7773 r_u->ctr.values = enum_values;
7777 done:
7778 free_a_printer(&printer, 2);
7780 return result;
7783 /****************************************************************************
7784 ****************************************************************************/
7786 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7788 init_unistr(&info->name, name);
7791 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
7792 UNISTR2 *environment,
7793 NEW_BUFFER *buffer,
7794 uint32 offered,
7795 uint32 *needed)
7797 pstring path;
7798 pstring long_archi;
7799 pstring short_archi;
7800 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7802 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7804 if (get_short_archi(short_archi, long_archi)==FALSE)
7805 return WERR_INVALID_ENVIRONMENT;
7807 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7808 return WERR_NOMEM;
7810 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
7812 fill_printprocessordirectory_1(info, path);
7814 *needed += spoolss_size_printprocessordirectory_info_1(info);
7816 if (!alloc_buffer_size(buffer, *needed)) {
7817 safe_free(info);
7818 return WERR_INSUFFICIENT_BUFFER;
7821 smb_io_printprocessordirectory_1("", buffer, info, 0);
7823 safe_free(info);
7825 if (*needed > offered)
7826 return WERR_INSUFFICIENT_BUFFER;
7827 else
7828 return WERR_OK;
7831 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7833 uint32 level = q_u->level;
7834 NEW_BUFFER *buffer = NULL;
7835 uint32 offered = q_u->offered;
7836 uint32 *needed = &r_u->needed;
7838 /* that's an [in out] buffer */
7839 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7840 buffer = r_u->buffer;
7842 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7844 *needed=0;
7846 switch(level) {
7847 case 1:
7848 return getprintprocessordirectory_level_1
7849 (&q_u->name, &q_u->environment, buffer, offered, needed);
7850 default:
7851 return WERR_UNKNOWN_LEVEL;
7854 return WERR_ACCESS_DENIED;