fix potential smbd crash when we fail to alloacte a policy handle for a printer open...
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobf8a1ef0f1ef2c9ba08a310d03141ce6dc3808cc3
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-2002,
8 * Copyright (C) Gerald Carter 2000-2003,
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 /* Table to map the driver version */
41 /* to OS */
42 const char * drv_ver_to_os[] = {
43 "WIN9X", /* driver version/cversion 0 */
44 "", /* unused ? */
45 "WINNT", /* driver version/cversion 2 */
46 "WIN2K", /* driver version/cversion 3 */
49 struct table_node {
50 const char *long_archi;
51 const char *short_archi;
52 int version;
56 /* structure to store the printer handles */
57 /* and a reference to what it's pointing to */
58 /* and the notify info asked about */
59 /* that's the central struct */
60 typedef struct _Printer{
61 struct _Printer *prev, *next;
62 BOOL document_started;
63 BOOL page_started;
64 int jobid; /* jobid in printing backend */
65 BOOL printer_type;
66 union {
67 fstring handlename;
68 fstring printerservername;
69 } dev;
70 uint32 type;
71 uint32 access_granted;
72 struct {
73 uint32 flags;
74 uint32 options;
75 fstring localmachine;
76 uint32 printerlocal;
77 SPOOL_NOTIFY_OPTION *option;
78 POLICY_HND client_hnd;
79 uint32 client_connected;
80 uint32 change;
81 } notify;
82 struct {
83 fstring machine;
84 fstring user;
85 } client;
86 } Printer_entry;
88 static Printer_entry *printers_list;
90 typedef struct _counter_printer_0 {
91 ubi_dlNode Next;
92 ubi_dlNode Prev;
94 int snum;
95 uint32 counter;
96 } counter_printer_0;
98 static ubi_dlList counter_list;
100 static struct cli_state cli;
101 static uint32 smb_connections=0;
104 /* in printing/nt_printing.c */
106 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
108 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
109 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
111 /* translate between internal status numbers and NT status numbers */
112 static int nt_printj_status(int v)
114 switch (v) {
115 case LPQ_QUEUED:
116 return 0;
117 case LPQ_PAUSED:
118 return JOB_STATUS_PAUSED;
119 case LPQ_SPOOLING:
120 return JOB_STATUS_SPOOLING;
121 case LPQ_PRINTING:
122 return JOB_STATUS_PRINTING;
123 case LPQ_ERROR:
124 return JOB_STATUS_ERROR;
125 case LPQ_DELETING:
126 return JOB_STATUS_DELETING;
127 case LPQ_OFFLINE:
128 return JOB_STATUS_OFFLINE;
129 case LPQ_PAPEROUT:
130 return JOB_STATUS_PAPEROUT;
131 case LPQ_PRINTED:
132 return JOB_STATUS_PRINTED;
133 case LPQ_DELETED:
134 return JOB_STATUS_DELETED;
135 case LPQ_BLOCKED:
136 return JOB_STATUS_BLOCKED;
137 case LPQ_USER_INTERVENTION:
138 return JOB_STATUS_USER_INTERVENTION;
140 return 0;
143 static int nt_printq_status(int v)
145 switch (v) {
146 case LPQ_PAUSED:
147 return PRINTER_STATUS_PAUSED;
148 case LPQ_QUEUED:
149 case LPQ_SPOOLING:
150 case LPQ_PRINTING:
151 return 0;
153 return 0;
156 /****************************************************************************
157 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
158 ****************************************************************************/
160 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
162 if (*pp == NULL)
163 return;
165 SAFE_FREE((*pp)->ctr.type);
166 SAFE_FREE(*pp);
169 /***************************************************************************
170 Disconnect from the client
171 ****************************************************************************/
173 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
175 WERROR result;
177 /* weird if the test succeds !!! */
178 if (smb_connections==0) {
179 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
180 return;
183 result = cli_spoolss_reply_close_printer(&cli, cli.mem_ctx, handle);
185 if (!W_ERROR_IS_OK(result))
186 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
187 dos_errstr(result)));
189 /* if it's the last connection, deconnect the IPC$ share */
190 if (smb_connections==1) {
191 if(!spoolss_disconnect_from_client(&cli))
192 return;
194 message_deregister(MSG_PRINTER_NOTIFY);
197 smb_connections--;
200 /****************************************************************************
201 Functions to free a printer entry datastruct.
202 ****************************************************************************/
204 static void free_printer_entry(void *ptr)
206 Printer_entry *Printer = (Printer_entry *)ptr;
208 if (Printer->notify.client_connected==True)
209 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 free_spool_notify_option(&Printer->notify.option);
216 Printer->notify.option=NULL;
217 Printer->notify.client_connected=False;
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
222 SAFE_FREE(Printer);
225 /****************************************************************************
226 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
227 ****************************************************************************/
229 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
231 SPOOL_NOTIFY_OPTION *new_sp = NULL;
233 if (!sp)
234 return NULL;
236 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
237 if (!new_sp)
238 return NULL;
240 *new_sp = *sp;
242 if (sp->ctr.count) {
243 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
245 if (!new_sp->ctr.type) {
246 SAFE_FREE(new_sp);
247 return NULL;
251 return new_sp;
254 /****************************************************************************
255 find printer index by handle
256 ****************************************************************************/
258 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
260 Printer_entry *find_printer = NULL;
262 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
263 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
264 return NULL;
267 return find_printer;
270 /****************************************************************************
271 Close printer index by handle.
272 ****************************************************************************/
274 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
276 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
278 if (!Printer) {
279 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
280 return False;
283 close_policy_hnd(p, hnd);
285 return True;
288 /****************************************************************************
289 Delete a printer given a handle.
290 ****************************************************************************/
292 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
294 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
296 if (!Printer) {
297 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
298 return WERR_BADFID;
302 * It turns out that Windows allows delete printer on a handle
303 * opened by an admin user, then used on a pipe handle created
304 * by an anonymous user..... but they're working on security.... riiight !
305 * JRA.
308 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
309 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
310 return WERR_ACCESS_DENIED;
313 #if 0
314 /* Check calling user has permission to delete printer. Note that
315 since we set the snum parameter to -1 only administrators can
316 delete the printer. This stops people with the Full Control
317 permission from deleting the printer. */
319 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
320 DEBUG(3, ("printer delete denied by security descriptor\n"));
321 return WERR_ACCESS_DENIED;
323 #endif
325 if (del_a_printer(Printer->dev.handlename) != 0) {
326 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
327 return WERR_BADFID;
330 if (*lp_deleteprinter_cmd()) {
332 char *cmd = lp_deleteprinter_cmd();
333 pstring command;
334 int ret;
335 int i;
337 /* Printer->dev.handlename equals portname equals sharename */
338 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
339 Printer->dev.handlename);
340 dos_to_unix(command); /* Convert printername to unix-codepage */
342 DEBUG(10,("Running [%s]\n", command));
343 ret = smbrun(command, NULL);
344 if (ret != 0) {
345 return WERR_BADFID; /* What to return here? */
347 DEBUGADD(10,("returned [%d]\n", ret));
349 /* Send SIGHUP to process group... is there a better way? */
350 kill(0, SIGHUP);
352 /* go ahead and re-read the services immediately */
353 reload_services( False );
355 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
356 return WERR_ACCESS_DENIED;
359 return WERR_OK;
362 /****************************************************************************
363 Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
366 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
368 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370 if (!Printer) {
371 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
372 return False;
375 switch (Printer->printer_type) {
376 case PRINTER_HANDLE_IS_PRINTER:
377 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
378 *number = print_queue_snum(Printer->dev.handlename);
379 return (*number != -1);
380 case PRINTER_HANDLE_IS_PRINTSERVER:
381 return False;
382 default:
383 return False;
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
398 return False;
401 /* it's a print server */
402 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
406 /* it's a printer */
407 else {
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
412 return True;
415 /****************************************************************************
416 Set printer handle name.
417 ****************************************************************************/
419 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
421 int snum;
422 int n_services=lp_numservices();
423 char *aprinter;
424 fstring sname;
425 BOOL found=False;
427 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
429 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
430 ZERO_STRUCT(Printer->dev.printerservername);
431 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
432 return True;
435 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
436 return False;
438 if (*handlename=='\\') {
439 aprinter=strchr(handlename+2, '\\');
440 aprinter++;
442 else {
443 aprinter=handlename;
446 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
449 * The original code allowed smbd to store a printer name that
450 * was different from the share name. This is not possible
451 * anymore, so I've simplified this loop greatly. Here
452 * we are just verifying that the printer name is a valid
453 * printer service defined in smb.conf
454 * --jerry [Fri Feb 15 11:17:46 CST 2002]
457 for (snum=0; snum<n_services; snum++) {
459 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
460 continue;
462 fstrcpy(sname, lp_servicename(snum));
464 DEBUGADD(5,("share:%s\n",sname));
466 if (! StrCaseCmp(sname, aprinter)) {
467 found = True;
468 break;
474 if (!found) {
475 DEBUGADD(4,("Printer not found\n"));
476 return False;
479 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
481 ZERO_STRUCT(Printer->dev.handlename);
482 fstrcpy(Printer->dev.handlename, sname);
484 return True;
487 /****************************************************************************
488 Find first available printer slot. creates a printer handle for you.
489 ****************************************************************************/
491 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
493 Printer_entry *new_printer;
495 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
497 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
498 return False;
500 ZERO_STRUCTP(new_printer);
502 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
503 SAFE_FREE(new_printer);
504 return False;
507 /* Add to the internal list. */
508 DLIST_ADD(printers_list, new_printer);
510 new_printer->notify.option=NULL;
512 if ( !(new_printer->ctx = talloc_init_named("Printer Entry [0x%x]", (uint32)hnd)) ) {
513 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
514 close_printer_handle(p, hnd);
515 return False;
518 if (!set_printer_hnd_printertype(new_printer, name)) {
519 close_printer_handle(p, hnd);
520 return False;
523 if (!set_printer_hnd_name(new_printer, name)) {
524 close_printer_handle(p, hnd);
525 return False;
528 new_printer->access_granted = access_granted;
530 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
532 return True;
535 /****************************************************************************
536 Allocate more memory for a BUFFER.
537 ****************************************************************************/
539 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
541 prs_struct *ps;
542 uint32 extra_space;
543 uint32 old_offset;
545 ps= &buffer->prs;
547 /* damn, I'm doing the reverse operation of prs_grow() :) */
548 if (buffer_size < prs_data_size(ps))
549 extra_space=0;
550 else
551 extra_space = buffer_size - prs_data_size(ps);
554 * save the offset and move to the end of the buffer
555 * prs_grow() checks the extra_space against the offset
557 old_offset=prs_offset(ps);
558 prs_set_offset(ps, prs_data_size(ps));
560 if (!prs_grow(ps, extra_space))
561 return False;
563 prs_set_offset(ps, old_offset);
565 buffer->string_at_end=prs_data_size(ps);
567 return True;
569 /***************************************************************************
570 Always give preference Printer_entry.notify.option over
571 Printer_entry.notify.flags. Return True if we should send notification
572 events using SPOOLSS_RRPCN. False means that we should use
573 SPOOLSS_ROUTERREPLYPRINTER.
574 **************************************************************************/
575 static BOOL valid_notify_options(Printer_entry *printer)
577 if (printer->notify.option == NULL)
578 return False;
580 return True;
583 /***************************************************************************
584 Simple check to see if the client motify handle is set to watch for events
585 represented by 'flags'
587 FIXME!!!! only a stub right now --jerry
588 **************************************************************************/
590 static BOOL is_client_monitoring_event(Printer_entry *p, uint32 flags)
593 return True;
596 /***************************************************************************
597 Server wrapper for cli_spoolss_routerreplyprinter() since the client
598 function can only send a single change notification at a time.
600 FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
601 --jerry
602 **************************************************************************/
604 static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
605 POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
606 NT_PRINTER_INFO_LEVEL *printer)
608 WERROR result;
609 uint32 condition = 0x0;
611 if (info->flags & PRINTER_MESSAGE_DRIVER)
612 condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
614 result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
615 printer->info_2->changeid);
617 return result;
620 /***********************************************************************
621 Wrapper around the decision of which RPC use to in the change
622 notification
623 **********************************************************************/
625 static WERROR srv_spoolss_send_event_to_client(Printer_entry* Printer,
626 struct cli_state *send_cli, PRINTER_MESSAGE_INFO *msg,
627 NT_PRINTER_INFO_LEVEL *info)
629 WERROR result;
631 if (valid_notify_options(Printer)) {
632 /* This is a single call that can send information about multiple changes */
633 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
634 msg->flags |= PRINTER_MESSAGE_ATTRIBUTES;
636 result = cli_spoolss_reply_rrpcn(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
637 msg, info);
639 else {
640 /* This requires that the server send an individual event notification for each change */
641 result = srv_spoolss_routerreplyprinter(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
642 msg, info);
645 return result;
649 /***********************************************************************
650 Send a change notication message on all handles which have a call
651 back registered
652 **********************************************************************/
654 static void send_spoolss_event_notification(PRINTER_MESSAGE_INFO *msg)
656 Printer_entry *find_printer;
657 WERROR result;
658 NT_PRINTER_INFO_LEVEL *printer = NULL;
660 if (!msg) {
661 DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n"));
662 return;
665 for(find_printer = printers_list; find_printer; find_printer = find_printer->next) {
668 * If the entry has a connected client we send the message. There should
669 * only be one of these normally when dealing with the NT/2k spooler.
670 * However, iterate over all to make sure we deal with user applications
671 * in addition to spooler service.
673 * While we are only maintaining a single connection to the client,
674 * the FindFirstPrinterChangeNotification() call is made on a printer
675 * handle, so "client_connected" represents the whether or not the
676 * client asked for change notication on this handle.
678 * --jerry
681 if (find_printer->notify.client_connected==True) {
683 msg->low = find_printer->notify.change;
685 /* does the client care about what changed? */
687 if (msg->flags && !is_client_monitoring_event(find_printer, msg->flags)) {
688 DEBUG(10,("send_spoolss_event_notification: Client [%s] not monitoring these events\n",
689 find_printer->client.machine));
690 continue;
693 if (find_printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
694 DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer->dev.printerservername ));
695 else
696 DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer->dev.handlename));
699 * if handle is a printer, only send if the printer_name matches.
700 * ...else if handle is a printerserver, send to all
703 if (*msg->printer_name && (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
704 && !strequal(msg->printer_name, find_printer->dev.handlename))
706 DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n",
707 msg->printer_name, find_printer->dev.handlename ));
708 continue;
712 /* lookup the printer if we have a name if we don't already have a
713 valid NT_PRINTER_INFO_LEVEL structure. And yes I'm assuming we
714 will always have a non-empty msg.printer_name */
716 if (!printer || !printer->info_2 || strcmp(msg->printer_name, printer->info_2->printername))
719 if (printer) {
720 free_a_printer(&printer, 2);
721 printer = NULL;
724 result = get_a_printer(&printer, 2, msg->printer_name);
725 if (!W_ERROR_IS_OK(result))
726 continue;
729 /* issue the client call */
731 result = srv_spoolss_send_event_to_client(find_printer, &cli, msg, printer);
733 if (!W_ERROR_IS_OK(result)) {
734 DEBUG(5,("send_spoolss_event_notification: Event notification failed [%s]\n",
735 dos_errstr(result)));
740 return;
742 /***************************************************************************
743 Receive the notify message and decode the message. Do not send
744 notification if we sent this originally as that would result in
745 duplicates.
746 ****************************************************************************/
748 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
750 PRINTER_MESSAGE_INFO msg;
752 if (len < sizeof(msg)) {
753 DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len));
754 return;
757 memcpy(&msg, buf, sizeof(PRINTER_MESSAGE_INFO));
759 DEBUG(10,("srv_spoolss_receive_message: Got message printer change [queue = %s] low=0x%x high=0x%x flags=0x%x\n",
760 msg.printer_name, (unsigned int)msg.low, (unsigned int)msg.high, msg.flags ));
762 /* Iterate the printer list */
764 send_spoolss_event_notification(&msg);
768 /***************************************************************************
769 Send a notify event.
770 ****************************************************************************/
772 static BOOL srv_spoolss_sendnotify(char* printer_name, uint32 high, uint32 low, uint32 flags)
774 char msg[sizeof(PRINTER_MESSAGE_INFO)];
775 PRINTER_MESSAGE_INFO info;
777 ZERO_STRUCT(info);
779 info.low = low;
780 info.high = high;
781 info.flags = flags;
782 fstrcpy(info.printer_name, printer_name);
784 memcpy(msg, &info, sizeof(PRINTER_MESSAGE_INFO));
786 DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x [%s], flags=0x%x\n",
787 low, high, printer_name, flags));
789 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(PRINTER_MESSAGE_INFO),
790 False, NULL);
792 return True;
795 /********************************************************************
796 Send a message to ourself about new driver being installed
797 so we can upgrade the information for each printer bound to this
798 driver
799 ********************************************************************/
801 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
803 int len = strlen(drivername);
805 if (!len)
806 return False;
808 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
809 drivername));
811 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
813 return True;
816 /**********************************************************************
817 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
818 over all printers, upgrading ones as neessary
819 **********************************************************************/
821 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
823 fstring drivername;
824 int snum;
825 int n_services = lp_numservices();
827 len = MIN(len,sizeof(drivername)-1);
828 strncpy(drivername, buf, len);
830 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
832 /* Iterate the printer list */
834 for (snum=0; snum<n_services; snum++)
836 if (lp_snum_ok(snum) && lp_print_ok(snum) )
838 WERROR result;
839 NT_PRINTER_INFO_LEVEL *printer = NULL;
841 result = get_a_printer(&printer, 2, lp_servicename(snum));
842 if (!W_ERROR_IS_OK(result))
843 continue;
845 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
847 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
849 /* all we care about currently is the change_id */
851 result = mod_a_printer(*printer, 2);
852 if (!W_ERROR_IS_OK(result)) {
853 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
854 dos_errstr(result)));
858 free_a_printer(&printer, 2);
862 /* all done */
865 /********************************************************************
866 Copy routines used by convert_to_openprinterex()
867 *******************************************************************/
869 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
871 DEVICEMODE *d;
872 int len;
874 if (!devmode)
875 return NULL;
877 DEBUG (8,("dup_devmode\n"));
879 /* bulk copy first */
881 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
882 if (!d)
883 return NULL;
885 /* dup the pointer members separately */
887 len = unistrlen(devmode->devicename.buffer);
888 if (len != -1) {
889 d->devicename.buffer = talloc(ctx, len*2);
890 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
891 return NULL;
895 len = unistrlen(devmode->formname.buffer);
896 if (len != -1) {
897 d->devicename.buffer = talloc(ctx, len*2);
898 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
899 return NULL;
902 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
904 return d;
907 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
909 if (!new_ctr || !ctr)
910 return;
912 DEBUG(8,("copy_devmode_ctr\n"));
914 new_ctr->size = ctr->size;
915 new_ctr->devmode_ptr = ctr->devmode_ptr;
917 if(ctr->devmode_ptr)
918 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
921 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
923 if (!new_def || !def)
924 return;
926 DEBUG(8,("copy_printer_defaults\n"));
928 new_def->datatype_ptr = def->datatype_ptr;
930 if (def->datatype_ptr)
931 copy_unistr2(&new_def->datatype, &def->datatype);
933 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
935 new_def->access_required = def->access_required;
938 /********************************************************************
939 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
940 * SPOOL_Q_OPEN_PRINTER_EX structure
941 ********************************************************************/
943 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
945 if (!q_u_ex || !q_u)
946 return;
948 DEBUG(8,("convert_to_openprinterex\n"));
950 q_u_ex->printername_ptr = q_u->printername_ptr;
952 if (q_u->printername_ptr)
953 copy_unistr2(&q_u_ex->printername, &q_u->printername);
955 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
958 /********************************************************************
959 * spoolss_open_printer
961 * called from the spoolss dispatcher
962 ********************************************************************/
964 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
966 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
967 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
969 if (!q_u || !r_u)
970 return WERR_NOMEM;
972 ZERO_STRUCT(q_u_ex);
973 ZERO_STRUCT(r_u_ex);
975 /* convert the OpenPrinter() call to OpenPrinterEx() */
977 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
979 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
981 /* convert back to OpenPrinter() */
983 memcpy(r_u, &r_u_ex, sizeof(*r_u));
985 return r_u->status;
988 /********************************************************************
989 * spoolss_open_printer
991 * If the openprinterex rpc call contains a devmode,
992 * it's a per-user one. This per-user devmode is derivated
993 * from the global devmode. Openprinterex() contains a per-user
994 * devmode for when you do EMF printing and spooling.
995 * In the EMF case, the NT workstation is only doing half the job
996 * of rendering the page. The other half is done by running the printer
997 * driver on the server.
998 * The EMF file doesn't contain the page description (paper size, orientation, ...).
999 * The EMF file only contains what is to be printed on the page.
1000 * So in order for the server to know how to print, the NT client sends
1001 * a devicemode attached to the openprinterex call.
1002 * But this devicemode is short lived, it's only valid for the current print job.
1004 * If Samba would have supported EMF spooling, this devicemode would
1005 * have been attached to the handle, to sent it to the driver to correctly
1006 * rasterize the EMF file.
1008 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1009 * we just act as a pass-thru between windows and the printer.
1011 * In order to know that Samba supports only RAW spooling, NT has to call
1012 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1013 * and until NT sends a RAW job, we refuse it.
1015 * But to call getprinter() or startdoc(), you first need a valid handle,
1016 * and to get an handle you have to call openprintex(). Hence why you have
1017 * a devicemode in the openprinterex() call.
1020 * Differences between NT4 and NT 2000.
1021 * NT4:
1022 * ---
1023 * On NT4, you only have a global devicemode. This global devicemode can be changed
1024 * by the administrator (or by a user with enough privs). Everytime a user
1025 * wants to print, the devicemode is resetted to the default. In Word, everytime
1026 * you print, the printer's characteristics are always reset to the global devicemode.
1028 * NT 2000:
1029 * -------
1030 * In W2K, there is the notion of per-user devicemode. The first time you use
1031 * a printer, a per-user devicemode is build from the global devicemode.
1032 * If you change your per-user devicemode, it is saved in the registry, under the
1033 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1034 * printer preferences available.
1036 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1037 * on the General Tab of the printer properties windows.
1039 * To change the global devicemode: it's the "Printing Defaults..." button
1040 * on the Advanced Tab of the printer properties window.
1042 * JFM.
1043 ********************************************************************/
1045 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1047 UNISTR2 *printername = NULL;
1048 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1049 /* uint32 user_switch = q_u->user_switch; - notused */
1050 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
1051 POLICY_HND *handle = &r_u->handle;
1053 fstring name;
1054 int snum;
1055 struct current_user user;
1056 Printer_entry *Printer=NULL;
1058 if (q_u->printername_ptr != 0)
1059 printername = &q_u->printername;
1061 if (printername == NULL)
1062 return WERR_INVALID_PRINTER_NAME;
1064 /* some sanity check because you can open a printer or a print server */
1065 /* aka: \\server\printer or \\server */
1066 unistr2_to_dos(name, printername, sizeof(name)-1);
1068 DEBUGADD(3,("checking name: %s\n",name));
1070 if (!open_printer_hnd(p, handle, name, 0))
1071 return WERR_INVALID_PRINTER_NAME;
1073 Printer=find_printer_index_by_hnd(p, handle);
1074 if (!Printer) {
1075 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1076 Can't find printer handle we created for printer %s\n", name ));
1077 close_printer_handle(p,handle);
1078 return WERR_INVALID_PRINTER_NAME;
1081 get_current_user(&user, p);
1084 * First case: the user is opening the print server:
1086 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1087 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1089 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1090 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1091 * or if the user is listed in the smb.conf printer admin parameter.
1093 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1094 * client view printer folder, but does not show the MSAPW.
1096 * Note: this test needs code to check access rights here too. Jeremy
1097 * could you look at this?
1099 * Second case: the user is opening a printer:
1100 * NT doesn't let us connect to a printer if the connecting user
1101 * doesn't have print permission.
1104 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1106 /* Printserver handles use global struct... */
1108 snum = -1;
1110 /* Map standard access rights to object specific access rights */
1112 se_map_standard(&printer_default->access_required,
1113 &printserver_std_mapping);
1115 /* Deny any object specific bits that don't apply to print
1116 servers (i.e printer and job specific bits) */
1118 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1120 if (printer_default->access_required &
1121 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1122 DEBUG(3, ("access DENIED for non-printserver bits"));
1123 close_printer_handle(p, handle);
1124 return WERR_ACCESS_DENIED;
1127 /* Allow admin access */
1129 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1131 if (!lp_ms_add_printer_wizard()) {
1132 close_printer_handle(p, handle);
1133 return WERR_ACCESS_DENIED;
1136 /* if the user is not root and not a printer admin, then fail */
1138 if ( user.uid != 0
1139 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1141 close_printer_handle(p, handle);
1142 return WERR_ACCESS_DENIED;
1145 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1147 else
1149 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1152 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1153 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1155 /* We fall through to return WERR_OK */
1158 else
1160 /* NT doesn't let us connect to a printer if the connecting user
1161 doesn't have print permission. */
1163 if (!get_printer_snum(p, handle, &snum))
1164 return WERR_BADFID;
1166 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1168 /* map an empty access mask to the minimum access mask */
1169 if (printer_default->access_required == 0x0)
1170 printer_default->access_required = PRINTER_ACCESS_USE;
1173 * If we are not serving the printer driver for this printer,
1174 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1175 * will keep NT clients happy --jerry
1178 if (lp_use_client_driver(snum)
1179 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1181 printer_default->access_required = PRINTER_ACCESS_USE;
1184 /* check smb.conf parameters and the the sec_desc */
1186 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1187 DEBUG(3, ("access DENIED for printer open\n"));
1188 close_printer_handle(p, handle);
1189 return WERR_ACCESS_DENIED;
1192 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1193 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1194 close_printer_handle(p, handle);
1195 return WERR_ACCESS_DENIED;
1198 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1199 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1200 else
1201 printer_default->access_required = PRINTER_ACCESS_USE;
1203 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1204 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1207 Printer->access_granted = printer_default->access_required;
1209 return WERR_OK;
1212 /****************************************************************************
1213 ****************************************************************************/
1215 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1216 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1218 BOOL ret = True;
1220 switch (level) {
1221 case 2:
1222 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1223 break;
1224 default:
1225 break;
1228 return ret;
1231 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1232 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1234 BOOL result = True;
1236 switch (level) {
1237 case 3:
1238 printer->info_3=NULL;
1239 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1240 result = False;
1241 break;
1242 case 6:
1243 printer->info_6=NULL;
1244 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1245 result = False;
1246 break;
1247 default:
1248 break;
1251 return result;
1254 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1255 NT_DEVICEMODE **pp_nt_devmode)
1257 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1260 * Ensure nt_devmode is a valid pointer
1261 * as we will be overwriting it.
1264 if (nt_devmode == NULL) {
1265 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1266 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1267 return False;
1270 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
1271 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
1273 nt_devmode->specversion=devmode->specversion;
1274 nt_devmode->driverversion=devmode->driverversion;
1275 nt_devmode->size=devmode->size;
1276 nt_devmode->fields=devmode->fields;
1277 nt_devmode->orientation=devmode->orientation;
1278 nt_devmode->papersize=devmode->papersize;
1279 nt_devmode->paperlength=devmode->paperlength;
1280 nt_devmode->paperwidth=devmode->paperwidth;
1281 nt_devmode->scale=devmode->scale;
1282 nt_devmode->copies=devmode->copies;
1283 nt_devmode->defaultsource=devmode->defaultsource;
1284 nt_devmode->printquality=devmode->printquality;
1285 nt_devmode->color=devmode->color;
1286 nt_devmode->duplex=devmode->duplex;
1287 nt_devmode->yresolution=devmode->yresolution;
1288 nt_devmode->ttoption=devmode->ttoption;
1289 nt_devmode->collate=devmode->collate;
1291 nt_devmode->logpixels=devmode->logpixels;
1292 nt_devmode->bitsperpel=devmode->bitsperpel;
1293 nt_devmode->pelswidth=devmode->pelswidth;
1294 nt_devmode->pelsheight=devmode->pelsheight;
1295 nt_devmode->displayflags=devmode->displayflags;
1296 nt_devmode->displayfrequency=devmode->displayfrequency;
1297 nt_devmode->icmmethod=devmode->icmmethod;
1298 nt_devmode->icmintent=devmode->icmintent;
1299 nt_devmode->mediatype=devmode->mediatype;
1300 nt_devmode->dithertype=devmode->dithertype;
1301 nt_devmode->reserved1=devmode->reserved1;
1302 nt_devmode->reserved2=devmode->reserved2;
1303 nt_devmode->panningwidth=devmode->panningwidth;
1304 nt_devmode->panningheight=devmode->panningheight;
1307 * Only change private and driverextra if the incoming devmode
1308 * has a new one. JRA.
1311 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1312 SAFE_FREE(nt_devmode->private);
1313 nt_devmode->driverextra=devmode->driverextra;
1314 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1315 return False;
1316 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1319 *pp_nt_devmode = nt_devmode;
1321 return True;
1324 /********************************************************************
1325 * _spoolss_enddocprinter_internal.
1326 ********************************************************************/
1328 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1330 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1332 if (!Printer) {
1333 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1334 return WERR_BADFID;
1337 Printer->document_started=False;
1338 print_job_end(Printer->jobid,True);
1339 /* error codes unhandled so far ... */
1341 return WERR_OK;
1344 /********************************************************************
1345 * api_spoolss_closeprinter
1346 ********************************************************************/
1348 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1350 POLICY_HND *handle = &q_u->handle;
1352 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1354 if (Printer && Printer->document_started)
1355 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1357 if (!close_printer_handle(p, handle))
1358 return WERR_BADFID;
1360 /* clear the returned printer handle. Observed behavior
1361 from Win2k server. Don't think this really matters.
1362 Previous code just copied the value of the closed
1363 handle. --jerry */
1365 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1367 return WERR_OK;
1370 /********************************************************************
1371 * api_spoolss_deleteprinter
1373 ********************************************************************/
1375 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1377 POLICY_HND *handle = &q_u->handle;
1378 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1379 WERROR result;
1381 if (Printer && Printer->document_started)
1382 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1384 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1386 result = delete_printer_handle(p, handle);
1388 update_c_setprinter(False);
1390 if (W_ERROR_IS_OK(result)) {
1391 srv_spoolss_sendnotify(Printer->dev.handlename, 0, PRINTER_CHANGE_DELETE_PRINTER, 0x0);
1394 return result;
1397 /*******************************************************************
1398 * static function to lookup the version id corresponding to an
1399 * long architecture string
1400 ******************************************************************/
1402 static int get_version_id (char * arch)
1404 int i;
1405 struct table_node archi_table[]= {
1407 {"Windows 4.0", "WIN40", 0 },
1408 {"Windows NT x86", "W32X86", 2 },
1409 {"Windows NT R4000", "W32MIPS", 2 },
1410 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1411 {"Windows NT PowerPC", "W32PPC", 2 },
1412 {NULL, "", -1 }
1415 for (i=0; archi_table[i].long_archi != NULL; i++)
1417 if (strcmp(arch, archi_table[i].long_archi) == 0)
1418 return (archi_table[i].version);
1421 return -1;
1424 /********************************************************************
1425 * _spoolss_deleteprinterdriver
1427 * We currently delete the driver for the architecture only.
1428 * This can leave the driver for other archtectures. However,
1429 * since every printer associates a "Windows NT x86" driver name
1430 * and we cannot delete that one while it is in use, **and** since
1431 * it is impossible to assign a driver to a Samba printer without
1432 * having the "Windows NT x86" driver installed,...
1434 * ....we should not get into trouble here.
1436 * --jerry
1437 ********************************************************************/
1439 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1440 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1442 fstring driver;
1443 fstring arch;
1444 NT_PRINTER_DRIVER_INFO_LEVEL info;
1445 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1446 int version;
1447 struct current_user user;
1448 WERROR status;
1449 WERROR status_win2k = WERR_ACCESS_DENIED;
1451 unistr2_to_dos(driver, &q_u->driver, sizeof(driver)-1 );
1452 unistr2_to_dos(arch, &q_u->arch, sizeof(arch)-1 );
1453 get_current_user(&user, p);
1455 unistr2_to_dos(arch, &q_u->arch, sizeof(arch)-1 );
1457 /* check that we have a valid driver name first */
1459 if ((version=get_version_id(arch)) == -1)
1460 return WERR_INVALID_ENVIRONMENT;
1462 ZERO_STRUCT(info);
1463 ZERO_STRUCT(info_win2k);
1465 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1467 /* try for Win2k driver if "Windows NT x86" */
1469 if ( version == 2 ) {
1470 version = 3;
1471 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1472 status = WERR_UNKNOWN_PRINTER_DRIVER;
1473 goto done;
1476 /* otherwise it was a failure */
1477 else {
1478 status = WERR_UNKNOWN_PRINTER_DRIVER;
1479 goto done;
1484 if (printer_driver_in_use(info.info_3)) {
1485 status = WERR_PRINTER_DRIVER_IN_USE;
1486 goto done;
1489 if ( version == 2 )
1491 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1493 /* if we get to here, we now have 2 driver info structures to remove */
1494 /* remove the Win2k driver first*/
1496 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1497 free_a_printer_driver( info_win2k, 3 );
1499 /* this should not have failed---if it did, report to client */
1500 if ( !W_ERROR_IS_OK(status_win2k) )
1501 goto done;
1505 status = delete_printer_driver(info.info_3, &user, version, False);
1507 /* if at least one of the deletes succeeded return OK */
1509 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1510 status = WERR_OK;
1512 done:
1513 free_a_printer_driver( info, 3 );
1515 return status;
1518 /********************************************************************
1519 GetPrinterData on a printer server Handle.
1520 ********************************************************************/
1522 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1524 int i;
1526 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1528 if (!strcmp(value, "W3SvcInstalled")) {
1529 *type = 0x4;
1530 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1531 return False;
1532 *needed = 0x4;
1533 return True;
1536 if (!strcmp(value, "BeepEnabled")) {
1537 *type = 0x4;
1538 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1539 return False;
1540 SIVAL(*data, 0, 0x00);
1541 *needed = 0x4;
1542 return True;
1545 if (!strcmp(value, "EventLog")) {
1546 *type = 0x4;
1547 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1548 return False;
1549 /* formally was 0x1b */
1550 SIVAL(*data, 0, 0x0);
1551 *needed = 0x4;
1552 return True;
1555 if (!strcmp(value, "NetPopup")) {
1556 *type = 0x4;
1557 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1558 return False;
1559 SIVAL(*data, 0, 0x00);
1560 *needed = 0x4;
1561 return True;
1564 if (!strcmp(value, "MajorVersion")) {
1565 *type = 0x4;
1566 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1567 return False;
1568 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1569 SIVAL(*data, 0, 2);
1570 #else
1571 SIVAL(*data, 0, 3);
1572 #endif
1573 *needed = 0x4;
1574 return True;
1577 if (!strcmp(value, "DefaultSpoolDirectory")) {
1578 fstring string;
1580 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1581 *type = 0x1;
1582 *needed = 2*(strlen(string)+1);
1583 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1584 return False;
1585 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1587 /* it's done by hand ready to go on the wire */
1588 for (i=0; i<strlen(string); i++) {
1589 (*data)[2*i]=string[i];
1590 (*data)[2*i+1]='\0';
1592 return True;
1595 if (!strcmp(value, "Architecture")) {
1596 pstring string="Windows NT x86";
1597 *type = 0x1;
1598 *needed = 2*(strlen(string)+1);
1599 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1600 return False;
1601 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1602 for (i=0; i<strlen(string); i++) {
1603 (*data)[2*i]=string[i];
1604 (*data)[2*i+1]='\0';
1606 return True;
1609 return False;
1612 /********************************************************************
1613 GetPrinterData on a printer Handle.
1614 ********************************************************************/
1616 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1617 fstring value, uint32 *type,
1618 uint8 **data, uint32 *needed, uint32 in_size )
1620 NT_PRINTER_INFO_LEVEL *printer = NULL;
1621 int snum=0;
1622 uint8 *idata=NULL;
1623 uint32 len;
1624 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1626 DEBUG(5,("getprinterdata_printer\n"));
1628 if (!Printer) {
1629 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1630 return False;
1633 if(!get_printer_snum(p, handle, &snum))
1634 return False;
1636 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1637 return False;
1639 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1640 free_a_printer(&printer, 2);
1641 return False;
1644 free_a_printer(&printer, 2);
1646 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1648 if (in_size) {
1649 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1650 return False;
1653 memset(*data, 0, in_size *sizeof(uint8));
1654 /* copy the min(in_size, len) */
1655 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1656 } else {
1657 *data = NULL;
1660 *needed = len;
1662 DEBUG(5,("getprinterdata_printer:copy done\n"));
1664 SAFE_FREE(idata);
1666 return True;
1669 /********************************************************************
1670 * spoolss_getprinterdata
1671 ********************************************************************/
1673 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1675 POLICY_HND *handle = &q_u->handle;
1676 UNISTR2 *valuename = &q_u->valuename;
1677 uint32 in_size = q_u->size;
1678 uint32 *type = &r_u->type;
1679 uint32 *out_size = &r_u->size;
1680 uint8 **data = &r_u->data;
1681 uint32 *needed = &r_u->needed;
1683 fstring value;
1684 BOOL found=False;
1685 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1688 * Reminder: when it's a string, the length is in BYTES
1689 * even if UNICODE is negociated.
1691 * JFM, 4/19/1999
1694 *out_size=in_size;
1696 /* in case of problem, return some default values */
1697 *needed=0;
1698 *type=0;
1700 DEBUG(4,("_spoolss_getprinterdata\n"));
1702 if (!Printer) {
1703 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1704 return WERR_NOMEM;
1705 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1706 return WERR_BADFID;
1709 unistr2_to_dos(value, valuename, sizeof(value)-1);
1711 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1712 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1713 else
1714 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1716 if (found==False) {
1717 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1718 /* reply this param doesn't exist */
1719 if (*out_size) {
1720 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1721 return WERR_NOMEM;
1722 } else {
1723 *data = NULL;
1726 /* error depends on handle type */
1728 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1729 return WERR_INVALID_PARAM;
1730 else
1731 return WERR_BADFILE;
1734 if (*needed > *out_size)
1735 return WERR_MORE_DATA;
1736 else
1737 return WERR_OK;
1740 /***************************************************************************
1741 Connect to the client.
1742 ****************************************************************************/
1744 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1746 WERROR result;
1749 * If it's the first connection, contact the client
1750 * and connect to the IPC$ share anonumously
1752 if (smb_connections==0) {
1753 fstring unix_printer;
1755 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1756 dos_to_unix(unix_printer);
1758 if(!spoolss_connect_to_client(&cli, unix_printer))
1759 return False;
1761 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1765 smb_connections++;
1767 result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
1768 type, handle);
1770 if (!W_ERROR_IS_OK(result))
1771 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1772 dos_errstr(result)));
1774 return (W_ERROR_IS_OK(result));
1777 /********************************************************************
1778 * _spoolss_rffpcnex
1779 * ReplyFindFirstPrinterChangeNotifyEx
1781 * before replying OK: status=0 a rpc call is made to the workstation
1782 * asking ReplyOpenPrinter
1784 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1785 * called from api_spoolss_rffpcnex
1786 ********************************************************************/
1788 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1790 POLICY_HND *handle = &q_u->handle;
1791 uint32 flags = q_u->flags;
1792 uint32 options = q_u->options;
1793 UNISTR2 *localmachine = &q_u->localmachine;
1794 uint32 printerlocal = q_u->printerlocal;
1795 SPOOL_NOTIFY_OPTION *option = q_u->option;
1797 /* store the notify value in the printer struct */
1799 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1801 if (!Printer) {
1802 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1803 return WERR_BADFID;
1806 Printer->notify.flags=flags;
1807 Printer->notify.options=options;
1808 Printer->notify.printerlocal=printerlocal;
1810 if (Printer->notify.option)
1811 free_spool_notify_option(&Printer->notify.option);
1813 Printer->notify.option=dup_spool_notify_option(option);
1815 unistr2_to_dos(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1817 /* connect to the client machine and send a ReplyOpenPrinter */
1818 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1819 Printer->notify.printerlocal, 1,
1820 &Printer->notify.client_hnd))
1822 Printer->notify.client_connected=True;
1825 return WERR_OK;
1828 /*******************************************************************
1829 * fill a notify_info_data with the servername
1830 ********************************************************************/
1832 void spoolss_notify_server_name(int snum,
1833 SPOOL_NOTIFY_INFO_DATA *data,
1834 print_queue_struct *queue,
1835 NT_PRINTER_INFO_LEVEL *printer,
1836 TALLOC_CTX *mem_ctx)
1838 pstring temp_name, temp;
1839 uint32 len;
1841 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1843 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1845 data->notify_data.data.length = len / 2 - 1;
1846 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1848 if (!data->notify_data.data.string) {
1849 data->notify_data.data.length = 0;
1850 return;
1853 memcpy(data->notify_data.data.string, temp, len);
1856 /*******************************************************************
1857 * fill a notify_info_data with the printername (not including the servername).
1858 ********************************************************************/
1860 void spoolss_notify_printer_name(int snum,
1861 SPOOL_NOTIFY_INFO_DATA *data,
1862 print_queue_struct *queue,
1863 NT_PRINTER_INFO_LEVEL *printer,
1864 TALLOC_CTX *mem_ctx)
1866 pstring temp;
1867 uint32 len;
1869 /* the notify name should not contain the \\server\ part */
1870 char *p = strrchr(printer->info_2->printername, '\\');
1872 if (!p) {
1873 p = printer->info_2->printername;
1874 } else {
1875 p++;
1878 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1880 data->notify_data.data.length = len / 2 - 1;
1881 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1883 if (!data->notify_data.data.string) {
1884 data->notify_data.data.length = 0;
1885 return;
1888 memcpy(data->notify_data.data.string, temp, len);
1891 /*******************************************************************
1892 * fill a notify_info_data with the servicename
1893 ********************************************************************/
1895 void spoolss_notify_share_name(int snum,
1896 SPOOL_NOTIFY_INFO_DATA *data,
1897 print_queue_struct *queue,
1898 NT_PRINTER_INFO_LEVEL *printer,
1899 TALLOC_CTX *mem_ctx)
1901 pstring temp;
1902 uint32 len;
1904 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1905 sizeof(temp) - 2, True);
1907 data->notify_data.data.length = len / 2 - 1;
1908 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1910 if (!data->notify_data.data.string) {
1911 data->notify_data.data.length = 0;
1912 return;
1915 memcpy(data->notify_data.data.string, temp, len);
1918 /*******************************************************************
1919 * fill a notify_info_data with the port name
1920 ********************************************************************/
1922 void spoolss_notify_port_name(int snum,
1923 SPOOL_NOTIFY_INFO_DATA *data,
1924 print_queue_struct *queue,
1925 NT_PRINTER_INFO_LEVEL *printer,
1926 TALLOC_CTX *mem_ctx)
1928 pstring temp;
1929 uint32 len;
1931 /* even if it's strange, that's consistant in all the code */
1933 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1934 sizeof(temp) - 2, True);
1936 data->notify_data.data.length = len / 2 - 1;
1937 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1939 if (!data->notify_data.data.string) {
1940 data->notify_data.data.length = 0;
1941 return;
1944 memcpy(data->notify_data.data.string, temp, len);
1947 /*******************************************************************
1948 * fill a notify_info_data with the printername
1949 * but it doesn't exist, have to see what to do
1950 ********************************************************************/
1952 void spoolss_notify_driver_name(int snum,
1953 SPOOL_NOTIFY_INFO_DATA *data,
1954 print_queue_struct *queue,
1955 NT_PRINTER_INFO_LEVEL *printer,
1956 TALLOC_CTX *mem_ctx)
1958 pstring temp;
1959 uint32 len;
1961 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1962 sizeof(temp) - 2, True);
1964 data->notify_data.data.length = len / 2 - 1;
1965 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1967 if (!data->notify_data.data.string) {
1968 data->notify_data.data.length = 0;
1969 return;
1972 memcpy(data->notify_data.data.string, temp, len);
1975 /*******************************************************************
1976 * fill a notify_info_data with the comment
1977 ********************************************************************/
1979 void spoolss_notify_comment(int snum,
1980 SPOOL_NOTIFY_INFO_DATA *data,
1981 print_queue_struct *queue,
1982 NT_PRINTER_INFO_LEVEL *printer,
1983 TALLOC_CTX *mem_ctx)
1985 pstring temp;
1986 uint32 len;
1988 if (*printer->info_2->comment == '\0')
1989 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1990 sizeof(temp) - 2, True);
1991 else
1992 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1993 sizeof(temp) - 2, True);
1995 data->notify_data.data.length = len / 2 - 1;
1996 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1998 if (!data->notify_data.data.string) {
1999 data->notify_data.data.length = 0;
2000 return;
2003 memcpy(data->notify_data.data.string, temp, len);
2006 /*******************************************************************
2007 * fill a notify_info_data with the comment
2008 * location = "Room 1, floor 2, building 3"
2009 ********************************************************************/
2011 void spoolss_notify_location(int snum,
2012 SPOOL_NOTIFY_INFO_DATA *data,
2013 print_queue_struct *queue,
2014 NT_PRINTER_INFO_LEVEL *printer,
2015 TALLOC_CTX *mem_ctx)
2017 pstring temp;
2018 uint32 len;
2020 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
2021 sizeof(temp) - 2, True);
2023 data->notify_data.data.length = len / 2 - 1;
2024 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2026 if (!data->notify_data.data.string) {
2027 data->notify_data.data.length = 0;
2028 return;
2031 memcpy(data->notify_data.data.string, temp, len);
2034 /*******************************************************************
2035 * fill a notify_info_data with the device mode
2036 * jfm:xxxx don't to it for know but that's a real problem !!!
2037 ********************************************************************/
2039 static void spoolss_notify_devmode(int snum,
2040 SPOOL_NOTIFY_INFO_DATA *data,
2041 print_queue_struct *queue,
2042 NT_PRINTER_INFO_LEVEL *printer,
2043 TALLOC_CTX *mem_ctx)
2047 /*******************************************************************
2048 * fill a notify_info_data with the separator file name
2049 ********************************************************************/
2051 void spoolss_notify_sepfile(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 pstring temp;
2058 uint32 len;
2060 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
2061 sizeof(temp) - 2, True);
2063 data->notify_data.data.length = len / 2 - 1;
2064 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2066 if (!data->notify_data.data.string) {
2067 data->notify_data.data.length = 0;
2068 return;
2071 memcpy(data->notify_data.data.string, temp, len);
2074 /*******************************************************************
2075 * fill a notify_info_data with the print processor
2076 * jfm:xxxx return always winprint to indicate we don't do anything to it
2077 ********************************************************************/
2079 void spoolss_notify_print_processor(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 pstring temp;
2086 uint32 len;
2088 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
2089 sizeof(temp) - 2, True);
2091 data->notify_data.data.length = len / 2 - 1;
2092 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2094 if (!data->notify_data.data.string) {
2095 data->notify_data.data.length = 0;
2096 return;
2099 memcpy(data->notify_data.data.string, temp, len);
2102 /*******************************************************************
2103 * fill a notify_info_data with the print processor options
2104 * jfm:xxxx send an empty string
2105 ********************************************************************/
2107 void spoolss_notify_parameters(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 pstring temp;
2114 uint32 len;
2116 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
2117 sizeof(temp) - 2, True);
2119 data->notify_data.data.length = len / 2 - 1;
2120 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2122 if (!data->notify_data.data.string) {
2123 data->notify_data.data.length = 0;
2124 return;
2127 memcpy(data->notify_data.data.string, temp, len);
2130 /*******************************************************************
2131 * fill a notify_info_data with the data type
2132 * jfm:xxxx always send RAW as data type
2133 ********************************************************************/
2135 void spoolss_notify_datatype(int snum,
2136 SPOOL_NOTIFY_INFO_DATA *data,
2137 print_queue_struct *queue,
2138 NT_PRINTER_INFO_LEVEL *printer,
2139 TALLOC_CTX *mem_ctx)
2141 pstring temp;
2142 uint32 len;
2144 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
2145 sizeof(pstring) - 2, True);
2147 data->notify_data.data.length = len / 2 - 1;
2148 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2150 if (!data->notify_data.data.string) {
2151 data->notify_data.data.length = 0;
2152 return;
2155 memcpy(data->notify_data.data.string, temp, len);
2158 /*******************************************************************
2159 * fill a notify_info_data with the security descriptor
2160 * jfm:xxxx send an null pointer to say no security desc
2161 * have to implement security before !
2162 ********************************************************************/
2164 static void spoolss_notify_security_desc(int snum,
2165 SPOOL_NOTIFY_INFO_DATA *data,
2166 print_queue_struct *queue,
2167 NT_PRINTER_INFO_LEVEL *printer,
2168 TALLOC_CTX *mem_ctx)
2170 data->notify_data.data.length=0;
2171 data->notify_data.data.string = NULL;
2174 /*******************************************************************
2175 * fill a notify_info_data with the attributes
2176 * jfm:xxxx a samba printer is always shared
2177 ********************************************************************/
2179 void spoolss_notify_attributes(int snum,
2180 SPOOL_NOTIFY_INFO_DATA *data,
2181 print_queue_struct *queue,
2182 NT_PRINTER_INFO_LEVEL *printer,
2183 TALLOC_CTX *mem_ctx)
2185 data->notify_data.value[0] = printer->info_2->attributes;
2186 data->notify_data.value[1] = 0;
2189 /*******************************************************************
2190 * fill a notify_info_data with the priority
2191 ********************************************************************/
2193 static void spoolss_notify_priority(int snum,
2194 SPOOL_NOTIFY_INFO_DATA *data,
2195 print_queue_struct *queue,
2196 NT_PRINTER_INFO_LEVEL *printer,
2197 TALLOC_CTX *mem_ctx)
2199 data->notify_data.value[0] = printer->info_2->priority;
2200 data->notify_data.value[1] = 0;
2203 /*******************************************************************
2204 * fill a notify_info_data with the default priority
2205 ********************************************************************/
2207 static void spoolss_notify_default_priority(int snum,
2208 SPOOL_NOTIFY_INFO_DATA *data,
2209 print_queue_struct *queue,
2210 NT_PRINTER_INFO_LEVEL *printer,
2211 TALLOC_CTX *mem_ctx)
2213 data->notify_data.value[0] = printer->info_2->default_priority;
2214 data->notify_data.value[1] = 0;
2217 /*******************************************************************
2218 * fill a notify_info_data with the start time
2219 ********************************************************************/
2221 static void spoolss_notify_start_time(int snum,
2222 SPOOL_NOTIFY_INFO_DATA *data,
2223 print_queue_struct *queue,
2224 NT_PRINTER_INFO_LEVEL *printer,
2225 TALLOC_CTX *mem_ctx)
2227 data->notify_data.value[0] = printer->info_2->starttime;
2228 data->notify_data.value[1] = 0;
2231 /*******************************************************************
2232 * fill a notify_info_data with the until time
2233 ********************************************************************/
2235 static void spoolss_notify_until_time(int snum,
2236 SPOOL_NOTIFY_INFO_DATA *data,
2237 print_queue_struct *queue,
2238 NT_PRINTER_INFO_LEVEL *printer,
2239 TALLOC_CTX *mem_ctx)
2241 data->notify_data.value[0] = printer->info_2->untiltime;
2242 data->notify_data.value[1] = 0;
2245 /*******************************************************************
2246 * fill a notify_info_data with the status
2247 ********************************************************************/
2249 static void spoolss_notify_status(int snum,
2250 SPOOL_NOTIFY_INFO_DATA *data,
2251 print_queue_struct *queue,
2252 NT_PRINTER_INFO_LEVEL *printer,
2253 TALLOC_CTX *mem_ctx)
2255 print_status_struct status;
2257 print_queue_length(snum, &status);
2258 data->notify_data.value[0]=(uint32) status.status;
2259 data->notify_data.value[1] = 0;
2262 /*******************************************************************
2263 * fill a notify_info_data with the number of jobs queued
2264 ********************************************************************/
2266 void spoolss_notify_cjobs(int snum,
2267 SPOOL_NOTIFY_INFO_DATA *data,
2268 print_queue_struct *queue,
2269 NT_PRINTER_INFO_LEVEL *printer,
2270 TALLOC_CTX *mem_ctx)
2272 data->notify_data.value[0] = print_queue_length(snum, NULL);
2273 data->notify_data.value[1] = 0;
2276 /*******************************************************************
2277 * fill a notify_info_data with the average ppm
2278 ********************************************************************/
2280 static void spoolss_notify_average_ppm(int snum,
2281 SPOOL_NOTIFY_INFO_DATA *data,
2282 print_queue_struct *queue,
2283 NT_PRINTER_INFO_LEVEL *printer,
2284 TALLOC_CTX *mem_ctx)
2286 /* always respond 8 pages per minutes */
2287 /* a little hard ! */
2288 data->notify_data.value[0] = printer->info_2->averageppm;
2289 data->notify_data.value[1] = 0;
2292 /*******************************************************************
2293 * fill a notify_info_data with username
2294 ********************************************************************/
2296 static void spoolss_notify_username(int snum,
2297 SPOOL_NOTIFY_INFO_DATA *data,
2298 print_queue_struct *queue,
2299 NT_PRINTER_INFO_LEVEL *printer,
2300 TALLOC_CTX *mem_ctx)
2302 pstring temp;
2303 uint32 len;
2305 len = (uint32)dos_PutUniCode(temp, queue->fs_user,
2306 sizeof(temp) - 2, True);
2308 data->notify_data.data.length = len / 2 - 1;
2309 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2311 if (!data->notify_data.data.string) {
2312 data->notify_data.data.length = 0;
2313 return;
2316 memcpy(data->notify_data.data.string, temp, len);
2319 /*******************************************************************
2320 * fill a notify_info_data with job status
2321 ********************************************************************/
2323 static void spoolss_notify_job_status(int snum,
2324 SPOOL_NOTIFY_INFO_DATA *data,
2325 print_queue_struct *queue,
2326 NT_PRINTER_INFO_LEVEL *printer,
2327 TALLOC_CTX *mem_ctx)
2329 data->notify_data.value[0]=nt_printj_status(queue->status);
2330 data->notify_data.value[1] = 0;
2333 /*******************************************************************
2334 * fill a notify_info_data with job name
2335 ********************************************************************/
2337 static void spoolss_notify_job_name(int snum,
2338 SPOOL_NOTIFY_INFO_DATA *data,
2339 print_queue_struct *queue,
2340 NT_PRINTER_INFO_LEVEL *printer,
2341 TALLOC_CTX *mem_ctx)
2343 pstring temp;
2344 uint32 len;
2346 len = (uint32)dos_PutUniCode(temp, queue->fs_file, sizeof(temp) - 2,
2347 True);
2349 data->notify_data.data.length = len / 2 - 1;
2350 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2352 if (!data->notify_data.data.string) {
2353 data->notify_data.data.length = 0;
2354 return;
2357 memcpy(data->notify_data.data.string, temp, len);
2360 /*******************************************************************
2361 * fill a notify_info_data with job status
2362 ********************************************************************/
2364 static void spoolss_notify_job_status_string(int snum,
2365 SPOOL_NOTIFY_INFO_DATA *data,
2366 print_queue_struct *queue,
2367 NT_PRINTER_INFO_LEVEL *printer,
2368 TALLOC_CTX *mem_ctx)
2371 * Now we're returning job status codes we just return a "" here. JRA.
2374 const char *p = "";
2375 pstring temp;
2376 uint32 len;
2378 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2379 p = "unknown";
2381 switch (queue->status) {
2382 case LPQ_QUEUED:
2383 p = "Queued";
2384 break;
2385 case LPQ_PAUSED:
2386 p = ""; /* NT provides the paused string */
2387 break;
2388 case LPQ_SPOOLING:
2389 p = "Spooling";
2390 break;
2391 case LPQ_PRINTING:
2392 p = "Printing";
2393 break;
2395 #endif /* NO LONGER NEEDED. */
2397 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
2399 data->notify_data.data.length = len / 2 - 1;
2400 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2402 if (!data->notify_data.data.string) {
2403 data->notify_data.data.length = 0;
2404 return;
2407 memcpy(data->notify_data.data.string, temp, len);
2410 /*******************************************************************
2411 * fill a notify_info_data with job time
2412 ********************************************************************/
2414 static void spoolss_notify_job_time(int snum,
2415 SPOOL_NOTIFY_INFO_DATA *data,
2416 print_queue_struct *queue,
2417 NT_PRINTER_INFO_LEVEL *printer,
2418 TALLOC_CTX *mem_ctx)
2420 data->notify_data.value[0]=0x0;
2421 data->notify_data.value[1]=0;
2424 /*******************************************************************
2425 * fill a notify_info_data with job size
2426 ********************************************************************/
2428 static void spoolss_notify_job_size(int snum,
2429 SPOOL_NOTIFY_INFO_DATA *data,
2430 print_queue_struct *queue,
2431 NT_PRINTER_INFO_LEVEL *printer,
2432 TALLOC_CTX *mem_ctx)
2434 data->notify_data.value[0]=queue->size;
2435 data->notify_data.value[1]=0;
2438 /*******************************************************************
2439 * fill a notify_info_data with page info
2440 ********************************************************************/
2441 static void spoolss_notify_total_pages(int snum,
2442 SPOOL_NOTIFY_INFO_DATA *data,
2443 print_queue_struct *queue,
2444 NT_PRINTER_INFO_LEVEL *printer,
2445 TALLOC_CTX *mem_ctx)
2447 data->notify_data.value[0]=queue->page_count;
2448 data->notify_data.value[1]=0;
2451 /*******************************************************************
2452 * fill a notify_info_data with pages printed info.
2453 ********************************************************************/
2454 static void spoolss_notify_pages_printed(int snum,
2455 SPOOL_NOTIFY_INFO_DATA *data,
2456 print_queue_struct *queue,
2457 NT_PRINTER_INFO_LEVEL *printer,
2458 TALLOC_CTX *mem_ctx)
2460 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2461 data->notify_data.value[1]=0;
2464 /*******************************************************************
2465 Fill a notify_info_data with job position.
2466 ********************************************************************/
2468 static void spoolss_notify_job_position(int snum,
2469 SPOOL_NOTIFY_INFO_DATA *data,
2470 print_queue_struct *queue,
2471 NT_PRINTER_INFO_LEVEL *printer,
2472 TALLOC_CTX *mem_ctx)
2474 data->notify_data.value[0]=queue->job;
2475 data->notify_data.value[1]=0;
2478 /*******************************************************************
2479 Fill a notify_info_data with submitted time.
2480 ********************************************************************/
2482 static void spoolss_notify_submitted_time(int snum,
2483 SPOOL_NOTIFY_INFO_DATA *data,
2484 print_queue_struct *queue,
2485 NT_PRINTER_INFO_LEVEL *printer,
2486 TALLOC_CTX *mem_ctx)
2488 struct tm *t;
2489 uint32 len;
2490 SYSTEMTIME st;
2491 char *p;
2493 t=gmtime(&queue->time);
2495 len = sizeof(SYSTEMTIME);
2497 data->notify_data.data.length = len;
2498 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2500 if (!data->notify_data.data.string) {
2501 data->notify_data.data.length = 0;
2502 return;
2505 make_systemtime(&st, t);
2508 * Systemtime must be linearized as a set of UINT16's.
2509 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2512 p = (char *)data->notify_data.data.string;
2513 SSVAL(p, 0, st.year);
2514 SSVAL(p, 2, st.month);
2515 SSVAL(p, 4, st.dayofweek);
2516 SSVAL(p, 6, st.day);
2517 SSVAL(p, 8, st.hour);
2518 SSVAL(p, 10, st.minute);
2519 SSVAL(p, 12, st.second);
2520 SSVAL(p, 14, st.milliseconds);
2523 #define END 65535
2525 struct s_notify_info_data_table
2527 uint16 type;
2528 uint16 field;
2529 const char *name;
2530 uint32 size;
2531 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2532 print_queue_struct *queue,
2533 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2536 /* A table describing the various print notification constants and
2537 whether the notification data is a pointer to a variable sized
2538 buffer, a one value uint32 or a two value uint32. */
2540 struct s_notify_info_data_table notify_info_data_table[] =
2542 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2543 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2544 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2545 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2546 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2547 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2548 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2549 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2550 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2551 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2552 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2553 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2554 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2555 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2556 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2557 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2558 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2559 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2560 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2561 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2562 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2563 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2564 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2565 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2566 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2567 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2568 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2569 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2570 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2571 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2572 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2573 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2574 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2575 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2576 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2577 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2578 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2579 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2580 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2581 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2582 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2583 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2584 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2585 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2586 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2587 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2588 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, spoolss_notify_total_pages },
2589 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, spoolss_notify_pages_printed },
2590 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2591 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2592 { END, END, "", END, NULL }
2595 /*******************************************************************
2596 Return the size of info_data structure.
2597 ********************************************************************/
2599 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2601 int i=0;
2603 while (notify_info_data_table[i].type != END)
2605 if ( (notify_info_data_table[i].type == type ) &&
2606 (notify_info_data_table[i].field == field ) )
2608 return (notify_info_data_table[i].size);
2610 i++;
2612 return (65535);
2615 /*******************************************************************
2616 Return the type of notify_info_data.
2617 ********************************************************************/
2619 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2621 int i=0;
2623 while (notify_info_data_table[i].type != END)
2625 if ( (notify_info_data_table[i].type == type ) &&
2626 (notify_info_data_table[i].field == field ) )
2628 if (notify_info_data_table[i].size == POINTER)
2630 return (False);
2632 else
2634 return (True);
2637 i++;
2639 return (False);
2642 /****************************************************************************
2643 ****************************************************************************/
2645 static int search_notify(uint16 type, uint16 field, int *value)
2647 int j;
2648 BOOL found;
2650 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2652 if ( (notify_info_data_table[j].type == type ) &&
2653 (notify_info_data_table[j].field == field ) )
2654 found=True;
2656 *value=--j;
2658 if ( found && (notify_info_data_table[j].fn != NULL) )
2659 return True;
2660 else
2661 return False;
2664 /****************************************************************************
2665 ****************************************************************************/
2667 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2669 info_data->type = type;
2670 info_data->field = field;
2671 info_data->reserved = 0;
2672 info_data->id = id;
2673 info_data->size = size_of_notify_info_data(type, field);
2674 info_data->enc_type = type_of_notify_info_data(type, field);
2678 /*******************************************************************
2680 * fill a notify_info struct with info asked
2682 ********************************************************************/
2684 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2685 snum, SPOOL_NOTIFY_OPTION_TYPE
2686 *option_type, uint32 id,
2687 TALLOC_CTX *mem_ctx)
2689 int field_num,j;
2690 uint16 type;
2691 uint16 field;
2693 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2694 NT_PRINTER_INFO_LEVEL *printer = NULL;
2695 print_queue_struct *queue=NULL;
2697 type=option_type->type;
2699 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2700 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2701 option_type->count, lp_servicename(snum)));
2703 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2704 return False;
2706 for(field_num=0; field_num<option_type->count; field_num++) {
2707 field = option_type->fields[field_num];
2708 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2710 if (!search_notify(type, field, &j) )
2711 continue;
2713 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2714 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2715 return False;
2717 else info->data = tid;
2719 current_data=&info->data[info->count];
2721 construct_info_data(current_data, type, field, id);
2723 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2724 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2726 notify_info_data_table[j].fn(snum, current_data, queue,
2727 printer, mem_ctx);
2729 info->count++;
2732 free_a_printer(&printer, 2);
2733 return True;
2736 /*******************************************************************
2738 * fill a notify_info struct with info asked
2740 ********************************************************************/
2742 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2743 SPOOL_NOTIFY_INFO *info,
2744 NT_PRINTER_INFO_LEVEL *printer,
2745 int snum, SPOOL_NOTIFY_OPTION_TYPE
2746 *option_type, uint32 id,
2747 TALLOC_CTX *mem_ctx)
2749 int field_num,j;
2750 uint16 type;
2751 uint16 field;
2753 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2755 DEBUG(4,("construct_notify_jobs_info\n"));
2757 type = option_type->type;
2759 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2760 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2761 option_type->count));
2763 for(field_num=0; field_num<option_type->count; field_num++) {
2764 field = option_type->fields[field_num];
2766 if (!search_notify(type, field, &j) )
2767 continue;
2769 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2770 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2771 return False;
2773 else info->data = tid;
2775 current_data=&(info->data[info->count]);
2777 construct_info_data(current_data, type, field, id);
2778 notify_info_data_table[j].fn(snum, current_data, queue,
2779 printer, mem_ctx);
2780 info->count++;
2783 return True;
2787 * JFM: The enumeration is not that simple, it's even non obvious.
2789 * let's take an example: I want to monitor the PRINTER SERVER for
2790 * the printer's name and the number of jobs currently queued.
2791 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2792 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2794 * I have 3 printers on the back of my server.
2796 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2797 * structures.
2798 * Number Data Id
2799 * 1 printer 1 name 1
2800 * 2 printer 1 cjob 1
2801 * 3 printer 2 name 2
2802 * 4 printer 2 cjob 2
2803 * 5 printer 3 name 3
2804 * 6 printer 3 name 3
2806 * that's the print server case, the printer case is even worse.
2809 /*******************************************************************
2811 * enumerate all printers on the printserver
2812 * fill a notify_info struct with info asked
2814 ********************************************************************/
2816 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2817 SPOOL_NOTIFY_INFO *info,
2818 TALLOC_CTX *mem_ctx)
2820 int snum;
2821 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2822 int n_services=lp_numservices();
2823 int i;
2824 uint32 id;
2825 SPOOL_NOTIFY_OPTION *option;
2826 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2828 DEBUG(4,("printserver_notify_info\n"));
2830 if (!Printer)
2831 return WERR_BADFID;
2833 option=Printer->notify.option;
2834 id=1;
2835 info->version=2;
2836 info->data=NULL;
2837 info->count=0;
2839 for (i=0; i<option->count; i++) {
2840 option_type=&(option->ctr.type[i]);
2842 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2843 continue;
2845 for (snum=0; snum<n_services; snum++)
2846 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2847 if (construct_notify_printer_info
2848 (info, snum, option_type, id, mem_ctx))
2849 id++;
2853 * Debugging information, don't delete.
2856 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2857 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2858 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2860 for (i=0; i<info->count; i++) {
2861 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2862 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2863 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2867 return WERR_OK;
2870 /*******************************************************************
2872 * fill a notify_info struct with info asked
2874 ********************************************************************/
2876 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2877 TALLOC_CTX *mem_ctx)
2879 int snum;
2880 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2881 int i;
2882 uint32 id;
2883 SPOOL_NOTIFY_OPTION *option;
2884 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2885 int count,j;
2886 print_queue_struct *queue=NULL;
2887 print_status_struct status;
2889 DEBUG(4,("printer_notify_info\n"));
2891 if (!Printer)
2892 return WERR_BADFID;
2894 option=Printer->notify.option;
2895 id = 0x0;
2896 info->version=2;
2897 info->data=NULL;
2898 info->count=0;
2900 get_printer_snum(p, hnd, &snum);
2902 for (i=0; i<option->count; i++) {
2903 option_type=&option->ctr.type[i];
2905 switch ( option_type->type ) {
2906 case PRINTER_NOTIFY_TYPE:
2907 if(construct_notify_printer_info(info, snum,
2908 option_type, id,
2909 mem_ctx))
2910 id--;
2911 break;
2913 case JOB_NOTIFY_TYPE: {
2914 NT_PRINTER_INFO_LEVEL *printer = NULL;
2916 count = print_queue_status(snum, &queue, &status);
2918 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2919 lp_servicename(snum))))
2920 goto done;
2922 for (j=0; j<count; j++) {
2923 construct_notify_jobs_info(&queue[j], info,
2924 printer, snum,
2925 option_type,
2926 queue[j].job,
2927 mem_ctx);
2930 free_a_printer(&printer, 2);
2932 done:
2933 SAFE_FREE(queue);
2934 break;
2940 * Debugging information, don't delete.
2943 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2944 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2945 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2947 for (i=0; i<info->count; i++) {
2948 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2949 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2950 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2953 return WERR_OK;
2956 /********************************************************************
2957 * spoolss_rfnpcnex
2958 ********************************************************************/
2960 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2962 POLICY_HND *handle = &q_u->handle;
2963 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2964 SPOOL_NOTIFY_INFO *info = &r_u->info;
2966 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2967 WERROR result = WERR_BADFID;
2969 /* we always have a NOTIFY_INFO struct */
2970 r_u->info_ptr=0x1;
2972 if (!Printer) {
2973 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
2974 OUR_HANDLE(handle)));
2975 goto done;
2978 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2981 * same thing for option->flags
2982 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2983 * I don't have a global notification system, I'm sending back all the
2984 * informations even when _NOTHING_ has changed.
2987 if (Printer->notify.client_connected)
2988 Printer->notify.change = q_u->change;
2990 /* just ignore the SPOOL_NOTIFY_OPTION */
2992 switch (Printer->printer_type) {
2993 case PRINTER_HANDLE_IS_PRINTSERVER:
2994 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2995 break;
2997 case PRINTER_HANDLE_IS_PRINTER:
2998 result = printer_notify_info(p, handle, info, p->mem_ctx);
2999 break;
3002 done:
3003 return result;
3006 /********************************************************************
3007 * construct_printer_info_0
3008 * fill a printer_info_0 struct
3009 ********************************************************************/
3011 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3013 pstring chaine;
3014 int count;
3015 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3016 counter_printer_0 *session_counter;
3017 uint32 global_counter;
3018 struct tm *t;
3019 time_t setuptime;
3020 print_status_struct status;
3022 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3023 return False;
3025 count = print_queue_length(snum, &status);
3027 /* check if we already have a counter for this printer */
3028 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3030 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3031 if (session_counter->snum == snum)
3032 break;
3035 /* it's the first time, add it to the list */
3036 if (session_counter==NULL) {
3037 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3038 free_a_printer(&ntprinter, 2);
3039 return False;
3041 ZERO_STRUCTP(session_counter);
3042 session_counter->snum=snum;
3043 session_counter->counter=0;
3044 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3047 /* increment it */
3048 session_counter->counter++;
3050 /* JFM:
3051 * the global_counter should be stored in a TDB as it's common to all the clients
3052 * and should be zeroed on samba startup
3054 global_counter=session_counter->counter;
3056 pstrcpy(chaine,ntprinter->info_2->printername);
3058 init_unistr(&printer->printername, chaine);
3060 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3061 init_unistr(&printer->servername, chaine);
3063 printer->cjobs = count;
3064 printer->total_jobs = 0;
3065 printer->total_bytes = 0;
3067 setuptime = (time_t)ntprinter->info_2->setuptime;
3068 t=gmtime(&setuptime);
3070 printer->year = t->tm_year+1900;
3071 printer->month = t->tm_mon+1;
3072 printer->dayofweek = t->tm_wday;
3073 printer->day = t->tm_mday;
3074 printer->hour = t->tm_hour;
3075 printer->minute = t->tm_min;
3076 printer->second = t->tm_sec;
3077 printer->milliseconds = 0;
3079 printer->global_counter = global_counter;
3080 printer->total_pages = 0;
3081 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3082 printer->major_version = 0x0004; /* NT 4 */
3083 printer->build_version = 0x0565; /* build 1381 */
3084 #else
3085 printer->major_version = 0x0005; /* NT 5 */
3086 printer->build_version = 0x0893; /* build 2195 */
3087 #endif
3088 printer->unknown7 = 0x1;
3089 printer->unknown8 = 0x0;
3090 printer->unknown9 = 0x0;
3091 printer->session_counter = session_counter->counter;
3092 printer->unknown11 = 0x0;
3093 printer->printer_errors = 0x0; /* number of print failure */
3094 printer->unknown13 = 0x0;
3095 printer->unknown14 = 0x1;
3096 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3097 printer->unknown16 = 0x0;
3098 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3099 printer->unknown18 = 0x0;
3100 printer->status = nt_printq_status(status.status);
3101 printer->unknown20 = 0x0;
3102 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3103 printer->unknown22 = 0x0;
3104 printer->unknown23 = 0x6; /* 6 ???*/
3105 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3106 printer->unknown25 = 0;
3107 printer->unknown26 = 0;
3108 printer->unknown27 = 0;
3109 printer->unknown28 = 0;
3110 printer->unknown29 = 0;
3112 free_a_printer(&ntprinter,2);
3113 return (True);
3116 /********************************************************************
3117 * construct_printer_info_1
3118 * fill a printer_info_1 struct
3119 ********************************************************************/
3120 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3122 pstring chaine;
3123 pstring chaine2;
3124 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3126 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3127 return False;
3129 printer->flags=flags;
3131 if (*ntprinter->info_2->comment == '\0') {
3132 init_unistr(&printer->comment, lp_comment(snum));
3133 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3134 ntprinter->info_2->drivername, lp_comment(snum));
3136 else {
3137 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3138 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3139 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3142 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3144 init_unistr(&printer->description, chaine);
3145 init_unistr(&printer->name, chaine2);
3147 free_a_printer(&ntprinter,2);
3149 return True;
3152 /****************************************************************************
3153 Free a DEVMODE struct.
3154 ****************************************************************************/
3156 static void free_dev_mode(DEVICEMODE *dev)
3158 if (dev == NULL)
3159 return;
3161 SAFE_FREE(dev->private);
3162 SAFE_FREE(dev);
3165 /****************************************************************************
3166 Create a DEVMODE struct. Returns malloced memory.
3167 ****************************************************************************/
3169 static DEVICEMODE *construct_dev_mode(int snum)
3171 char adevice[32];
3172 char aform[32];
3173 NT_PRINTER_INFO_LEVEL *printer = NULL;
3174 NT_DEVICEMODE *ntdevmode = NULL;
3175 DEVICEMODE *devmode = NULL;
3177 DEBUG(7,("construct_dev_mode\n"));
3179 DEBUGADD(8,("getting printer characteristics\n"));
3181 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3182 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3183 return NULL;
3186 ZERO_STRUCTP(devmode);
3188 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3189 goto fail;
3191 if (printer->info_2->devmode)
3192 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3194 if (ntdevmode == NULL)
3195 goto fail;
3197 DEBUGADD(8,("loading DEVICEMODE\n"));
3199 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3200 init_unistr(&devmode->devicename, adevice);
3202 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3203 init_unistr(&devmode->formname, aform);
3205 devmode->specversion = ntdevmode->specversion;
3206 devmode->driverversion = ntdevmode->driverversion;
3207 devmode->size = ntdevmode->size;
3208 devmode->driverextra = ntdevmode->driverextra;
3209 devmode->fields = ntdevmode->fields;
3211 devmode->orientation = ntdevmode->orientation;
3212 devmode->papersize = ntdevmode->papersize;
3213 devmode->paperlength = ntdevmode->paperlength;
3214 devmode->paperwidth = ntdevmode->paperwidth;
3215 devmode->scale = ntdevmode->scale;
3216 devmode->copies = ntdevmode->copies;
3217 devmode->defaultsource = ntdevmode->defaultsource;
3218 devmode->printquality = ntdevmode->printquality;
3219 devmode->color = ntdevmode->color;
3220 devmode->duplex = ntdevmode->duplex;
3221 devmode->yresolution = ntdevmode->yresolution;
3222 devmode->ttoption = ntdevmode->ttoption;
3223 devmode->collate = ntdevmode->collate;
3224 devmode->icmmethod = ntdevmode->icmmethod;
3225 devmode->icmintent = ntdevmode->icmintent;
3226 devmode->mediatype = ntdevmode->mediatype;
3227 devmode->dithertype = ntdevmode->dithertype;
3229 if (ntdevmode->private != NULL) {
3230 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3231 goto fail;
3234 free_nt_devicemode(&ntdevmode);
3235 free_a_printer(&printer,2);
3237 return devmode;
3239 fail:
3241 if (ntdevmode)
3242 free_nt_devicemode(&ntdevmode);
3243 if (printer)
3244 free_a_printer(&printer,2);
3245 free_dev_mode(devmode);
3247 return NULL;
3250 /********************************************************************
3251 * construct_printer_info_2
3252 * fill a printer_info_2 struct
3253 ********************************************************************/
3255 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3257 int count;
3258 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3260 print_status_struct status;
3262 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3263 return False;
3265 count = print_queue_length(snum, &status);
3267 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3268 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3269 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3270 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3271 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3273 if (*ntprinter->info_2->comment == '\0')
3274 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3275 else
3276 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3278 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3279 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3280 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3281 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3282 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3284 printer->attributes = ntprinter->info_2->attributes;
3286 printer->priority = ntprinter->info_2->priority; /* priority */
3287 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3288 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3289 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3290 printer->status = nt_printq_status(status.status); /* status */
3291 printer->cjobs = count; /* jobs */
3292 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3294 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3295 DEBUG(8, ("Returning NULL Devicemode!\n"));
3298 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3299 /* steal the printer info sec_desc structure. [badly done]. */
3300 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3301 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3302 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3303 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3305 else {
3306 printer->secdesc = NULL;
3309 free_a_printer(&ntprinter, 2);
3310 return True;
3313 /********************************************************************
3314 * construct_printer_info_3
3315 * fill a printer_info_3 struct
3316 ********************************************************************/
3318 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3320 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3321 PRINTER_INFO_3 *printer = NULL;
3323 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3324 return False;
3326 *pp_printer = NULL;
3327 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3328 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3329 return False;
3332 ZERO_STRUCTP(printer);
3334 printer->flags = 4; /* These are the components of the SD we are returning. */
3335 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3336 /* steal the printer info sec_desc structure. [badly done]. */
3337 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3339 #if 0
3341 * Set the flags for the components we are returning.
3344 if (printer->secdesc->owner_sid)
3345 printer->flags |= OWNER_SECURITY_INFORMATION;
3347 if (printer->secdesc->grp_sid)
3348 printer->flags |= GROUP_SECURITY_INFORMATION;
3350 if (printer->secdesc->dacl)
3351 printer->flags |= DACL_SECURITY_INFORMATION;
3353 if (printer->secdesc->sacl)
3354 printer->flags |= SACL_SECURITY_INFORMATION;
3355 #endif
3357 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3358 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3359 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3362 free_a_printer(&ntprinter, 2);
3364 *pp_printer = printer;
3365 return True;
3368 /********************************************************************
3369 * construct_printer_info_4
3370 * fill a printer_info_4 struct
3371 ********************************************************************/
3373 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3375 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3377 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3378 return False;
3380 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3381 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3382 printer->attributes = ntprinter->info_2->attributes;
3384 free_a_printer(&ntprinter, 2);
3385 return True;
3388 /********************************************************************
3389 * construct_printer_info_5
3390 * fill a printer_info_5 struct
3391 ********************************************************************/
3393 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3395 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3397 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3398 return False;
3400 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3401 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3402 printer->attributes = ntprinter->info_2->attributes;
3403 printer->device_not_selected_timeout = 0x3a98;
3404 printer->transmission_retry_timeout = 0xafc8;
3406 free_a_printer(&ntprinter, 2);
3407 return True;
3410 /********************************************************************
3411 Spoolss_enumprinters.
3412 ********************************************************************/
3414 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3416 int snum;
3417 int i;
3418 int n_services=lp_numservices();
3419 PRINTER_INFO_1 *tp, *printers=NULL;
3420 PRINTER_INFO_1 current_prt;
3422 DEBUG(4,("enum_all_printers_info_1\n"));
3424 for (snum=0; snum<n_services; snum++) {
3425 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3426 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3428 if (construct_printer_info_1(flags, &current_prt, snum)) {
3429 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3430 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3431 SAFE_FREE(printers);
3432 *returned=0;
3433 return WERR_NOMEM;
3435 else printers = tp;
3436 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3438 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
3439 (*returned)++;
3444 /* check the required size. */
3445 for (i=0; i<*returned; i++)
3446 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3448 if (!alloc_buffer_size(buffer, *needed))
3449 return WERR_INSUFFICIENT_BUFFER;
3451 /* fill the buffer with the structures */
3452 for (i=0; i<*returned; i++)
3453 smb_io_printer_info_1("", buffer, &printers[i], 0);
3455 /* clear memory */
3456 SAFE_FREE(printers);
3458 if (*needed > offered) {
3459 *returned=0;
3460 return WERR_INSUFFICIENT_BUFFER;
3462 else
3463 return WERR_OK;
3466 /********************************************************************
3467 enum_all_printers_info_1_local.
3468 *********************************************************************/
3470 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3472 DEBUG(4,("enum_all_printers_info_1_local\n"));
3474 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3477 /********************************************************************
3478 enum_all_printers_info_1_name.
3479 *********************************************************************/
3481 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3483 char *s = name;
3485 DEBUG(4,("enum_all_printers_info_1_name\n"));
3487 if ((name[0] == '\\') && (name[1] == '\\'))
3488 s = name + 2;
3490 if (is_myname_or_ipaddr(s)) {
3491 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3493 else
3494 return WERR_INVALID_NAME;
3497 /********************************************************************
3498 enum_all_printers_info_1_remote.
3499 *********************************************************************/
3501 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3503 PRINTER_INFO_1 *printer;
3504 fstring printername;
3505 fstring desc;
3506 fstring comment;
3507 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3509 /* JFM: currently it's more a place holder than anything else.
3510 * In the spooler world there is a notion of server registration.
3511 * the print servers are registring (sp ?) on the PDC (in the same domain)
3513 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3516 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3517 return WERR_NOMEM;
3519 *returned=1;
3521 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3522 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3523 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3525 init_unistr(&printer->description, desc);
3526 init_unistr(&printer->name, printername);
3527 init_unistr(&printer->comment, comment);
3528 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3530 /* check the required size. */
3531 *needed += spoolss_size_printer_info_1(printer);
3533 if (!alloc_buffer_size(buffer, *needed)) {
3534 SAFE_FREE(printer);
3535 return WERR_INSUFFICIENT_BUFFER;
3538 /* fill the buffer with the structures */
3539 smb_io_printer_info_1("", buffer, printer, 0);
3541 /* clear memory */
3542 SAFE_FREE(printer);
3544 if (*needed > offered) {
3545 *returned=0;
3546 return WERR_INSUFFICIENT_BUFFER;
3548 else
3549 return WERR_OK;
3552 /********************************************************************
3553 enum_all_printers_info_1_network.
3554 *********************************************************************/
3556 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3558 char *s = name;
3560 DEBUG(4,("enum_all_printers_info_1_network\n"));
3562 /* If we respond to a enum_printers level 1 on our name with flags
3563 set to PRINTER_ENUM_REMOTE with a list of printers then these
3564 printers incorrectly appear in the APW browse list.
3565 Specifically the printers for the server appear at the workgroup
3566 level where all the other servers in the domain are
3567 listed. Windows responds to this call with a
3568 WERR_CAN_NOT_COMPLETE so we should do the same. */
3570 if (name[0] == '\\' && name[1] == '\\')
3571 s = name + 2;
3573 if (is_myname_or_ipaddr(s))
3574 return WERR_CAN_NOT_COMPLETE;
3576 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3579 /********************************************************************
3580 * api_spoolss_enumprinters
3582 * called from api_spoolss_enumprinters (see this to understand)
3583 ********************************************************************/
3585 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3587 int snum;
3588 int i;
3589 int n_services=lp_numservices();
3590 PRINTER_INFO_2 *tp, *printers=NULL;
3591 PRINTER_INFO_2 current_prt;
3593 for (snum=0; snum<n_services; snum++) {
3594 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3595 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3597 if (construct_printer_info_2(&current_prt, snum)) {
3598 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3599 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3600 SAFE_FREE(printers);
3601 *returned = 0;
3602 return WERR_NOMEM;
3604 else printers = tp;
3605 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3606 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3607 (*returned)++;
3612 /* check the required size. */
3613 for (i=0; i<*returned; i++)
3614 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3616 if (!alloc_buffer_size(buffer, *needed)) {
3617 for (i=0; i<*returned; i++) {
3618 free_devmode(printers[i].devmode);
3620 SAFE_FREE(printers);
3621 return WERR_INSUFFICIENT_BUFFER;
3624 /* fill the buffer with the structures */
3625 for (i=0; i<*returned; i++)
3626 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3628 /* clear memory */
3629 for (i=0; i<*returned; i++) {
3630 free_devmode(printers[i].devmode);
3632 SAFE_FREE(printers);
3634 if (*needed > offered) {
3635 *returned=0;
3636 return WERR_INSUFFICIENT_BUFFER;
3638 else
3639 return WERR_OK;
3642 /********************************************************************
3643 * handle enumeration of printers at level 1
3644 ********************************************************************/
3646 static WERROR enumprinters_level1( uint32 flags, fstring name,
3647 NEW_BUFFER *buffer, uint32 offered,
3648 uint32 *needed, uint32 *returned)
3650 /* Not all the flags are equals */
3652 if (flags & PRINTER_ENUM_LOCAL)
3653 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3655 if (flags & PRINTER_ENUM_NAME)
3656 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3658 if (flags & PRINTER_ENUM_REMOTE)
3659 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3661 if (flags & PRINTER_ENUM_NETWORK)
3662 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
3664 return WERR_OK; /* NT4sp5 does that */
3667 /********************************************************************
3668 * handle enumeration of printers at level 2
3669 ********************************************************************/
3671 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3672 NEW_BUFFER *buffer, uint32 offered,
3673 uint32 *needed, uint32 *returned)
3675 char *s = servername;
3677 if (flags & PRINTER_ENUM_LOCAL) {
3678 return enum_all_printers_info_2(buffer, offered, needed, returned);
3681 if (flags & PRINTER_ENUM_NAME) {
3682 if ((servername[0] == '\\') && (servername[1] == '\\'))
3683 s = servername + 2;
3684 if (is_myname_or_ipaddr(s))
3685 return enum_all_printers_info_2(buffer, offered, needed, returned);
3686 else
3687 return WERR_INVALID_NAME;
3690 if (flags & PRINTER_ENUM_REMOTE)
3691 return WERR_UNKNOWN_LEVEL;
3693 return WERR_OK;
3696 /********************************************************************
3697 * handle enumeration of printers at level 5
3698 ********************************************************************/
3700 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3701 NEW_BUFFER *buffer, uint32 offered,
3702 uint32 *needed, uint32 *returned)
3704 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3705 return WERR_OK;
3708 /********************************************************************
3709 * api_spoolss_enumprinters
3711 * called from api_spoolss_enumprinters (see this to understand)
3712 ********************************************************************/
3714 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3716 uint32 flags = q_u->flags;
3717 UNISTR2 *servername = &q_u->servername;
3718 uint32 level = q_u->level;
3719 NEW_BUFFER *buffer = NULL;
3720 uint32 offered = q_u->offered;
3721 uint32 *needed = &r_u->needed;
3722 uint32 *returned = &r_u->returned;
3724 fstring name;
3726 /* that's an [in out] buffer */
3727 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3728 buffer = r_u->buffer;
3730 DEBUG(4,("_spoolss_enumprinters\n"));
3732 *needed=0;
3733 *returned=0;
3736 * Level 1:
3737 * flags==PRINTER_ENUM_NAME
3738 * if name=="" then enumerates all printers
3739 * if name!="" then enumerate the printer
3740 * flags==PRINTER_ENUM_REMOTE
3741 * name is NULL, enumerate printers
3742 * Level 2: name!="" enumerates printers, name can't be NULL
3743 * Level 3: doesn't exist
3744 * Level 4: does a local registry lookup
3745 * Level 5: same as Level 2
3748 unistr2_to_dos(name, servername, sizeof(name)-1);
3749 strupper(name);
3751 switch (level) {
3752 case 1:
3753 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3754 case 2:
3755 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3756 case 5:
3757 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3758 case 3:
3759 case 4:
3760 break;
3762 return WERR_UNKNOWN_LEVEL;
3765 /****************************************************************************
3766 ****************************************************************************/
3768 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3770 PRINTER_INFO_0 *printer=NULL;
3772 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3773 return WERR_NOMEM;
3775 construct_printer_info_0(printer, snum);
3777 /* check the required size. */
3778 *needed += spoolss_size_printer_info_0(printer);
3780 if (!alloc_buffer_size(buffer, *needed)) {
3781 SAFE_FREE(printer);
3782 return WERR_INSUFFICIENT_BUFFER;
3785 /* fill the buffer with the structures */
3786 smb_io_printer_info_0("", buffer, printer, 0);
3788 /* clear memory */
3789 SAFE_FREE(printer);
3791 if (*needed > offered) {
3792 return WERR_INSUFFICIENT_BUFFER;
3795 return WERR_OK;
3798 /****************************************************************************
3799 ****************************************************************************/
3801 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3803 PRINTER_INFO_1 *printer=NULL;
3805 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3806 return WERR_NOMEM;
3808 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3810 /* check the required size. */
3811 *needed += spoolss_size_printer_info_1(printer);
3813 if (!alloc_buffer_size(buffer, *needed)) {
3814 SAFE_FREE(printer);
3815 return WERR_INSUFFICIENT_BUFFER;
3818 /* fill the buffer with the structures */
3819 smb_io_printer_info_1("", buffer, printer, 0);
3821 /* clear memory */
3822 SAFE_FREE(printer);
3824 if (*needed > offered) {
3825 return WERR_INSUFFICIENT_BUFFER;
3828 return WERR_OK;
3831 /****************************************************************************
3832 ****************************************************************************/
3834 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3836 PRINTER_INFO_2 *printer=NULL;
3838 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3839 return WERR_NOMEM;
3841 construct_printer_info_2(printer, snum);
3843 /* check the required size. */
3844 *needed += spoolss_size_printer_info_2(printer);
3846 if (!alloc_buffer_size(buffer, *needed)) {
3847 free_printer_info_2(printer);
3848 return WERR_INSUFFICIENT_BUFFER;
3851 /* fill the buffer with the structures */
3852 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3853 free_printer_info_2(printer);
3854 return WERR_NOMEM;
3857 /* clear memory */
3858 free_printer_info_2(printer);
3860 if (*needed > offered) {
3861 return WERR_INSUFFICIENT_BUFFER;
3864 return WERR_OK;
3867 /****************************************************************************
3868 ****************************************************************************/
3870 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3872 PRINTER_INFO_3 *printer=NULL;
3874 if (!construct_printer_info_3(&printer, snum))
3875 return WERR_NOMEM;
3877 /* check the required size. */
3878 *needed += spoolss_size_printer_info_3(printer);
3880 if (!alloc_buffer_size(buffer, *needed)) {
3881 free_printer_info_3(printer);
3882 return WERR_INSUFFICIENT_BUFFER;
3885 /* fill the buffer with the structures */
3886 smb_io_printer_info_3("", buffer, printer, 0);
3888 /* clear memory */
3889 free_printer_info_3(printer);
3891 if (*needed > offered) {
3892 return WERR_INSUFFICIENT_BUFFER;
3895 return WERR_OK;
3898 /****************************************************************************
3899 ****************************************************************************/
3901 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3903 PRINTER_INFO_4 *printer=NULL;
3905 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3906 return WERR_NOMEM;
3908 if (!construct_printer_info_4(printer, snum))
3909 return WERR_NOMEM;
3911 /* check the required size. */
3912 *needed += spoolss_size_printer_info_4(printer);
3914 if (!alloc_buffer_size(buffer, *needed)) {
3915 free_printer_info_4(printer);
3916 return WERR_INSUFFICIENT_BUFFER;
3919 /* fill the buffer with the structures */
3920 smb_io_printer_info_4("", buffer, printer, 0);
3922 /* clear memory */
3923 free_printer_info_4(printer);
3925 if (*needed > offered) {
3926 return WERR_INSUFFICIENT_BUFFER;
3929 return WERR_OK;
3932 /****************************************************************************
3933 ****************************************************************************/
3935 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3937 PRINTER_INFO_5 *printer=NULL;
3939 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3940 return WERR_NOMEM;
3942 if (!construct_printer_info_5(printer, snum))
3943 return WERR_NOMEM;
3945 /* check the required size. */
3946 *needed += spoolss_size_printer_info_5(printer);
3948 if (!alloc_buffer_size(buffer, *needed)) {
3949 free_printer_info_5(printer);
3950 return WERR_INSUFFICIENT_BUFFER;
3953 /* fill the buffer with the structures */
3954 smb_io_printer_info_5("", buffer, printer, 0);
3956 /* clear memory */
3957 free_printer_info_5(printer);
3959 if (*needed > offered) {
3960 return WERR_INSUFFICIENT_BUFFER;
3963 return WERR_OK;
3966 /****************************************************************************
3967 ****************************************************************************/
3969 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3971 POLICY_HND *handle = &q_u->handle;
3972 uint32 level = q_u->level;
3973 NEW_BUFFER *buffer = NULL;
3974 uint32 offered = q_u->offered;
3975 uint32 *needed = &r_u->needed;
3977 int snum;
3979 /* that's an [in out] buffer */
3980 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3981 buffer = r_u->buffer;
3983 *needed=0;
3985 if (!get_printer_snum(p, handle, &snum))
3986 return WERR_BADFID;
3988 switch (level) {
3989 case 0:
3990 return getprinter_level_0(snum, buffer, offered, needed);
3991 case 1:
3992 return getprinter_level_1(snum, buffer, offered, needed);
3993 case 2:
3994 return getprinter_level_2(snum, buffer, offered, needed);
3995 case 3:
3996 return getprinter_level_3(snum, buffer, offered, needed);
3997 case 4:
3998 return getprinter_level_4(snum, buffer, offered, needed);
3999 case 5:
4000 return getprinter_level_5(snum, buffer, offered, needed);
4002 return WERR_UNKNOWN_LEVEL;
4005 /********************************************************************
4006 * fill a DRIVER_INFO_1 struct
4007 ********************************************************************/
4009 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4011 init_unistr( &info->name, driver.info_3->name);
4014 /********************************************************************
4015 * construct_printer_driver_info_1
4016 ********************************************************************/
4018 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4020 NT_PRINTER_INFO_LEVEL *printer = NULL;
4021 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4023 ZERO_STRUCT(driver);
4025 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4026 return WERR_INVALID_PRINTER_NAME;
4028 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4029 return WERR_UNKNOWN_PRINTER_DRIVER;
4031 fill_printer_driver_info_1(info, driver, servername, architecture);
4033 free_a_printer(&printer,2);
4035 return WERR_OK;
4038 /********************************************************************
4039 * construct_printer_driver_info_2
4040 * fill a printer_info_2 struct
4041 ********************************************************************/
4043 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4045 pstring temp;
4047 info->version=driver.info_3->cversion;
4049 init_unistr( &info->name, driver.info_3->name );
4050 init_unistr( &info->architecture, driver.info_3->environment );
4053 if (strlen(driver.info_3->driverpath)) {
4054 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4055 init_unistr( &info->driverpath, temp );
4056 } else
4057 init_unistr( &info->driverpath, "" );
4059 if (strlen(driver.info_3->datafile)) {
4060 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4061 init_unistr( &info->datafile, temp );
4062 } else
4063 init_unistr( &info->datafile, "" );
4065 if (strlen(driver.info_3->configfile)) {
4066 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4067 init_unistr( &info->configfile, temp );
4068 } else
4069 init_unistr( &info->configfile, "" );
4072 /********************************************************************
4073 * construct_printer_driver_info_2
4074 * fill a printer_info_2 struct
4075 ********************************************************************/
4077 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4079 NT_PRINTER_INFO_LEVEL *printer = NULL;
4080 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4082 ZERO_STRUCT(printer);
4083 ZERO_STRUCT(driver);
4085 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4086 return WERR_INVALID_PRINTER_NAME;
4088 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4089 return WERR_UNKNOWN_PRINTER_DRIVER;
4091 fill_printer_driver_info_2(info, driver, servername);
4093 free_a_printer(&printer,2);
4095 return WERR_OK;
4098 /********************************************************************
4099 * copy a strings array and convert to UNICODE
4101 * convert an array of ascii string to a UNICODE string
4102 ********************************************************************/
4104 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4106 int i=0;
4107 int j=0;
4108 const char *v;
4109 pstring line;
4110 uint16 *tuary;
4112 DEBUG(6,("init_unistr_array\n"));
4113 *uni_array=NULL;
4115 while (1) {
4116 if (char_array == NULL)
4117 v = "";
4118 else {
4119 v = char_array[i];
4120 if (!v) v = ""; /* hack to handle null lists */
4122 if (strlen(v) == 0) break;
4123 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
4124 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4125 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
4126 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4127 return;
4128 } else
4129 *uni_array = tuary;
4130 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
4131 i++;
4134 if (*uni_array) {
4135 (*uni_array)[j]=0x0000;
4138 DEBUGADD(6,("last one:done\n"));
4141 /********************************************************************
4142 * construct_printer_info_3
4143 * fill a printer_info_3 struct
4144 ********************************************************************/
4146 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4148 pstring temp;
4150 ZERO_STRUCTP(info);
4152 info->version=driver.info_3->cversion;
4154 init_unistr( &info->name, driver.info_3->name );
4155 init_unistr( &info->architecture, driver.info_3->environment );
4157 if (strlen(driver.info_3->driverpath)) {
4158 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4159 init_unistr( &info->driverpath, temp );
4160 } else
4161 init_unistr( &info->driverpath, "" );
4163 if (strlen(driver.info_3->datafile)) {
4164 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4165 init_unistr( &info->datafile, temp );
4166 } else
4167 init_unistr( &info->datafile, "" );
4169 if (strlen(driver.info_3->configfile)) {
4170 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4171 init_unistr( &info->configfile, temp );
4172 } else
4173 init_unistr( &info->configfile, "" );
4175 if (strlen(driver.info_3->helpfile)) {
4176 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4177 init_unistr( &info->helpfile, temp );
4178 } else
4179 init_unistr( &info->helpfile, "" );
4181 init_unistr( &info->monitorname, driver.info_3->monitorname );
4182 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4184 info->dependentfiles=NULL;
4185 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4188 /********************************************************************
4189 * construct_printer_info_3
4190 * fill a printer_info_3 struct
4191 ********************************************************************/
4193 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4195 NT_PRINTER_INFO_LEVEL *printer = NULL;
4196 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4197 WERROR status;
4198 ZERO_STRUCT(driver);
4200 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4201 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4202 if (!W_ERROR_IS_OK(status))
4203 return WERR_INVALID_PRINTER_NAME;
4205 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4206 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4208 #if 0 /* JERRY */
4211 * I put this code in during testing. Helpful when commenting out the
4212 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4213 * as win2k always queries the driver using an infor level of 6.
4214 * I've left it in (but ifdef'd out) because I'll probably
4215 * use it in experimentation again in the future. --jerry 22/01/2002
4218 if (!W_ERROR_IS_OK(status)) {
4220 * Is this a W2k client ?
4222 if (version == 3) {
4223 /* Yes - try again with a WinNT driver. */
4224 version = 2;
4225 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4226 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4228 #endif
4230 if (!W_ERROR_IS_OK(status)) {
4231 free_a_printer(&printer,2);
4232 return WERR_UNKNOWN_PRINTER_DRIVER;
4235 #if 0 /* JERRY */
4237 #endif
4240 fill_printer_driver_info_3(info, driver, servername);
4242 free_a_printer(&printer,2);
4244 return WERR_OK;
4247 /********************************************************************
4248 * construct_printer_info_6
4249 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4250 ********************************************************************/
4252 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4254 pstring temp;
4255 fstring nullstr;
4257 ZERO_STRUCTP(info);
4258 memset(&nullstr, '\0', sizeof(fstring));
4260 info->version=driver.info_3->cversion;
4262 init_unistr( &info->name, driver.info_3->name );
4263 init_unistr( &info->architecture, driver.info_3->environment );
4265 if (strlen(driver.info_3->driverpath)) {
4266 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4267 init_unistr( &info->driverpath, temp );
4268 } else
4269 init_unistr( &info->driverpath, "" );
4271 if (strlen(driver.info_3->datafile)) {
4272 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4273 init_unistr( &info->datafile, temp );
4274 } else
4275 init_unistr( &info->datafile, "" );
4277 if (strlen(driver.info_3->configfile)) {
4278 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4279 init_unistr( &info->configfile, temp );
4280 } else
4281 init_unistr( &info->configfile, "" );
4283 if (strlen(driver.info_3->helpfile)) {
4284 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4285 init_unistr( &info->helpfile, temp );
4286 } else
4287 init_unistr( &info->helpfile, "" );
4289 init_unistr( &info->monitorname, driver.info_3->monitorname );
4290 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4292 info->dependentfiles=NULL;
4293 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4295 info->previousdrivernames=NULL;
4296 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4298 info->driver_date.low=0;
4299 info->driver_date.high=0;
4301 info->padding=0;
4302 info->driver_version_low=0;
4303 info->driver_version_high=0;
4305 init_unistr( &info->mfgname, "");
4306 init_unistr( &info->oem_url, "");
4307 init_unistr( &info->hardware_id, "");
4308 init_unistr( &info->provider, "");
4311 /********************************************************************
4312 * construct_printer_info_6
4313 * fill a printer_info_6 struct
4314 ********************************************************************/
4316 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4318 NT_PRINTER_INFO_LEVEL *printer = NULL;
4319 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4320 WERROR status;
4321 ZERO_STRUCT(driver);
4323 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4324 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4325 if (!W_ERROR_IS_OK(status))
4326 return WERR_INVALID_PRINTER_NAME;
4328 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4329 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4330 if (!W_ERROR_IS_OK(status)) {
4332 * Is this a W2k client ?
4335 if (version < 3) {
4336 free_a_printer(&printer,2);
4337 return WERR_UNKNOWN_PRINTER_DRIVER;
4340 /* Yes - try again with a WinNT driver. */
4341 version = 2;
4342 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4343 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4344 if (!W_ERROR_IS_OK(status)) {
4345 free_a_printer(&printer,2);
4346 return WERR_UNKNOWN_PRINTER_DRIVER;
4350 fill_printer_driver_info_6(info, driver, servername);
4352 free_a_printer(&printer,2);
4354 return WERR_OK;
4357 /****************************************************************************
4358 ****************************************************************************/
4360 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4362 SAFE_FREE(info->dependentfiles);
4365 /****************************************************************************
4366 ****************************************************************************/
4368 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4370 SAFE_FREE(info->dependentfiles);
4374 /****************************************************************************
4375 ****************************************************************************/
4377 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4379 DRIVER_INFO_1 *info=NULL;
4380 WERROR status;
4382 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4383 return WERR_NOMEM;
4385 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4386 if (!W_ERROR_IS_OK(status)) {
4387 SAFE_FREE(info);
4388 return status;
4391 /* check the required size. */
4392 *needed += spoolss_size_printer_driver_info_1(info);
4394 if (!alloc_buffer_size(buffer, *needed)) {
4395 SAFE_FREE(info);
4396 return WERR_INSUFFICIENT_BUFFER;
4399 /* fill the buffer with the structures */
4400 smb_io_printer_driver_info_1("", buffer, info, 0);
4402 /* clear memory */
4403 SAFE_FREE(info);
4405 if (*needed > offered)
4406 return WERR_INSUFFICIENT_BUFFER;
4408 return WERR_OK;
4411 /****************************************************************************
4412 ****************************************************************************/
4414 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4416 DRIVER_INFO_2 *info=NULL;
4417 WERROR status;
4419 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4420 return WERR_NOMEM;
4422 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4423 if (!W_ERROR_IS_OK(status)) {
4424 SAFE_FREE(info);
4425 return status;
4428 /* check the required size. */
4429 *needed += spoolss_size_printer_driver_info_2(info);
4431 if (!alloc_buffer_size(buffer, *needed)) {
4432 SAFE_FREE(info);
4433 return WERR_INSUFFICIENT_BUFFER;
4436 /* fill the buffer with the structures */
4437 smb_io_printer_driver_info_2("", buffer, info, 0);
4439 /* clear memory */
4440 SAFE_FREE(info);
4442 if (*needed > offered)
4443 return WERR_INSUFFICIENT_BUFFER;
4445 return WERR_OK;
4448 /****************************************************************************
4449 ****************************************************************************/
4451 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4453 DRIVER_INFO_3 info;
4454 WERROR status;
4456 ZERO_STRUCT(info);
4458 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4459 if (!W_ERROR_IS_OK(status)) {
4460 return status;
4463 /* check the required size. */
4464 *needed += spoolss_size_printer_driver_info_3(&info);
4466 if (!alloc_buffer_size(buffer, *needed)) {
4467 free_printer_driver_info_3(&info);
4468 return WERR_INSUFFICIENT_BUFFER;
4471 /* fill the buffer with the structures */
4472 smb_io_printer_driver_info_3("", buffer, &info, 0);
4474 free_printer_driver_info_3(&info);
4476 if (*needed > offered)
4477 return WERR_INSUFFICIENT_BUFFER;
4479 return WERR_OK;
4482 /****************************************************************************
4483 ****************************************************************************/
4485 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4487 DRIVER_INFO_6 info;
4488 WERROR status;
4490 ZERO_STRUCT(info);
4492 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4493 if (!W_ERROR_IS_OK(status)) {
4494 return status;
4497 /* check the required size. */
4498 *needed += spoolss_size_printer_driver_info_6(&info);
4500 if (!alloc_buffer_size(buffer, *needed)) {
4501 free_printer_driver_info_6(&info);
4502 return WERR_INSUFFICIENT_BUFFER;
4505 /* fill the buffer with the structures */
4506 smb_io_printer_driver_info_6("", buffer, &info, 0);
4508 free_printer_driver_info_6(&info);
4510 if (*needed > offered)
4511 return WERR_INSUFFICIENT_BUFFER;
4513 return WERR_OK;
4516 /****************************************************************************
4517 ****************************************************************************/
4519 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4521 POLICY_HND *handle = &q_u->handle;
4522 UNISTR2 *uni_arch = &q_u->architecture;
4523 uint32 level = q_u->level;
4524 uint32 clientmajorversion = q_u->clientmajorversion;
4525 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4526 NEW_BUFFER *buffer = NULL;
4527 uint32 offered = q_u->offered;
4528 uint32 *needed = &r_u->needed;
4529 uint32 *servermajorversion = &r_u->servermajorversion;
4530 uint32 *serverminorversion = &r_u->serverminorversion;
4532 fstring servername;
4533 fstring architecture;
4534 int snum;
4536 /* that's an [in out] buffer */
4537 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4538 buffer = r_u->buffer;
4540 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4542 *needed=0;
4543 *servermajorversion=0;
4544 *serverminorversion=0;
4546 pstrcpy(servername, get_called_name());
4547 unistr2_to_dos(architecture, uni_arch, sizeof(architecture)-1);
4549 if (!get_printer_snum(p, handle, &snum))
4550 return WERR_BADFID;
4552 switch (level) {
4553 case 1:
4554 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4555 case 2:
4556 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4557 case 3:
4558 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4559 case 6:
4560 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4563 return WERR_UNKNOWN_LEVEL;
4566 /****************************************************************************
4567 ****************************************************************************/
4569 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4571 POLICY_HND *handle = &q_u->handle;
4573 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4575 if (!Printer) {
4576 DEBUG(3,("Error in startpageprinter printer handle\n"));
4577 return WERR_BADFID;
4580 Printer->page_started=True;
4581 return WERR_OK;
4584 /****************************************************************************
4585 ****************************************************************************/
4587 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4589 POLICY_HND *handle = &q_u->handle;
4591 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4593 if (!Printer) {
4594 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4595 return WERR_BADFID;
4598 Printer->page_started=False;
4599 print_job_endpage(Printer->jobid);
4601 return WERR_OK;
4604 /********************************************************************
4605 * api_spoolss_getprinter
4606 * called from the spoolss dispatcher
4608 ********************************************************************/
4610 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4612 POLICY_HND *handle = &q_u->handle;
4613 /* uint32 level = q_u->doc_info_container.level; - notused. */
4614 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4615 uint32 *jobid = &r_u->jobid;
4617 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4618 int snum;
4619 pstring jobname;
4620 fstring datatype;
4621 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4622 struct current_user user;
4624 if (!Printer) {
4625 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4626 return WERR_BADFID;
4629 get_current_user(&user, p);
4632 * a nice thing with NT is it doesn't listen to what you tell it.
4633 * when asked to send _only_ RAW datas, it tries to send datas
4634 * in EMF format.
4636 * So I add checks like in NT Server ...
4638 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4639 * there's a bug in NT client-side code, so we'll fix it in the
4640 * server-side code. *nnnnnggggh!*
4643 if (info_1->p_datatype != 0) {
4644 unistr2_to_dos(datatype, &info_1->datatype, sizeof(datatype));
4645 if (strcmp(datatype, "RAW") != 0) {
4646 (*jobid)=0;
4647 return WERR_INVALID_DATATYPE;
4651 /* get the share number of the printer */
4652 if (!get_printer_snum(p, handle, &snum)) {
4653 return WERR_BADFID;
4656 unistr2_to_dos(jobname, &info_1->docname, sizeof(jobname));
4658 Printer->jobid = print_job_start(&user, snum, jobname);
4660 /* An error occured in print_job_start() so return an appropriate
4661 NT error code. */
4663 if (Printer->jobid == -1) {
4664 return map_werror_from_unix(errno);
4667 Printer->document_started=True;
4668 (*jobid) = Printer->jobid;
4670 return WERR_OK;
4673 /********************************************************************
4674 * api_spoolss_getprinter
4675 * called from the spoolss dispatcher
4677 ********************************************************************/
4679 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4681 POLICY_HND *handle = &q_u->handle;
4683 return _spoolss_enddocprinter_internal(p, handle);
4686 /****************************************************************************
4687 ****************************************************************************/
4689 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4691 POLICY_HND *handle = &q_u->handle;
4692 uint32 buffer_size = q_u->buffer_size;
4693 uint8 *buffer = q_u->buffer;
4694 uint32 *buffer_written = &q_u->buffer_size2;
4696 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4698 if (!Printer) {
4699 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4700 r_u->buffer_written = q_u->buffer_size2;
4701 return WERR_BADFID;
4704 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4707 r_u->buffer_written = q_u->buffer_size2;
4709 return WERR_OK;
4712 /********************************************************************
4713 * api_spoolss_getprinter
4714 * called from the spoolss dispatcher
4716 ********************************************************************/
4718 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4719 pipes_struct *p)
4721 struct current_user user;
4722 int snum;
4723 WERROR errcode = WERR_BADFUNC;
4724 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4726 get_current_user(&user, p);
4728 if (!Printer) {
4729 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4730 return WERR_BADFID;
4733 if (!get_printer_snum(p, handle, &snum))
4734 return WERR_BADFID;
4736 switch (command) {
4737 case PRINTER_CONTROL_PAUSE:
4738 if (print_queue_pause(&user, snum, &errcode)) {
4739 errcode = WERR_OK;
4741 break;
4742 case PRINTER_CONTROL_RESUME:
4743 case PRINTER_CONTROL_UNPAUSE:
4744 if (print_queue_resume(&user, snum, &errcode)) {
4745 errcode = WERR_OK;
4747 break;
4748 case PRINTER_CONTROL_PURGE:
4749 if (print_queue_purge(&user, snum, &errcode)) {
4750 errcode = WERR_OK;
4752 break;
4753 default:
4754 return WERR_UNKNOWN_LEVEL;
4757 return errcode;
4760 /********************************************************************
4761 * api_spoolss_abortprinter
4762 ********************************************************************/
4764 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4766 POLICY_HND *handle = &q_u->handle;
4768 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4771 /********************************************************************
4772 * called by spoolss_api_setprinter
4773 * when updating a printer description
4774 ********************************************************************/
4776 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4777 const SPOOL_PRINTER_INFO_LEVEL *info,
4778 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4780 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4781 struct current_user user;
4782 WERROR result;
4783 int snum;
4785 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4787 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4788 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4789 OUR_HANDLE(handle)));
4791 result = WERR_BADFID;
4792 goto done;
4795 /* NT seems to like setting the security descriptor even though
4796 nothing may have actually changed. This causes annoying
4797 dialog boxes when the user doesn't have permission to change
4798 the security descriptor. */
4800 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4802 if (DEBUGLEVEL >= 10) {
4803 SEC_ACL *the_acl;
4804 int i;
4806 the_acl = old_secdesc_ctr->sec->dacl;
4807 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4808 PRINTERNAME(snum), the_acl->num_aces));
4810 for (i = 0; i < the_acl->num_aces; i++) {
4811 fstring sid_str;
4813 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4815 DEBUG(10, ("%s 0x%08x\n", sid_str,
4816 the_acl->ace[i].info.mask));
4819 the_acl = secdesc_ctr->sec->dacl;
4821 if (the_acl) {
4822 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4823 PRINTERNAME(snum), the_acl->num_aces));
4825 for (i = 0; i < the_acl->num_aces; i++) {
4826 fstring sid_str;
4828 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4830 DEBUG(10, ("%s 0x%08x\n", sid_str,
4831 the_acl->ace[i].info.mask));
4833 } else {
4834 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4838 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4840 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4841 result = WERR_OK;
4842 goto done;
4845 /* Work out which user is performing the operation */
4847 get_current_user(&user, p);
4849 /* Check the user has permissions to change the security
4850 descriptor. By experimentation with two NT machines, the user
4851 requires Full Access to the printer to change security
4852 information. */
4854 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4855 result = WERR_ACCESS_DENIED;
4856 goto done;
4859 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4861 done:
4863 return result;
4866 /********************************************************************
4867 Do Samba sanity checks on a printer info struct.
4868 this has changed purpose: it now "canonicalises" printer
4869 info from a client rather than just checking it is correct
4870 ********************************************************************/
4872 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4874 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4875 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4877 /* we force some elements to "correct" values */
4878 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4879 fstrcpy(info->sharename, lp_servicename(snum));
4880 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4881 get_called_name(), info->sharename);
4882 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
4884 return True;
4887 /****************************************************************************
4888 ****************************************************************************/
4890 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4892 char *cmd = lp_addprinter_cmd();
4893 char **qlines;
4894 pstring command;
4895 pstring driverlocation;
4896 int numlines;
4897 int ret;
4898 int fd;
4899 fstring remote_machine = "%m";
4901 /* build driver path... only 9X architecture is needed for legacy reasons */
4902 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4903 get_called_name());
4904 /* change \ to \\ for the shell */
4905 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4906 standard_sub_basic(remote_machine,sizeof(remote_machine));
4908 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4909 cmd, printer->info_2->printername, printer->info_2->sharename,
4910 printer->info_2->portname, printer->info_2->drivername,
4911 printer->info_2->location, driverlocation, remote_machine);
4913 /* Convert script args to unix-codepage */
4914 dos_to_unix(command);
4915 DEBUG(10,("Running [%s]\n", command));
4916 ret = smbrun(command, &fd);
4917 DEBUGADD(10,("returned [%d]\n", ret));
4919 if ( ret != 0 ) {
4920 if (fd != -1)
4921 close(fd);
4922 return False;
4925 numlines = 0;
4926 /* Get lines and convert them back to dos-codepage */
4927 qlines = fd_lines_load(fd, &numlines, True);
4928 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4929 close(fd);
4931 if(numlines) {
4932 /* Set the portname to what the script says the portname should be. */
4933 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4934 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4936 /* Send SIGHUP to process group... is there a better way? */
4937 kill(0, SIGHUP);
4939 /* reload our services immediately */
4940 reload_services( False );
4943 file_lines_free(qlines);
4944 return True;
4947 #if 0 /* JERRY */
4949 /* Return true if two devicemodes are equal */
4951 #define DEVMODE_CHECK_INT(field) \
4952 if (d1->field != d2->field) { \
4953 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4954 d1->field, d2->field)); \
4955 return False; \
4958 /************************************************************************
4959 Handy, but currently unused functions
4960 ***********************************************************************/
4962 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4964 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4966 if (!d1 ^ !d2) {
4967 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4968 return False; /* if either is exclusively NULL are not equal */
4971 if (!strequal(d1->devicename, d2->devicename)) {
4972 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4973 return False;
4976 if (!strequal(d1->formname, d2->formname)) {
4977 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4978 return False;
4981 DEVMODE_CHECK_INT(specversion);
4982 DEVMODE_CHECK_INT(driverversion);
4983 DEVMODE_CHECK_INT(driverextra);
4984 DEVMODE_CHECK_INT(orientation);
4985 DEVMODE_CHECK_INT(papersize);
4986 DEVMODE_CHECK_INT(paperlength);
4987 DEVMODE_CHECK_INT(paperwidth);
4988 DEVMODE_CHECK_INT(scale);
4989 DEVMODE_CHECK_INT(copies);
4990 DEVMODE_CHECK_INT(defaultsource);
4991 DEVMODE_CHECK_INT(printquality);
4992 DEVMODE_CHECK_INT(color);
4993 DEVMODE_CHECK_INT(duplex);
4994 DEVMODE_CHECK_INT(yresolution);
4995 DEVMODE_CHECK_INT(ttoption);
4996 DEVMODE_CHECK_INT(collate);
4997 DEVMODE_CHECK_INT(logpixels);
4999 DEVMODE_CHECK_INT(fields);
5000 DEVMODE_CHECK_INT(bitsperpel);
5001 DEVMODE_CHECK_INT(pelswidth);
5002 DEVMODE_CHECK_INT(pelsheight);
5003 DEVMODE_CHECK_INT(displayflags);
5004 DEVMODE_CHECK_INT(displayfrequency);
5005 DEVMODE_CHECK_INT(icmmethod);
5006 DEVMODE_CHECK_INT(icmintent);
5007 DEVMODE_CHECK_INT(mediatype);
5008 DEVMODE_CHECK_INT(dithertype);
5009 DEVMODE_CHECK_INT(reserved1);
5010 DEVMODE_CHECK_INT(reserved2);
5011 DEVMODE_CHECK_INT(panningwidth);
5012 DEVMODE_CHECK_INT(panningheight);
5014 /* compare the private data if it exists */
5015 if (!d1->driverextra && !d2->driverextra) goto equal;
5018 DEVMODE_CHECK_INT(driverextra);
5020 if (memcmp(d1->private, d2->private, d1->driverextra)) {
5021 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
5022 return False;
5025 equal:
5026 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
5027 return True;
5030 /* Return true if two NT_PRINTER_PARAM structures are equal */
5032 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
5033 NT_PRINTER_PARAM *p2)
5035 if (!p1 && !p2) goto equal;
5037 if ((!p1 && p2) || (p1 && !p2)) {
5038 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
5039 return False;
5042 /* Compare lists of printer parameters */
5044 while (p1) {
5045 BOOL found = False;
5046 NT_PRINTER_PARAM *q = p1;
5048 /* Find the parameter in the second structure */
5050 while(q) {
5052 if (strequal(p1->value, q->value)) {
5054 if (p1->type != q->type) {
5055 DEBUG(10, ("nt_printer_param_equal():"
5056 "types for %s differ (%d != %d)\n",
5057 p1->value, p1->type,
5058 q->type));
5059 break;
5062 if (p1->data_len != q->data_len) {
5063 DEBUG(10, ("nt_printer_param_equal():"
5064 "len for %s differs (%d != %d)\n",
5065 p1->value, p1->data_len,
5066 q->data_len));
5067 break;
5070 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
5071 found = True;
5072 } else {
5073 DEBUG(10, ("nt_printer_param_equal():"
5074 "data for %s differs\n", p1->value));
5077 break;
5080 q = q->next;
5083 if (!found) {
5084 DEBUG(10, ("nt_printer_param_equal(): param %s "
5085 "does not exist\n", p1->value));
5086 return False;
5089 p1 = p1->next;
5092 equal:
5094 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
5095 return True;
5098 /********************************************************************
5099 * Called by update_printer when trying to work out whether to
5100 * actually update printer info.
5101 ********************************************************************/
5103 #define PI_CHECK_INT(field) \
5104 if (pi1->field != pi2->field) { \
5105 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
5106 pi1->field, pi2->field)); \
5107 return False; \
5110 #define PI_CHECK_STR(field) \
5111 if (!strequal(pi1->field, pi2->field)) { \
5112 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
5113 pi1->field, pi2->field)); \
5114 return False; \
5117 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
5118 NT_PRINTER_INFO_LEVEL *p2)
5120 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
5122 /* Trivial conditions */
5124 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
5125 goto equal;
5128 if ((!p1 && p2) || (p1 && !p2) ||
5129 (!p1->info_2 && p2->info_2) ||
5130 (p1->info_2 && !p2->info_2)) {
5131 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
5132 "differ\n"));
5133 return False;
5136 /* Compare two nt_printer_info_level structures. Don't compare
5137 status or cjobs as they seem to have something to do with the
5138 printer queue. */
5140 pi1 = p1->info_2;
5141 pi2 = p2->info_2;
5143 /* Don't check the attributes as we stomp on the value in
5144 check_printer_ok() anyway. */
5146 #if 0
5147 PI_CHECK_INT(attributes);
5148 #endif
5150 PI_CHECK_INT(priority);
5151 PI_CHECK_INT(default_priority);
5152 PI_CHECK_INT(starttime);
5153 PI_CHECK_INT(untiltime);
5154 PI_CHECK_INT(averageppm);
5156 /* Yuck - don't check the printername or servername as the
5157 mod_a_printer() code plays games with them. You can't
5158 change the printername or the sharename through this interface
5159 in Samba. */
5161 PI_CHECK_STR(sharename);
5162 PI_CHECK_STR(portname);
5163 PI_CHECK_STR(drivername);
5164 PI_CHECK_STR(comment);
5165 PI_CHECK_STR(location);
5167 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
5168 return False;
5171 PI_CHECK_STR(sepfile);
5172 PI_CHECK_STR(printprocessor);
5173 PI_CHECK_STR(datatype);
5174 PI_CHECK_STR(parameters);
5176 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
5177 return False;
5180 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
5181 return False;
5184 PI_CHECK_INT(changeid);
5185 PI_CHECK_INT(c_setprinter);
5186 PI_CHECK_INT(setuptime);
5188 equal:
5189 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5190 return True;
5193 #endif
5195 /********************************************************************
5196 * Called by spoolss_api_setprinter
5197 * when updating a printer description.
5198 ********************************************************************/
5200 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5201 const SPOOL_PRINTER_INFO_LEVEL *info,
5202 DEVICEMODE *devmode)
5204 int snum;
5205 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5206 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5207 PRINTER_MESSAGE_INFO msg;
5208 WERROR result;
5210 DEBUG(8,("update_printer\n"));
5212 ZERO_STRUCT(msg);
5214 result = WERR_OK;
5216 if (level!=2) {
5217 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5218 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5219 result = WERR_UNKNOWN_LEVEL;
5220 goto done;
5223 if (!Printer) {
5224 result = WERR_BADFID;
5225 goto done;
5228 if (!get_printer_snum(p, handle, &snum)) {
5229 result = WERR_BADFID;
5230 goto done;
5233 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5234 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5235 result = WERR_BADFID;
5236 goto done;
5239 DEBUGADD(8,("Converting info_2 struct\n"));
5242 * convert_printer_info converts the incoming
5243 * info from the client and overwrites the info
5244 * just read from the tdb in the pointer 'printer'.
5247 if (!convert_printer_info(info, printer, level)) {
5248 result = WERR_NOMEM;
5249 goto done;
5252 if (devmode) {
5253 /* we have a valid devmode
5254 convert it and link it*/
5256 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5257 if (!convert_devicemode(printer->info_2->printername, devmode,
5258 &printer->info_2->devmode)) {
5259 result = WERR_NOMEM;
5260 goto done;
5264 * make sure we actually reload the services after
5265 * this as smb.conf could have a new section in it
5266 * .... shouldn't .... but could
5268 reload_services(False);
5271 /* Do sanity check on the requested changes for Samba */
5273 if (!check_printer_ok(printer->info_2, snum)) {
5274 result = WERR_INVALID_PARAM;
5275 goto done;
5278 #if 0 /* JERRY */
5281 * Another one of those historical misunderstandings...
5282 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5283 * I'm leaving it here as a reminder. --jerry
5286 if (nt_printer_info_level_equal(printer, old_printer)) {
5287 DEBUG(3, ("update_printer: printer info has not changed\n"));
5288 result = WERR_OK;
5289 goto done;
5292 #endif
5294 /* Check calling user has permission to update printer description */
5296 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5297 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5298 result = WERR_ACCESS_DENIED;
5299 goto done;
5302 /* Call addprinter hook */
5304 if (*lp_addprinter_cmd()) {
5305 if ( !add_printer_hook(printer) ) {
5306 result = WERR_ACCESS_DENIED;
5307 goto done;
5312 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5313 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5314 * requires Win32 client code (see other notes elsewhere in the code).
5316 if (printer->info_2->devmode &&
5317 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5319 DEBUG(10,("update_printer: Save printer driver init data\n"));
5320 printer->info_2->devmode->displayfrequency = 0;
5322 if (update_driver_init(*printer, 2)!=0) {
5323 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5324 result = WERR_ACCESS_DENIED;
5325 goto done;
5327 } else {
5329 * When a *new* driver is bound to a printer, the drivername is used to
5330 * lookup previously saved driver initialization info, which is then
5331 * bound to the printer, simulating what happens in the Windows arch.
5333 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5334 if (!set_driver_init(printer, 2)) {
5335 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5336 printer->info_2->drivername));
5338 msg.flags |= PRINTER_MESSAGE_DRIVER;
5342 /* Update printer info */
5343 result = mod_a_printer(*printer, 2);
5345 /* flag which changes actually occured. This is a small subset of
5346 all the possible changes */
5348 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5349 msg.flags |= PRINTER_MESSAGE_COMMENT;
5351 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5352 msg.flags |= PRINTER_MESSAGE_SHARENAME;
5354 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5355 msg.flags |= PRINTER_MESSAGE_PORT;
5357 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5358 msg.flags |= PRINTER_MESSAGE_LOCATION;
5360 msg.low = PRINTER_CHANGE_ADD_PRINTER;
5361 fstrcpy(msg.printer_name, printer->info_2->printername);
5363 /* only send a notify if something changed */
5364 if (msg.flags) {
5365 srv_spoolss_sendnotify(msg.printer_name, 0, PRINTER_CHANGE_ADD_PRINTER, msg.flags);
5368 done:
5369 free_a_printer(&printer, 2);
5370 free_a_printer(&old_printer, 2);
5373 return result;
5376 /****************************************************************************
5377 ****************************************************************************/
5379 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5381 POLICY_HND *handle = &q_u->handle;
5382 uint32 level = q_u->level;
5383 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5384 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5385 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5386 uint32 command = q_u->command;
5388 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5390 if (!Printer) {
5391 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5392 return WERR_BADFID;
5395 /* check the level */
5396 switch (level) {
5397 case 0:
5398 return control_printer(handle, command, p);
5399 case 2:
5400 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5401 case 3:
5402 return update_printer_sec(handle, level, info, p,
5403 secdesc_ctr);
5404 default:
5405 return WERR_UNKNOWN_LEVEL;
5409 /****************************************************************************
5410 ****************************************************************************/
5412 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5414 POLICY_HND *handle = &q_u->handle;
5416 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5418 if (!Printer) {
5419 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5420 return WERR_BADFID;
5423 if (Printer->notify.client_connected==True)
5424 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5426 Printer->notify.flags=0;
5427 Printer->notify.options=0;
5428 Printer->notify.localmachine[0]='\0';
5429 Printer->notify.printerlocal=0;
5430 if (Printer->notify.option)
5431 free_spool_notify_option(&Printer->notify.option);
5432 Printer->notify.client_connected=False;
5434 return WERR_OK;
5437 /****************************************************************************
5438 ****************************************************************************/
5440 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5442 /* that's an [in out] buffer (despite appearences to the contrary) */
5443 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5445 r_u->needed = 0;
5446 return WERR_INVALID_PARAM; /* this is what a NT server
5447 returns for AddJob. AddJob
5448 must fail on non-local
5449 printers */
5452 /****************************************************************************
5453 ****************************************************************************/
5455 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5456 int position, int snum)
5458 pstring temp_name;
5460 struct tm *t;
5462 t=gmtime(&queue->time);
5463 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5465 job_info->jobid=queue->job;
5466 init_unistr(&job_info->printername, lp_servicename(snum));
5467 init_unistr(&job_info->machinename, temp_name);
5468 init_unistr(&job_info->username, queue->fs_user);
5469 init_unistr(&job_info->document, queue->fs_file);
5470 init_unistr(&job_info->datatype, "RAW");
5471 init_unistr(&job_info->text_status, "");
5472 job_info->status=nt_printj_status(queue->status);
5473 job_info->priority=queue->priority;
5474 job_info->position=position;
5475 job_info->totalpages=queue->page_count;
5476 job_info->pagesprinted=0;
5478 make_systemtime(&job_info->submitted, t);
5481 /****************************************************************************
5482 ****************************************************************************/
5484 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5485 int position, int snum,
5486 NT_PRINTER_INFO_LEVEL *ntprinter,
5487 DEVICEMODE *devmode)
5489 pstring temp_name;
5490 struct tm *t;
5492 t=gmtime(&queue->time);
5493 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5495 job_info->jobid=queue->job;
5497 init_unistr(&job_info->printername, ntprinter->info_2->printername);
5499 init_unistr(&job_info->machinename, temp_name);
5500 init_unistr(&job_info->username, queue->fs_user);
5501 init_unistr(&job_info->document, queue->fs_file);
5502 init_unistr(&job_info->notifyname, queue->fs_user);
5503 init_unistr(&job_info->datatype, "RAW");
5504 init_unistr(&job_info->printprocessor, "winprint");
5505 init_unistr(&job_info->parameters, "");
5506 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5507 init_unistr(&job_info->text_status, "");
5509 /* and here the security descriptor */
5511 job_info->status=nt_printj_status(queue->status);
5512 job_info->priority=queue->priority;
5513 job_info->position=position;
5514 job_info->starttime=0;
5515 job_info->untiltime=0;
5516 job_info->totalpages=queue->page_count;
5517 job_info->size=queue->size;
5518 make_systemtime(&(job_info->submitted), t);
5519 job_info->timeelapsed=0;
5520 job_info->pagesprinted=0;
5522 job_info->devmode = devmode;
5524 return (True);
5527 /****************************************************************************
5528 Enumjobs at level 1.
5529 ****************************************************************************/
5531 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5532 NEW_BUFFER *buffer, uint32 offered,
5533 uint32 *needed, uint32 *returned)
5535 JOB_INFO_1 *info;
5536 int i;
5538 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5539 if (info==NULL) {
5540 SAFE_FREE(queue);
5541 *returned=0;
5542 return WERR_NOMEM;
5545 for (i=0; i<*returned; i++)
5546 fill_job_info_1(&info[i], &queue[i], i, snum);
5548 SAFE_FREE(queue);
5550 /* check the required size. */
5551 for (i=0; i<*returned; i++)
5552 (*needed) += spoolss_size_job_info_1(&info[i]);
5554 if (!alloc_buffer_size(buffer, *needed)) {
5555 SAFE_FREE(info);
5556 return WERR_INSUFFICIENT_BUFFER;
5559 /* fill the buffer with the structures */
5560 for (i=0; i<*returned; i++)
5561 smb_io_job_info_1("", buffer, &info[i], 0);
5563 /* clear memory */
5564 SAFE_FREE(info);
5566 if (*needed > offered) {
5567 *returned=0;
5568 return WERR_INSUFFICIENT_BUFFER;
5571 return WERR_OK;
5574 /****************************************************************************
5575 Enumjobs at level 2.
5576 ****************************************************************************/
5578 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5579 NEW_BUFFER *buffer, uint32 offered,
5580 uint32 *needed, uint32 *returned)
5582 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5583 JOB_INFO_2 *info = NULL;
5584 int i;
5585 WERROR result;
5586 DEVICEMODE *devmode = NULL;
5588 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5589 if (info==NULL) {
5590 *returned=0;
5591 result = WERR_NOMEM;
5592 goto done;
5595 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5596 if (!W_ERROR_IS_OK(result)) {
5597 *returned = 0;
5598 goto done;
5601 /* this should not be a failure condition if the devmode is NULL */
5603 devmode = construct_dev_mode(snum);
5605 for (i=0; i<*returned; i++)
5606 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5607 devmode);
5609 free_a_printer(&ntprinter, 2);
5610 SAFE_FREE(queue);
5612 /* check the required size. */
5613 for (i=0; i<*returned; i++)
5614 (*needed) += spoolss_size_job_info_2(&info[i]);
5616 if (*needed > offered) {
5617 *returned=0;
5618 result = WERR_INSUFFICIENT_BUFFER;
5619 goto done;
5622 if (!alloc_buffer_size(buffer, *needed)) {
5623 SAFE_FREE(info);
5624 result = WERR_INSUFFICIENT_BUFFER;
5625 goto done;
5628 /* fill the buffer with the structures */
5629 for (i=0; i<*returned; i++)
5630 smb_io_job_info_2("", buffer, &info[i], 0);
5632 result = WERR_OK;
5634 done:
5635 free_a_printer(&ntprinter, 2);
5636 free_devmode(devmode);
5637 SAFE_FREE(queue);
5638 SAFE_FREE(info);
5640 return result;
5644 /****************************************************************************
5645 Enumjobs.
5646 ****************************************************************************/
5648 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5650 POLICY_HND *handle = &q_u->handle;
5651 /* uint32 firstjob = q_u->firstjob; - notused. */
5652 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5653 uint32 level = q_u->level;
5654 NEW_BUFFER *buffer = NULL;
5655 uint32 offered = q_u->offered;
5656 uint32 *needed = &r_u->needed;
5657 uint32 *returned = &r_u->returned;
5659 int snum;
5660 print_status_struct prt_status;
5661 print_queue_struct *queue=NULL;
5663 /* that's an [in out] buffer */
5664 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5665 buffer = r_u->buffer;
5667 DEBUG(4,("_spoolss_enumjobs\n"));
5669 *needed=0;
5670 *returned=0;
5672 if (!get_printer_snum(p, handle, &snum))
5673 return WERR_BADFID;
5675 *returned = print_queue_status(snum, &queue, &prt_status);
5676 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5678 if (*returned == 0) {
5679 SAFE_FREE(queue);
5680 return WERR_OK;
5683 switch (level) {
5684 case 1:
5685 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5686 case 2:
5687 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5688 default:
5689 SAFE_FREE(queue);
5690 *returned=0;
5691 return WERR_UNKNOWN_LEVEL;
5695 /****************************************************************************
5696 ****************************************************************************/
5698 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5700 return WERR_OK;
5703 /****************************************************************************
5704 ****************************************************************************/
5706 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5708 POLICY_HND *handle = &q_u->handle;
5709 uint32 jobid = q_u->jobid;
5710 /* uint32 level = q_u->level; - notused. */
5711 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5712 uint32 command = q_u->command;
5714 struct current_user user;
5715 int snum;
5716 WERROR errcode = WERR_BADFUNC;
5718 if (!get_printer_snum(p, handle, &snum)) {
5719 return WERR_BADFID;
5722 if (!print_job_exists(jobid)) {
5723 return WERR_INVALID_PRINTER_NAME;
5726 get_current_user(&user, p);
5728 switch (command) {
5729 case JOB_CONTROL_CANCEL:
5730 case JOB_CONTROL_DELETE:
5731 if (print_job_delete(&user, jobid, &errcode)) {
5732 errcode = WERR_OK;
5734 break;
5735 case JOB_CONTROL_PAUSE:
5736 if (print_job_pause(&user, jobid, &errcode)) {
5737 errcode = WERR_OK;
5739 break;
5740 case JOB_CONTROL_RESTART:
5741 case JOB_CONTROL_RESUME:
5742 if (print_job_resume(&user, jobid, &errcode)) {
5743 errcode = WERR_OK;
5745 break;
5746 default:
5747 return WERR_UNKNOWN_LEVEL;
5750 return errcode;
5753 /****************************************************************************
5754 Enumerates all printer drivers at level 1.
5755 ****************************************************************************/
5757 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5759 int i;
5760 int ndrivers;
5761 uint32 version;
5762 fstring *list = NULL;
5764 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5765 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5767 *returned=0;
5769 #define MAX_VERSION 4
5771 for (version=0; version<MAX_VERSION; version++) {
5772 list=NULL;
5773 ndrivers=get_ntdrivers(&list, architecture, version);
5774 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5776 if(ndrivers == -1)
5777 return WERR_NOMEM;
5779 if(ndrivers != 0) {
5780 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5781 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5782 SAFE_FREE(driver_info_1);
5783 SAFE_FREE(list);
5784 return WERR_NOMEM;
5786 else driver_info_1 = tdi1;
5789 for (i=0; i<ndrivers; i++) {
5790 WERROR status;
5791 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5792 ZERO_STRUCT(driver);
5793 status = get_a_printer_driver(&driver, 3, list[i],
5794 architecture, version);
5795 if (!W_ERROR_IS_OK(status)) {
5796 SAFE_FREE(list);
5797 return status;
5799 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5800 free_a_printer_driver(driver, 3);
5803 *returned+=ndrivers;
5804 SAFE_FREE(list);
5807 /* check the required size. */
5808 for (i=0; i<*returned; i++) {
5809 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5810 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5813 if (!alloc_buffer_size(buffer, *needed)) {
5814 SAFE_FREE(driver_info_1);
5815 return WERR_INSUFFICIENT_BUFFER;
5818 /* fill the buffer with the driver structures */
5819 for (i=0; i<*returned; i++) {
5820 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5821 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5824 SAFE_FREE(driver_info_1);
5826 if (*needed > offered) {
5827 *returned=0;
5828 return WERR_INSUFFICIENT_BUFFER;
5831 return WERR_OK;
5834 /****************************************************************************
5835 Enumerates all printer drivers at level 2.
5836 ****************************************************************************/
5838 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5840 int i;
5841 int ndrivers;
5842 uint32 version;
5843 fstring *list = NULL;
5845 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5846 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5848 *returned=0;
5850 #define MAX_VERSION 4
5852 for (version=0; version<MAX_VERSION; version++) {
5853 list=NULL;
5854 ndrivers=get_ntdrivers(&list, architecture, version);
5855 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5857 if(ndrivers == -1)
5858 return WERR_NOMEM;
5860 if(ndrivers != 0) {
5861 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5862 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5863 SAFE_FREE(driver_info_2);
5864 SAFE_FREE(list);
5865 return WERR_NOMEM;
5867 else driver_info_2 = tdi2;
5870 for (i=0; i<ndrivers; i++) {
5871 WERROR status;
5873 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5874 ZERO_STRUCT(driver);
5875 status = get_a_printer_driver(&driver, 3, list[i],
5876 architecture, version);
5877 if (!W_ERROR_IS_OK(status)) {
5878 SAFE_FREE(list);
5879 return status;
5881 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5882 free_a_printer_driver(driver, 3);
5885 *returned+=ndrivers;
5886 SAFE_FREE(list);
5889 /* check the required size. */
5890 for (i=0; i<*returned; i++) {
5891 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5892 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5895 if (!alloc_buffer_size(buffer, *needed)) {
5896 SAFE_FREE(driver_info_2);
5897 return WERR_INSUFFICIENT_BUFFER;
5900 /* fill the buffer with the form structures */
5901 for (i=0; i<*returned; i++) {
5902 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5903 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5906 SAFE_FREE(driver_info_2);
5908 if (*needed > offered) {
5909 *returned=0;
5910 return WERR_INSUFFICIENT_BUFFER;
5913 return WERR_OK;
5916 /****************************************************************************
5917 Enumerates all printer drivers at level 3.
5918 ****************************************************************************/
5920 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5922 int i;
5923 int ndrivers;
5924 uint32 version;
5925 fstring *list = NULL;
5927 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5928 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5930 *returned=0;
5932 #define MAX_VERSION 4
5934 for (version=0; version<MAX_VERSION; version++) {
5935 list=NULL;
5936 ndrivers=get_ntdrivers(&list, architecture, version);
5937 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5939 if(ndrivers == -1)
5940 return WERR_NOMEM;
5942 if(ndrivers != 0) {
5943 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5944 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5945 SAFE_FREE(driver_info_3);
5946 SAFE_FREE(list);
5947 return WERR_NOMEM;
5949 else driver_info_3 = tdi3;
5952 for (i=0; i<ndrivers; i++) {
5953 WERROR status;
5955 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5956 ZERO_STRUCT(driver);
5957 status = get_a_printer_driver(&driver, 3, list[i],
5958 architecture, version);
5959 if (!W_ERROR_IS_OK(status)) {
5960 SAFE_FREE(list);
5961 return status;
5963 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5964 free_a_printer_driver(driver, 3);
5967 *returned+=ndrivers;
5968 SAFE_FREE(list);
5971 /* check the required size. */
5972 for (i=0; i<*returned; i++) {
5973 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5974 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5977 if (!alloc_buffer_size(buffer, *needed)) {
5978 SAFE_FREE(driver_info_3);
5979 return WERR_INSUFFICIENT_BUFFER;
5982 /* fill the buffer with the driver structures */
5983 for (i=0; i<*returned; i++) {
5984 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5985 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5988 for (i=0; i<*returned; i++)
5989 SAFE_FREE(driver_info_3[i].dependentfiles);
5991 SAFE_FREE(driver_info_3);
5993 if (*needed > offered) {
5994 *returned=0;
5995 return WERR_INSUFFICIENT_BUFFER;
5998 return WERR_OK;
6001 /****************************************************************************
6002 Enumerates all printer drivers.
6003 ****************************************************************************/
6005 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6007 /* UNISTR2 *name = &q_u->name; - notused. */
6008 UNISTR2 *environment = &q_u->environment;
6009 uint32 level = q_u->level;
6010 NEW_BUFFER *buffer = NULL;
6011 uint32 offered = q_u->offered;
6012 uint32 *needed = &r_u->needed;
6013 uint32 *returned = &r_u->returned;
6015 fstring *list = NULL;
6016 fstring servername;
6017 fstring architecture;
6019 /* that's an [in out] buffer */
6020 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6021 buffer = r_u->buffer;
6023 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6024 fstrcpy(servername, get_called_name());
6025 *needed=0;
6026 *returned=0;
6028 unistr2_to_dos(architecture, environment, sizeof(architecture)-1);
6030 switch (level) {
6031 case 1:
6032 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6033 case 2:
6034 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6035 case 3:
6036 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6037 default:
6038 *returned=0;
6039 SAFE_FREE(list);
6040 return WERR_UNKNOWN_LEVEL;
6044 /****************************************************************************
6045 ****************************************************************************/
6047 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6049 form->flag=list->flag;
6050 init_unistr(&form->name, list->name);
6051 form->width=list->width;
6052 form->length=list->length;
6053 form->left=list->left;
6054 form->top=list->top;
6055 form->right=list->right;
6056 form->bottom=list->bottom;
6059 /****************************************************************************
6060 ****************************************************************************/
6062 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6064 /* POLICY_HND *handle = &q_u->handle; - notused. */
6065 uint32 level = q_u->level;
6066 NEW_BUFFER *buffer = NULL;
6067 uint32 offered = q_u->offered;
6068 uint32 *needed = &r_u->needed;
6069 uint32 *numofforms = &r_u->numofforms;
6070 uint32 numbuiltinforms;
6072 nt_forms_struct *list=NULL;
6073 nt_forms_struct *builtinlist=NULL;
6074 FORM_1 *forms_1;
6075 int buffer_size=0;
6076 int i;
6078 /* that's an [in out] buffer */
6079 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6080 buffer = r_u->buffer;
6082 DEBUG(4,("_spoolss_enumforms\n"));
6083 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6084 DEBUGADD(5,("Info level [%d]\n", level));
6086 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6087 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6088 *numofforms = get_ntforms(&list);
6089 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6090 *numofforms += numbuiltinforms;
6092 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6094 switch (level) {
6095 case 1:
6096 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6097 *numofforms=0;
6098 return WERR_NOMEM;
6101 /* construct the list of form structures */
6102 for (i=0; i<numbuiltinforms; i++) {
6103 DEBUGADD(6,("Filling form number [%d]\n",i));
6104 fill_form_1(&forms_1[i], &builtinlist[i]);
6107 SAFE_FREE(builtinlist);
6109 for (; i<*numofforms; i++) {
6110 DEBUGADD(6,("Filling form number [%d]\n",i));
6111 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6114 SAFE_FREE(list);
6116 /* check the required size. */
6117 for (i=0; i<numbuiltinforms; i++) {
6118 DEBUGADD(6,("adding form [%d]'s size\n",i));
6119 buffer_size += spoolss_size_form_1(&forms_1[i]);
6121 for (; i<*numofforms; i++) {
6122 DEBUGADD(6,("adding form [%d]'s size\n",i));
6123 buffer_size += spoolss_size_form_1(&forms_1[i]);
6126 *needed=buffer_size;
6128 if (!alloc_buffer_size(buffer, buffer_size)){
6129 SAFE_FREE(forms_1);
6130 return WERR_INSUFFICIENT_BUFFER;
6133 /* fill the buffer with the form structures */
6134 for (i=0; i<numbuiltinforms; i++) {
6135 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6136 smb_io_form_1("", buffer, &forms_1[i], 0);
6138 for (; i<*numofforms; i++) {
6139 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6140 smb_io_form_1("", buffer, &forms_1[i], 0);
6143 SAFE_FREE(forms_1);
6145 if (*needed > offered) {
6146 *numofforms=0;
6147 return WERR_INSUFFICIENT_BUFFER;
6149 else
6150 return WERR_OK;
6152 default:
6153 SAFE_FREE(list);
6154 SAFE_FREE(builtinlist);
6155 return WERR_UNKNOWN_LEVEL;
6160 /****************************************************************************
6161 ****************************************************************************/
6163 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6165 /* POLICY_HND *handle = &q_u->handle; - notused. */
6166 uint32 level = q_u->level;
6167 UNISTR2 *uni_formname = &q_u->formname;
6168 NEW_BUFFER *buffer = NULL;
6169 uint32 offered = q_u->offered;
6170 uint32 *needed = &r_u->needed;
6172 nt_forms_struct *list=NULL;
6173 nt_forms_struct builtin_form;
6174 BOOL foundBuiltin;
6175 FORM_1 form_1;
6176 fstring form_name;
6177 int buffer_size=0;
6178 int numofforms=0, i=0;
6180 /* that's an [in out] buffer */
6181 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6182 buffer = r_u->buffer;
6184 unistr2_to_dos(form_name, uni_formname, sizeof(form_name)-1);
6186 DEBUG(4,("_spoolss_getform\n"));
6187 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6188 DEBUGADD(5,("Info level [%d]\n", level));
6190 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6191 if (!foundBuiltin) {
6192 numofforms = get_ntforms(&list);
6193 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6195 if (numofforms == 0)
6196 return WERR_BADFID;
6199 switch (level) {
6200 case 1:
6201 if (foundBuiltin) {
6202 fill_form_1(&form_1, &builtin_form);
6203 } else {
6205 /* Check if the requested name is in the list of form structures */
6206 for (i=0; i<numofforms; i++) {
6208 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6210 if (strequal(form_name, list[i].name)) {
6211 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6212 fill_form_1(&form_1, &list[i]);
6213 break;
6217 SAFE_FREE(list);
6218 if (i == numofforms) {
6219 return WERR_BADFID;
6222 /* check the required size. */
6224 *needed=spoolss_size_form_1(&form_1);
6226 if (!alloc_buffer_size(buffer, buffer_size)){
6227 return WERR_INSUFFICIENT_BUFFER;
6230 if (*needed > offered) {
6231 return WERR_INSUFFICIENT_BUFFER;
6234 /* fill the buffer with the form structures */
6235 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6236 smb_io_form_1("", buffer, &form_1, 0);
6238 return WERR_OK;
6240 default:
6241 SAFE_FREE(list);
6242 return WERR_UNKNOWN_LEVEL;
6246 /****************************************************************************
6247 ****************************************************************************/
6249 static void fill_port_1(PORT_INFO_1 *port, const char *name)
6251 init_unistr(&port->port_name, name);
6254 /****************************************************************************
6255 ****************************************************************************/
6257 static void fill_port_2(PORT_INFO_2 *port, const char *name)
6259 init_unistr(&port->port_name, name);
6260 init_unistr(&port->monitor_name, "Local Monitor");
6261 init_unistr(&port->description, "Local Port");
6262 #define PORT_TYPE_WRITE 1
6263 port->port_type=PORT_TYPE_WRITE;
6264 port->reserved=0x0;
6267 /****************************************************************************
6268 enumports level 1.
6269 ****************************************************************************/
6271 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6273 PORT_INFO_1 *ports=NULL;
6274 int i=0;
6276 if (*lp_enumports_cmd()) {
6277 char *cmd = lp_enumports_cmd();
6278 char **qlines;
6279 pstring command;
6280 int numlines;
6281 int ret;
6282 int fd;
6284 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6286 DEBUG(10,("Running [%s]\n", command));
6287 ret = smbrun(command, &fd);
6288 DEBUG(10,("Returned [%d]\n", ret));
6289 if (ret != 0) {
6290 if (fd != -1)
6291 close(fd);
6292 /* Is this the best error to return here? */
6293 return WERR_ACCESS_DENIED;
6296 numlines = 0;
6297 qlines = fd_lines_load(fd, &numlines,True);
6298 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6299 close(fd);
6301 if(numlines) {
6302 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6303 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6304 dos_errstr(WERR_NOMEM)));
6305 file_lines_free(qlines);
6306 return WERR_NOMEM;
6309 for (i=0; i<numlines; i++) {
6310 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6311 fill_port_1(&ports[i], qlines[i]);
6314 file_lines_free(qlines);
6317 *returned = numlines;
6319 } else {
6320 *returned = 1; /* Sole Samba port returned. */
6322 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6323 return WERR_NOMEM;
6325 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6327 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6330 /* check the required size. */
6331 for (i=0; i<*returned; i++) {
6332 DEBUGADD(6,("adding port [%d]'s size\n", i));
6333 *needed += spoolss_size_port_info_1(&ports[i]);
6336 if (!alloc_buffer_size(buffer, *needed)) {
6337 SAFE_FREE(ports);
6338 return WERR_INSUFFICIENT_BUFFER;
6341 /* fill the buffer with the ports structures */
6342 for (i=0; i<*returned; i++) {
6343 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6344 smb_io_port_1("", buffer, &ports[i], 0);
6347 SAFE_FREE(ports);
6349 if (*needed > offered) {
6350 *returned=0;
6351 return WERR_INSUFFICIENT_BUFFER;
6354 return WERR_OK;
6357 /****************************************************************************
6358 enumports level 2.
6359 ****************************************************************************/
6361 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6363 PORT_INFO_2 *ports=NULL;
6364 int i=0;
6366 if (*lp_enumports_cmd()) {
6367 char *cmd = lp_enumports_cmd();
6368 char *path;
6369 char **qlines;
6370 pstring tmp_file;
6371 pstring command;
6372 int numlines;
6373 int ret;
6374 int fd;
6376 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6377 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6378 else
6379 path = lp_lockdir();
6381 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6382 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6384 unlink(tmp_file);
6385 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6386 ret = smbrun(command, &fd);
6387 DEBUGADD(10,("returned [%d]\n", ret));
6388 if (ret != 0) {
6389 if (fd != -1)
6390 close(fd);
6391 /* Is this the best error to return here? */
6392 return WERR_ACCESS_DENIED;
6395 numlines = 0;
6396 qlines = fd_lines_load(fd, &numlines,True);
6397 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6398 close(fd);
6400 if(numlines) {
6401 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6402 file_lines_free(qlines);
6403 return WERR_NOMEM;
6406 for (i=0; i<numlines; i++) {
6407 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6408 fill_port_2(&(ports[i]), qlines[i]);
6411 file_lines_free(qlines);
6414 *returned = numlines;
6416 } else {
6418 *returned = 1;
6420 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6421 return WERR_NOMEM;
6423 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6425 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6428 /* check the required size. */
6429 for (i=0; i<*returned; i++) {
6430 DEBUGADD(6,("adding port [%d]'s size\n", i));
6431 *needed += spoolss_size_port_info_2(&ports[i]);
6434 if (!alloc_buffer_size(buffer, *needed)) {
6435 SAFE_FREE(ports);
6436 return WERR_INSUFFICIENT_BUFFER;
6439 /* fill the buffer with the ports structures */
6440 for (i=0; i<*returned; i++) {
6441 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6442 smb_io_port_2("", buffer, &ports[i], 0);
6445 SAFE_FREE(ports);
6447 if (*needed > offered) {
6448 *returned=0;
6449 return WERR_INSUFFICIENT_BUFFER;
6452 return WERR_OK;
6455 /****************************************************************************
6456 enumports.
6457 ****************************************************************************/
6459 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6461 /* UNISTR2 *name = &q_u->name; - notused. */
6462 uint32 level = q_u->level;
6463 NEW_BUFFER *buffer = NULL;
6464 uint32 offered = q_u->offered;
6465 uint32 *needed = &r_u->needed;
6466 uint32 *returned = &r_u->returned;
6468 /* that's an [in out] buffer */
6469 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6470 buffer = r_u->buffer;
6472 DEBUG(4,("_spoolss_enumports\n"));
6474 *returned=0;
6475 *needed=0;
6477 switch (level) {
6478 case 1:
6479 return enumports_level_1(buffer, offered, needed, returned);
6480 case 2:
6481 return enumports_level_2(buffer, offered, needed, returned);
6482 default:
6483 return WERR_UNKNOWN_LEVEL;
6487 /****************************************************************************
6488 ****************************************************************************/
6490 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6491 const SPOOL_PRINTER_INFO_LEVEL *info,
6492 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6493 uint32 user_switch, const SPOOL_USER_CTR *user,
6494 POLICY_HND *handle)
6496 NT_PRINTER_INFO_LEVEL *printer = NULL;
6497 fstring name;
6498 int snum;
6499 WERROR err = WERR_OK;
6501 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6502 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6503 return WERR_NOMEM;
6506 ZERO_STRUCTP(printer);
6508 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6509 if (!convert_printer_info(info, printer, 2)) {
6510 free_a_printer(&printer, 2);
6511 return WERR_NOMEM;
6514 /* check to see if the printer already exists */
6516 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6517 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6518 printer->info_2->sharename));
6519 free_a_printer(&printer, 2);
6520 return WERR_PRINTER_ALREADY_EXISTS;
6523 if (*lp_addprinter_cmd() ) {
6524 if ( !add_printer_hook(printer) ) {
6525 free_a_printer(&printer,2);
6526 return WERR_ACCESS_DENIED;
6530 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6531 printer->info_2->sharename);
6534 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6535 free_a_printer(&printer,2);
6536 return WERR_ACCESS_DENIED;
6539 /* you must be a printer admin to add a new printer */
6540 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6541 free_a_printer(&printer,2);
6542 return WERR_ACCESS_DENIED;
6546 * Do sanity check on the requested changes for Samba.
6549 if (!check_printer_ok(printer->info_2, snum)) {
6550 free_a_printer(&printer,2);
6551 return WERR_INVALID_PARAM;
6555 * When a printer is created, the drivername bound to the printer is used
6556 * to lookup previously saved driver initialization info, which is then
6557 * bound to the new printer, simulating what happens in the Windows arch.
6560 if (!devmode)
6561 set_driver_init(printer, 2);
6562 else {
6563 /* A valid devmode was included, convert and link it
6565 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6567 if (!convert_devicemode(printer->info_2->printername, devmode,
6568 &printer->info_2->devmode))
6569 return WERR_NOMEM;
6572 set_driver_init(printer, 2);
6574 /* write the ASCII on disk */
6575 err = mod_a_printer(*printer, 2);
6576 if (!W_ERROR_IS_OK(err)) {
6577 free_a_printer(&printer,2);
6578 return err;
6581 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6582 /* Handle open failed - remove addition. */
6583 del_a_printer(printer->info_2->sharename);
6584 free_a_printer(&printer,2);
6585 return WERR_ACCESS_DENIED;
6588 update_c_setprinter(False);
6590 srv_spoolss_sendnotify(printer->info_2->printername, 0, PRINTER_CHANGE_ADD_PRINTER, 0x0);
6592 free_a_printer(&printer,2);
6594 return WERR_OK;
6597 /****************************************************************************
6598 ****************************************************************************/
6600 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6602 UNISTR2 *uni_srv_name = &q_u->server_name;
6603 uint32 level = q_u->level;
6604 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6605 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6606 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6607 uint32 user_switch = q_u->user_switch;
6608 SPOOL_USER_CTR *user = &q_u->user_ctr;
6609 POLICY_HND *handle = &r_u->handle;
6611 switch (level) {
6612 case 1:
6613 /* we don't handle yet */
6614 /* but I know what to do ... */
6615 return WERR_UNKNOWN_LEVEL;
6616 case 2:
6617 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6618 devmode, sdb,
6619 user_switch, user, handle);
6620 default:
6621 return WERR_UNKNOWN_LEVEL;
6625 /****************************************************************************
6626 ****************************************************************************/
6628 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6630 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6631 uint32 level = q_u->level;
6632 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6633 WERROR err = WERR_OK;
6634 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6635 struct current_user user;
6636 fstring driver_name;
6637 uint32 version;
6639 ZERO_STRUCT(driver);
6641 get_current_user(&user, p);
6643 if (!convert_printer_driver_info(info, &driver, level)) {
6644 err = WERR_NOMEM;
6645 goto done;
6648 DEBUG(5,("Cleaning driver's information\n"));
6649 err = clean_up_driver_struct(driver, level, &user);
6650 if (!W_ERROR_IS_OK(err))
6651 goto done;
6653 DEBUG(5,("Moving driver to final destination\n"));
6654 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6655 if (W_ERROR_IS_OK(err))
6656 err = WERR_ACCESS_DENIED;
6657 goto done;
6660 if (add_a_printer_driver(driver, level)!=0) {
6661 err = WERR_ACCESS_DENIED;
6662 goto done;
6665 /* BEGIN_ADMIN_LOG */
6666 switch(level) {
6667 case 3:
6668 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6669 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6670 fstrcpy(driver_name, driver.info_3->name);
6671 break;
6672 case 6:
6673 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6674 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6675 fstrcpy(driver_name, driver.info_6->name);
6676 break;
6678 /* END_ADMIN_LOG */
6681 * I think this is where he DrvUpgradePrinter() hook would be
6682 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6683 * server. Right now, we just need to send ourselves a message
6684 * to update each printer bound to this driver. --jerry
6687 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6688 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6689 driver_name));
6693 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6694 * decide if the driver init data should be deleted. The rules are:
6695 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6696 * 2) delete init data only if there is no 2k/Xp driver
6697 * 3) always delete init data
6698 * The generalized rule is always use init data from the highest order driver.
6699 * It is necessary to follow the driver install by an initialization step to
6700 * finish off this process.
6702 if (level == 3)
6703 version = driver.info_3->cversion;
6704 else if (level == 6)
6705 version = driver.info_6->version;
6706 else
6707 version = -1;
6708 switch (version) {
6710 * 9x printer driver - never delete init data
6712 case 0:
6713 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6714 driver_name));
6715 break;
6718 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6719 * there is no 2k/Xp driver init data for this driver name.
6721 case 2:
6723 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
6725 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
6727 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6729 if (!del_driver_init(driver_name))
6730 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
6731 } else {
6733 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6735 free_a_printer_driver(driver1,3);
6736 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6737 driver_name));
6740 break;
6743 * 2k or Xp printer driver - always delete init data
6745 case 3:
6746 if (!del_driver_init(driver_name))
6747 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
6748 break;
6750 default:
6751 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
6752 break;
6756 done:
6757 free_a_printer_driver(driver, level);
6758 return err;
6761 /****************************************************************************
6762 ****************************************************************************/
6764 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6766 init_unistr(&info->name, name);
6769 /****************************************************************************
6770 ****************************************************************************/
6772 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6774 pstring path;
6775 pstring long_archi;
6776 pstring short_archi;
6777 DRIVER_DIRECTORY_1 *info=NULL;
6779 unistr2_to_dos(long_archi, uni_environment, sizeof(long_archi)-1);
6781 if (get_short_archi(short_archi, long_archi)==False)
6782 return WERR_INVALID_ENVIRONMENT;
6784 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6785 return WERR_NOMEM;
6787 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6789 DEBUG(4,("printer driver directory: [%s]\n", path));
6791 fill_driverdir_1(info, path);
6793 *needed += spoolss_size_driverdir_info_1(info);
6795 if (!alloc_buffer_size(buffer, *needed)) {
6796 SAFE_FREE(info);
6797 return WERR_INSUFFICIENT_BUFFER;
6800 smb_io_driverdir_1("", buffer, info, 0);
6802 SAFE_FREE(info);
6804 if (*needed > offered)
6805 return WERR_INSUFFICIENT_BUFFER;
6807 return WERR_OK;
6810 /****************************************************************************
6811 ****************************************************************************/
6813 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6815 UNISTR2 *name = &q_u->name;
6816 UNISTR2 *uni_environment = &q_u->environment;
6817 uint32 level = q_u->level;
6818 NEW_BUFFER *buffer = NULL;
6819 uint32 offered = q_u->offered;
6820 uint32 *needed = &r_u->needed;
6822 /* that's an [in out] buffer */
6823 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6824 buffer = r_u->buffer;
6826 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6828 *needed=0;
6830 switch(level) {
6831 case 1:
6832 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6833 default:
6834 return WERR_UNKNOWN_LEVEL;
6838 /****************************************************************************
6839 ****************************************************************************/
6841 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6843 POLICY_HND *handle = &q_u->handle;
6844 uint32 idx = q_u->index;
6845 uint32 in_value_len = q_u->valuesize;
6846 uint32 in_data_len = q_u->datasize;
6847 uint32 *out_max_value_len = &r_u->valuesize;
6848 uint16 **out_value = &r_u->value;
6849 uint32 *out_value_len = &r_u->realvaluesize;
6850 uint32 *out_type = &r_u->type;
6851 uint32 *out_max_data_len = &r_u->datasize;
6852 uint8 **data_out = &r_u->data;
6853 uint32 *out_data_len = &r_u->realdatasize;
6855 NT_PRINTER_INFO_LEVEL *printer = NULL;
6857 fstring value;
6859 uint32 param_index;
6860 uint32 biggest_valuesize;
6861 uint32 biggest_datasize;
6862 uint32 data_len;
6863 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6864 int snum;
6865 uint8 *data=NULL;
6866 uint32 type;
6867 WERROR result;
6869 ZERO_STRUCT(printer);
6871 *out_type=0;
6873 *out_max_data_len=0;
6874 *data_out=NULL;
6875 *out_data_len=0;
6877 DEBUG(5,("spoolss_enumprinterdata\n"));
6879 if (!Printer) {
6880 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6881 return WERR_BADFID;
6884 if (!get_printer_snum(p,handle, &snum))
6885 return WERR_BADFID;
6887 result = get_a_printer(&printer, 2, lp_servicename(snum));
6888 if (!W_ERROR_IS_OK(result))
6889 return result;
6892 * The NT machine wants to know the biggest size of value and data
6894 * cf: MSDN EnumPrinterData remark section
6896 if ( (in_value_len==0) && (in_data_len==0) ) {
6897 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6899 SAFE_FREE(data);
6901 param_index=0;
6902 biggest_valuesize=0;
6903 biggest_datasize=0;
6905 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6906 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6907 if (data_len > biggest_datasize) biggest_datasize=data_len;
6909 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6911 SAFE_FREE(data);
6912 param_index++;
6915 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6916 *out_value_len=2*(1+biggest_valuesize);
6917 *out_data_len=biggest_datasize;
6919 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6921 free_a_printer(&printer, 2);
6922 return WERR_OK;
6926 * the value len is wrong in NT sp3
6927 * that's the number of bytes not the number of unicode chars
6930 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6932 SAFE_FREE(data);
6933 free_a_printer(&printer, 2);
6935 /* out_value should default to "" or else NT4 has
6936 problems unmarshalling the response */
6938 *out_max_value_len=(in_value_len/sizeof(uint16));
6939 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
6940 return WERR_NOMEM;
6942 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, "", in_value_len, True);
6944 /* the data is counted in bytes */
6945 *out_max_data_len = in_data_len;
6946 *out_data_len = in_data_len;
6947 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
6948 return WERR_NOMEM;
6950 return WERR_NO_MORE_ITEMS;
6953 free_a_printer(&printer, 2);
6956 * the value is:
6957 * - counted in bytes in the request
6958 * - counted in UNICODE chars in the max reply
6959 * - counted in bytes in the real size
6961 * take a pause *before* coding not *during* coding
6964 *out_max_value_len=(in_value_len/sizeof(uint16));
6965 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6966 SAFE_FREE(data);
6967 return WERR_NOMEM;
6970 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
6972 *out_type=type;
6974 /* the data is counted in bytes */
6975 *out_max_data_len=in_data_len;
6976 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6977 SAFE_FREE(data);
6978 return WERR_NOMEM;
6981 memcpy(*data_out, data, (size_t)data_len);
6982 *out_data_len=data_len;
6984 SAFE_FREE(data);
6986 return WERR_OK;
6989 /****************************************************************************
6990 ****************************************************************************/
6992 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6994 POLICY_HND *handle = &q_u->handle;
6995 UNISTR2 *value = &q_u->value;
6996 uint32 type = q_u->type;
6997 /* uint32 max_len = q_u->max_len; - notused. */
6998 uint8 *data = q_u->data;
6999 uint32 real_len = q_u->real_len;
7000 /* uint32 numeric_data = q_u->numeric_data; - notused. */
7002 NT_PRINTER_INFO_LEVEL *printer = NULL;
7003 NT_PRINTER_PARAM *param = NULL, old_param;
7004 int snum=0;
7005 WERROR status = WERR_OK;
7006 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7008 DEBUG(5,("spoolss_setprinterdata\n"));
7010 if (!Printer) {
7011 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7012 return WERR_BADFID;
7015 if (!get_printer_snum(p,handle, &snum))
7016 return WERR_BADFID;
7018 ZERO_STRUCT(old_param);
7021 * Access check : NT returns "access denied" if you make a
7022 * SetPrinterData call without the necessary privildge.
7023 * we were originally returning OK if nothing changed
7024 * which made Win2k issue **a lot** of SetPrinterData
7025 * when connecting to a printer --jerry
7028 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7029 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7030 status = WERR_ACCESS_DENIED;
7031 goto done;
7034 /* Check if we are making any changes or not. Return true if
7035 nothing is actually changing. This is not needed anymore but
7036 has been left in as an optimization to keep from from
7037 writing to disk as often --jerry */
7039 status = get_a_printer(&printer, 2, lp_servicename(snum));
7040 if (!W_ERROR_IS_OK(status))
7041 return status;
7043 convert_specific_param(&param, value , type, data, real_len);
7045 unlink_specific_param_if_exist(printer->info_2, param);
7048 * When client side code sets a magic printer data key, detect it and save
7049 * the current printer data and the magic key's data (its the DEVMODE) for
7050 * future printer/driver initializations.
7052 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
7054 * Set devmode and printer initialization info
7056 status = save_driver_init(printer, 2, param);
7058 else {
7059 add_a_specific_param(printer->info_2, &param);
7060 status = mod_a_printer(*printer, 2);
7063 done:
7064 free_a_printer(&printer, 2);
7065 if (param)
7066 free_nt_printer_param(&param);
7067 SAFE_FREE(old_param.data);
7069 return status;
7072 /****************************************************************************
7073 ****************************************************************************/
7075 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7077 POLICY_HND *handle = &q_u->handle;
7078 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7079 int snum;
7081 DEBUG(5,("_spoolss_resetprinter\n"));
7084 * All we do is to check to see if the handle and queue is valid.
7085 * This call really doesn't mean anything to us because we only
7086 * support RAW printing. --jerry
7089 if (!Printer) {
7090 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7091 return WERR_BADFID;
7094 if (!get_printer_snum(p,handle, &snum))
7095 return WERR_BADFID;
7098 /* blindly return success */
7099 return WERR_OK;
7103 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7105 POLICY_HND *handle = &q_u->handle;
7106 UNISTR2 *value = &q_u->valuename;
7108 NT_PRINTER_INFO_LEVEL *printer = NULL;
7109 NT_PRINTER_PARAM param;
7110 int snum=0;
7111 WERROR status = WERR_OK;
7112 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7114 DEBUG(5,("spoolss_deleteprinterdata\n"));
7116 if (!Printer) {
7117 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7118 return WERR_BADFID;
7121 if (!get_printer_snum(p, handle, &snum))
7122 return WERR_BADFID;
7124 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7125 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7126 return WERR_ACCESS_DENIED;
7129 status = get_a_printer(&printer, 2, lp_servicename(snum));
7130 if (!W_ERROR_IS_OK(status))
7131 return status;
7133 ZERO_STRUCTP(&param);
7134 unistr2_to_dos(param.value, value, sizeof(param.value)-1);
7136 if(!unlink_specific_param_if_exist(printer->info_2, &param))
7137 status = WERR_INVALID_PARAM;
7138 else
7139 status = mod_a_printer(*printer, 2);
7141 free_a_printer(&printer, 2);
7142 return status;
7145 /****************************************************************************
7146 ****************************************************************************/
7148 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7150 POLICY_HND *handle = &q_u->handle;
7151 /* uint32 level = q_u->level; - notused. */
7152 FORM *form = &q_u->form;
7153 nt_forms_struct tmpForm;
7154 int snum;
7155 WERROR status = WERR_OK;
7156 NT_PRINTER_INFO_LEVEL *printer = NULL;
7158 int count=0;
7159 nt_forms_struct *list=NULL;
7160 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7162 DEBUG(5,("spoolss_addform\n"));
7164 if (!Printer) {
7165 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7166 return WERR_BADFID;
7170 /* forms can be added on printer of on the print server handle */
7172 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7174 if (!get_printer_snum(p,handle, &snum))
7175 return WERR_BADFID;
7177 status = get_a_printer(&printer, 2, lp_servicename(snum));
7178 if (!W_ERROR_IS_OK(status))
7179 goto done;
7182 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7183 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7184 status = WERR_ACCESS_DENIED;
7185 goto done;
7188 /* can't add if builtin */
7190 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7191 status = WERR_ALREADY_EXISTS;
7192 goto done;
7195 count = get_ntforms(&list);
7197 if(!add_a_form(&list, form, &count)) {
7198 status = WERR_NOMEM;
7199 goto done;
7202 write_ntforms(&list, count);
7205 * ChangeID must always be set if this is a printer
7208 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7209 status = mod_a_printer(*printer, 2);
7211 done:
7212 if ( printer )
7213 free_a_printer(&printer, 2);
7214 SAFE_FREE(list);
7216 return status;
7219 /****************************************************************************
7220 ****************************************************************************/
7222 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7224 POLICY_HND *handle = &q_u->handle;
7225 UNISTR2 *form_name = &q_u->name;
7226 nt_forms_struct tmpForm;
7227 int count=0;
7228 nt_forms_struct *list=NULL;
7229 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7230 int snum;
7231 WERROR status = WERR_OK;
7232 NT_PRINTER_INFO_LEVEL *printer = NULL;
7234 DEBUG(5,("spoolss_deleteform\n"));
7236 if (!Printer) {
7237 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7238 return WERR_BADFID;
7241 /* forms can be deleted on printer of on the print server handle */
7243 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7245 if (!get_printer_snum(p,handle, &snum))
7246 return WERR_BADFID;
7248 status = get_a_printer(&printer, 2, lp_servicename(snum));
7249 if (!W_ERROR_IS_OK(status))
7250 goto done;
7253 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7254 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7255 status = WERR_ACCESS_DENIED;
7256 goto done;
7259 /* can't delete if builtin */
7261 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7262 status = WERR_INVALID_PARAM;
7263 goto done;
7266 count = get_ntforms(&list);
7268 if ( !delete_a_form(&list, form_name, &count, &status ))
7269 goto done;
7272 * ChangeID must always be set if this is a printer
7275 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7276 status = mod_a_printer(*printer, 2);
7278 done:
7279 if ( printer )
7280 free_a_printer(&printer, 2);
7281 SAFE_FREE(list);
7283 return status;
7286 /****************************************************************************
7287 ****************************************************************************/
7289 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7291 POLICY_HND *handle = &q_u->handle;
7292 /* UNISTR2 *uni_name = &q_u->name; - notused. */
7293 /* uint32 level = q_u->level; - notused. */
7294 FORM *form = &q_u->form;
7295 nt_forms_struct tmpForm;
7296 int snum;
7297 WERROR status = WERR_OK;
7298 NT_PRINTER_INFO_LEVEL *printer = NULL;
7300 int count=0;
7301 nt_forms_struct *list=NULL;
7302 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7304 DEBUG(5,("spoolss_setform\n"));
7306 if (!Printer) {
7307 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7308 return WERR_BADFID;
7311 /* forms can be modified on printer of on the print server handle */
7313 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7315 if (!get_printer_snum(p,handle, &snum))
7316 return WERR_BADFID;
7318 status = get_a_printer(&printer, 2, lp_servicename(snum));
7319 if (!W_ERROR_IS_OK(status))
7320 goto done;
7323 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7324 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7325 status = WERR_ACCESS_DENIED;
7326 goto done;
7329 /* can't set if builtin */
7330 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7331 status = WERR_INVALID_PARAM;
7332 goto done;
7335 count = get_ntforms(&list);
7336 update_a_form(&list, form, count);
7337 write_ntforms(&list, count);
7340 * ChangeID must always be set if this is a printer
7343 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7344 status = mod_a_printer(*printer, 2);
7347 done:
7348 if ( printer )
7349 free_a_printer(&printer, 2);
7350 SAFE_FREE(list);
7352 return status;
7355 /****************************************************************************
7356 enumprintprocessors level 1.
7357 ****************************************************************************/
7359 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7361 PRINTPROCESSOR_1 *info_1=NULL;
7363 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7364 return WERR_NOMEM;
7366 (*returned) = 0x1;
7368 init_unistr(&info_1->name, "winprint");
7370 *needed += spoolss_size_printprocessor_info_1(info_1);
7372 if (!alloc_buffer_size(buffer, *needed))
7373 return WERR_INSUFFICIENT_BUFFER;
7375 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7377 SAFE_FREE(info_1);
7379 if (*needed > offered) {
7380 *returned=0;
7381 return WERR_INSUFFICIENT_BUFFER;
7384 return WERR_OK;
7387 /****************************************************************************
7388 ****************************************************************************/
7390 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7392 /* UNISTR2 *name = &q_u->name; - notused. */
7393 /* UNISTR2 *environment = &q_u->environment; - notused. */
7394 uint32 level = q_u->level;
7395 NEW_BUFFER *buffer = NULL;
7396 uint32 offered = q_u->offered;
7397 uint32 *needed = &r_u->needed;
7398 uint32 *returned = &r_u->returned;
7400 /* that's an [in out] buffer */
7401 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7402 buffer = r_u->buffer;
7404 DEBUG(5,("spoolss_enumprintprocessors\n"));
7407 * Enumerate the print processors ...
7409 * Just reply with "winprint", to keep NT happy
7410 * and I can use my nice printer checker.
7413 *returned=0;
7414 *needed=0;
7416 switch (level) {
7417 case 1:
7418 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7419 default:
7420 return WERR_UNKNOWN_LEVEL;
7424 /****************************************************************************
7425 enumprintprocdatatypes level 1.
7426 ****************************************************************************/
7428 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7430 PRINTPROCDATATYPE_1 *info_1=NULL;
7432 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7433 return WERR_NOMEM;
7435 (*returned) = 0x1;
7437 init_unistr(&info_1->name, "RAW");
7439 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7441 if (!alloc_buffer_size(buffer, *needed))
7442 return WERR_INSUFFICIENT_BUFFER;
7444 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7446 SAFE_FREE(info_1);
7448 if (*needed > offered) {
7449 *returned=0;
7450 return WERR_INSUFFICIENT_BUFFER;
7453 return WERR_OK;
7456 /****************************************************************************
7457 ****************************************************************************/
7459 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7461 /* UNISTR2 *name = &q_u->name; - notused. */
7462 /* UNISTR2 *processor = &q_u->processor; - notused. */
7463 uint32 level = q_u->level;
7464 NEW_BUFFER *buffer = NULL;
7465 uint32 offered = q_u->offered;
7466 uint32 *needed = &r_u->needed;
7467 uint32 *returned = &r_u->returned;
7469 /* that's an [in out] buffer */
7470 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7471 buffer = r_u->buffer;
7473 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7475 *returned=0;
7476 *needed=0;
7478 switch (level) {
7479 case 1:
7480 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7481 default:
7482 return WERR_UNKNOWN_LEVEL;
7486 /****************************************************************************
7487 enumprintmonitors level 1.
7488 ****************************************************************************/
7490 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7492 PRINTMONITOR_1 *info_1=NULL;
7494 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7495 return WERR_NOMEM;
7497 (*returned) = 0x1;
7499 init_unistr(&info_1->name, "Local Port");
7501 *needed += spoolss_size_printmonitor_info_1(info_1);
7503 if (!alloc_buffer_size(buffer, *needed))
7504 return WERR_INSUFFICIENT_BUFFER;
7506 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7508 SAFE_FREE(info_1);
7510 if (*needed > offered) {
7511 *returned=0;
7512 return WERR_INSUFFICIENT_BUFFER;
7515 return WERR_OK;
7518 /****************************************************************************
7519 enumprintmonitors level 2.
7520 ****************************************************************************/
7522 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7524 PRINTMONITOR_2 *info_2=NULL;
7526 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7527 return WERR_NOMEM;
7529 (*returned) = 0x1;
7531 init_unistr(&info_2->name, "Local Port");
7532 init_unistr(&info_2->environment, "Windows NT X86");
7533 init_unistr(&info_2->dll_name, "localmon.dll");
7535 *needed += spoolss_size_printmonitor_info_2(info_2);
7537 if (!alloc_buffer_size(buffer, *needed))
7538 return WERR_INSUFFICIENT_BUFFER;
7540 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7542 SAFE_FREE(info_2);
7544 if (*needed > offered) {
7545 *returned=0;
7546 return WERR_INSUFFICIENT_BUFFER;
7549 return WERR_OK;
7552 /****************************************************************************
7553 ****************************************************************************/
7555 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7557 /* UNISTR2 *name = &q_u->name; - notused. */
7558 uint32 level = q_u->level;
7559 NEW_BUFFER *buffer = NULL;
7560 uint32 offered = q_u->offered;
7561 uint32 *needed = &r_u->needed;
7562 uint32 *returned = &r_u->returned;
7564 /* that's an [in out] buffer */
7565 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7566 buffer = r_u->buffer;
7568 DEBUG(5,("spoolss_enumprintmonitors\n"));
7571 * Enumerate the print monitors ...
7573 * Just reply with "Local Port", to keep NT happy
7574 * and I can use my nice printer checker.
7577 *returned=0;
7578 *needed=0;
7580 switch (level) {
7581 case 1:
7582 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7583 case 2:
7584 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7585 default:
7586 return WERR_UNKNOWN_LEVEL;
7590 /****************************************************************************
7591 ****************************************************************************/
7593 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7595 int i=0;
7596 BOOL found=False;
7597 JOB_INFO_1 *info_1=NULL;
7599 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7601 if (info_1 == NULL) {
7602 SAFE_FREE(queue);
7603 return WERR_NOMEM;
7606 for (i=0; i<count && found==False; i++) {
7607 if (queue[i].job==(int)jobid)
7608 found=True;
7611 if (found==False) {
7612 SAFE_FREE(queue);
7613 SAFE_FREE(info_1);
7614 /* NT treats not found as bad param... yet another bad choice */
7615 return WERR_INVALID_PARAM;
7618 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7620 SAFE_FREE(queue);
7622 *needed += spoolss_size_job_info_1(info_1);
7624 if (!alloc_buffer_size(buffer, *needed)) {
7625 SAFE_FREE(info_1);
7626 return WERR_INSUFFICIENT_BUFFER;
7629 smb_io_job_info_1("", buffer, info_1, 0);
7631 SAFE_FREE(info_1);
7633 if (*needed > offered)
7634 return WERR_INSUFFICIENT_BUFFER;
7636 return WERR_OK;
7639 /****************************************************************************
7640 ****************************************************************************/
7642 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7644 int i=0;
7645 BOOL found=False;
7646 JOB_INFO_2 *info_2;
7647 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7648 WERROR ret;
7649 DEVICEMODE *devmode = NULL;
7651 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7653 ZERO_STRUCTP(info_2);
7655 if (info_2 == NULL) {
7656 ret = WERR_NOMEM;
7657 goto done;
7660 for (i=0; i<count && found==False; i++) {
7661 if (queue[i].job==(int)jobid)
7662 found=True;
7665 if (found==False) {
7666 /* NT treats not found as bad param... yet another bad
7667 choice */
7668 ret = WERR_INVALID_PARAM;
7669 goto done;
7672 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7673 if (!W_ERROR_IS_OK(ret))
7674 goto done;
7676 /* not a failure condition if devmode == NULL */
7678 construct_dev_mode(snum);
7680 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7682 *needed += spoolss_size_job_info_2(info_2);
7684 if (!alloc_buffer_size(buffer, *needed)) {
7685 ret = WERR_INSUFFICIENT_BUFFER;
7686 goto done;
7689 smb_io_job_info_2("", buffer, info_2, 0);
7691 if (*needed > offered) {
7692 ret = WERR_INSUFFICIENT_BUFFER;
7693 goto done;
7696 ret = WERR_OK;
7698 done:
7699 /* Cleanup allocated memory */
7701 SAFE_FREE(queue);
7702 free_job_info_2(info_2); /* Also frees devmode */
7703 SAFE_FREE(info_2);
7704 free_a_printer(&ntprinter, 2);
7706 return ret;
7709 /****************************************************************************
7710 ****************************************************************************/
7712 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7714 POLICY_HND *handle = &q_u->handle;
7715 uint32 jobid = q_u->jobid;
7716 uint32 level = q_u->level;
7717 NEW_BUFFER *buffer = NULL;
7718 uint32 offered = q_u->offered;
7719 uint32 *needed = &r_u->needed;
7721 int snum;
7722 int count;
7723 print_queue_struct *queue=NULL;
7724 print_status_struct prt_status;
7726 /* that's an [in out] buffer */
7727 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7728 buffer = r_u->buffer;
7730 DEBUG(5,("spoolss_getjob\n"));
7732 *needed=0;
7734 if (!get_printer_snum(p, handle, &snum))
7735 return WERR_BADFID;
7737 count = print_queue_status(snum, &queue, &prt_status);
7739 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7740 count, prt_status.status, prt_status.message));
7742 switch (level) {
7743 case 1:
7744 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7745 case 2:
7746 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7747 default:
7748 SAFE_FREE(queue);
7749 return WERR_UNKNOWN_LEVEL;
7753 /********************************************************************
7754 * spoolss_getprinterdataex
7755 ********************************************************************/
7757 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7759 POLICY_HND *handle = &q_u->handle;
7760 uint32 in_size = q_u->size;
7761 uint32 *type = &r_u->type;
7762 uint32 *out_size = &r_u->size;
7763 uint8 **data = &r_u->data;
7764 uint32 *needed = &r_u->needed;
7766 fstring key, value;
7767 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7768 BOOL found = False;
7770 DEBUG(4,("_spoolss_getprinterdataex\n"));
7772 unistr2_to_dos(key, &q_u->keyname, sizeof(key) - 1);
7773 unistr2_to_dos(value, &q_u->valuename, sizeof(value) - 1);
7775 /* in case of problem, return some default values */
7776 *needed=0;
7777 *type=0;
7778 *out_size=0;
7781 if (!Printer) {
7782 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7783 return WERR_NOMEM;
7784 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7785 return WERR_BADFID;
7789 /* Is the handle to a printer or to the server? */
7791 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7793 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7794 return WERR_INVALID_PARAM;
7796 else
7799 * From MSDN documentation of GetPrinterDataEx: pass request
7800 * to GetPrinterData if key is "PrinterDriverData". This is
7801 * the only key we really support. Other keys to implement:
7802 * (a) DsDriver
7803 * (b) DsSpooler
7804 * (c) PnPData
7807 if (strcmp(key, "PrinterDriverData") != 0)
7808 return WERR_BADFILE;
7810 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7811 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7812 type, data, needed, in_size);
7816 if (!found) {
7817 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7819 /* reply this param doesn't exist */
7820 if (*out_size) {
7821 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7822 return WERR_NOMEM;
7823 } else {
7824 *data = NULL;
7827 return WERR_INVALID_PARAM;
7830 if (*needed > *out_size)
7831 return WERR_MORE_DATA;
7832 else
7833 return WERR_OK;
7836 /********************************************************************
7837 * spoolss_setprinterdata
7838 ********************************************************************/
7840 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7842 SPOOL_Q_SETPRINTERDATA q_u_local;
7843 SPOOL_R_SETPRINTERDATA r_u_local;
7844 fstring key;
7846 DEBUG(4,("_spoolss_setprinterdataex\n"));
7848 /* From MSDN documentation of SetPrinterDataEx: pass request to
7849 SetPrinterData if key is "PrinterDriverData" */
7851 unistr2_to_dos(key, &q_u->key, sizeof(key) - 1);
7853 if (strcmp(key, "PrinterDriverData") != 0)
7854 return WERR_INVALID_PARAM;
7856 ZERO_STRUCT(q_u_local);
7857 ZERO_STRUCT(r_u_local);
7859 /* make a copy to call _spoolss_setprinterdata() */
7861 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7862 copy_unistr2(&q_u_local.value, &q_u->value);
7863 q_u_local.type = q_u->type;
7864 q_u_local.max_len = q_u->max_len;
7865 q_u_local.data = q_u->data;
7866 q_u_local.real_len = q_u->real_len;
7867 q_u_local.numeric_data = q_u->numeric_data;
7869 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7872 /********************************************************************
7873 * spoolss_enumprinterkey
7874 ********************************************************************/
7876 /* constants for EnumPrinterKey() */
7877 #define ENUMERATED_KEY_SIZE 19
7879 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7881 fstring key;
7882 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
7883 fstring PrinterKey;
7884 UNISTR2 uni_keys;
7885 int enum_key_len;
7887 DEBUG(4,("_spoolss_enumprinterkey\n"));
7889 unistr2_to_dos(key, &q_u->key, sizeof(key) - 1);
7891 ZERO_STRUCTP(PrinterKey);
7892 fstrcpy( PrinterKey, "PrinterDriverData" );
7894 /* add space for 2 terminating NULLs */
7896 enum_key_len = strlen( PrinterKey ) + 2;
7900 * we only support enumating all keys (key == "")
7901 * Of course, the only key we support is the "PrinterDriverData"
7902 * key
7904 if (strlen(key) == 0)
7906 r_u->needed = enum_key_len*2;
7907 if (q_u->size < r_u->needed)
7908 return WERR_MORE_DATA;
7910 init_unistr2( &uni_keys, PrinterKey, enum_key_len );
7912 if ( !make_spoolss_buffer5(p->mem_ctx, &r_u->keys, enum_key_len, uni_keys.buffer) )
7913 return WERR_BADFILE;
7915 return WERR_OK;
7918 /* The "PrinterDriverData" key should have no subkeys */
7919 if (strcmp(key, PrinterKey) == 0)
7921 r_u-> needed = 2;
7922 if (q_u->size < r_u->needed)
7923 return WERR_MORE_DATA;
7924 enumkeys[0] = 0x0;
7925 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7926 return WERR_BADFILE;
7928 return WERR_OK;
7932 /* The return value for an unknown key is documented in MSDN
7933 EnumPrinterKey description */
7934 return WERR_BADFILE;
7937 /********************************************************************
7938 * spoolss_enumprinterdataex
7939 ********************************************************************/
7941 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7943 POLICY_HND *handle = &q_u->handle;
7944 uint32 in_size = q_u->size;
7945 uint32 num_entries,
7946 needed;
7947 NT_PRINTER_INFO_LEVEL *printer = NULL;
7948 PRINTER_ENUM_VALUES *enum_values = NULL;
7949 fstring key, value;
7950 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7951 int snum;
7952 uint32 param_index,
7953 data_len,
7954 type;
7955 WERROR result;
7956 uint8 *data=NULL;
7959 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7961 if (!Printer) {
7962 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
7963 return WERR_BADFID;
7968 * The only key we support is "PrinterDriverData". This should return
7969 > an array of all the key/value pairs returned by EnumPrinterDataSee
7970 * _spoolss_getprinterdataex() for details --jerry
7973 unistr2_to_dos(key, &q_u->key, sizeof(key) - 1);
7974 if (strcmp(key, "PrinterDriverData") != 0)
7976 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7977 return WERR_INVALID_PARAM;
7981 if (!get_printer_snum(p,handle, &snum))
7982 return WERR_BADFID;
7984 ZERO_STRUCT(printer);
7985 result = get_a_printer(&printer, 2, lp_servicename(snum));
7986 if (!W_ERROR_IS_OK(result))
7987 return result;
7991 * loop through all params and build the array to pass
7992 * back to the client
7994 result = WERR_OK;
7995 param_index = 0;
7996 needed = 0;
7997 num_entries = 0;
7999 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
8001 PRINTER_ENUM_VALUES *ptr;
8003 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
8005 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
8007 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
8008 result = WERR_NOMEM;
8009 goto done;
8011 enum_values = ptr;
8013 ZERO_STRUCTP( &enum_values[num_entries] );
8015 /* copy the data */
8017 init_unistr(&enum_values[num_entries].valuename, value);
8018 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
8019 enum_values[num_entries].type = type;
8021 if ( data_len )
8023 if ( !(enum_values[num_entries].data = talloc_zero(p->mem_ctx, data_len)) ) {
8024 DEBUG(0,("talloc_realloc failed to allocate more memory [data_len=%d] for data!\n", data_len ));
8025 result = WERR_NOMEM;
8026 goto done;
8028 memcpy(enum_values[num_entries].data, data, data_len);
8031 enum_values[num_entries].data_len = data_len;
8033 /* keep track of the size of the array in bytes */
8035 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
8037 num_entries++;
8038 param_index++;
8041 r_u->needed = needed;
8042 r_u->returned = num_entries;
8044 if (needed > in_size) {
8045 result = WERR_MORE_DATA;
8046 goto done;
8049 /* copy data into the reply */
8051 r_u->ctr.size = r_u->needed;
8052 r_u->ctr.size_of_array = r_u->returned;
8053 r_u->ctr.values = enum_values;
8057 done:
8058 free_a_printer(&printer, 2);
8060 return result;
8063 /****************************************************************************
8064 ****************************************************************************/
8066 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8068 init_unistr(&info->name, name);
8071 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8072 UNISTR2 *environment,
8073 NEW_BUFFER *buffer,
8074 uint32 offered,
8075 uint32 *needed)
8077 pstring path;
8078 pstring long_archi;
8079 pstring short_archi;
8080 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8082 unistr2_to_dos(long_archi, environment, sizeof(long_archi)-1);
8084 if (get_short_archi(short_archi, long_archi)==False)
8085 return WERR_INVALID_ENVIRONMENT;
8087 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8088 return WERR_NOMEM;
8090 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8092 fill_printprocessordirectory_1(info, path);
8094 *needed += spoolss_size_printprocessordirectory_info_1(info);
8096 if (!alloc_buffer_size(buffer, *needed)) {
8097 safe_free(info);
8098 return WERR_INSUFFICIENT_BUFFER;
8101 smb_io_printprocessordirectory_1("", buffer, info, 0);
8103 safe_free(info);
8105 if (*needed > offered)
8106 return WERR_INSUFFICIENT_BUFFER;
8107 else
8108 return WERR_OK;
8111 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8113 uint32 level = q_u->level;
8114 NEW_BUFFER *buffer = NULL;
8115 uint32 offered = q_u->offered;
8116 uint32 *needed = &r_u->needed;
8117 WERROR result;
8119 /* that's an [in out] buffer */
8120 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8121 buffer = r_u->buffer;
8123 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8125 *needed=0;
8127 switch(level) {
8128 case 1:
8129 result = getprintprocessordirectory_level_1
8130 (&q_u->name, &q_u->environment, buffer, offered, needed);
8131 break;
8132 default:
8133 result = WERR_UNKNOWN_LEVEL;
8136 return result;