Fairly large change to printing code.
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob2aa11530f80032c8ef854d95aad451fd9bdec700
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001,
8 * Copyright (C) Gerald Carter 2000-2002,
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 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
33 /* #define EMULATE_WIN2K_HACK 1 */
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41 #define PRINTER_HANDLE_IS_PRINTER 0
42 #define PRINTER_HANDLE_IS_PRINTSERVER 1
44 /* Table to map the driver version */
45 /* to OS */
46 char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
48 "", /* unused ? */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 struct table_node {
54 char *long_archi;
55 char *short_archi;
56 int version;
60 /* structure to store the printer handles */
61 /* and a reference to what it's pointing to */
62 /* and the notify info asked about */
63 /* that's the central struct */
64 typedef struct _Printer{
65 struct _Printer *prev, *next;
66 BOOL document_started;
67 BOOL page_started;
68 uint32 jobid; /* jobid in printing backend */
69 BOOL printer_type;
70 union {
71 fstring handlename;
72 fstring printerservername;
73 } dev;
74 uint32 type;
75 uint32 access_granted;
76 struct {
77 uint32 flags;
78 uint32 options;
79 fstring localmachine;
80 uint32 printerlocal;
81 SPOOL_NOTIFY_OPTION *option;
82 POLICY_HND client_hnd;
83 uint32 client_connected;
84 uint32 change;
85 } notify;
86 struct {
87 fstring machine;
88 fstring user;
89 } client;
90 } Printer_entry;
92 static Printer_entry *printers_list;
94 typedef struct _counter_printer_0 {
95 ubi_dlNode Next;
96 ubi_dlNode Prev;
98 int snum;
99 uint32 counter;
100 } counter_printer_0;
102 static ubi_dlList counter_list;
104 static struct cli_state notify_cli; /* print notify back-channel */
105 static uint32 smb_connections=0;
108 /* in printing/nt_printing.c */
110 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
112 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
113 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
115 /* translate between internal status numbers and NT status numbers */
116 static int nt_printj_status(int v)
118 switch (v) {
119 case LPQ_QUEUED:
120 return 0;
121 case LPQ_PAUSED:
122 return JOB_STATUS_PAUSED;
123 case LPQ_SPOOLING:
124 return JOB_STATUS_SPOOLING;
125 case LPQ_PRINTING:
126 return JOB_STATUS_PRINTING;
127 case LPQ_ERROR:
128 return JOB_STATUS_ERROR;
129 case LPQ_DELETING:
130 return JOB_STATUS_DELETING;
131 case LPQ_OFFLINE:
132 return JOB_STATUS_OFFLINE;
133 case LPQ_PAPEROUT:
134 return JOB_STATUS_PAPEROUT;
135 case LPQ_PRINTED:
136 return JOB_STATUS_PRINTED;
137 case LPQ_DELETED:
138 return JOB_STATUS_DELETED;
139 case LPQ_BLOCKED:
140 return JOB_STATUS_BLOCKED;
141 case LPQ_USER_INTERVENTION:
142 return JOB_STATUS_USER_INTERVENTION;
144 return 0;
147 static int nt_printq_status(int v)
149 switch (v) {
150 case LPQ_PAUSED:
151 return PRINTER_STATUS_PAUSED;
152 case LPQ_QUEUED:
153 case LPQ_SPOOLING:
154 case LPQ_PRINTING:
155 return 0;
157 return 0;
160 /****************************************************************************
161 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
162 ****************************************************************************/
164 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
166 if (*pp == NULL)
167 return;
169 SAFE_FREE((*pp)->ctr.type);
170 SAFE_FREE(*pp);
173 /***************************************************************************
174 Disconnect from the client
175 ****************************************************************************/
177 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
179 WERROR result;
181 /* weird if the test succeds !!! */
182 if (smb_connections==0) {
183 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
184 return;
187 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
189 if (!W_ERROR_IS_OK(result))
190 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
191 dos_errstr(result)));
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
195 cli_nt_session_close(&notify_cli);
196 cli_ulogoff(&notify_cli);
197 cli_shutdown(&notify_cli);
198 message_deregister(MSG_PRINTER_NOTIFY2);
201 smb_connections--;
204 /****************************************************************************
205 Functions to free a printer entry datastruct.
206 ****************************************************************************/
208 static void free_printer_entry(void *ptr)
210 Printer_entry *Printer = (Printer_entry *)ptr;
212 if (Printer->notify.client_connected==True)
213 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
215 Printer->notify.flags=0;
216 Printer->notify.options=0;
217 Printer->notify.localmachine[0]='\0';
218 Printer->notify.printerlocal=0;
219 free_spool_notify_option(&Printer->notify.option);
220 Printer->notify.option=NULL;
221 Printer->notify.client_connected=False;
223 /* Remove from the internal list. */
224 DLIST_REMOVE(printers_list, Printer);
226 SAFE_FREE(Printer);
229 /****************************************************************************
230 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
231 ****************************************************************************/
233 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
235 SPOOL_NOTIFY_OPTION *new_sp = NULL;
237 if (!sp)
238 return NULL;
240 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
241 if (!new_sp)
242 return NULL;
244 *new_sp = *sp;
246 if (sp->ctr.count) {
247 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
249 if (!new_sp->ctr.type) {
250 SAFE_FREE(new_sp);
251 return NULL;
255 return new_sp;
258 /****************************************************************************
259 find printer index by handle
260 ****************************************************************************/
262 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
264 Printer_entry *find_printer = NULL;
266 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
267 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
268 return NULL;
271 return find_printer;
274 /****************************************************************************
275 Close printer index by handle.
276 ****************************************************************************/
278 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
280 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
282 if (!Printer) {
283 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
284 return False;
287 close_policy_hnd(p, hnd);
289 return True;
292 /****************************************************************************
293 Delete a printer given a handle.
294 ****************************************************************************/
296 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
298 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
300 if (!Printer) {
301 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
302 return WERR_BADFID;
305 if (del_a_printer(Printer->dev.handlename) != 0) {
306 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
307 return WERR_BADFID;
310 /* Check calling user has permission to delete printer. Note that
311 since we set the snum parameter to -1 only administrators can
312 delete the printer. This stops people with the Full Control
313 permission from deleting the printer. */
315 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
316 DEBUG(3, ("printer delete denied by security descriptor\n"));
317 return WERR_ACCESS_DENIED;
320 if (*lp_deleteprinter_cmd()) {
322 char *cmd = lp_deleteprinter_cmd();
323 pstring command;
324 int ret;
325 int i;
327 /* Printer->dev.handlename equals portname equals sharename */
328 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
329 Printer->dev.handlename);
331 DEBUG(10,("Running [%s]\n", command));
332 ret = smbrun(command, NULL);
333 if (ret != 0) {
334 return WERR_BADFID; /* What to return here? */
336 DEBUGADD(10,("returned [%d]\n", ret));
338 /* Send SIGHUP to process group... is there a better way? */
339 kill(0, SIGHUP);
341 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
342 lp_killservice( i );
343 return WERR_OK;
344 } else
345 return WERR_ACCESS_DENIED;
348 return WERR_OK;
351 /****************************************************************************
352 Return the snum of a printer corresponding to an handle.
353 ****************************************************************************/
355 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
357 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
359 if (!Printer) {
360 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
361 return False;
364 switch (Printer->printer_type) {
365 case PRINTER_HANDLE_IS_PRINTER:
366 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
367 *number = print_queue_snum(Printer->dev.handlename);
368 return (*number != -1);
369 case PRINTER_HANDLE_IS_PRINTSERVER:
370 return False;
371 default:
372 return False;
376 /****************************************************************************
377 Set printer handle type.
378 Check if it's \\server or \\server\printer
379 ****************************************************************************/
381 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
383 DEBUG(3,("Setting printer type=%s\n", handlename));
385 if ( strlen(handlename) < 3 ) {
386 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
387 return False;
390 /* it's a print server */
391 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
392 DEBUGADD(4,("Printer is a print server\n"));
393 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
395 /* it's a printer */
396 else {
397 DEBUGADD(4,("Printer is a printer\n"));
398 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
401 return True;
404 /****************************************************************************
405 Set printer handle name.
406 ****************************************************************************/
408 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
410 int snum;
411 int n_services=lp_numservices();
412 char *aprinter;
413 fstring sname;
414 BOOL found=False;
416 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
418 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
419 ZERO_STRUCT(Printer->dev.printerservername);
420 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
421 return True;
424 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
425 return False;
427 if (*handlename=='\\') {
428 aprinter=strchr_m(handlename+2, '\\');
429 aprinter++;
431 else {
432 aprinter=handlename;
435 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
438 * The original code allowed smbd to store a printer name that
439 * was different from the share name. This is not possible
440 * anymore, so I've simplified this loop greatly. Here
441 * we are just verifying that the printer name is a valid
442 * printer service defined in smb.conf
443 * --jerry [Fri Feb 15 11:17:46 CST 2002]
446 for (snum=0; snum<n_services; snum++) {
448 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
449 continue;
451 fstrcpy(sname, lp_servicename(snum));
453 DEBUGADD(5,("share:%s\n",sname));
455 if (! StrCaseCmp(sname, aprinter)) {
456 found = True;
457 break;
463 if (!found) {
464 DEBUGADD(4,("Printer not found\n"));
465 return False;
468 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
470 ZERO_STRUCT(Printer->dev.handlename);
471 fstrcpy(Printer->dev.handlename, sname);
473 return True;
476 /****************************************************************************
477 Find first available printer slot. creates a printer handle for you.
478 ****************************************************************************/
480 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
482 Printer_entry *new_printer;
484 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
486 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
487 return False;
489 ZERO_STRUCTP(new_printer);
491 new_printer->notify.option=NULL;
493 /* Add to the internal list. */
494 DLIST_ADD(printers_list, new_printer);
496 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
497 SAFE_FREE(new_printer);
498 return False;
501 if (!set_printer_hnd_printertype(new_printer, name)) {
502 close_printer_handle(p, hnd);
503 return False;
506 if (!set_printer_hnd_name(new_printer, name)) {
507 close_printer_handle(p, hnd);
508 return False;
511 new_printer->access_granted = access_granted;
513 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
515 return True;
518 /****************************************************************************
519 Allocate more memory for a BUFFER.
520 ****************************************************************************/
522 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
524 prs_struct *ps;
525 uint32 extra_space;
526 uint32 old_offset;
528 ps= &buffer->prs;
530 /* damn, I'm doing the reverse operation of prs_grow() :) */
531 if (buffer_size < prs_data_size(ps))
532 extra_space=0;
533 else
534 extra_space = buffer_size - prs_data_size(ps);
537 * save the offset and move to the end of the buffer
538 * prs_grow() checks the extra_space against the offset
540 old_offset=prs_offset(ps);
541 prs_set_offset(ps, prs_data_size(ps));
543 if (!prs_grow(ps, extra_space))
544 return False;
546 prs_set_offset(ps, old_offset);
548 buffer->string_at_end=prs_data_size(ps);
550 return True;
553 /***************************************************************************
554 check to see if the client motify handle is monitoring the notification
555 given by (notify_type, notify_field).
556 **************************************************************************/
558 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
559 uint16 notify_field)
561 return True;
564 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
565 uint16 notify_field)
567 SPOOL_NOTIFY_OPTION *option = p->notify.option;
568 uint32 i, j;
570 if (p->notify.flags)
571 return is_monitoring_event_flags(
572 p->notify.flags, notify_type, notify_field);
574 for (i = 0; i < option->count; i++) {
576 /* Check match for notify_type */
578 if (option->ctr.type[i].type != notify_type)
579 continue;
581 /* Check match for field */
583 for (j = 0; j < option->ctr.type[i].count; j++) {
584 if (option->ctr.type[i].fields[j] == notify_field) {
585 return True;
590 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
591 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
592 p->dev.handlename : p->dev.printerservername,
593 notify_type, notify_field));
595 return False;
598 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
600 static void notify_one_value(struct spoolss_notify_msg *msg,
601 SPOOL_NOTIFY_INFO_DATA *data,
602 TALLOC_CTX *mem_ctx)
604 data->notify_data.value[0] = msg->notify.value[0];
605 data->notify_data.value[1] = 0;
608 static void notify_string(struct spoolss_notify_msg *msg,
609 SPOOL_NOTIFY_INFO_DATA *data,
610 TALLOC_CTX *mem_ctx)
612 UNISTR2 unistr;
614 /* The length of the message includes the trailing \0 */
616 init_unistr2(&unistr, msg->notify.data, msg->len);
618 data->notify_data.data.length = msg->len * 2;
619 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
621 if (!data->notify_data.data.string) {
622 data->notify_data.data.length = 0;
623 return;
626 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
629 static void notify_system_time(struct spoolss_notify_msg *msg,
630 SPOOL_NOTIFY_INFO_DATA *data,
631 TALLOC_CTX *mem_ctx)
633 SYSTEMTIME systime;
634 prs_struct ps;
636 if (msg->len != sizeof(time_t)) {
637 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
638 msg->len));
639 return;
642 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
643 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
644 return;
647 if (!make_systemtime(&systime, localtime((time_t *)msg->notify.data))) {
648 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
649 return;
652 if (!spoolss_io_system_time("", &ps, 0, &systime))
653 return;
655 data->notify_data.data.length = prs_offset(&ps);
656 data->notify_data.data.string =
657 talloc(mem_ctx, prs_offset(&ps));
659 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
661 prs_mem_free(&ps);
664 struct notify2_message_table {
665 char *name;
666 void (*fn)(struct spoolss_notify_msg *msg,
667 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
670 static struct notify2_message_table printer_notify_table[] = {
671 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
672 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
673 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
674 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
675 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
676 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
677 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
678 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
679 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
680 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
681 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
682 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
683 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
684 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
685 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
686 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
687 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
688 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
689 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
692 static struct notify2_message_table job_notify_table[] = {
693 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
694 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
695 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
696 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
697 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
698 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
699 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
700 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
701 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
702 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
703 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
704 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
705 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
706 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
707 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
708 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
709 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
710 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
711 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
712 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
713 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
714 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
715 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
716 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
719 /***********************************************************************
720 Send a change notication message on all handles which have a call
721 back registered
722 **********************************************************************/
724 static void process_notify2_message(struct spoolss_notify_msg *msg,
725 TALLOC_CTX *mem_ctx)
727 Printer_entry *p;
729 DEBUG(8,("process_notify2_message: Enter...[%s]\n", msg->printer));
731 for (p = printers_list; p; p = p->next) {
732 SPOOL_NOTIFY_INFO_DATA *data;
733 uint32 data_len = 1;
734 uint32 id;
736 /* Is there notification on this handle? */
738 if (!p->notify.client_connected)
739 continue;
741 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
743 /* For this printer? Print servers always receive
744 notifications. */
746 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
747 ( !strequal(msg->printer, p->dev.handlename) ) )
748 continue;
750 DEBUG(10,("Our printer\n"));
752 /* Are we monitoring this event? */
754 if (!is_monitoring_event(p, msg->type, msg->field))
755 continue;
757 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
758 msg->type, msg->field, p->dev.handlename));
760 /* OK - send the event to the client */
762 data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA));
764 ZERO_STRUCTP(data);
767 * if the is a printer notification handle and not a job notification
768 * type, then set the id to 0. Other wise just use what was specified
769 * in the message.
771 * When registering change notification on a print server handle
772 * we always need to send back the id (snum) matching the printer
773 * for which the change took place. For change notify registered
774 * on a printer handle, this does not matter and the id should be 0.
776 * --jerry
779 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
780 id = 0;
781 else
782 id = msg->id;
785 /* Convert unix jobid to smb jobid */
787 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
789 id = sysjob_to_jobid(msg->id);
791 if (id == -1) {
792 DEBUG(3, ("no such unix jobid %d\n", msg->id));
793 goto done;
797 construct_info_data(data, msg->type, msg->field, id);
799 switch(msg->type) {
800 case PRINTER_NOTIFY_TYPE:
801 if ( !printer_notify_table[msg->field].fn )
802 goto done;
804 printer_notify_table[msg->field].fn(msg, data, mem_ctx);
806 break;
808 case JOB_NOTIFY_TYPE:
809 if ( !job_notify_table[msg->field].fn )
810 goto done;
812 job_notify_table[msg->field].fn(msg, data, mem_ctx);
814 break;
816 default:
817 DEBUG(5, ("Unknown notification type %d\n", msg->type));
818 goto done;
821 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
822 data_len, data, p->notify.change, 0 );
824 done:
825 DEBUG(8,("process_notify2_message: Exit...\n"));
826 return;
829 /* Receive a notify2 message */
831 static void receive_notify2_message(int msg_type, pid_t src, void *buf,
832 size_t len)
834 struct spoolss_notify_msg msg;
835 int offset = 0;
836 TALLOC_CTX *mem_ctx = talloc_init();
838 /* Unpack message */
840 ZERO_STRUCT(msg);
842 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
843 msg.printer);
845 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
846 &msg.type, &msg.field, &msg.id, &msg.len, &msg.flags);
848 if (msg.len == 0)
849 tdb_unpack((char *)buf + offset, len - offset, "dd",
850 &msg.notify.value[0], &msg.notify.value[1]);
851 else
852 tdb_unpack((char *)buf + offset, len - offset, "B",
853 &msg.len, &msg.notify.data);
855 DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
856 msg.type, msg.field, msg.flags));
858 if (msg.len == 0)
859 DEBUG(3, ("value1 = %d, value2 = %d\n", msg.notify.value[0],
860 msg.notify.value[1]));
861 else
862 dump_data(3, msg.notify.data, msg.len);
864 /* Process message */
866 process_notify2_message(&msg, mem_ctx);
868 /* Free message */
870 if (msg.len > 0)
871 free(msg.notify.data);
873 talloc_destroy(mem_ctx);
876 /********************************************************************
877 Send a message to ourself about new driver being installed
878 so we can upgrade the information for each printer bound to this
879 driver
880 ********************************************************************/
882 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
884 int len = strlen(drivername);
886 if (!len)
887 return False;
889 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
890 drivername));
892 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
894 return True;
897 /**********************************************************************
898 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
899 over all printers, upgrading ones as neessary
900 **********************************************************************/
902 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
904 fstring drivername;
905 int snum;
906 int n_services = lp_numservices();
908 len = MIN(len,sizeof(drivername)-1);
909 strncpy(drivername, buf, len);
911 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
913 /* Iterate the printer list */
915 for (snum=0; snum<n_services; snum++)
917 if (lp_snum_ok(snum) && lp_print_ok(snum) )
919 WERROR result;
920 NT_PRINTER_INFO_LEVEL *printer = NULL;
922 result = get_a_printer(&printer, 2, lp_servicename(snum));
923 if (!W_ERROR_IS_OK(result))
924 continue;
926 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
928 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
930 /* all we care about currently is the change_id */
932 result = mod_a_printer(*printer, 2);
933 if (!W_ERROR_IS_OK(result)) {
934 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
935 dos_errstr(result)));
939 free_a_printer(&printer, 2);
943 /* all done */
946 /********************************************************************
947 Send a message to ourself about new driver being installed
948 so we can upgrade the information for each printer bound to this
949 driver
950 ********************************************************************/
952 static BOOL srv_spoolss_reset_printerdata(char* drivername)
954 int len = strlen(drivername);
956 if (!len)
957 return False;
959 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
960 drivername));
962 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
964 return True;
967 /**********************************************************************
968 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
969 over all printers, resetting printer data as neessary
970 **********************************************************************/
972 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
974 fstring drivername;
975 int snum;
976 int n_services = lp_numservices();
978 len = MIN( len, sizeof(drivername)-1 );
979 strncpy( drivername, buf, len );
981 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
983 /* Iterate the printer list */
985 for ( snum=0; snum<n_services; snum++ )
987 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
989 WERROR result;
990 NT_PRINTER_INFO_LEVEL *printer = NULL;
992 result = get_a_printer( &printer, 2, lp_servicename(snum) );
993 if ( !W_ERROR_IS_OK(result) )
994 continue;
997 * if the printer is bound to the driver,
998 * then reset to the new driver initdata
1001 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1003 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1005 if ( !set_driver_init(printer, 2) ) {
1006 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1007 printer->info_2->printername, printer->info_2->drivername));
1011 free_a_printer( &printer, 2 );
1015 /* all done */
1017 return;
1020 /********************************************************************
1021 Copy routines used by convert_to_openprinterex()
1022 *******************************************************************/
1024 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1026 DEVICEMODE *d;
1027 int len;
1029 if (!devmode)
1030 return NULL;
1032 DEBUG (8,("dup_devmode\n"));
1034 /* bulk copy first */
1036 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1037 if (!d)
1038 return NULL;
1040 /* dup the pointer members separately */
1042 len = unistrlen(devmode->devicename.buffer);
1043 if (len != -1) {
1044 d->devicename.buffer = talloc(ctx, len*2);
1045 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1046 return NULL;
1050 len = unistrlen(devmode->formname.buffer);
1051 if (len != -1) {
1052 d->devicename.buffer = talloc(ctx, len*2);
1053 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1054 return NULL;
1057 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1059 return d;
1062 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1064 if (!new_ctr || !ctr)
1065 return;
1067 DEBUG(8,("copy_devmode_ctr\n"));
1069 new_ctr->size = ctr->size;
1070 new_ctr->devmode_ptr = ctr->devmode_ptr;
1072 if(ctr->devmode_ptr)
1073 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1076 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1078 if (!new_def || !def)
1079 return;
1081 DEBUG(8,("copy_printer_defaults\n"));
1083 new_def->datatype_ptr = def->datatype_ptr;
1085 if (def->datatype_ptr)
1086 copy_unistr2(&new_def->datatype, &def->datatype);
1088 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1090 new_def->access_required = def->access_required;
1093 /********************************************************************
1094 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1095 * SPOOL_Q_OPEN_PRINTER_EX structure
1096 ********************************************************************/
1098 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1100 if (!q_u_ex || !q_u)
1101 return;
1103 DEBUG(8,("convert_to_openprinterex\n"));
1105 q_u_ex->printername_ptr = q_u->printername_ptr;
1107 if (q_u->printername_ptr)
1108 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1110 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1113 /********************************************************************
1114 * spoolss_open_printer
1116 * called from the spoolss dispatcher
1117 ********************************************************************/
1119 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1121 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1122 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1124 if (!q_u || !r_u)
1125 return WERR_NOMEM;
1127 ZERO_STRUCT(q_u_ex);
1128 ZERO_STRUCT(r_u_ex);
1130 /* convert the OpenPrinter() call to OpenPrinterEx() */
1132 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1134 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1136 /* convert back to OpenPrinter() */
1138 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1140 return r_u->status;
1143 /********************************************************************
1144 * spoolss_open_printer
1146 * called from the spoolss dispatcher
1147 ********************************************************************/
1149 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1151 UNISTR2 *printername = NULL;
1152 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1153 POLICY_HND *handle = &r_u->handle;
1155 fstring name;
1156 int snum;
1157 struct current_user user;
1158 Printer_entry *Printer=NULL;
1160 if (q_u->printername_ptr != 0)
1161 printername = &q_u->printername;
1163 if (printername == NULL)
1164 return WERR_INVALID_PRINTER_NAME;
1166 /* some sanity check because you can open a printer or a print server */
1167 /* aka: \\server\printer or \\server */
1168 unistr2_to_ascii(name, printername, sizeof(name)-1);
1170 DEBUGADD(3,("checking name: %s\n",name));
1172 if (!open_printer_hnd(p, handle, name, 0))
1173 return WERR_INVALID_PRINTER_NAME;
1175 Printer=find_printer_index_by_hnd(p, handle);
1176 if (!Printer) {
1177 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1178 Can't find printer handle we created for printer %s\n", name ));
1179 close_printer_handle(p,handle);
1180 return WERR_INVALID_PRINTER_NAME;
1184 First case: the user is opening the print server:
1186 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1187 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1189 Then both Win2k and WinNT clients try an OpenPrinterEx with
1190 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1191 or if the user is listed in the smb.conf printer admin parameter.
1193 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1194 client view printer folder, but does not show the MSAPW.
1196 Note: this test needs code to check access rights here too. Jeremy
1197 could you look at this?
1200 Second case: the user is opening a printer:
1201 NT doesn't let us connect to a printer if the connecting user
1202 doesn't have print permission.
1206 get_current_user(&user, p);
1208 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
1210 /* Printserver handles use global struct... */
1212 snum = -1;
1214 /* Map standard access rights to object specific access
1215 rights */
1217 se_map_standard(&printer_default->access_required,
1218 &printserver_std_mapping);
1220 /* Deny any object specific bits that don't apply to print
1221 servers (i.e printer and job specific bits) */
1223 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1225 if (printer_default->access_required &
1226 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1227 DEBUG(3, ("access DENIED for non-printserver bits"));
1228 close_printer_handle(p, handle);
1229 return WERR_ACCESS_DENIED;
1232 /* Allow admin access */
1234 if (printer_default->access_required &
1235 SERVER_ACCESS_ADMINISTER) {
1237 if (!lp_ms_add_printer_wizard()) {
1238 close_printer_handle(p, handle);
1239 return WERR_ACCESS_DENIED;
1242 if (user.uid == 0 ||
1243 user_in_list(uidtoname(user.uid),
1244 lp_printer_admin(snum)))
1245 return WERR_OK;
1247 close_printer_handle(p, handle);
1248 return WERR_ACCESS_DENIED;
1251 /* We fall through to return WERR_OK */
1254 else
1256 /* NT doesn't let us connect to a printer if the connecting user
1257 doesn't have print permission. */
1259 if (!get_printer_snum(p, handle, &snum))
1260 return WERR_BADFID;
1262 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1264 /* map an empty access mask to the minimum access mask */
1265 if (printer_default->access_required == 0x0)
1266 printer_default->access_required = PRINTER_ACCESS_USE;
1269 * If we are not serving the printer driver for this printer,
1270 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1271 * will keep NT clients happy --jerry
1274 if (lp_use_client_driver(snum)
1275 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1277 printer_default->access_required = PRINTER_ACCESS_USE;
1280 /* check smb.conf parameters and the the sec_desc */
1282 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1283 DEBUG(3, ("access DENIED for printer open\n"));
1284 close_printer_handle(p, handle);
1285 return WERR_ACCESS_DENIED;
1288 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1289 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1290 close_printer_handle(p, handle);
1291 return WERR_ACCESS_DENIED;
1294 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1295 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1296 else
1297 printer_default->access_required = PRINTER_ACCESS_USE;
1299 DEBUG(4,("Setting printer access=%x\n", printer_default->access_required));
1300 Printer->access_granted = printer_default->access_required;
1303 * If we have a default device pointer in the
1304 * printer_default struct, then we need to get
1305 * the printer info from the tdb and if there is
1306 * no default devicemode there then we do a *SET*
1307 * here ! This is insanity.... JRA.
1311 * If the openprinterex rpc call contains a devmode,
1312 * it's a per-user one. This per-user devmode is derivated
1313 * from the global devmode. Openprinterex() contains a per-user
1314 * devmode for when you do EMF printing and spooling.
1315 * In the EMF case, the NT workstation is only doing half the job
1316 * of rendering the page. The other half is done by running the printer
1317 * driver on the server.
1318 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1319 * The EMF file only contains what is to be printed on the page.
1320 * So in order for the server to know how to print, the NT client sends
1321 * a devicemode attached to the openprinterex call.
1322 * But this devicemode is short lived, it's only valid for the current print job.
1324 * If Samba would have supported EMF spooling, this devicemode would
1325 * have been attached to the handle, to sent it to the driver to correctly
1326 * rasterize the EMF file.
1328 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1329 * we just act as a pass-thru between windows and the printer.
1331 * In order to know that Samba supports only RAW spooling, NT has to call
1332 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1333 * and until NT sends a RAW job, we refuse it.
1335 * But to call getprinter() or startdoc(), you first need a valid handle,
1336 * and to get an handle you have to call openprintex(). Hence why you have
1337 * a devicemode in the openprinterex() call.
1340 * Differences between NT4 and NT 2000.
1341 * NT4:
1342 * ---
1343 * On NT4, you only have a global devicemode. This global devicemode can be changed
1344 * by the administrator (or by a user with enough privs). Everytime a user
1345 * wants to print, the devicemode is resetted to the default. In Word, everytime
1346 * you print, the printer's characteristics are always reset to the global devicemode.
1348 * NT 2000:
1349 * -------
1350 * In W2K, there is the notion of per-user devicemode. The first time you use
1351 * a printer, a per-user devicemode is build from the global devicemode.
1352 * If you change your per-user devicemode, it is saved in the registry, under the
1353 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1354 * printer preferences available.
1356 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1357 * on the General Tab of the printer properties windows.
1359 * To change the global devicemode: it's the "Printing Defaults..." button
1360 * on the Advanced Tab of the printer properties window.
1362 * JFM.
1367 #if 0
1368 if (printer_default->devmode_cont.devmode != NULL) {
1369 result = printer_write_default_dev( snum, printer_default);
1370 if (result != 0) {
1371 close_printer_handle(p, handle);
1372 return result;
1375 #endif
1378 return WERR_OK;
1381 /****************************************************************************
1382 ****************************************************************************/
1384 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1385 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1387 BOOL ret = True;
1389 switch (level) {
1390 case 2:
1391 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1392 break;
1393 default:
1394 break;
1397 return ret;
1400 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1401 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1403 BOOL result = True;
1405 switch (level) {
1406 case 3:
1407 printer->info_3=NULL;
1408 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1409 result = False;
1410 break;
1411 case 6:
1412 printer->info_6=NULL;
1413 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1414 result = False;
1415 break;
1416 default:
1417 break;
1420 return result;
1423 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1424 NT_DEVICEMODE **pp_nt_devmode)
1426 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1429 * Ensure nt_devmode is a valid pointer
1430 * as we will be overwriting it.
1433 if (nt_devmode == NULL) {
1434 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1435 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1436 return False;
1439 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1440 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1442 nt_devmode->specversion=devmode->specversion;
1443 nt_devmode->driverversion=devmode->driverversion;
1444 nt_devmode->size=devmode->size;
1445 nt_devmode->fields=devmode->fields;
1446 nt_devmode->orientation=devmode->orientation;
1447 nt_devmode->papersize=devmode->papersize;
1448 nt_devmode->paperlength=devmode->paperlength;
1449 nt_devmode->paperwidth=devmode->paperwidth;
1450 nt_devmode->scale=devmode->scale;
1451 nt_devmode->copies=devmode->copies;
1452 nt_devmode->defaultsource=devmode->defaultsource;
1453 nt_devmode->printquality=devmode->printquality;
1454 nt_devmode->color=devmode->color;
1455 nt_devmode->duplex=devmode->duplex;
1456 nt_devmode->yresolution=devmode->yresolution;
1457 nt_devmode->ttoption=devmode->ttoption;
1458 nt_devmode->collate=devmode->collate;
1460 nt_devmode->logpixels=devmode->logpixels;
1461 nt_devmode->bitsperpel=devmode->bitsperpel;
1462 nt_devmode->pelswidth=devmode->pelswidth;
1463 nt_devmode->pelsheight=devmode->pelsheight;
1464 nt_devmode->displayflags=devmode->displayflags;
1465 nt_devmode->displayfrequency=devmode->displayfrequency;
1466 nt_devmode->icmmethod=devmode->icmmethod;
1467 nt_devmode->icmintent=devmode->icmintent;
1468 nt_devmode->mediatype=devmode->mediatype;
1469 nt_devmode->dithertype=devmode->dithertype;
1470 nt_devmode->reserved1=devmode->reserved1;
1471 nt_devmode->reserved2=devmode->reserved2;
1472 nt_devmode->panningwidth=devmode->panningwidth;
1473 nt_devmode->panningheight=devmode->panningheight;
1476 * Only change private and driverextra if the incoming devmode
1477 * has a new one. JRA.
1480 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1481 SAFE_FREE(nt_devmode->private);
1482 nt_devmode->driverextra=devmode->driverextra;
1483 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1484 return False;
1485 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1488 *pp_nt_devmode = nt_devmode;
1490 return True;
1493 /********************************************************************
1494 * _spoolss_enddocprinter_internal.
1495 ********************************************************************/
1497 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1499 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1500 int snum;
1502 if (!Printer) {
1503 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1504 return WERR_BADFID;
1507 if (!get_printer_snum(p, handle, &snum))
1508 return WERR_BADFID;
1510 Printer->document_started=False;
1511 print_job_end(snum, Printer->jobid,True);
1512 /* error codes unhandled so far ... */
1514 return WERR_OK;
1517 /********************************************************************
1518 * api_spoolss_closeprinter
1519 ********************************************************************/
1521 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1523 POLICY_HND *handle = &q_u->handle;
1525 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1527 if (Printer && Printer->document_started)
1528 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1530 if (!close_printer_handle(p, handle))
1531 return WERR_BADFID;
1533 /* clear the returned printer handle. Observed behavior
1534 from Win2k server. Don't think this really matters.
1535 Previous code just copied the value of the closed
1536 handle. --jerry */
1538 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1540 return WERR_OK;
1543 /********************************************************************
1544 * api_spoolss_deleteprinter
1546 ********************************************************************/
1548 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1550 POLICY_HND *handle = &q_u->handle;
1551 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1552 WERROR result;
1554 if (Printer && Printer->document_started)
1555 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1557 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1559 result = delete_printer_handle(p, handle);
1561 update_c_setprinter(False);
1563 return result;
1566 /*******************************************************************
1567 * static function to lookup the version id corresponding to an
1568 * long architecture string
1569 ******************************************************************/
1571 static int get_version_id (char * arch)
1573 int i;
1574 struct table_node archi_table[]= {
1576 {"Windows 4.0", "WIN40", 0 },
1577 {"Windows NT x86", "W32X86", 2 },
1578 {"Windows NT R4000", "W32MIPS", 2 },
1579 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1580 {"Windows NT PowerPC", "W32PPC", 2 },
1581 {NULL, "", -1 }
1584 for (i=0; archi_table[i].long_archi != NULL; i++)
1586 if (strcmp(arch, archi_table[i].long_archi) == 0)
1587 return (archi_table[i].version);
1590 return -1;
1593 /********************************************************************
1594 * _spoolss_deleteprinterdriver
1595 ********************************************************************/
1597 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1599 fstring driver;
1600 fstring arch;
1601 NT_PRINTER_DRIVER_INFO_LEVEL info;
1602 int version;
1603 struct current_user user;
1605 get_current_user(&user, p);
1607 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1608 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1610 /* check that we have a valid driver name first */
1611 if ((version=get_version_id(arch)) == -1) {
1612 /* this is what NT returns */
1613 return WERR_INVALID_ENVIRONMENT;
1616 /* if they said "Windows NT x86", then try for version 2 & 3 */
1618 if ( version == 2 )
1619 version = DRIVER_ANY_VERSION;
1621 ZERO_STRUCT(info);
1623 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1624 return WERR_UNKNOWN_PRINTER_DRIVER;
1626 if (printer_driver_in_use(info.info_3))
1627 return WERR_PRINTER_DRIVER_IN_USE;
1629 return delete_printer_driver(info.info_3, &user, DRIVER_ANY_VERSION, False);
1632 /********************************************************************
1633 * spoolss_deleteprinterdriverex
1634 ********************************************************************/
1636 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1638 fstring driver;
1639 fstring arch;
1640 NT_PRINTER_DRIVER_INFO_LEVEL info;
1641 int version;
1642 uint32 flags = q_u->delete_flags;
1643 BOOL delete_files;
1644 struct current_user user;
1646 get_current_user(&user, p);
1648 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1649 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1651 /* check that we have a valid driver name first */
1652 if ((version=get_version_id(arch)) == -1) {
1653 /* this is what NT returns */
1654 return WERR_INVALID_ENVIRONMENT;
1657 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1658 version = q_u->version;
1659 else if ( version == 2 )
1660 /* if they said "Windows NT x86", then try for version 2 & 3 */
1661 version = DRIVER_ANY_VERSION;
1663 ZERO_STRUCT(info);
1665 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1666 return WERR_UNKNOWN_PRINTER_DRIVER;
1668 if ( printer_driver_in_use(info.info_3) )
1669 return WERR_PRINTER_DRIVER_IN_USE;
1672 * we have a couple of cases to consider.
1673 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1674 * then the delete should fail if **any** files overlap with
1675 * other drivers
1676 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1677 * non-overlapping files
1678 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1679 * is set, the do not delete any files
1680 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1683 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1685 if ( delete_files )
1687 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1689 if ( printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) )
1690 /* no idea of the correct error here */
1691 return WERR_ACCESS_DENIED;
1694 return delete_printer_driver(info.info_3, &user, version, delete_files);
1698 /********************************************************************
1699 GetPrinterData on a printer server Handle.
1700 ********************************************************************/
1702 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1704 int i;
1706 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1708 if (!strcmp(value, "W3SvcInstalled")) {
1709 *type = 0x4;
1710 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1711 return False;
1712 *needed = 0x4;
1713 return True;
1716 if (!strcmp(value, "BeepEnabled")) {
1717 *type = 0x4;
1718 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1719 return False;
1720 SIVAL(*data, 0, 0x00);
1721 *needed = 0x4;
1722 return True;
1725 if (!strcmp(value, "EventLog")) {
1726 *type = 0x4;
1727 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1728 return False;
1729 /* formally was 0x1b */
1730 SIVAL(*data, 0, 0x0);
1731 *needed = 0x4;
1732 return True;
1735 if (!strcmp(value, "NetPopup")) {
1736 *type = 0x4;
1737 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1738 return False;
1739 SIVAL(*data, 0, 0x00);
1740 *needed = 0x4;
1741 return True;
1744 if (!strcmp(value, "MajorVersion")) {
1745 *type = 0x4;
1746 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1747 return False;
1748 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1749 SIVAL(*data, 0, 2);
1750 #else
1751 SIVAL(*data, 0, 3);
1752 #endif
1753 *needed = 0x4;
1754 return True;
1757 if (!strcmp(value, "DefaultSpoolDirectory")) {
1758 fstring string;
1760 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1761 *type = 0x1;
1762 *needed = 2*(strlen(string)+1);
1763 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1764 return False;
1765 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1767 /* it's done by hand ready to go on the wire */
1768 for (i=0; i<strlen(string); i++) {
1769 (*data)[2*i]=string[i];
1770 (*data)[2*i+1]='\0';
1772 return True;
1775 if (!strcmp(value, "Architecture")) {
1776 pstring string="Windows NT x86";
1777 *type = 0x1;
1778 *needed = 2*(strlen(string)+1);
1779 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1780 return False;
1781 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1782 for (i=0; i<strlen(string); i++) {
1783 (*data)[2*i]=string[i];
1784 (*data)[2*i+1]='\0';
1786 return True;
1789 return False;
1792 /********************************************************************
1793 GetPrinterData on a printer Handle.
1794 ********************************************************************/
1796 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1797 fstring value, uint32 *type,
1798 uint8 **data, uint32 *needed, uint32 in_size )
1800 NT_PRINTER_INFO_LEVEL *printer = NULL;
1801 int snum=0;
1802 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1803 REGISTRY_VALUE *val;
1804 int size = 0;
1806 DEBUG(5,("getprinterdata_printer\n"));
1808 if ( !Printer ) {
1809 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1810 return False;
1813 if ( !get_printer_snum(p, handle, &snum) )
1814 return False;
1816 if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
1817 return False;
1819 if ( !(val = get_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, value)) )
1821 free_a_printer(&printer, 2);
1822 return False;
1825 *type = regval_type( val );
1828 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1830 if (in_size)
1832 if ( (*data = (uint8 *)talloc(ctx, in_size * sizeof(uint8))) == NULL )
1833 return False;
1835 memset( *data, 0, in_size *sizeof(uint8) );
1837 /* copy the min(in_size, len) */
1839 size = regval_size( val );
1840 memcpy( *data, regval_data_p(val), (size > in_size) ? in_size : size*sizeof(uint8) );
1842 else
1843 *data = NULL;
1845 *needed = size;
1847 DEBUG(5,("getprinterdata_printer:copy done\n"));
1850 free_a_printer(&printer, 2);
1851 return True;
1854 /********************************************************************
1855 * spoolss_getprinterdata
1856 ********************************************************************/
1858 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1860 POLICY_HND *handle = &q_u->handle;
1861 UNISTR2 *valuename = &q_u->valuename;
1862 uint32 in_size = q_u->size;
1863 uint32 *type = &r_u->type;
1864 uint32 *out_size = &r_u->size;
1865 uint8 **data = &r_u->data;
1866 uint32 *needed = &r_u->needed;
1868 fstring value;
1869 BOOL found=False;
1870 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1873 * Reminder: when it's a string, the length is in BYTES
1874 * even if UNICODE is negociated.
1876 * JFM, 4/19/1999
1879 *out_size = in_size;
1881 /* in case of problem, return some default values */
1883 *needed = 0;
1884 *type = 0;
1886 DEBUG(4,("_spoolss_getprinterdata\n"));
1888 if (!Printer) {
1889 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1890 return WERR_NOMEM;
1891 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1892 return WERR_BADFID;
1895 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1897 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1898 found = getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1899 else
1900 found = getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1902 if ( !found )
1904 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1906 /* reply this param doesn't exist */
1908 if (*out_size) {
1909 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1910 return WERR_NOMEM;
1911 } else {
1912 *data = NULL;
1915 /* error depends on handle type */
1917 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1918 return WERR_INVALID_PARAM;
1919 else
1920 return WERR_BADFILE;
1923 if (*needed > *out_size)
1924 return WERR_MORE_DATA;
1925 else
1926 return WERR_OK;
1929 /*********************************************************
1930 Connect to the client machine.
1931 **********************************************************/
1933 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
1935 extern pstring global_myname;
1937 ZERO_STRUCTP(the_cli);
1938 if(cli_initialise(the_cli) == NULL) {
1939 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
1940 return False;
1943 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
1944 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
1945 cli_shutdown(the_cli);
1946 return False;
1949 if (ismyip(the_cli->dest_ip)) {
1950 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
1951 cli_shutdown(the_cli);
1952 return False;
1955 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
1956 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1957 cli_shutdown(the_cli);
1958 return False;
1961 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
1962 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
1963 remote_machine));
1964 return False;
1967 the_cli->protocol = PROTOCOL_NT1;
1969 if (!cli_negprot(the_cli)) {
1970 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1971 cli_shutdown(the_cli);
1972 return False;
1975 if (the_cli->protocol != PROTOCOL_NT1) {
1976 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
1977 cli_shutdown(the_cli);
1978 return False;
1982 * Do an anonymous session setup.
1985 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
1986 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1987 cli_shutdown(the_cli);
1988 return False;
1991 if (!(the_cli->sec_mode & 1)) {
1992 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
1993 cli_shutdown(the_cli);
1994 return False;
1997 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
1998 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1999 cli_shutdown(the_cli);
2000 return False;
2004 * Ok - we have an anonymous connection to the IPC$ share.
2005 * Now start the NT Domain stuff :-).
2008 if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
2009 DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2010 cli_nt_session_close(the_cli);
2011 cli_ulogoff(the_cli);
2012 cli_shutdown(the_cli);
2013 return False;
2016 return True;
2019 /***************************************************************************
2020 Connect to the client.
2021 ****************************************************************************/
2023 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2025 WERROR result;
2028 * If it's the first connection, contact the client
2029 * and connect to the IPC$ share anonumously
2031 if (smb_connections==0) {
2032 fstring unix_printer;
2034 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2036 if(!spoolss_connect_to_client(&notify_cli, unix_printer))
2037 return False;
2039 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
2042 smb_connections++;
2044 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2045 type, handle);
2047 if (!W_ERROR_IS_OK(result))
2048 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2049 dos_errstr(result)));
2051 return (W_ERROR_IS_OK(result));
2054 /********************************************************************
2055 * _spoolss_rffpcnex
2056 * ReplyFindFirstPrinterChangeNotifyEx
2058 * before replying OK: status=0 a rpc call is made to the workstation
2059 * asking ReplyOpenPrinter
2061 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2062 * called from api_spoolss_rffpcnex
2063 ********************************************************************/
2065 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2067 POLICY_HND *handle = &q_u->handle;
2068 uint32 flags = q_u->flags;
2069 uint32 options = q_u->options;
2070 UNISTR2 *localmachine = &q_u->localmachine;
2071 uint32 printerlocal = q_u->printerlocal;
2072 SPOOL_NOTIFY_OPTION *option = q_u->option;
2074 /* store the notify value in the printer struct */
2076 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2078 if (!Printer) {
2079 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2080 return WERR_BADFID;
2083 Printer->notify.flags=flags;
2084 Printer->notify.options=options;
2085 Printer->notify.printerlocal=printerlocal;
2087 if (Printer->notify.option)
2088 free_spool_notify_option(&Printer->notify.option);
2090 Printer->notify.option=dup_spool_notify_option(option);
2092 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2093 sizeof(Printer->notify.localmachine)-1);
2095 /* Connect to the client machine and send a ReplyOpenPrinter */
2097 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
2098 Printer->notify.printerlocal, 1,
2099 &Printer->notify.client_hnd))
2100 return WERR_SERVER_UNAVAILABLE;
2102 Printer->notify.client_connected=True;
2104 return WERR_OK;
2107 /*******************************************************************
2108 * fill a notify_info_data with the servername
2109 ********************************************************************/
2111 void spoolss_notify_server_name(int snum,
2112 SPOOL_NOTIFY_INFO_DATA *data,
2113 print_queue_struct *queue,
2114 NT_PRINTER_INFO_LEVEL *printer,
2115 TALLOC_CTX *mem_ctx)
2117 pstring temp_name, temp;
2118 uint32 len;
2120 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2122 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2124 data->notify_data.data.length = len;
2125 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2127 if (!data->notify_data.data.string) {
2128 data->notify_data.data.length = 0;
2129 return;
2132 memcpy(data->notify_data.data.string, temp, len);
2135 /*******************************************************************
2136 * fill a notify_info_data with the printername (not including the servername).
2137 ********************************************************************/
2139 void spoolss_notify_printer_name(int snum,
2140 SPOOL_NOTIFY_INFO_DATA *data,
2141 print_queue_struct *queue,
2142 NT_PRINTER_INFO_LEVEL *printer,
2143 TALLOC_CTX *mem_ctx)
2145 pstring temp;
2146 uint32 len;
2148 /* the notify name should not contain the \\server\ part */
2149 char *p = strrchr(printer->info_2->printername, '\\');
2151 if (!p) {
2152 p = printer->info_2->printername;
2153 } else {
2154 p++;
2157 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2159 data->notify_data.data.length = len;
2160 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2162 if (!data->notify_data.data.string) {
2163 data->notify_data.data.length = 0;
2164 return;
2167 memcpy(data->notify_data.data.string, temp, len);
2170 /*******************************************************************
2171 * fill a notify_info_data with the servicename
2172 ********************************************************************/
2174 void spoolss_notify_share_name(int snum,
2175 SPOOL_NOTIFY_INFO_DATA *data,
2176 print_queue_struct *queue,
2177 NT_PRINTER_INFO_LEVEL *printer,
2178 TALLOC_CTX *mem_ctx)
2180 pstring temp;
2181 uint32 len;
2183 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2185 data->notify_data.data.length = len;
2186 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2188 if (!data->notify_data.data.string) {
2189 data->notify_data.data.length = 0;
2190 return;
2193 memcpy(data->notify_data.data.string, temp, len);
2196 /*******************************************************************
2197 * fill a notify_info_data with the port name
2198 ********************************************************************/
2200 void spoolss_notify_port_name(int snum,
2201 SPOOL_NOTIFY_INFO_DATA *data,
2202 print_queue_struct *queue,
2203 NT_PRINTER_INFO_LEVEL *printer,
2204 TALLOC_CTX *mem_ctx)
2206 pstring temp;
2207 uint32 len;
2209 /* even if it's strange, that's consistant in all the code */
2211 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2213 data->notify_data.data.length = len;
2214 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2216 if (!data->notify_data.data.string) {
2217 data->notify_data.data.length = 0;
2218 return;
2221 memcpy(data->notify_data.data.string, temp, len);
2224 /*******************************************************************
2225 * fill a notify_info_data with the printername
2226 * but it doesn't exist, have to see what to do
2227 ********************************************************************/
2229 void spoolss_notify_driver_name(int snum,
2230 SPOOL_NOTIFY_INFO_DATA *data,
2231 print_queue_struct *queue,
2232 NT_PRINTER_INFO_LEVEL *printer,
2233 TALLOC_CTX *mem_ctx)
2235 pstring temp;
2236 uint32 len;
2238 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2240 data->notify_data.data.length = len;
2241 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2243 if (!data->notify_data.data.string) {
2244 data->notify_data.data.length = 0;
2245 return;
2248 memcpy(data->notify_data.data.string, temp, len);
2251 /*******************************************************************
2252 * fill a notify_info_data with the comment
2253 ********************************************************************/
2255 void spoolss_notify_comment(int snum,
2256 SPOOL_NOTIFY_INFO_DATA *data,
2257 print_queue_struct *queue,
2258 NT_PRINTER_INFO_LEVEL *printer,
2259 TALLOC_CTX *mem_ctx)
2261 pstring temp;
2262 uint32 len;
2264 if (*printer->info_2->comment == '\0')
2265 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2266 else
2267 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2269 data->notify_data.data.length = len;
2270 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2272 if (!data->notify_data.data.string) {
2273 data->notify_data.data.length = 0;
2274 return;
2277 memcpy(data->notify_data.data.string, temp, len);
2280 /*******************************************************************
2281 * fill a notify_info_data with the comment
2282 * location = "Room 1, floor 2, building 3"
2283 ********************************************************************/
2285 void spoolss_notify_location(int snum,
2286 SPOOL_NOTIFY_INFO_DATA *data,
2287 print_queue_struct *queue,
2288 NT_PRINTER_INFO_LEVEL *printer,
2289 TALLOC_CTX *mem_ctx)
2291 pstring temp;
2292 uint32 len;
2294 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2296 data->notify_data.data.length = len;
2297 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2299 if (!data->notify_data.data.string) {
2300 data->notify_data.data.length = 0;
2301 return;
2304 memcpy(data->notify_data.data.string, temp, len);
2307 /*******************************************************************
2308 * fill a notify_info_data with the device mode
2309 * jfm:xxxx don't to it for know but that's a real problem !!!
2310 ********************************************************************/
2312 static void spoolss_notify_devmode(int snum,
2313 SPOOL_NOTIFY_INFO_DATA *data,
2314 print_queue_struct *queue,
2315 NT_PRINTER_INFO_LEVEL *printer,
2316 TALLOC_CTX *mem_ctx)
2320 /*******************************************************************
2321 * fill a notify_info_data with the separator file name
2322 ********************************************************************/
2324 void spoolss_notify_sepfile(int snum,
2325 SPOOL_NOTIFY_INFO_DATA *data,
2326 print_queue_struct *queue,
2327 NT_PRINTER_INFO_LEVEL *printer,
2328 TALLOC_CTX *mem_ctx)
2330 pstring temp;
2331 uint32 len;
2333 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2335 data->notify_data.data.length = len;
2336 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2338 if (!data->notify_data.data.string) {
2339 data->notify_data.data.length = 0;
2340 return;
2343 memcpy(data->notify_data.data.string, temp, len);
2346 /*******************************************************************
2347 * fill a notify_info_data with the print processor
2348 * jfm:xxxx return always winprint to indicate we don't do anything to it
2349 ********************************************************************/
2351 void spoolss_notify_print_processor(int snum,
2352 SPOOL_NOTIFY_INFO_DATA *data,
2353 print_queue_struct *queue,
2354 NT_PRINTER_INFO_LEVEL *printer,
2355 TALLOC_CTX *mem_ctx)
2357 pstring temp;
2358 uint32 len;
2360 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2362 data->notify_data.data.length = len;
2363 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2365 if (!data->notify_data.data.string) {
2366 data->notify_data.data.length = 0;
2367 return;
2370 memcpy(data->notify_data.data.string, temp, len);
2373 /*******************************************************************
2374 * fill a notify_info_data with the print processor options
2375 * jfm:xxxx send an empty string
2376 ********************************************************************/
2378 void spoolss_notify_parameters(int snum,
2379 SPOOL_NOTIFY_INFO_DATA *data,
2380 print_queue_struct *queue,
2381 NT_PRINTER_INFO_LEVEL *printer,
2382 TALLOC_CTX *mem_ctx)
2384 pstring temp;
2385 uint32 len;
2387 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2389 data->notify_data.data.length = len;
2390 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2392 if (!data->notify_data.data.string) {
2393 data->notify_data.data.length = 0;
2394 return;
2397 memcpy(data->notify_data.data.string, temp, len);
2400 /*******************************************************************
2401 * fill a notify_info_data with the data type
2402 * jfm:xxxx always send RAW as data type
2403 ********************************************************************/
2405 void spoolss_notify_datatype(int snum,
2406 SPOOL_NOTIFY_INFO_DATA *data,
2407 print_queue_struct *queue,
2408 NT_PRINTER_INFO_LEVEL *printer,
2409 TALLOC_CTX *mem_ctx)
2411 pstring temp;
2412 uint32 len;
2414 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2416 data->notify_data.data.length = len;
2417 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2419 if (!data->notify_data.data.string) {
2420 data->notify_data.data.length = 0;
2421 return;
2424 memcpy(data->notify_data.data.string, temp, len);
2427 /*******************************************************************
2428 * fill a notify_info_data with the security descriptor
2429 * jfm:xxxx send an null pointer to say no security desc
2430 * have to implement security before !
2431 ********************************************************************/
2433 static void spoolss_notify_security_desc(int snum,
2434 SPOOL_NOTIFY_INFO_DATA *data,
2435 print_queue_struct *queue,
2436 NT_PRINTER_INFO_LEVEL *printer,
2437 TALLOC_CTX *mem_ctx)
2439 data->notify_data.data.length=0;
2440 data->notify_data.data.string = NULL;
2443 /*******************************************************************
2444 * fill a notify_info_data with the attributes
2445 * jfm:xxxx a samba printer is always shared
2446 ********************************************************************/
2448 void spoolss_notify_attributes(int snum,
2449 SPOOL_NOTIFY_INFO_DATA *data,
2450 print_queue_struct *queue,
2451 NT_PRINTER_INFO_LEVEL *printer,
2452 TALLOC_CTX *mem_ctx)
2454 data->notify_data.value[0] = printer->info_2->attributes;
2455 data->notify_data.value[1] = 0;
2458 /*******************************************************************
2459 * fill a notify_info_data with the priority
2460 ********************************************************************/
2462 static void spoolss_notify_priority(int snum,
2463 SPOOL_NOTIFY_INFO_DATA *data,
2464 print_queue_struct *queue,
2465 NT_PRINTER_INFO_LEVEL *printer,
2466 TALLOC_CTX *mem_ctx)
2468 data->notify_data.value[0] = printer->info_2->priority;
2469 data->notify_data.value[1] = 0;
2472 /*******************************************************************
2473 * fill a notify_info_data with the default priority
2474 ********************************************************************/
2476 static void spoolss_notify_default_priority(int snum,
2477 SPOOL_NOTIFY_INFO_DATA *data,
2478 print_queue_struct *queue,
2479 NT_PRINTER_INFO_LEVEL *printer,
2480 TALLOC_CTX *mem_ctx)
2482 data->notify_data.value[0] = printer->info_2->default_priority;
2483 data->notify_data.value[1] = 0;
2486 /*******************************************************************
2487 * fill a notify_info_data with the start time
2488 ********************************************************************/
2490 static void spoolss_notify_start_time(int snum,
2491 SPOOL_NOTIFY_INFO_DATA *data,
2492 print_queue_struct *queue,
2493 NT_PRINTER_INFO_LEVEL *printer,
2494 TALLOC_CTX *mem_ctx)
2496 data->notify_data.value[0] = printer->info_2->starttime;
2497 data->notify_data.value[1] = 0;
2500 /*******************************************************************
2501 * fill a notify_info_data with the until time
2502 ********************************************************************/
2504 static void spoolss_notify_until_time(int snum,
2505 SPOOL_NOTIFY_INFO_DATA *data,
2506 print_queue_struct *queue,
2507 NT_PRINTER_INFO_LEVEL *printer,
2508 TALLOC_CTX *mem_ctx)
2510 data->notify_data.value[0] = printer->info_2->untiltime;
2511 data->notify_data.value[1] = 0;
2514 /*******************************************************************
2515 * fill a notify_info_data with the status
2516 ********************************************************************/
2518 static void spoolss_notify_status(int snum,
2519 SPOOL_NOTIFY_INFO_DATA *data,
2520 print_queue_struct *queue,
2521 NT_PRINTER_INFO_LEVEL *printer,
2522 TALLOC_CTX *mem_ctx)
2524 print_status_struct status;
2526 print_queue_length(snum, &status);
2527 data->notify_data.value[0]=(uint32) status.status;
2528 data->notify_data.value[1] = 0;
2531 /*******************************************************************
2532 * fill a notify_info_data with the number of jobs queued
2533 ********************************************************************/
2535 void spoolss_notify_cjobs(int snum,
2536 SPOOL_NOTIFY_INFO_DATA *data,
2537 print_queue_struct *queue,
2538 NT_PRINTER_INFO_LEVEL *printer,
2539 TALLOC_CTX *mem_ctx)
2541 data->notify_data.value[0] = print_queue_length(snum, NULL);
2542 data->notify_data.value[1] = 0;
2545 /*******************************************************************
2546 * fill a notify_info_data with the average ppm
2547 ********************************************************************/
2549 static void spoolss_notify_average_ppm(int snum,
2550 SPOOL_NOTIFY_INFO_DATA *data,
2551 print_queue_struct *queue,
2552 NT_PRINTER_INFO_LEVEL *printer,
2553 TALLOC_CTX *mem_ctx)
2555 /* always respond 8 pages per minutes */
2556 /* a little hard ! */
2557 data->notify_data.value[0] = printer->info_2->averageppm;
2558 data->notify_data.value[1] = 0;
2561 /*******************************************************************
2562 * fill a notify_info_data with username
2563 ********************************************************************/
2565 static void spoolss_notify_username(int snum,
2566 SPOOL_NOTIFY_INFO_DATA *data,
2567 print_queue_struct *queue,
2568 NT_PRINTER_INFO_LEVEL *printer,
2569 TALLOC_CTX *mem_ctx)
2571 pstring temp;
2572 uint32 len;
2574 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2576 data->notify_data.data.length = len;
2577 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2579 if (!data->notify_data.data.string) {
2580 data->notify_data.data.length = 0;
2581 return;
2584 memcpy(data->notify_data.data.string, temp, len);
2587 /*******************************************************************
2588 * fill a notify_info_data with job status
2589 ********************************************************************/
2591 static void spoolss_notify_job_status(int snum,
2592 SPOOL_NOTIFY_INFO_DATA *data,
2593 print_queue_struct *queue,
2594 NT_PRINTER_INFO_LEVEL *printer,
2595 TALLOC_CTX *mem_ctx)
2597 data->notify_data.value[0]=nt_printj_status(queue->status);
2598 data->notify_data.value[1] = 0;
2601 /*******************************************************************
2602 * fill a notify_info_data with job name
2603 ********************************************************************/
2605 static void spoolss_notify_job_name(int snum,
2606 SPOOL_NOTIFY_INFO_DATA *data,
2607 print_queue_struct *queue,
2608 NT_PRINTER_INFO_LEVEL *printer,
2609 TALLOC_CTX *mem_ctx)
2611 pstring temp;
2612 uint32 len;
2614 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2616 data->notify_data.data.length = len;
2617 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2619 if (!data->notify_data.data.string) {
2620 data->notify_data.data.length = 0;
2621 return;
2624 memcpy(data->notify_data.data.string, temp, len);
2627 /*******************************************************************
2628 * fill a notify_info_data with job status
2629 ********************************************************************/
2631 static void spoolss_notify_job_status_string(int snum,
2632 SPOOL_NOTIFY_INFO_DATA *data,
2633 print_queue_struct *queue,
2634 NT_PRINTER_INFO_LEVEL *printer,
2635 TALLOC_CTX *mem_ctx)
2638 * Now we're returning job status codes we just return a "" here. JRA.
2641 char *p = "";
2642 pstring temp;
2643 uint32 len;
2645 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2646 p = "unknown";
2648 switch (queue->status) {
2649 case LPQ_QUEUED:
2650 p = "Queued";
2651 break;
2652 case LPQ_PAUSED:
2653 p = ""; /* NT provides the paused string */
2654 break;
2655 case LPQ_SPOOLING:
2656 p = "Spooling";
2657 break;
2658 case LPQ_PRINTING:
2659 p = "Printing";
2660 break;
2662 #endif /* NO LONGER NEEDED. */
2664 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2666 data->notify_data.data.length = len;
2667 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2669 if (!data->notify_data.data.string) {
2670 data->notify_data.data.length = 0;
2671 return;
2674 memcpy(data->notify_data.data.string, temp, len);
2677 /*******************************************************************
2678 * fill a notify_info_data with job time
2679 ********************************************************************/
2681 static void spoolss_notify_job_time(int snum,
2682 SPOOL_NOTIFY_INFO_DATA *data,
2683 print_queue_struct *queue,
2684 NT_PRINTER_INFO_LEVEL *printer,
2685 TALLOC_CTX *mem_ctx)
2687 data->notify_data.value[0]=0x0;
2688 data->notify_data.value[1]=0;
2691 /*******************************************************************
2692 * fill a notify_info_data with job size
2693 ********************************************************************/
2695 static void spoolss_notify_job_size(int snum,
2696 SPOOL_NOTIFY_INFO_DATA *data,
2697 print_queue_struct *queue,
2698 NT_PRINTER_INFO_LEVEL *printer,
2699 TALLOC_CTX *mem_ctx)
2701 data->notify_data.value[0]=queue->size;
2702 data->notify_data.value[1]=0;
2705 /*******************************************************************
2706 * fill a notify_info_data with page info
2707 ********************************************************************/
2708 static void spoolss_notify_total_pages(int snum,
2709 SPOOL_NOTIFY_INFO_DATA *data,
2710 print_queue_struct *queue,
2711 NT_PRINTER_INFO_LEVEL *printer,
2712 TALLOC_CTX *mem_ctx)
2714 data->notify_data.value[0]=queue->page_count;
2715 data->notify_data.value[1]=0;
2718 /*******************************************************************
2719 * fill a notify_info_data with pages printed info.
2720 ********************************************************************/
2721 static void spoolss_notify_pages_printed(int snum,
2722 SPOOL_NOTIFY_INFO_DATA *data,
2723 print_queue_struct *queue,
2724 NT_PRINTER_INFO_LEVEL *printer,
2725 TALLOC_CTX *mem_ctx)
2727 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2728 data->notify_data.value[1]=0;
2731 /*******************************************************************
2732 Fill a notify_info_data with job position.
2733 ********************************************************************/
2735 static void spoolss_notify_job_position(int snum,
2736 SPOOL_NOTIFY_INFO_DATA *data,
2737 print_queue_struct *queue,
2738 NT_PRINTER_INFO_LEVEL *printer,
2739 TALLOC_CTX *mem_ctx)
2741 data->notify_data.value[0]=queue->job;
2742 data->notify_data.value[1]=0;
2745 /*******************************************************************
2746 Fill a notify_info_data with submitted time.
2747 ********************************************************************/
2749 static void spoolss_notify_submitted_time(int snum,
2750 SPOOL_NOTIFY_INFO_DATA *data,
2751 print_queue_struct *queue,
2752 NT_PRINTER_INFO_LEVEL *printer,
2753 TALLOC_CTX *mem_ctx)
2755 struct tm *t;
2756 uint32 len;
2757 SYSTEMTIME st;
2758 char *p;
2760 t=gmtime(&queue->time);
2762 len = sizeof(SYSTEMTIME);
2764 data->notify_data.data.length = len;
2765 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2767 if (!data->notify_data.data.string) {
2768 data->notify_data.data.length = 0;
2769 return;
2772 make_systemtime(&st, t);
2775 * Systemtime must be linearized as a set of UINT16's.
2776 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2779 p = (char *)data->notify_data.data.string;
2780 SSVAL(p, 0, st.year);
2781 SSVAL(p, 2, st.month);
2782 SSVAL(p, 4, st.dayofweek);
2783 SSVAL(p, 6, st.day);
2784 SSVAL(p, 8, st.hour);
2785 SSVAL(p, 10, st.minute);
2786 SSVAL(p, 12, st.second);
2787 SSVAL(p, 14, st.milliseconds);
2790 struct s_notify_info_data_table
2792 uint16 type;
2793 uint16 field;
2794 char *name;
2795 uint32 size;
2796 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2797 print_queue_struct *queue,
2798 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2801 /* A table describing the various print notification constants and
2802 whether the notification data is a pointer to a variable sized
2803 buffer, a one value uint32 or a two value uint32. */
2805 struct s_notify_info_data_table notify_info_data_table[] =
2807 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2808 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2809 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
2810 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2811 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2812 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
2813 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
2814 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2815 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
2816 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2817 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2818 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2819 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
2820 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
2821 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2822 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
2823 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2824 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2825 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
2826 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
2827 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
2828 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
2829 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
2830 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
2831 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
2832 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
2833 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2834 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2835 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2836 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
2837 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
2838 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2839 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2840 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2841 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2842 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2843 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
2844 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
2845 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
2846 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
2847 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2848 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
2849 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
2850 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2851 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2852 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
2853 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
2854 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
2855 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
2858 /*******************************************************************
2859 Return the size of info_data structure.
2860 ********************************************************************/
2862 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2864 int i=0;
2866 for (i = 0; i < sizeof(notify_info_data_table); i++)
2868 if ( (notify_info_data_table[i].type == type)
2869 && (notify_info_data_table[i].field == field) )
2871 switch(notify_info_data_table[i].size)
2873 case NOTIFY_ONE_VALUE:
2874 case NOTIFY_TWO_VALUE:
2875 return 1;
2876 case NOTIFY_STRING:
2877 return 2;
2879 /* The only pointer notify data I have seen on
2880 the wire is the submitted time and this has
2881 the notify size set to 4. -tpot */
2883 case NOTIFY_POINTER:
2884 return 4;
2886 case NOTIFY_SECDESC:
2887 return 5;
2892 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2894 return 0;
2897 /*******************************************************************
2898 Return the type of notify_info_data.
2899 ********************************************************************/
2901 static int type_of_notify_info_data(uint16 type, uint16 field)
2903 int i=0;
2905 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2906 if (notify_info_data_table[i].type == type &&
2907 notify_info_data_table[i].field == field)
2908 return notify_info_data_table[i].size;
2911 return False;
2914 /****************************************************************************
2915 ****************************************************************************/
2917 static int search_notify(uint16 type, uint16 field, int *value)
2919 int i;
2921 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2922 if (notify_info_data_table[i].type == type &&
2923 notify_info_data_table[i].field == field &&
2924 notify_info_data_table[i].fn != NULL) {
2925 *value = i;
2926 return True;
2930 return False;
2933 /****************************************************************************
2934 ****************************************************************************/
2936 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2938 info_data->type = type;
2939 info_data->field = field;
2940 info_data->reserved = 0;
2942 info_data->size = size_of_notify_info_data(type, field);
2943 info_data->enc_type = type_of_notify_info_data(type, field);
2945 info_data->id = id;
2950 /*******************************************************************
2952 * fill a notify_info struct with info asked
2954 ********************************************************************/
2956 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2957 snum, SPOOL_NOTIFY_OPTION_TYPE
2958 *option_type, uint32 id,
2959 TALLOC_CTX *mem_ctx)
2961 int field_num,j;
2962 uint16 type;
2963 uint16 field;
2965 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2966 NT_PRINTER_INFO_LEVEL *printer = NULL;
2967 print_queue_struct *queue=NULL;
2969 type=option_type->type;
2971 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2972 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2973 option_type->count, lp_servicename(snum)));
2975 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2976 return False;
2978 for(field_num=0; field_num<option_type->count; field_num++)
2980 field = option_type->fields[field_num];
2982 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2984 if (!search_notify(type, field, &j) )
2985 continue;
2987 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
2989 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2990 return False;
2992 else
2993 info->data = tid;
2995 current_data = &info->data[info->count];
2997 construct_info_data(current_data, type, field, id);
2999 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3000 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3002 notify_info_data_table[j].fn(snum, current_data, queue,
3003 printer, mem_ctx);
3005 info->count++;
3008 free_a_printer(&printer, 2);
3009 return True;
3012 /*******************************************************************
3014 * fill a notify_info struct with info asked
3016 ********************************************************************/
3018 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3019 SPOOL_NOTIFY_INFO *info,
3020 NT_PRINTER_INFO_LEVEL *printer,
3021 int snum, SPOOL_NOTIFY_OPTION_TYPE
3022 *option_type, uint32 id,
3023 TALLOC_CTX *mem_ctx)
3025 int field_num,j;
3026 uint16 type;
3027 uint16 field;
3029 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3031 DEBUG(4,("construct_notify_jobs_info\n"));
3033 type = option_type->type;
3035 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3036 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3037 option_type->count));
3039 for(field_num=0; field_num<option_type->count; field_num++) {
3040 field = option_type->fields[field_num];
3042 if (!search_notify(type, field, &j) )
3043 continue;
3045 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3046 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3047 return False;
3049 else info->data = tid;
3051 current_data=&(info->data[info->count]);
3053 construct_info_data(current_data, type, field, id);
3054 notify_info_data_table[j].fn(snum, current_data, queue,
3055 printer, mem_ctx);
3056 info->count++;
3059 return True;
3063 * JFM: The enumeration is not that simple, it's even non obvious.
3065 * let's take an example: I want to monitor the PRINTER SERVER for
3066 * the printer's name and the number of jobs currently queued.
3067 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3068 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3070 * I have 3 printers on the back of my server.
3072 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3073 * structures.
3074 * Number Data Id
3075 * 1 printer 1 name 1
3076 * 2 printer 1 cjob 1
3077 * 3 printer 2 name 2
3078 * 4 printer 2 cjob 2
3079 * 5 printer 3 name 3
3080 * 6 printer 3 name 3
3082 * that's the print server case, the printer case is even worse.
3085 /*******************************************************************
3087 * enumerate all printers on the printserver
3088 * fill a notify_info struct with info asked
3090 ********************************************************************/
3092 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3093 SPOOL_NOTIFY_INFO *info,
3094 TALLOC_CTX *mem_ctx)
3096 int snum;
3097 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3098 int n_services=lp_numservices();
3099 int i;
3100 uint32 id;
3101 SPOOL_NOTIFY_OPTION *option;
3102 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3104 DEBUG(4,("printserver_notify_info\n"));
3106 if (!Printer)
3107 return WERR_BADFID;
3109 option=Printer->notify.option;
3110 id=1;
3111 info->version=2;
3112 info->data=NULL;
3113 info->count=0;
3115 for (i=0; i<option->count; i++) {
3116 option_type=&(option->ctr.type[i]);
3118 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3119 continue;
3121 for (snum=0; snum<n_services; snum++)
3123 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3124 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3128 #if 0
3130 * Debugging information, don't delete.
3133 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3134 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3135 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3137 for (i=0; i<info->count; i++) {
3138 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3139 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3140 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3142 #endif
3144 return WERR_OK;
3147 /*******************************************************************
3149 * fill a notify_info struct with info asked
3151 ********************************************************************/
3153 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3154 TALLOC_CTX *mem_ctx)
3156 int snum;
3157 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3158 int i;
3159 uint32 id;
3160 SPOOL_NOTIFY_OPTION *option;
3161 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3162 int count,j;
3163 print_queue_struct *queue=NULL;
3164 print_status_struct status;
3166 DEBUG(4,("printer_notify_info\n"));
3168 if (!Printer)
3169 return WERR_BADFID;
3171 option=Printer->notify.option;
3172 id = 0x0;
3173 info->version=2;
3174 info->data=NULL;
3175 info->count=0;
3177 get_printer_snum(p, hnd, &snum);
3179 for (i=0; i<option->count; i++) {
3180 option_type=&option->ctr.type[i];
3182 switch ( option_type->type ) {
3183 case PRINTER_NOTIFY_TYPE:
3184 if(construct_notify_printer_info(info, snum,
3185 option_type, id,
3186 mem_ctx))
3187 id--;
3188 break;
3190 case JOB_NOTIFY_TYPE: {
3191 NT_PRINTER_INFO_LEVEL *printer = NULL;
3193 count = print_queue_status(snum, &queue, &status);
3195 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3196 lp_servicename(snum))))
3197 goto done;
3199 for (j=0; j<count; j++) {
3200 construct_notify_jobs_info(&queue[j], info,
3201 printer, snum,
3202 option_type,
3203 queue[j].job,
3204 mem_ctx);
3207 free_a_printer(&printer, 2);
3209 done:
3210 SAFE_FREE(queue);
3211 break;
3217 * Debugging information, don't delete.
3220 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3221 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3222 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3224 for (i=0; i<info->count; i++) {
3225 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3226 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3227 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3230 return WERR_OK;
3233 /********************************************************************
3234 * spoolss_rfnpcnex
3235 ********************************************************************/
3237 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3239 POLICY_HND *handle = &q_u->handle;
3240 SPOOL_NOTIFY_INFO *info = &r_u->info;
3242 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3243 WERROR result = WERR_BADFID;
3245 /* we always have a NOTIFY_INFO struct */
3246 r_u->info_ptr=0x1;
3248 if (!Printer) {
3249 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3250 OUR_HANDLE(handle)));
3251 goto done;
3254 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3257 * We are now using the change value, and
3258 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3259 * I don't have a global notification system, I'm sending back all the
3260 * informations even when _NOTHING_ has changed.
3263 /* We need to keep track of the change value to send back in
3264 RRPCN replies otherwise our updates are ignored. */
3266 if (Printer->notify.client_connected) {
3267 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3268 Printer->notify.change = q_u->change;
3271 /* just ignore the SPOOL_NOTIFY_OPTION */
3273 switch (Printer->printer_type) {
3274 case PRINTER_HANDLE_IS_PRINTSERVER:
3275 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3276 break;
3278 case PRINTER_HANDLE_IS_PRINTER:
3279 result = printer_notify_info(p, handle, info, p->mem_ctx);
3280 break;
3283 done:
3284 return result;
3287 /********************************************************************
3288 * construct_printer_info_0
3289 * fill a printer_info_0 struct
3290 ********************************************************************/
3292 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3294 pstring chaine;
3295 int count;
3296 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3297 counter_printer_0 *session_counter;
3298 uint32 global_counter;
3299 struct tm *t;
3300 time_t setuptime;
3301 print_status_struct status;
3303 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3304 return False;
3306 count = print_queue_length(snum, &status);
3308 /* check if we already have a counter for this printer */
3309 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3311 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3312 if (session_counter->snum == snum)
3313 break;
3316 /* it's the first time, add it to the list */
3317 if (session_counter==NULL) {
3318 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3319 free_a_printer(&ntprinter, 2);
3320 return False;
3322 ZERO_STRUCTP(session_counter);
3323 session_counter->snum=snum;
3324 session_counter->counter=0;
3325 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3328 /* increment it */
3329 session_counter->counter++;
3331 /* JFM:
3332 * the global_counter should be stored in a TDB as it's common to all the clients
3333 * and should be zeroed on samba startup
3335 global_counter=session_counter->counter;
3337 pstrcpy(chaine,ntprinter->info_2->printername);
3339 init_unistr(&printer->printername, chaine);
3341 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3342 init_unistr(&printer->servername, chaine);
3344 printer->cjobs = count;
3345 printer->total_jobs = 0;
3346 printer->total_bytes = 0;
3348 setuptime = (time_t)ntprinter->info_2->setuptime;
3349 t=gmtime(&setuptime);
3351 printer->year = t->tm_year+1900;
3352 printer->month = t->tm_mon+1;
3353 printer->dayofweek = t->tm_wday;
3354 printer->day = t->tm_mday;
3355 printer->hour = t->tm_hour;
3356 printer->minute = t->tm_min;
3357 printer->second = t->tm_sec;
3358 printer->milliseconds = 0;
3360 printer->global_counter = global_counter;
3361 printer->total_pages = 0;
3362 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3363 printer->major_version = 0x0004; /* NT 4 */
3364 printer->build_version = 0x0565; /* build 1381 */
3365 #else
3366 printer->major_version = 0x0005; /* NT 5 */
3367 printer->build_version = 0x0893; /* build 2195 */
3368 #endif
3369 printer->unknown7 = 0x1;
3370 printer->unknown8 = 0x0;
3371 printer->unknown9 = 0x0;
3372 printer->session_counter = session_counter->counter;
3373 printer->unknown11 = 0x0;
3374 printer->printer_errors = 0x0; /* number of print failure */
3375 printer->unknown13 = 0x0;
3376 printer->unknown14 = 0x1;
3377 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3378 printer->unknown16 = 0x0;
3379 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3380 printer->unknown18 = 0x0;
3381 printer->status = nt_printq_status(status.status);
3382 printer->unknown20 = 0x0;
3383 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3384 printer->unknown22 = 0x0;
3385 printer->unknown23 = 0x6; /* 6 ???*/
3386 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3387 printer->unknown25 = 0;
3388 printer->unknown26 = 0;
3389 printer->unknown27 = 0;
3390 printer->unknown28 = 0;
3391 printer->unknown29 = 0;
3393 free_a_printer(&ntprinter,2);
3394 return (True);
3397 /********************************************************************
3398 * construct_printer_info_1
3399 * fill a printer_info_1 struct
3400 ********************************************************************/
3401 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3403 pstring chaine;
3404 pstring chaine2;
3405 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3407 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3408 return False;
3410 printer->flags=flags;
3412 if (*ntprinter->info_2->comment == '\0') {
3413 init_unistr(&printer->comment, lp_comment(snum));
3414 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3415 ntprinter->info_2->drivername, lp_comment(snum));
3417 else {
3418 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3419 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3420 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3423 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3425 init_unistr(&printer->description, chaine);
3426 init_unistr(&printer->name, chaine2);
3428 free_a_printer(&ntprinter,2);
3430 return True;
3433 /****************************************************************************
3434 Free a DEVMODE struct.
3435 ****************************************************************************/
3437 static void free_dev_mode(DEVICEMODE *dev)
3439 if (dev == NULL)
3440 return;
3442 SAFE_FREE(dev->private);
3443 SAFE_FREE(dev);
3446 /****************************************************************************
3447 Create a DEVMODE struct. Returns malloced memory.
3448 ****************************************************************************/
3450 DEVICEMODE *construct_dev_mode(int snum)
3452 char adevice[32];
3453 char aform[32];
3454 NT_PRINTER_INFO_LEVEL *printer = NULL;
3455 NT_DEVICEMODE *ntdevmode = NULL;
3456 DEVICEMODE *devmode = NULL;
3458 DEBUG(7,("construct_dev_mode\n"));
3460 DEBUGADD(8,("getting printer characteristics\n"));
3462 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3463 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3464 return NULL;
3467 ZERO_STRUCTP(devmode);
3469 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3470 goto fail;
3472 if (printer->info_2->devmode)
3473 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3475 if (ntdevmode == NULL) {
3476 DEBUG(5, ("BONG! There was no device mode!\n"));
3477 goto fail;
3480 DEBUGADD(8,("loading DEVICEMODE\n"));
3482 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3483 init_unistr(&devmode->devicename, adevice);
3485 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3486 init_unistr(&devmode->formname, aform);
3488 devmode->specversion = ntdevmode->specversion;
3489 devmode->driverversion = ntdevmode->driverversion;
3490 devmode->size = ntdevmode->size;
3491 devmode->driverextra = ntdevmode->driverextra;
3492 devmode->fields = ntdevmode->fields;
3494 devmode->orientation = ntdevmode->orientation;
3495 devmode->papersize = ntdevmode->papersize;
3496 devmode->paperlength = ntdevmode->paperlength;
3497 devmode->paperwidth = ntdevmode->paperwidth;
3498 devmode->scale = ntdevmode->scale;
3499 devmode->copies = ntdevmode->copies;
3500 devmode->defaultsource = ntdevmode->defaultsource;
3501 devmode->printquality = ntdevmode->printquality;
3502 devmode->color = ntdevmode->color;
3503 devmode->duplex = ntdevmode->duplex;
3504 devmode->yresolution = ntdevmode->yresolution;
3505 devmode->ttoption = ntdevmode->ttoption;
3506 devmode->collate = ntdevmode->collate;
3507 devmode->icmmethod = ntdevmode->icmmethod;
3508 devmode->icmintent = ntdevmode->icmintent;
3509 devmode->mediatype = ntdevmode->mediatype;
3510 devmode->dithertype = ntdevmode->dithertype;
3512 if (ntdevmode->private != NULL) {
3513 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3514 goto fail;
3517 free_nt_devicemode(&ntdevmode);
3518 free_a_printer(&printer,2);
3520 return devmode;
3522 fail:
3524 if (ntdevmode)
3525 free_nt_devicemode(&ntdevmode);
3526 if (printer)
3527 free_a_printer(&printer,2);
3528 free_dev_mode(devmode);
3530 return NULL;
3533 /********************************************************************
3534 * construct_printer_info_2
3535 * fill a printer_info_2 struct
3536 ********************************************************************/
3538 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3540 int count;
3541 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3543 print_status_struct status;
3545 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3546 return False;
3548 count = print_queue_length(snum, &status);
3550 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3551 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3552 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3553 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3554 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3556 if (*ntprinter->info_2->comment == '\0')
3557 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3558 else
3559 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3561 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3562 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3563 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3564 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3565 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3567 printer->attributes = ntprinter->info_2->attributes;
3569 printer->priority = ntprinter->info_2->priority; /* priority */
3570 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3571 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3572 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3573 printer->status = nt_printq_status(status.status); /* status */
3574 printer->cjobs = count; /* jobs */
3575 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3577 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3578 DEBUG(8, ("Returning NULL Devicemode!\n"));
3581 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3582 /* steal the printer info sec_desc structure. [badly done]. */
3583 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3584 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3585 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3586 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3588 else {
3589 printer->secdesc = NULL;
3592 free_a_printer(&ntprinter, 2);
3593 return True;
3596 /********************************************************************
3597 * construct_printer_info_3
3598 * fill a printer_info_3 struct
3599 ********************************************************************/
3601 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3603 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3604 PRINTER_INFO_3 *printer = NULL;
3606 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3607 return False;
3609 *pp_printer = NULL;
3610 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3611 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3612 return False;
3615 ZERO_STRUCTP(printer);
3617 printer->flags = 4; /* These are the components of the SD we are returning. */
3618 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3619 /* steal the printer info sec_desc structure. [badly done]. */
3620 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3622 #if 0
3624 * Set the flags for the components we are returning.
3627 if (printer->secdesc->owner_sid)
3628 printer->flags |= OWNER_SECURITY_INFORMATION;
3630 if (printer->secdesc->grp_sid)
3631 printer->flags |= GROUP_SECURITY_INFORMATION;
3633 if (printer->secdesc->dacl)
3634 printer->flags |= DACL_SECURITY_INFORMATION;
3636 if (printer->secdesc->sacl)
3637 printer->flags |= SACL_SECURITY_INFORMATION;
3638 #endif
3640 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3641 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3642 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3645 free_a_printer(&ntprinter, 2);
3647 *pp_printer = printer;
3648 return True;
3651 /********************************************************************
3652 * construct_printer_info_4
3653 * fill a printer_info_4 struct
3654 ********************************************************************/
3656 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3658 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3660 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3661 return False;
3663 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3664 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3665 printer->attributes = ntprinter->info_2->attributes;
3667 free_a_printer(&ntprinter, 2);
3668 return True;
3671 /********************************************************************
3672 * construct_printer_info_5
3673 * fill a printer_info_5 struct
3674 ********************************************************************/
3676 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3678 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3680 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3681 return False;
3683 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3684 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3685 printer->attributes = ntprinter->info_2->attributes;
3686 printer->device_not_selected_timeout = 0x3a98;
3687 printer->transmission_retry_timeout = 0xafc8;
3689 free_a_printer(&ntprinter, 2);
3690 return True;
3693 /********************************************************************
3694 Spoolss_enumprinters.
3695 ********************************************************************/
3697 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3699 int snum;
3700 int i;
3701 int n_services=lp_numservices();
3702 PRINTER_INFO_1 *tp, *printers=NULL;
3703 PRINTER_INFO_1 current_prt;
3705 DEBUG(4,("enum_all_printers_info_1\n"));
3707 for (snum=0; snum<n_services; snum++) {
3708 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3709 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3711 if (construct_printer_info_1(flags, &current_prt, snum)) {
3712 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3713 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3714 SAFE_FREE(printers);
3715 *returned=0;
3716 return WERR_NOMEM;
3718 else printers = tp;
3719 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3721 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
3722 (*returned)++;
3727 /* check the required size. */
3728 for (i=0; i<*returned; i++)
3729 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3731 if (!alloc_buffer_size(buffer, *needed))
3732 return WERR_INSUFFICIENT_BUFFER;
3734 /* fill the buffer with the structures */
3735 for (i=0; i<*returned; i++)
3736 smb_io_printer_info_1("", buffer, &printers[i], 0);
3738 /* clear memory */
3739 SAFE_FREE(printers);
3741 if (*needed > offered) {
3742 *returned=0;
3743 return WERR_INSUFFICIENT_BUFFER;
3745 else
3746 return WERR_OK;
3749 /********************************************************************
3750 enum_all_printers_info_1_local.
3751 *********************************************************************/
3753 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3755 DEBUG(4,("enum_all_printers_info_1_local\n"));
3757 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3760 /********************************************************************
3761 enum_all_printers_info_1_name.
3762 *********************************************************************/
3764 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3766 char *s = name;
3768 DEBUG(4,("enum_all_printers_info_1_name\n"));
3770 if ((name[0] == '\\') && (name[1] == '\\'))
3771 s = name + 2;
3773 if (is_myname_or_ipaddr(s)) {
3774 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3776 else
3777 return WERR_INVALID_NAME;
3780 /********************************************************************
3781 enum_all_printers_info_1_remote.
3782 *********************************************************************/
3784 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3786 PRINTER_INFO_1 *printer;
3787 fstring printername;
3788 fstring desc;
3789 fstring comment;
3790 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3792 /* JFM: currently it's more a place holder than anything else.
3793 * In the spooler world there is a notion of server registration.
3794 * the print servers are registring (sp ?) on the PDC (in the same domain)
3796 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3799 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3800 return WERR_NOMEM;
3802 *returned=1;
3804 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3805 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3806 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3808 init_unistr(&printer->description, desc);
3809 init_unistr(&printer->name, printername);
3810 init_unistr(&printer->comment, comment);
3811 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3813 /* check the required size. */
3814 *needed += spoolss_size_printer_info_1(printer);
3816 if (!alloc_buffer_size(buffer, *needed)) {
3817 SAFE_FREE(printer);
3818 return WERR_INSUFFICIENT_BUFFER;
3821 /* fill the buffer with the structures */
3822 smb_io_printer_info_1("", buffer, printer, 0);
3824 /* clear memory */
3825 SAFE_FREE(printer);
3827 if (*needed > offered) {
3828 *returned=0;
3829 return WERR_INSUFFICIENT_BUFFER;
3831 else
3832 return WERR_OK;
3835 /********************************************************************
3836 enum_all_printers_info_1_network.
3837 *********************************************************************/
3839 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3841 char *s = name;
3843 DEBUG(4,("enum_all_printers_info_1_network\n"));
3845 /* If we respond to a enum_printers level 1 on our name with flags
3846 set to PRINTER_ENUM_REMOTE with a list of printers then these
3847 printers incorrectly appear in the APW browse list.
3848 Specifically the printers for the server appear at the workgroup
3849 level where all the other servers in the domain are
3850 listed. Windows responds to this call with a
3851 WERR_CAN_NOT_COMPLETE so we should do the same. */
3853 if (name[0] == '\\' && name[1] == '\\')
3854 s = name + 2;
3856 if (is_myname_or_ipaddr(s))
3857 return WERR_CAN_NOT_COMPLETE;
3859 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3862 /********************************************************************
3863 * api_spoolss_enumprinters
3865 * called from api_spoolss_enumprinters (see this to understand)
3866 ********************************************************************/
3868 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3870 int snum;
3871 int i;
3872 int n_services=lp_numservices();
3873 PRINTER_INFO_2 *tp, *printers=NULL;
3874 PRINTER_INFO_2 current_prt;
3876 for (snum=0; snum<n_services; snum++) {
3877 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3878 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3880 if (construct_printer_info_2(&current_prt, snum)) {
3881 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3882 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3883 SAFE_FREE(printers);
3884 *returned = 0;
3885 return WERR_NOMEM;
3887 else printers = tp;
3888 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3889 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3890 (*returned)++;
3895 /* check the required size. */
3896 for (i=0; i<*returned; i++)
3897 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3899 if (!alloc_buffer_size(buffer, *needed)) {
3900 for (i=0; i<*returned; i++) {
3901 free_devmode(printers[i].devmode);
3903 SAFE_FREE(printers);
3904 return WERR_INSUFFICIENT_BUFFER;
3907 /* fill the buffer with the structures */
3908 for (i=0; i<*returned; i++)
3909 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3911 /* clear memory */
3912 for (i=0; i<*returned; i++) {
3913 free_devmode(printers[i].devmode);
3915 SAFE_FREE(printers);
3917 if (*needed > offered) {
3918 *returned=0;
3919 return WERR_INSUFFICIENT_BUFFER;
3921 else
3922 return WERR_OK;
3925 /********************************************************************
3926 * handle enumeration of printers at level 1
3927 ********************************************************************/
3929 static WERROR enumprinters_level1( uint32 flags, fstring name,
3930 NEW_BUFFER *buffer, uint32 offered,
3931 uint32 *needed, uint32 *returned)
3933 /* Not all the flags are equals */
3935 if (flags & PRINTER_ENUM_LOCAL)
3936 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3938 if (flags & PRINTER_ENUM_NAME)
3939 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3941 if (flags & PRINTER_ENUM_REMOTE)
3942 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3944 if (flags & PRINTER_ENUM_NETWORK)
3945 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
3947 return WERR_OK; /* NT4sp5 does that */
3950 /********************************************************************
3951 * handle enumeration of printers at level 2
3952 ********************************************************************/
3954 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3955 NEW_BUFFER *buffer, uint32 offered,
3956 uint32 *needed, uint32 *returned)
3958 char *s = servername;
3960 if (flags & PRINTER_ENUM_LOCAL) {
3961 return enum_all_printers_info_2(buffer, offered, needed, returned);
3964 if (flags & PRINTER_ENUM_NAME) {
3965 if ((servername[0] == '\\') && (servername[1] == '\\'))
3966 s = servername + 2;
3967 if (is_myname_or_ipaddr(s))
3968 return enum_all_printers_info_2(buffer, offered, needed, returned);
3969 else
3970 return WERR_INVALID_NAME;
3973 if (flags & PRINTER_ENUM_REMOTE)
3974 return WERR_UNKNOWN_LEVEL;
3976 return WERR_OK;
3979 /********************************************************************
3980 * handle enumeration of printers at level 5
3981 ********************************************************************/
3983 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3984 NEW_BUFFER *buffer, uint32 offered,
3985 uint32 *needed, uint32 *returned)
3987 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3988 return WERR_OK;
3991 /********************************************************************
3992 * api_spoolss_enumprinters
3994 * called from api_spoolss_enumprinters (see this to understand)
3995 ********************************************************************/
3997 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3999 uint32 flags = q_u->flags;
4000 UNISTR2 *servername = &q_u->servername;
4001 uint32 level = q_u->level;
4002 NEW_BUFFER *buffer = NULL;
4003 uint32 offered = q_u->offered;
4004 uint32 *needed = &r_u->needed;
4005 uint32 *returned = &r_u->returned;
4007 fstring name;
4009 /* that's an [in out] buffer */
4010 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4011 buffer = r_u->buffer;
4013 DEBUG(4,("_spoolss_enumprinters\n"));
4015 *needed=0;
4016 *returned=0;
4019 * Level 1:
4020 * flags==PRINTER_ENUM_NAME
4021 * if name=="" then enumerates all printers
4022 * if name!="" then enumerate the printer
4023 * flags==PRINTER_ENUM_REMOTE
4024 * name is NULL, enumerate printers
4025 * Level 2: name!="" enumerates printers, name can't be NULL
4026 * Level 3: doesn't exist
4027 * Level 4: does a local registry lookup
4028 * Level 5: same as Level 2
4031 unistr2_to_ascii(name, servername, sizeof(name)-1);
4032 strupper(name);
4034 switch (level) {
4035 case 1:
4036 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4037 case 2:
4038 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4039 case 5:
4040 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4041 case 3:
4042 case 4:
4043 break;
4045 return WERR_UNKNOWN_LEVEL;
4048 /****************************************************************************
4049 ****************************************************************************/
4051 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4053 PRINTER_INFO_0 *printer=NULL;
4055 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4056 return WERR_NOMEM;
4058 construct_printer_info_0(printer, snum);
4060 /* check the required size. */
4061 *needed += spoolss_size_printer_info_0(printer);
4063 if (!alloc_buffer_size(buffer, *needed)) {
4064 SAFE_FREE(printer);
4065 return WERR_INSUFFICIENT_BUFFER;
4068 /* fill the buffer with the structures */
4069 smb_io_printer_info_0("", buffer, printer, 0);
4071 /* clear memory */
4072 SAFE_FREE(printer);
4074 if (*needed > offered) {
4075 return WERR_INSUFFICIENT_BUFFER;
4078 return WERR_OK;
4081 /****************************************************************************
4082 ****************************************************************************/
4084 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4086 PRINTER_INFO_1 *printer=NULL;
4088 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4089 return WERR_NOMEM;
4091 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4093 /* check the required size. */
4094 *needed += spoolss_size_printer_info_1(printer);
4096 if (!alloc_buffer_size(buffer, *needed)) {
4097 SAFE_FREE(printer);
4098 return WERR_INSUFFICIENT_BUFFER;
4101 /* fill the buffer with the structures */
4102 smb_io_printer_info_1("", buffer, printer, 0);
4104 /* clear memory */
4105 SAFE_FREE(printer);
4107 if (*needed > offered) {
4108 return WERR_INSUFFICIENT_BUFFER;
4111 return WERR_OK;
4114 /****************************************************************************
4115 ****************************************************************************/
4117 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4119 PRINTER_INFO_2 *printer=NULL;
4121 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4122 return WERR_NOMEM;
4124 construct_printer_info_2(printer, snum);
4126 /* check the required size. */
4127 *needed += spoolss_size_printer_info_2(printer);
4129 if (!alloc_buffer_size(buffer, *needed)) {
4130 free_printer_info_2(printer);
4131 return WERR_INSUFFICIENT_BUFFER;
4134 /* fill the buffer with the structures */
4135 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4136 free_printer_info_2(printer);
4137 return WERR_NOMEM;
4140 /* clear memory */
4141 free_printer_info_2(printer);
4143 if (*needed > offered) {
4144 return WERR_INSUFFICIENT_BUFFER;
4147 return WERR_OK;
4150 /****************************************************************************
4151 ****************************************************************************/
4153 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4155 PRINTER_INFO_3 *printer=NULL;
4157 if (!construct_printer_info_3(&printer, snum))
4158 return WERR_NOMEM;
4160 /* check the required size. */
4161 *needed += spoolss_size_printer_info_3(printer);
4163 if (!alloc_buffer_size(buffer, *needed)) {
4164 free_printer_info_3(printer);
4165 return WERR_INSUFFICIENT_BUFFER;
4168 /* fill the buffer with the structures */
4169 smb_io_printer_info_3("", buffer, printer, 0);
4171 /* clear memory */
4172 free_printer_info_3(printer);
4174 if (*needed > offered) {
4175 return WERR_INSUFFICIENT_BUFFER;
4178 return WERR_OK;
4181 /****************************************************************************
4182 ****************************************************************************/
4184 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4186 PRINTER_INFO_4 *printer=NULL;
4188 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4189 return WERR_NOMEM;
4191 if (!construct_printer_info_4(printer, snum))
4192 return WERR_NOMEM;
4194 /* check the required size. */
4195 *needed += spoolss_size_printer_info_4(printer);
4197 if (!alloc_buffer_size(buffer, *needed)) {
4198 free_printer_info_4(printer);
4199 return WERR_INSUFFICIENT_BUFFER;
4202 /* fill the buffer with the structures */
4203 smb_io_printer_info_4("", buffer, printer, 0);
4205 /* clear memory */
4206 free_printer_info_4(printer);
4208 if (*needed > offered) {
4209 return WERR_INSUFFICIENT_BUFFER;
4212 return WERR_OK;
4215 /****************************************************************************
4216 ****************************************************************************/
4218 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4220 PRINTER_INFO_5 *printer=NULL;
4222 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4223 return WERR_NOMEM;
4225 if (!construct_printer_info_5(printer, snum))
4226 return WERR_NOMEM;
4228 /* check the required size. */
4229 *needed += spoolss_size_printer_info_5(printer);
4231 if (!alloc_buffer_size(buffer, *needed)) {
4232 free_printer_info_5(printer);
4233 return WERR_INSUFFICIENT_BUFFER;
4236 /* fill the buffer with the structures */
4237 smb_io_printer_info_5("", buffer, printer, 0);
4239 /* clear memory */
4240 free_printer_info_5(printer);
4242 if (*needed > offered) {
4243 return WERR_INSUFFICIENT_BUFFER;
4246 return WERR_OK;
4249 /****************************************************************************
4250 ****************************************************************************/
4252 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4254 POLICY_HND *handle = &q_u->handle;
4255 uint32 level = q_u->level;
4256 NEW_BUFFER *buffer = NULL;
4257 uint32 offered = q_u->offered;
4258 uint32 *needed = &r_u->needed;
4260 int snum;
4262 /* that's an [in out] buffer */
4263 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4264 buffer = r_u->buffer;
4266 *needed=0;
4268 if (!get_printer_snum(p, handle, &snum))
4269 return WERR_BADFID;
4271 switch (level) {
4272 case 0:
4273 return getprinter_level_0(snum, buffer, offered, needed);
4274 case 1:
4275 return getprinter_level_1(snum, buffer, offered, needed);
4276 case 2:
4277 return getprinter_level_2(snum, buffer, offered, needed);
4278 case 3:
4279 return getprinter_level_3(snum, buffer, offered, needed);
4280 case 4:
4281 return getprinter_level_4(snum, buffer, offered, needed);
4282 case 5:
4283 return getprinter_level_5(snum, buffer, offered, needed);
4285 return WERR_UNKNOWN_LEVEL;
4288 /********************************************************************
4289 * fill a DRIVER_INFO_1 struct
4290 ********************************************************************/
4292 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4294 init_unistr( &info->name, driver.info_3->name);
4297 /********************************************************************
4298 * construct_printer_driver_info_1
4299 ********************************************************************/
4301 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4303 NT_PRINTER_INFO_LEVEL *printer = NULL;
4304 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4306 ZERO_STRUCT(driver);
4308 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4309 return WERR_INVALID_PRINTER_NAME;
4311 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4312 return WERR_UNKNOWN_PRINTER_DRIVER;
4314 fill_printer_driver_info_1(info, driver, servername, architecture);
4316 free_a_printer(&printer,2);
4318 return WERR_OK;
4321 /********************************************************************
4322 * construct_printer_driver_info_2
4323 * fill a printer_info_2 struct
4324 ********************************************************************/
4326 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4328 pstring temp;
4330 info->version=driver.info_3->cversion;
4332 init_unistr( &info->name, driver.info_3->name );
4333 init_unistr( &info->architecture, driver.info_3->environment );
4336 if (strlen(driver.info_3->driverpath)) {
4337 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4338 init_unistr( &info->driverpath, temp );
4339 } else
4340 init_unistr( &info->driverpath, "" );
4342 if (strlen(driver.info_3->datafile)) {
4343 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4344 init_unistr( &info->datafile, temp );
4345 } else
4346 init_unistr( &info->datafile, "" );
4348 if (strlen(driver.info_3->configfile)) {
4349 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4350 init_unistr( &info->configfile, temp );
4351 } else
4352 init_unistr( &info->configfile, "" );
4355 /********************************************************************
4356 * construct_printer_driver_info_2
4357 * fill a printer_info_2 struct
4358 ********************************************************************/
4360 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4362 NT_PRINTER_INFO_LEVEL *printer = NULL;
4363 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4365 ZERO_STRUCT(printer);
4366 ZERO_STRUCT(driver);
4368 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4369 return WERR_INVALID_PRINTER_NAME;
4371 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4372 return WERR_UNKNOWN_PRINTER_DRIVER;
4374 fill_printer_driver_info_2(info, driver, servername);
4376 free_a_printer(&printer,2);
4378 return WERR_OK;
4381 /********************************************************************
4382 * copy a strings array and convert to UNICODE
4384 * convert an array of ascii string to a UNICODE string
4385 ********************************************************************/
4387 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4389 int i=0;
4390 int j=0;
4391 char *v;
4392 pstring line;
4393 uint16 *tuary;
4395 DEBUG(6,("init_unistr_array\n"));
4396 *uni_array=NULL;
4398 while (1) {
4399 if (char_array == NULL)
4400 v = "";
4401 else {
4402 v = char_array[i];
4403 if (!v) v = ""; /* hack to handle null lists */
4405 if (strlen(v) == 0) break;
4406 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
4407 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4408 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
4409 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4410 return;
4411 } else
4412 *uni_array = tuary;
4413 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
4414 i++;
4417 if (*uni_array) {
4418 (*uni_array)[j]=0x0000;
4421 DEBUGADD(6,("last one:done\n"));
4424 /********************************************************************
4425 * construct_printer_info_3
4426 * fill a printer_info_3 struct
4427 ********************************************************************/
4429 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4431 pstring temp;
4433 ZERO_STRUCTP(info);
4435 info->version=driver.info_3->cversion;
4437 init_unistr( &info->name, driver.info_3->name );
4438 init_unistr( &info->architecture, driver.info_3->environment );
4440 if (strlen(driver.info_3->driverpath)) {
4441 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4442 init_unistr( &info->driverpath, temp );
4443 } else
4444 init_unistr( &info->driverpath, "" );
4446 if (strlen(driver.info_3->datafile)) {
4447 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4448 init_unistr( &info->datafile, temp );
4449 } else
4450 init_unistr( &info->datafile, "" );
4452 if (strlen(driver.info_3->configfile)) {
4453 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4454 init_unistr( &info->configfile, temp );
4455 } else
4456 init_unistr( &info->configfile, "" );
4458 if (strlen(driver.info_3->helpfile)) {
4459 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4460 init_unistr( &info->helpfile, temp );
4461 } else
4462 init_unistr( &info->helpfile, "" );
4464 init_unistr( &info->monitorname, driver.info_3->monitorname );
4465 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4467 info->dependentfiles=NULL;
4468 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4471 /********************************************************************
4472 * construct_printer_info_3
4473 * fill a printer_info_3 struct
4474 ********************************************************************/
4476 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4478 NT_PRINTER_INFO_LEVEL *printer = NULL;
4479 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4480 WERROR status;
4481 ZERO_STRUCT(driver);
4483 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4484 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4485 if (!W_ERROR_IS_OK(status))
4486 return WERR_INVALID_PRINTER_NAME;
4488 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4489 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4491 #if 0 /* JERRY */
4494 * I put this code in during testing. Helpful when commenting out the
4495 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4496 * as win2k always queries the driver using an infor level of 6.
4497 * I've left it in (but ifdef'd out) because I'll probably
4498 * use it in experimentation again in the future. --jerry 22/01/2002
4501 if (!W_ERROR_IS_OK(status)) {
4503 * Is this a W2k client ?
4505 if (version == 3) {
4506 /* Yes - try again with a WinNT driver. */
4507 version = 2;
4508 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4509 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4511 #endif
4513 if (!W_ERROR_IS_OK(status)) {
4514 free_a_printer(&printer,2);
4515 return WERR_UNKNOWN_PRINTER_DRIVER;
4518 #if 0 /* JERRY */
4520 #endif
4523 fill_printer_driver_info_3(info, driver, servername);
4525 free_a_printer(&printer,2);
4527 return WERR_OK;
4530 /********************************************************************
4531 * construct_printer_info_6
4532 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4533 ********************************************************************/
4535 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4537 pstring temp;
4538 fstring nullstr;
4540 ZERO_STRUCTP(info);
4541 memset(&nullstr, '\0', sizeof(fstring));
4543 info->version=driver.info_3->cversion;
4545 init_unistr( &info->name, driver.info_3->name );
4546 init_unistr( &info->architecture, driver.info_3->environment );
4548 if (strlen(driver.info_3->driverpath)) {
4549 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4550 init_unistr( &info->driverpath, temp );
4551 } else
4552 init_unistr( &info->driverpath, "" );
4554 if (strlen(driver.info_3->datafile)) {
4555 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4556 init_unistr( &info->datafile, temp );
4557 } else
4558 init_unistr( &info->datafile, "" );
4560 if (strlen(driver.info_3->configfile)) {
4561 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4562 init_unistr( &info->configfile, temp );
4563 } else
4564 init_unistr( &info->configfile, "" );
4566 if (strlen(driver.info_3->helpfile)) {
4567 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4568 init_unistr( &info->helpfile, temp );
4569 } else
4570 init_unistr( &info->helpfile, "" );
4572 init_unistr( &info->monitorname, driver.info_3->monitorname );
4573 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4575 info->dependentfiles=NULL;
4576 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4578 info->previousdrivernames=NULL;
4579 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4581 info->driver_date.low=0;
4582 info->driver_date.high=0;
4584 info->padding=0;
4585 info->driver_version_low=0;
4586 info->driver_version_high=0;
4588 init_unistr( &info->mfgname, "");
4589 init_unistr( &info->oem_url, "");
4590 init_unistr( &info->hardware_id, "");
4591 init_unistr( &info->provider, "");
4594 /********************************************************************
4595 * construct_printer_info_6
4596 * fill a printer_info_6 struct
4597 ********************************************************************/
4599 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4601 NT_PRINTER_INFO_LEVEL *printer = NULL;
4602 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4603 WERROR status;
4604 ZERO_STRUCT(driver);
4606 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4607 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4608 if (!W_ERROR_IS_OK(status))
4609 return WERR_INVALID_PRINTER_NAME;
4611 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4612 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4613 if (!W_ERROR_IS_OK(status)) {
4615 * Is this a W2k client ?
4618 if (version < 3) {
4619 free_a_printer(&printer,2);
4620 return WERR_UNKNOWN_PRINTER_DRIVER;
4623 /* Yes - try again with a WinNT driver. */
4624 version = 2;
4625 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4626 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4627 if (!W_ERROR_IS_OK(status)) {
4628 free_a_printer(&printer,2);
4629 return WERR_UNKNOWN_PRINTER_DRIVER;
4633 fill_printer_driver_info_6(info, driver, servername);
4635 free_a_printer(&printer,2);
4637 return WERR_OK;
4640 /****************************************************************************
4641 ****************************************************************************/
4643 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4645 SAFE_FREE(info->dependentfiles);
4648 /****************************************************************************
4649 ****************************************************************************/
4651 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4653 SAFE_FREE(info->dependentfiles);
4657 /****************************************************************************
4658 ****************************************************************************/
4660 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4662 DRIVER_INFO_1 *info=NULL;
4663 WERROR status;
4665 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4666 return WERR_NOMEM;
4668 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4669 if (!W_ERROR_IS_OK(status)) {
4670 SAFE_FREE(info);
4671 return status;
4674 /* check the required size. */
4675 *needed += spoolss_size_printer_driver_info_1(info);
4677 if (!alloc_buffer_size(buffer, *needed)) {
4678 SAFE_FREE(info);
4679 return WERR_INSUFFICIENT_BUFFER;
4682 /* fill the buffer with the structures */
4683 smb_io_printer_driver_info_1("", buffer, info, 0);
4685 /* clear memory */
4686 SAFE_FREE(info);
4688 if (*needed > offered)
4689 return WERR_INSUFFICIENT_BUFFER;
4691 return WERR_OK;
4694 /****************************************************************************
4695 ****************************************************************************/
4697 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4699 DRIVER_INFO_2 *info=NULL;
4700 WERROR status;
4702 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4703 return WERR_NOMEM;
4705 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4706 if (!W_ERROR_IS_OK(status)) {
4707 SAFE_FREE(info);
4708 return status;
4711 /* check the required size. */
4712 *needed += spoolss_size_printer_driver_info_2(info);
4714 if (!alloc_buffer_size(buffer, *needed)) {
4715 SAFE_FREE(info);
4716 return WERR_INSUFFICIENT_BUFFER;
4719 /* fill the buffer with the structures */
4720 smb_io_printer_driver_info_2("", buffer, info, 0);
4722 /* clear memory */
4723 SAFE_FREE(info);
4725 if (*needed > offered)
4726 return WERR_INSUFFICIENT_BUFFER;
4728 return WERR_OK;
4731 /****************************************************************************
4732 ****************************************************************************/
4734 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4736 DRIVER_INFO_3 info;
4737 WERROR status;
4739 ZERO_STRUCT(info);
4741 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4742 if (!W_ERROR_IS_OK(status)) {
4743 return status;
4746 /* check the required size. */
4747 *needed += spoolss_size_printer_driver_info_3(&info);
4749 if (!alloc_buffer_size(buffer, *needed)) {
4750 free_printer_driver_info_3(&info);
4751 return WERR_INSUFFICIENT_BUFFER;
4754 /* fill the buffer with the structures */
4755 smb_io_printer_driver_info_3("", buffer, &info, 0);
4757 free_printer_driver_info_3(&info);
4759 if (*needed > offered)
4760 return WERR_INSUFFICIENT_BUFFER;
4762 return WERR_OK;
4765 /****************************************************************************
4766 ****************************************************************************/
4768 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4770 DRIVER_INFO_6 info;
4771 WERROR status;
4773 ZERO_STRUCT(info);
4775 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4776 if (!W_ERROR_IS_OK(status)) {
4777 return status;
4780 /* check the required size. */
4781 *needed += spoolss_size_printer_driver_info_6(&info);
4783 if (!alloc_buffer_size(buffer, *needed)) {
4784 free_printer_driver_info_6(&info);
4785 return WERR_INSUFFICIENT_BUFFER;
4788 /* fill the buffer with the structures */
4789 smb_io_printer_driver_info_6("", buffer, &info, 0);
4791 free_printer_driver_info_6(&info);
4793 if (*needed > offered)
4794 return WERR_INSUFFICIENT_BUFFER;
4796 return WERR_OK;
4799 /****************************************************************************
4800 ****************************************************************************/
4802 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4804 POLICY_HND *handle = &q_u->handle;
4805 UNISTR2 *uni_arch = &q_u->architecture;
4806 uint32 level = q_u->level;
4807 uint32 clientmajorversion = q_u->clientmajorversion;
4808 NEW_BUFFER *buffer = NULL;
4809 uint32 offered = q_u->offered;
4810 uint32 *needed = &r_u->needed;
4811 uint32 *servermajorversion = &r_u->servermajorversion;
4812 uint32 *serverminorversion = &r_u->serverminorversion;
4814 fstring servername;
4815 fstring architecture;
4816 int snum;
4818 /* that's an [in out] buffer */
4819 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4820 buffer = r_u->buffer;
4822 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4824 *needed=0;
4825 *servermajorversion=0;
4826 *serverminorversion=0;
4828 pstrcpy(servername, get_called_name());
4829 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4831 if (!get_printer_snum(p, handle, &snum))
4832 return WERR_BADFID;
4834 switch (level) {
4835 case 1:
4836 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4837 case 2:
4838 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4839 case 3:
4840 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4841 case 6:
4842 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4845 return WERR_UNKNOWN_LEVEL;
4848 /****************************************************************************
4849 ****************************************************************************/
4851 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4853 POLICY_HND *handle = &q_u->handle;
4855 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4857 if (!Printer) {
4858 DEBUG(3,("Error in startpageprinter printer handle\n"));
4859 return WERR_BADFID;
4862 Printer->page_started=True;
4863 return WERR_OK;
4866 /****************************************************************************
4867 ****************************************************************************/
4869 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4871 POLICY_HND *handle = &q_u->handle;
4872 int snum;
4874 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4876 if (!Printer) {
4877 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4878 return WERR_BADFID;
4881 if (!get_printer_snum(p, handle, &snum))
4882 return WERR_BADFID;
4884 Printer->page_started=False;
4885 print_job_endpage(snum, Printer->jobid);
4887 return WERR_OK;
4890 /********************************************************************
4891 * api_spoolss_getprinter
4892 * called from the spoolss dispatcher
4894 ********************************************************************/
4896 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4898 POLICY_HND *handle = &q_u->handle;
4899 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4900 uint32 *jobid = &r_u->jobid;
4902 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4903 int snum;
4904 pstring jobname;
4905 fstring datatype;
4906 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4907 struct current_user user;
4909 if (!Printer) {
4910 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4911 return WERR_BADFID;
4914 get_current_user(&user, p);
4917 * a nice thing with NT is it doesn't listen to what you tell it.
4918 * when asked to send _only_ RAW datas, it tries to send datas
4919 * in EMF format.
4921 * So I add checks like in NT Server ...
4923 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4924 * there's a bug in NT client-side code, so we'll fix it in the
4925 * server-side code. *nnnnnggggh!*
4928 if (info_1->p_datatype != 0) {
4929 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4930 if (strcmp(datatype, "RAW") != 0) {
4931 (*jobid)=0;
4932 return WERR_INVALID_DATATYPE;
4936 /* get the share number of the printer */
4937 if (!get_printer_snum(p, handle, &snum)) {
4938 return WERR_BADFID;
4941 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4943 Printer->jobid = print_job_start(&user, snum, jobname);
4945 /* An error occured in print_job_start() so return an appropriate
4946 NT error code. */
4948 if (Printer->jobid == -1) {
4949 return map_werror_from_unix(errno);
4952 Printer->document_started=True;
4953 (*jobid) = Printer->jobid;
4955 return WERR_OK;
4958 /********************************************************************
4959 * api_spoolss_getprinter
4960 * called from the spoolss dispatcher
4962 ********************************************************************/
4964 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4966 POLICY_HND *handle = &q_u->handle;
4968 return _spoolss_enddocprinter_internal(p, handle);
4971 /****************************************************************************
4972 ****************************************************************************/
4974 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4976 POLICY_HND *handle = &q_u->handle;
4977 uint32 buffer_size = q_u->buffer_size;
4978 uint8 *buffer = q_u->buffer;
4979 uint32 *buffer_written = &q_u->buffer_size2;
4980 int snum;
4981 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4983 if (!Printer) {
4984 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4985 r_u->buffer_written = q_u->buffer_size2;
4986 return WERR_BADFID;
4989 if (!get_printer_snum(p, handle, &snum))
4990 return WERR_BADFID;
4992 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
4994 r_u->buffer_written = q_u->buffer_size2;
4996 return WERR_OK;
4999 /********************************************************************
5000 * api_spoolss_getprinter
5001 * called from the spoolss dispatcher
5003 ********************************************************************/
5005 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5006 pipes_struct *p)
5008 struct current_user user;
5009 int snum;
5010 WERROR errcode = WERR_BADFUNC;
5011 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5013 get_current_user(&user, p);
5015 if (!Printer) {
5016 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5017 return WERR_BADFID;
5020 if (!get_printer_snum(p, handle, &snum))
5021 return WERR_BADFID;
5023 switch (command) {
5024 case PRINTER_CONTROL_PAUSE:
5025 if (print_queue_pause(&user, snum, &errcode)) {
5026 errcode = WERR_OK;
5028 break;
5029 case PRINTER_CONTROL_RESUME:
5030 case PRINTER_CONTROL_UNPAUSE:
5031 if (print_queue_resume(&user, snum, &errcode)) {
5032 errcode = WERR_OK;
5034 break;
5035 case PRINTER_CONTROL_PURGE:
5036 if (print_queue_purge(&user, snum, &errcode)) {
5037 errcode = WERR_OK;
5039 break;
5040 default:
5041 return WERR_UNKNOWN_LEVEL;
5044 return errcode;
5047 /********************************************************************
5048 * api_spoolss_abortprinter
5049 ********************************************************************/
5051 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5053 POLICY_HND *handle = &q_u->handle;
5055 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
5058 /********************************************************************
5059 * called by spoolss_api_setprinter
5060 * when updating a printer description
5061 ********************************************************************/
5063 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5064 const SPOOL_PRINTER_INFO_LEVEL *info,
5065 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5067 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5068 struct current_user user;
5069 WERROR result;
5070 int snum;
5072 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5074 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5075 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5076 OUR_HANDLE(handle)));
5078 result = WERR_BADFID;
5079 goto done;
5082 /* NT seems to like setting the security descriptor even though
5083 nothing may have actually changed. This causes annoying
5084 dialog boxes when the user doesn't have permission to change
5085 the security descriptor. */
5087 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5089 if (DEBUGLEVEL >= 10) {
5090 SEC_ACL *the_acl;
5091 int i;
5093 the_acl = old_secdesc_ctr->sec->dacl;
5094 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5095 PRINTERNAME(snum), the_acl->num_aces));
5097 for (i = 0; i < the_acl->num_aces; i++) {
5098 fstring sid_str;
5100 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5102 DEBUG(10, ("%s 0x%08x\n", sid_str,
5103 the_acl->ace[i].info.mask));
5106 the_acl = secdesc_ctr->sec->dacl;
5108 if (the_acl) {
5109 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5110 PRINTERNAME(snum), the_acl->num_aces));
5112 for (i = 0; i < the_acl->num_aces; i++) {
5113 fstring sid_str;
5115 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5117 DEBUG(10, ("%s 0x%08x\n", sid_str,
5118 the_acl->ace[i].info.mask));
5120 } else {
5121 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5125 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5127 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5128 result = WERR_OK;
5129 goto done;
5132 /* Work out which user is performing the operation */
5134 get_current_user(&user, p);
5136 /* Check the user has permissions to change the security
5137 descriptor. By experimentation with two NT machines, the user
5138 requires Full Access to the printer to change security
5139 information. */
5141 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5142 result = WERR_ACCESS_DENIED;
5143 goto done;
5146 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5148 done:
5150 return result;
5153 /********************************************************************
5154 Do Samba sanity checks on a printer info struct.
5155 this has changed purpose: it now "canonicalises" printer
5156 info from a client rather than just checking it is correct
5157 ********************************************************************/
5159 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5161 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5162 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5164 /* we force some elements to "correct" values */
5165 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5166 fstrcpy(info->sharename, lp_servicename(snum));
5167 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5168 get_called_name(), info->sharename);
5169 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5171 return True;
5174 /****************************************************************************
5175 ****************************************************************************/
5177 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5179 extern userdom_struct current_user_info;
5180 char *cmd = lp_addprinter_cmd();
5181 char **qlines;
5182 pstring command;
5183 pstring driverlocation;
5184 int numlines;
5185 int ret;
5186 int fd;
5187 fstring remote_machine = "%m";
5189 /* build driver path... only 9X architecture is needed for legacy reasons */
5190 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5191 get_called_name());
5192 /* change \ to \\ for the shell */
5193 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5194 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5196 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5197 cmd, printer->info_2->printername, printer->info_2->sharename,
5198 printer->info_2->portname, printer->info_2->drivername,
5199 printer->info_2->location, driverlocation, remote_machine);
5201 DEBUG(10,("Running [%s]\n", command));
5202 ret = smbrun(command, &fd);
5203 DEBUGADD(10,("returned [%d]\n", ret));
5205 if ( ret != 0 ) {
5206 if (fd != -1)
5207 close(fd);
5208 return False;
5211 numlines = 0;
5212 /* Get lines and convert them back to dos-codepage */
5213 qlines = fd_lines_load(fd, &numlines);
5214 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5215 close(fd);
5217 if(numlines) {
5218 /* Set the portname to what the script says the portname should be. */
5219 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5220 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5222 /* Send SIGHUP to process group... is there a better way? */
5223 kill(0, SIGHUP);
5224 add_all_printers();
5227 file_lines_free(qlines);
5228 return True;
5231 /********************************************************************
5232 * Called by spoolss_api_setprinter
5233 * when updating a printer description.
5234 ********************************************************************/
5236 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5237 const SPOOL_PRINTER_INFO_LEVEL *info,
5238 DEVICEMODE *devmode)
5240 int snum;
5241 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5243 WERROR result;
5245 DEBUG(8,("update_printer\n"));
5247 result = WERR_OK;
5249 if (level!=2) {
5250 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5251 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5252 result = WERR_UNKNOWN_LEVEL;
5253 goto done;
5256 if (!Printer) {
5257 result = WERR_BADFID;
5258 goto done;
5261 if (!get_printer_snum(p, handle, &snum)) {
5262 result = WERR_BADFID;
5263 goto done;
5266 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5267 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5268 result = WERR_BADFID;
5269 goto done;
5272 DEBUGADD(8,("Converting info_2 struct\n"));
5275 * convert_printer_info converts the incoming
5276 * info from the client and overwrites the info
5277 * just read from the tdb in the pointer 'printer'.
5280 if (!convert_printer_info(info, printer, level)) {
5281 result = WERR_NOMEM;
5282 goto done;
5285 if (devmode) {
5286 /* we have a valid devmode
5287 convert it and link it*/
5289 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5290 if (!convert_devicemode(printer->info_2->printername, devmode,
5291 &printer->info_2->devmode)) {
5292 result = WERR_NOMEM;
5293 goto done;
5297 /* Do sanity check on the requested changes for Samba */
5299 if (!check_printer_ok(printer->info_2, snum)) {
5300 result = WERR_INVALID_PARAM;
5301 goto done;
5304 #if 0 /* JERRY */
5307 * Another one of those historical misunderstandings...
5308 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5309 * I'm leaving it here as a reminder. --jerry
5312 if (nt_printer_info_level_equal(printer, old_printer)) {
5313 DEBUG(3, ("update_printer: printer info has not changed\n"));
5314 result = WERR_OK;
5315 goto done;
5318 #endif
5320 /* Check calling user has permission to update printer description */
5322 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5323 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5324 result = WERR_ACCESS_DENIED;
5325 goto done;
5328 /* Call addprinter hook */
5330 if (*lp_addprinter_cmd()) {
5331 if ( !add_printer_hook(printer) ) {
5332 result = WERR_ACCESS_DENIED;
5333 goto done;
5338 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5339 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5340 * requires Win32 client code (see other notes elsewhere in the code).
5342 if (printer->info_2->devmode &&
5343 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5345 DEBUG(10,("update_printer: Save printer driver init data\n"));
5346 printer->info_2->devmode->displayfrequency = 0;
5348 if (update_driver_init(*printer, 2)!=0) {
5349 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5350 result = WERR_ACCESS_DENIED;
5351 goto done;
5354 /* we need to reset all driver init data for all printers
5355 bound to this driver */
5357 srv_spoolss_reset_printerdata( printer->info_2->drivername );
5359 } else {
5361 * When a *new* driver is bound to a printer, the drivername is used to
5362 * lookup previously saved driver initialization info, which is then
5363 * bound to the printer, simulating what happens in the Windows arch.
5365 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5366 if (!set_driver_init(printer, 2)) {
5367 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5368 printer->info_2->drivername));
5371 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5372 printer->info_2->drivername));
5373 notify_printer_driver(snum, printer->info_2->drivername);
5377 /* Update printer info */
5378 result = mod_a_printer(*printer, 2);
5380 /* flag which changes actually occured. This is a small subset of
5381 all the possible changes */
5383 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5384 notify_printer_comment(snum, printer->info_2->comment);
5386 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5387 notify_printer_sharename(snum, printer->info_2->sharename);
5389 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5390 notify_printer_port(snum, printer->info_2->portname);
5392 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5393 notify_printer_location(snum, printer->info_2->location);
5395 done:
5396 free_a_printer(&printer, 2);
5397 free_a_printer(&old_printer, 2);
5400 return result;
5403 /****************************************************************************
5404 ****************************************************************************/
5406 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5408 POLICY_HND *handle = &q_u->handle;
5409 uint32 level = q_u->level;
5410 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5411 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5412 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5413 uint32 command = q_u->command;
5415 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5417 if (!Printer) {
5418 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5419 return WERR_BADFID;
5422 /* check the level */
5423 switch (level) {
5424 case 0:
5425 return control_printer(handle, command, p);
5426 case 2:
5427 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5428 case 3:
5429 return update_printer_sec(handle, level, info, p,
5430 secdesc_ctr);
5431 default:
5432 return WERR_UNKNOWN_LEVEL;
5436 /****************************************************************************
5437 ****************************************************************************/
5439 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5441 POLICY_HND *handle = &q_u->handle;
5443 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5445 if (!Printer) {
5446 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5447 return WERR_BADFID;
5450 if (Printer->notify.client_connected==True)
5451 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5453 Printer->notify.flags=0;
5454 Printer->notify.options=0;
5455 Printer->notify.localmachine[0]='\0';
5456 Printer->notify.printerlocal=0;
5457 if (Printer->notify.option)
5458 free_spool_notify_option(&Printer->notify.option);
5459 Printer->notify.client_connected=False;
5461 return WERR_OK;
5464 /****************************************************************************
5465 ****************************************************************************/
5467 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5469 /* that's an [in out] buffer (despite appearences to the contrary) */
5470 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5472 r_u->needed = 0;
5473 return WERR_INVALID_PARAM; /* this is what a NT server
5474 returns for AddJob. AddJob
5475 must fail on non-local
5476 printers */
5479 /****************************************************************************
5480 ****************************************************************************/
5482 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5483 int position, int snum)
5485 pstring temp_name;
5487 struct tm *t;
5489 t=gmtime(&queue->time);
5490 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5492 job_info->jobid=queue->job;
5493 init_unistr(&job_info->printername, lp_servicename(snum));
5494 init_unistr(&job_info->machinename, temp_name);
5495 init_unistr(&job_info->username, queue->fs_user);
5496 init_unistr(&job_info->document, queue->fs_file);
5497 init_unistr(&job_info->datatype, "RAW");
5498 init_unistr(&job_info->text_status, "");
5499 job_info->status=nt_printj_status(queue->status);
5500 job_info->priority=queue->priority;
5501 job_info->position=position;
5502 job_info->totalpages=queue->page_count;
5503 job_info->pagesprinted=0;
5505 make_systemtime(&job_info->submitted, t);
5508 /****************************************************************************
5509 ****************************************************************************/
5511 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5512 int position, int snum,
5513 NT_PRINTER_INFO_LEVEL *ntprinter,
5514 DEVICEMODE *devmode)
5516 pstring temp_name;
5517 pstring chaine;
5518 struct tm *t;
5520 t=gmtime(&queue->time);
5521 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5523 job_info->jobid=queue->job;
5525 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5527 init_unistr(&job_info->printername, chaine);
5529 init_unistr(&job_info->machinename, temp_name);
5530 init_unistr(&job_info->username, queue->fs_user);
5531 init_unistr(&job_info->document, queue->fs_file);
5532 init_unistr(&job_info->notifyname, queue->fs_user);
5533 init_unistr(&job_info->datatype, "RAW");
5534 init_unistr(&job_info->printprocessor, "winprint");
5535 init_unistr(&job_info->parameters, "");
5536 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5537 init_unistr(&job_info->text_status, "");
5539 /* and here the security descriptor */
5541 job_info->status=nt_printj_status(queue->status);
5542 job_info->priority=queue->priority;
5543 job_info->position=position;
5544 job_info->starttime=0;
5545 job_info->untiltime=0;
5546 job_info->totalpages=queue->page_count;
5547 job_info->size=queue->size;
5548 make_systemtime(&(job_info->submitted), t);
5549 job_info->timeelapsed=0;
5550 job_info->pagesprinted=0;
5552 job_info->devmode = devmode;
5554 return (True);
5557 /****************************************************************************
5558 Enumjobs at level 1.
5559 ****************************************************************************/
5561 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5562 NEW_BUFFER *buffer, uint32 offered,
5563 uint32 *needed, uint32 *returned)
5565 JOB_INFO_1 *info;
5566 int i;
5568 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5569 if (info==NULL) {
5570 SAFE_FREE(queue);
5571 *returned=0;
5572 return WERR_NOMEM;
5575 for (i=0; i<*returned; i++)
5576 fill_job_info_1(&info[i], &queue[i], i, snum);
5578 SAFE_FREE(queue);
5580 /* check the required size. */
5581 for (i=0; i<*returned; i++)
5582 (*needed) += spoolss_size_job_info_1(&info[i]);
5584 if (!alloc_buffer_size(buffer, *needed)) {
5585 SAFE_FREE(info);
5586 return WERR_INSUFFICIENT_BUFFER;
5589 /* fill the buffer with the structures */
5590 for (i=0; i<*returned; i++)
5591 smb_io_job_info_1("", buffer, &info[i], 0);
5593 /* clear memory */
5594 SAFE_FREE(info);
5596 if (*needed > offered) {
5597 *returned=0;
5598 return WERR_INSUFFICIENT_BUFFER;
5601 return WERR_OK;
5604 /****************************************************************************
5605 Enumjobs at level 2.
5606 ****************************************************************************/
5608 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5609 NEW_BUFFER *buffer, uint32 offered,
5610 uint32 *needed, uint32 *returned)
5612 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5613 JOB_INFO_2 *info = NULL;
5614 int i;
5615 WERROR result;
5616 DEVICEMODE *devmode = NULL;
5618 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5619 if (info==NULL) {
5620 *returned=0;
5621 result = WERR_NOMEM;
5622 goto done;
5625 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5626 if (!W_ERROR_IS_OK(result)) {
5627 *returned = 0;
5628 goto done;
5631 if (!(devmode = construct_dev_mode(snum))) {
5632 *returned = 0;
5633 result = WERR_NOMEM;
5634 goto done;
5637 for (i=0; i<*returned; i++)
5638 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5639 devmode);
5641 free_a_printer(&ntprinter, 2);
5642 SAFE_FREE(queue);
5644 /* check the required size. */
5645 for (i=0; i<*returned; i++)
5646 (*needed) += spoolss_size_job_info_2(&info[i]);
5648 if (*needed > offered) {
5649 *returned=0;
5650 result = WERR_INSUFFICIENT_BUFFER;
5651 goto done;
5654 if (!alloc_buffer_size(buffer, *needed)) {
5655 SAFE_FREE(info);
5656 result = WERR_INSUFFICIENT_BUFFER;
5657 goto done;
5660 /* fill the buffer with the structures */
5661 for (i=0; i<*returned; i++)
5662 smb_io_job_info_2("", buffer, &info[i], 0);
5664 result = WERR_OK;
5666 done:
5667 free_a_printer(&ntprinter, 2);
5668 free_devmode(devmode);
5669 SAFE_FREE(queue);
5670 SAFE_FREE(info);
5672 return result;
5676 /****************************************************************************
5677 Enumjobs.
5678 ****************************************************************************/
5680 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5682 POLICY_HND *handle = &q_u->handle;
5683 uint32 level = q_u->level;
5684 NEW_BUFFER *buffer = NULL;
5685 uint32 offered = q_u->offered;
5686 uint32 *needed = &r_u->needed;
5687 uint32 *returned = &r_u->returned;
5689 int snum;
5690 print_status_struct prt_status;
5691 print_queue_struct *queue=NULL;
5693 /* that's an [in out] buffer */
5694 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5695 buffer = r_u->buffer;
5697 DEBUG(4,("_spoolss_enumjobs\n"));
5699 *needed=0;
5700 *returned=0;
5702 if (!get_printer_snum(p, handle, &snum))
5703 return WERR_BADFID;
5705 *returned = print_queue_status(snum, &queue, &prt_status);
5706 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5708 if (*returned == 0) {
5709 SAFE_FREE(queue);
5710 return WERR_OK;
5713 switch (level) {
5714 case 1:
5715 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5716 case 2:
5717 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5718 default:
5719 SAFE_FREE(queue);
5720 *returned=0;
5721 return WERR_UNKNOWN_LEVEL;
5725 /****************************************************************************
5726 ****************************************************************************/
5728 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5730 return WERR_OK;
5733 /****************************************************************************
5734 ****************************************************************************/
5736 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5738 POLICY_HND *handle = &q_u->handle;
5739 uint32 jobid = q_u->jobid;
5740 uint32 command = q_u->command;
5742 struct current_user user;
5743 int snum;
5744 WERROR errcode = WERR_BADFUNC;
5746 if (!get_printer_snum(p, handle, &snum)) {
5747 return WERR_BADFID;
5750 if (!print_job_exists(snum, jobid)) {
5751 return WERR_INVALID_PRINTER_NAME;
5754 get_current_user(&user, p);
5756 switch (command) {
5757 case JOB_CONTROL_CANCEL:
5758 case JOB_CONTROL_DELETE:
5759 if (print_job_delete(&user, snum, jobid, &errcode)) {
5760 errcode = WERR_OK;
5762 break;
5763 case JOB_CONTROL_PAUSE:
5764 if (print_job_pause(&user, snum, jobid, &errcode)) {
5765 errcode = WERR_OK;
5767 break;
5768 case JOB_CONTROL_RESTART:
5769 case JOB_CONTROL_RESUME:
5770 if (print_job_resume(&user, snum, jobid, &errcode)) {
5771 errcode = WERR_OK;
5773 break;
5774 default:
5775 return WERR_UNKNOWN_LEVEL;
5778 return errcode;
5781 /****************************************************************************
5782 Enumerates all printer drivers at level 1.
5783 ****************************************************************************/
5785 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5787 int i;
5788 int ndrivers;
5789 uint32 version;
5790 fstring *list = NULL;
5792 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5793 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5795 *returned=0;
5797 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5798 list=NULL;
5799 ndrivers=get_ntdrivers(&list, architecture, version);
5800 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5802 if(ndrivers == -1)
5803 return WERR_NOMEM;
5805 if(ndrivers != 0) {
5806 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5807 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5808 SAFE_FREE(driver_info_1);
5809 SAFE_FREE(list);
5810 return WERR_NOMEM;
5812 else driver_info_1 = tdi1;
5815 for (i=0; i<ndrivers; i++) {
5816 WERROR status;
5817 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5818 ZERO_STRUCT(driver);
5819 status = get_a_printer_driver(&driver, 3, list[i],
5820 architecture, version);
5821 if (!W_ERROR_IS_OK(status)) {
5822 SAFE_FREE(list);
5823 return status;
5825 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5826 free_a_printer_driver(driver, 3);
5829 *returned+=ndrivers;
5830 SAFE_FREE(list);
5833 /* check the required size. */
5834 for (i=0; i<*returned; i++) {
5835 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5836 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5839 if (!alloc_buffer_size(buffer, *needed)) {
5840 SAFE_FREE(driver_info_1);
5841 return WERR_INSUFFICIENT_BUFFER;
5844 /* fill the buffer with the driver structures */
5845 for (i=0; i<*returned; i++) {
5846 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5847 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5850 SAFE_FREE(driver_info_1);
5852 if (*needed > offered) {
5853 *returned=0;
5854 return WERR_INSUFFICIENT_BUFFER;
5857 return WERR_OK;
5860 /****************************************************************************
5861 Enumerates all printer drivers at level 2.
5862 ****************************************************************************/
5864 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5866 int i;
5867 int ndrivers;
5868 uint32 version;
5869 fstring *list = NULL;
5871 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5872 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5874 *returned=0;
5876 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5877 list=NULL;
5878 ndrivers=get_ntdrivers(&list, architecture, version);
5879 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5881 if(ndrivers == -1)
5882 return WERR_NOMEM;
5884 if(ndrivers != 0) {
5885 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5886 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5887 SAFE_FREE(driver_info_2);
5888 SAFE_FREE(list);
5889 return WERR_NOMEM;
5891 else driver_info_2 = tdi2;
5894 for (i=0; i<ndrivers; i++) {
5895 WERROR status;
5897 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5898 ZERO_STRUCT(driver);
5899 status = get_a_printer_driver(&driver, 3, list[i],
5900 architecture, version);
5901 if (!W_ERROR_IS_OK(status)) {
5902 SAFE_FREE(list);
5903 return status;
5905 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5906 free_a_printer_driver(driver, 3);
5909 *returned+=ndrivers;
5910 SAFE_FREE(list);
5913 /* check the required size. */
5914 for (i=0; i<*returned; i++) {
5915 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5916 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5919 if (!alloc_buffer_size(buffer, *needed)) {
5920 SAFE_FREE(driver_info_2);
5921 return WERR_INSUFFICIENT_BUFFER;
5924 /* fill the buffer with the form structures */
5925 for (i=0; i<*returned; i++) {
5926 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5927 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5930 SAFE_FREE(driver_info_2);
5932 if (*needed > offered) {
5933 *returned=0;
5934 return WERR_INSUFFICIENT_BUFFER;
5937 return WERR_OK;
5940 /****************************************************************************
5941 Enumerates all printer drivers at level 3.
5942 ****************************************************************************/
5944 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5946 int i;
5947 int ndrivers;
5948 uint32 version;
5949 fstring *list = NULL;
5951 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5952 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5954 *returned=0;
5956 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5957 list=NULL;
5958 ndrivers=get_ntdrivers(&list, architecture, version);
5959 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5961 if(ndrivers == -1)
5962 return WERR_NOMEM;
5964 if(ndrivers != 0) {
5965 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5966 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5967 SAFE_FREE(driver_info_3);
5968 SAFE_FREE(list);
5969 return WERR_NOMEM;
5971 else driver_info_3 = tdi3;
5974 for (i=0; i<ndrivers; i++) {
5975 WERROR status;
5977 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5978 ZERO_STRUCT(driver);
5979 status = get_a_printer_driver(&driver, 3, list[i],
5980 architecture, version);
5981 if (!W_ERROR_IS_OK(status)) {
5982 SAFE_FREE(list);
5983 return status;
5985 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5986 free_a_printer_driver(driver, 3);
5989 *returned+=ndrivers;
5990 SAFE_FREE(list);
5993 /* check the required size. */
5994 for (i=0; i<*returned; i++) {
5995 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5996 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5999 if (!alloc_buffer_size(buffer, *needed)) {
6000 SAFE_FREE(driver_info_3);
6001 return WERR_INSUFFICIENT_BUFFER;
6004 /* fill the buffer with the driver structures */
6005 for (i=0; i<*returned; i++) {
6006 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6007 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6010 for (i=0; i<*returned; i++)
6011 SAFE_FREE(driver_info_3[i].dependentfiles);
6013 SAFE_FREE(driver_info_3);
6015 if (*needed > offered) {
6016 *returned=0;
6017 return WERR_INSUFFICIENT_BUFFER;
6020 return WERR_OK;
6023 /****************************************************************************
6024 Enumerates all printer drivers.
6025 ****************************************************************************/
6027 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6029 UNISTR2 *environment = &q_u->environment;
6030 uint32 level = q_u->level;
6031 NEW_BUFFER *buffer = NULL;
6032 uint32 offered = q_u->offered;
6033 uint32 *needed = &r_u->needed;
6034 uint32 *returned = &r_u->returned;
6036 fstring *list = NULL;
6037 fstring servername;
6038 fstring architecture;
6040 /* that's an [in out] buffer */
6041 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6042 buffer = r_u->buffer;
6044 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6045 fstrcpy(servername, get_called_name());
6046 *needed=0;
6047 *returned=0;
6049 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6051 switch (level) {
6052 case 1:
6053 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6054 case 2:
6055 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6056 case 3:
6057 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6058 default:
6059 *returned=0;
6060 SAFE_FREE(list);
6061 return WERR_UNKNOWN_LEVEL;
6065 /****************************************************************************
6066 ****************************************************************************/
6068 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6070 form->flag=list->flag;
6071 init_unistr(&form->name, list->name);
6072 form->width=list->width;
6073 form->length=list->length;
6074 form->left=list->left;
6075 form->top=list->top;
6076 form->right=list->right;
6077 form->bottom=list->bottom;
6080 /****************************************************************************
6081 ****************************************************************************/
6083 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6085 uint32 level = q_u->level;
6086 NEW_BUFFER *buffer = NULL;
6087 uint32 offered = q_u->offered;
6088 uint32 *needed = &r_u->needed;
6089 uint32 *numofforms = &r_u->numofforms;
6090 uint32 numbuiltinforms;
6092 nt_forms_struct *list=NULL;
6093 nt_forms_struct *builtinlist=NULL;
6094 FORM_1 *forms_1;
6095 int buffer_size=0;
6096 int i;
6098 /* that's an [in out] buffer */
6099 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6100 buffer = r_u->buffer;
6102 DEBUG(4,("_spoolss_enumforms\n"));
6103 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6104 DEBUGADD(5,("Info level [%d]\n", level));
6106 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6107 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6108 *numofforms = get_ntforms(&list);
6109 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6110 *numofforms += numbuiltinforms;
6112 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6114 switch (level) {
6115 case 1:
6116 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6117 *numofforms=0;
6118 return WERR_NOMEM;
6121 /* construct the list of form structures */
6122 for (i=0; i<numbuiltinforms; i++) {
6123 DEBUGADD(6,("Filling form number [%d]\n",i));
6124 fill_form_1(&forms_1[i], &builtinlist[i]);
6127 SAFE_FREE(builtinlist);
6129 for (; i<*numofforms; i++) {
6130 DEBUGADD(6,("Filling form number [%d]\n",i));
6131 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6134 SAFE_FREE(list);
6136 /* check the required size. */
6137 for (i=0; i<numbuiltinforms; i++) {
6138 DEBUGADD(6,("adding form [%d]'s size\n",i));
6139 buffer_size += spoolss_size_form_1(&forms_1[i]);
6141 for (; i<*numofforms; i++) {
6142 DEBUGADD(6,("adding form [%d]'s size\n",i));
6143 buffer_size += spoolss_size_form_1(&forms_1[i]);
6146 *needed=buffer_size;
6148 if (!alloc_buffer_size(buffer, buffer_size)){
6149 SAFE_FREE(forms_1);
6150 return WERR_INSUFFICIENT_BUFFER;
6153 /* fill the buffer with the form structures */
6154 for (i=0; i<numbuiltinforms; i++) {
6155 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6156 smb_io_form_1("", buffer, &forms_1[i], 0);
6158 for (; i<*numofforms; i++) {
6159 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6160 smb_io_form_1("", buffer, &forms_1[i], 0);
6163 SAFE_FREE(forms_1);
6165 if (*needed > offered) {
6166 *numofforms=0;
6167 return WERR_INSUFFICIENT_BUFFER;
6169 else
6170 return WERR_OK;
6172 default:
6173 SAFE_FREE(list);
6174 SAFE_FREE(builtinlist);
6175 return WERR_UNKNOWN_LEVEL;
6180 /****************************************************************************
6181 ****************************************************************************/
6183 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6185 uint32 level = q_u->level;
6186 UNISTR2 *uni_formname = &q_u->formname;
6187 NEW_BUFFER *buffer = NULL;
6188 uint32 offered = q_u->offered;
6189 uint32 *needed = &r_u->needed;
6191 nt_forms_struct *list=NULL;
6192 nt_forms_struct builtin_form;
6193 BOOL foundBuiltin;
6194 FORM_1 form_1;
6195 fstring form_name;
6196 int buffer_size=0;
6197 int numofforms=0, i=0;
6199 /* that's an [in out] buffer */
6200 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6201 buffer = r_u->buffer;
6203 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6205 DEBUG(4,("_spoolss_getform\n"));
6206 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6207 DEBUGADD(5,("Info level [%d]\n", level));
6209 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6210 if (!foundBuiltin) {
6211 numofforms = get_ntforms(&list);
6212 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6214 if (numofforms == 0)
6215 return WERR_BADFID;
6218 switch (level) {
6219 case 1:
6220 if (foundBuiltin) {
6221 fill_form_1(&form_1, &builtin_form);
6222 } else {
6224 /* Check if the requested name is in the list of form structures */
6225 for (i=0; i<numofforms; i++) {
6227 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6229 if (strequal(form_name, list[i].name)) {
6230 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6231 fill_form_1(&form_1, &list[i]);
6232 break;
6236 SAFE_FREE(list);
6237 if (i == numofforms) {
6238 return WERR_BADFID;
6241 /* check the required size. */
6243 *needed=spoolss_size_form_1(&form_1);
6245 if (!alloc_buffer_size(buffer, buffer_size)){
6246 return WERR_INSUFFICIENT_BUFFER;
6249 if (*needed > offered) {
6250 return WERR_INSUFFICIENT_BUFFER;
6253 /* fill the buffer with the form structures */
6254 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6255 smb_io_form_1("", buffer, &form_1, 0);
6257 return WERR_OK;
6259 default:
6260 SAFE_FREE(list);
6261 return WERR_UNKNOWN_LEVEL;
6265 /****************************************************************************
6266 ****************************************************************************/
6268 static void fill_port_1(PORT_INFO_1 *port, char *name)
6270 init_unistr(&port->port_name, name);
6273 /****************************************************************************
6274 ****************************************************************************/
6276 static void fill_port_2(PORT_INFO_2 *port, char *name)
6278 init_unistr(&port->port_name, name);
6279 init_unistr(&port->monitor_name, "Local Monitor");
6280 init_unistr(&port->description, "Local Port");
6281 #define PORT_TYPE_WRITE 1
6282 port->port_type=PORT_TYPE_WRITE;
6283 port->reserved=0x0;
6286 /****************************************************************************
6287 enumports level 1.
6288 ****************************************************************************/
6290 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6292 PORT_INFO_1 *ports=NULL;
6293 int i=0;
6295 if (*lp_enumports_cmd()) {
6296 char *cmd = lp_enumports_cmd();
6297 char **qlines;
6298 pstring command;
6299 int numlines;
6300 int ret;
6301 int fd;
6303 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6305 DEBUG(10,("Running [%s]\n", command));
6306 ret = smbrun(command, &fd);
6307 DEBUG(10,("Returned [%d]\n", ret));
6308 if (ret != 0) {
6309 if (fd != -1)
6310 close(fd);
6311 /* Is this the best error to return here? */
6312 return WERR_ACCESS_DENIED;
6315 numlines = 0;
6316 qlines = fd_lines_load(fd, &numlines);
6317 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6318 close(fd);
6320 if(numlines) {
6321 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6322 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6323 dos_errstr(WERR_NOMEM)));
6324 file_lines_free(qlines);
6325 return WERR_NOMEM;
6328 for (i=0; i<numlines; i++) {
6329 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6330 fill_port_1(&ports[i], qlines[i]);
6333 file_lines_free(qlines);
6336 *returned = numlines;
6338 } else {
6339 *returned = 1; /* Sole Samba port returned. */
6341 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6342 return WERR_NOMEM;
6344 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6346 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6349 /* check the required size. */
6350 for (i=0; i<*returned; i++) {
6351 DEBUGADD(6,("adding port [%d]'s size\n", i));
6352 *needed += spoolss_size_port_info_1(&ports[i]);
6355 if (!alloc_buffer_size(buffer, *needed)) {
6356 SAFE_FREE(ports);
6357 return WERR_INSUFFICIENT_BUFFER;
6360 /* fill the buffer with the ports structures */
6361 for (i=0; i<*returned; i++) {
6362 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6363 smb_io_port_1("", buffer, &ports[i], 0);
6366 SAFE_FREE(ports);
6368 if (*needed > offered) {
6369 *returned=0;
6370 return WERR_INSUFFICIENT_BUFFER;
6373 return WERR_OK;
6376 /****************************************************************************
6377 enumports level 2.
6378 ****************************************************************************/
6380 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6382 PORT_INFO_2 *ports=NULL;
6383 int i=0;
6385 if (*lp_enumports_cmd()) {
6386 char *cmd = lp_enumports_cmd();
6387 char *path;
6388 char **qlines;
6389 pstring tmp_file;
6390 pstring command;
6391 int numlines;
6392 int ret;
6393 int fd;
6395 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6396 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6397 else
6398 path = lp_lockdir();
6400 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6401 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6403 unlink(tmp_file);
6404 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6405 ret = smbrun(command, &fd);
6406 DEBUGADD(10,("returned [%d]\n", ret));
6407 if (ret != 0) {
6408 if (fd != -1)
6409 close(fd);
6410 /* Is this the best error to return here? */
6411 return WERR_ACCESS_DENIED;
6414 numlines = 0;
6415 qlines = fd_lines_load(fd, &numlines);
6416 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6417 close(fd);
6419 if(numlines) {
6420 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6421 file_lines_free(qlines);
6422 return WERR_NOMEM;
6425 for (i=0; i<numlines; i++) {
6426 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6427 fill_port_2(&(ports[i]), qlines[i]);
6430 file_lines_free(qlines);
6433 *returned = numlines;
6435 } else {
6437 *returned = 1;
6439 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6440 return WERR_NOMEM;
6442 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6444 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6447 /* check the required size. */
6448 for (i=0; i<*returned; i++) {
6449 DEBUGADD(6,("adding port [%d]'s size\n", i));
6450 *needed += spoolss_size_port_info_2(&ports[i]);
6453 if (!alloc_buffer_size(buffer, *needed)) {
6454 SAFE_FREE(ports);
6455 return WERR_INSUFFICIENT_BUFFER;
6458 /* fill the buffer with the ports structures */
6459 for (i=0; i<*returned; i++) {
6460 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6461 smb_io_port_2("", buffer, &ports[i], 0);
6464 SAFE_FREE(ports);
6466 if (*needed > offered) {
6467 *returned=0;
6468 return WERR_INSUFFICIENT_BUFFER;
6471 return WERR_OK;
6474 /****************************************************************************
6475 enumports.
6476 ****************************************************************************/
6478 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6480 uint32 level = q_u->level;
6481 NEW_BUFFER *buffer = NULL;
6482 uint32 offered = q_u->offered;
6483 uint32 *needed = &r_u->needed;
6484 uint32 *returned = &r_u->returned;
6486 /* that's an [in out] buffer */
6487 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6488 buffer = r_u->buffer;
6490 DEBUG(4,("_spoolss_enumports\n"));
6492 *returned=0;
6493 *needed=0;
6495 switch (level) {
6496 case 1:
6497 return enumports_level_1(buffer, offered, needed, returned);
6498 case 2:
6499 return enumports_level_2(buffer, offered, needed, returned);
6500 default:
6501 return WERR_UNKNOWN_LEVEL;
6505 /****************************************************************************
6506 ****************************************************************************/
6508 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6509 const SPOOL_PRINTER_INFO_LEVEL *info,
6510 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6511 uint32 user_switch, const SPOOL_USER_CTR *user,
6512 POLICY_HND *handle)
6514 NT_PRINTER_INFO_LEVEL *printer = NULL;
6515 fstring name;
6516 int snum;
6517 WERROR err = WERR_OK;
6519 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6520 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6521 return WERR_NOMEM;
6524 ZERO_STRUCTP(printer);
6526 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6527 if (!convert_printer_info(info, printer, 2)) {
6528 free_a_printer(&printer, 2);
6529 return WERR_NOMEM;
6532 /* check to see if the printer already exists */
6534 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6535 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6536 printer->info_2->sharename));
6537 free_a_printer(&printer, 2);
6538 return WERR_PRINTER_ALREADY_EXISTS;
6541 if (*lp_addprinter_cmd() )
6542 if ( !add_printer_hook(printer) ) {
6543 free_a_printer(&printer,2);
6544 return WERR_ACCESS_DENIED;
6547 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6548 printer->info_2->sharename);
6550 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6551 free_a_printer(&printer,2);
6552 return WERR_ACCESS_DENIED;
6555 /* you must be a printer admin to add a new printer */
6556 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6557 free_a_printer(&printer,2);
6558 return WERR_ACCESS_DENIED;
6562 * Do sanity check on the requested changes for Samba.
6565 if (!check_printer_ok(printer->info_2, snum)) {
6566 free_a_printer(&printer,2);
6567 return WERR_INVALID_PARAM;
6571 * When a printer is created, the drivername bound to the printer is used
6572 * to lookup previously saved driver initialization info, which is then
6573 * bound to the new printer, simulating what happens in the Windows arch.
6576 if (!devmode)
6577 set_driver_init(printer, 2);
6578 else {
6579 /* A valid devmode was included, convert and link it
6581 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6583 if (!convert_devicemode(printer->info_2->printername, devmode,
6584 &printer->info_2->devmode))
6585 return WERR_NOMEM;
6588 set_driver_init(printer, 2);
6590 /* write the ASCII on disk */
6591 err = mod_a_printer(*printer, 2);
6592 if (!W_ERROR_IS_OK(err)) {
6593 free_a_printer(&printer,2);
6594 return err;
6597 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6598 /* Handle open failed - remove addition. */
6599 del_a_printer(printer->info_2->sharename);
6600 free_a_printer(&printer,2);
6601 return WERR_ACCESS_DENIED;
6604 update_c_setprinter(False);
6605 free_a_printer(&printer,2);
6607 return WERR_OK;
6610 /****************************************************************************
6611 ****************************************************************************/
6613 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6615 UNISTR2 *uni_srv_name = &q_u->server_name;
6616 uint32 level = q_u->level;
6617 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6618 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6619 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6620 uint32 user_switch = q_u->user_switch;
6621 SPOOL_USER_CTR *user = &q_u->user_ctr;
6622 POLICY_HND *handle = &r_u->handle;
6624 switch (level) {
6625 case 1:
6626 /* we don't handle yet */
6627 /* but I know what to do ... */
6628 return WERR_UNKNOWN_LEVEL;
6629 case 2:
6630 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6631 devmode, sdb,
6632 user_switch, user, handle);
6633 default:
6634 return WERR_UNKNOWN_LEVEL;
6638 /****************************************************************************
6639 ****************************************************************************/
6641 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6643 uint32 level = q_u->level;
6644 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6645 WERROR err = WERR_OK;
6646 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6647 struct current_user user;
6648 fstring driver_name;
6649 uint32 version;
6651 ZERO_STRUCT(driver);
6653 get_current_user(&user, p);
6655 if (!convert_printer_driver_info(info, &driver, level)) {
6656 err = WERR_NOMEM;
6657 goto done;
6660 DEBUG(5,("Cleaning driver's information\n"));
6661 err = clean_up_driver_struct(driver, level, &user);
6662 if (!W_ERROR_IS_OK(err))
6663 goto done;
6665 DEBUG(5,("Moving driver to final destination\n"));
6666 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6667 if (W_ERROR_IS_OK(err))
6668 err = WERR_ACCESS_DENIED;
6669 goto done;
6672 if (add_a_printer_driver(driver, level)!=0) {
6673 err = WERR_ACCESS_DENIED;
6674 goto done;
6677 /* BEGIN_ADMIN_LOG */
6678 switch(level) {
6679 case 3:
6680 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6681 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6682 fstrcpy(driver_name, driver.info_3->name);
6683 break;
6684 case 6:
6685 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6686 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6687 fstrcpy(driver_name, driver.info_6->name);
6688 break;
6690 /* END_ADMIN_LOG */
6693 * I think this is where he DrvUpgradePrinter() hook would be
6694 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6695 * server. Right now, we just need to send ourselves a message
6696 * to update each printer bound to this driver. --jerry
6699 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6700 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6701 driver_name));
6705 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6706 * decide if the driver init data should be deleted. The rules are:
6707 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6708 * 2) delete init data only if there is no 2k/Xp driver
6709 * 3) always delete init data
6710 * The generalized rule is always use init data from the highest order driver.
6711 * It is necessary to follow the driver install by an initialization step to
6712 * finish off this process.
6714 if (level == 3)
6715 version = driver.info_3->cversion;
6716 else if (level == 6)
6717 version = driver.info_6->version;
6718 else
6719 version = -1;
6720 switch (version) {
6722 * 9x printer driver - never delete init data
6724 case 0:
6725 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6726 driver_name));
6727 break;
6730 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6731 * there is no 2k/Xp driver init data for this driver name.
6733 case 2:
6735 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
6737 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
6739 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6741 if (!del_driver_init(driver_name))
6742 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
6743 } else {
6745 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6747 free_a_printer_driver(driver1,3);
6748 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6749 driver_name));
6752 break;
6755 * 2k or Xp printer driver - always delete init data
6757 case 3:
6758 if (!del_driver_init(driver_name))
6759 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
6760 break;
6762 default:
6763 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
6764 break;
6768 done:
6769 free_a_printer_driver(driver, level);
6770 return err;
6773 /********************************************************************
6774 * spoolss_addprinterdriverex
6775 ********************************************************************/
6777 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
6779 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
6780 SPOOL_R_ADDPRINTERDRIVER r_u_local;
6783 * we only support the semantics of AddPrinterDriver()
6784 * i.e. only copy files that are newer than existing ones
6787 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
6788 return WERR_ACCESS_DENIED;
6790 ZERO_STRUCT(q_u_local);
6791 ZERO_STRUCT(r_u_local);
6793 /* just pass the information off to _spoolss_addprinterdriver() */
6794 q_u_local.server_name_ptr = q_u->server_name_ptr;
6795 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
6796 q_u_local.level = q_u->level;
6797 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
6799 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
6802 /****************************************************************************
6803 ****************************************************************************/
6805 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6807 init_unistr(&info->name, name);
6810 /****************************************************************************
6811 ****************************************************************************/
6813 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6815 pstring path;
6816 pstring long_archi;
6817 pstring short_archi;
6818 DRIVER_DIRECTORY_1 *info=NULL;
6820 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6822 if (get_short_archi(short_archi, long_archi)==False)
6823 return WERR_INVALID_ENVIRONMENT;
6825 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6826 return WERR_NOMEM;
6828 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6830 DEBUG(4,("printer driver directory: [%s]\n", path));
6832 fill_driverdir_1(info, path);
6834 *needed += spoolss_size_driverdir_info_1(info);
6836 if (!alloc_buffer_size(buffer, *needed)) {
6837 SAFE_FREE(info);
6838 return WERR_INSUFFICIENT_BUFFER;
6841 smb_io_driverdir_1("", buffer, info, 0);
6843 SAFE_FREE(info);
6845 if (*needed > offered)
6846 return WERR_INSUFFICIENT_BUFFER;
6848 return WERR_OK;
6851 /****************************************************************************
6852 ****************************************************************************/
6854 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6856 UNISTR2 *name = &q_u->name;
6857 UNISTR2 *uni_environment = &q_u->environment;
6858 uint32 level = q_u->level;
6859 NEW_BUFFER *buffer = NULL;
6860 uint32 offered = q_u->offered;
6861 uint32 *needed = &r_u->needed;
6863 /* that's an [in out] buffer */
6864 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6865 buffer = r_u->buffer;
6867 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6869 *needed=0;
6871 switch(level) {
6872 case 1:
6873 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6874 default:
6875 return WERR_UNKNOWN_LEVEL;
6879 /****************************************************************************
6880 ****************************************************************************/
6882 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6884 POLICY_HND *handle = &q_u->handle;
6885 uint32 idx = q_u->index;
6886 uint32 in_value_len = q_u->valuesize;
6887 uint32 in_data_len = q_u->datasize;
6888 uint32 *out_max_value_len= &r_u->valuesize;
6889 uint16 **out_value = &r_u->value;
6890 uint32 *out_value_len = &r_u->realvaluesize;
6891 uint32 *out_type = &r_u->type;
6892 uint32 *out_max_data_len = &r_u->datasize;
6893 uint8 **data_out = &r_u->data;
6894 uint32 *out_data_len = &r_u->realdatasize;
6896 NT_PRINTER_INFO_LEVEL *printer = NULL;
6898 uint32 param_index;
6899 uint32 biggest_valuesize;
6900 uint32 biggest_datasize;
6901 uint32 data_len;
6902 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6903 int snum;
6904 WERROR result;
6905 REGISTRY_VALUE *val;
6906 NT_PRINTER_DATA *p_data;
6907 int i, key_index, num_values;
6908 int name_length;
6910 ZERO_STRUCT( printer );
6912 *out_type = 0;
6914 *out_max_data_len = 0;
6915 *data_out = NULL;
6916 *out_data_len = 0;
6918 DEBUG(5,("spoolss_enumprinterdata\n"));
6920 if (!Printer) {
6921 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6922 return WERR_BADFID;
6925 if (!get_printer_snum(p,handle, &snum))
6926 return WERR_BADFID;
6928 result = get_a_printer(&printer, 2, lp_servicename(snum));
6929 if (!W_ERROR_IS_OK(result))
6930 return result;
6932 p_data = &printer->info_2->data;
6933 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
6935 result = WERR_OK;
6938 * The NT machine wants to know the biggest size of value and data
6940 * cf: MSDN EnumPrinterData remark section
6943 if ( !in_value_len && !in_data_len )
6945 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6947 param_index = 0;
6948 biggest_valuesize = 0;
6949 biggest_datasize = 0;
6951 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
6953 for ( i=0; i<num_values; i++ )
6955 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
6957 name_length = strlen(val->valuename);
6958 if ( strlen(val->valuename) > biggest_valuesize )
6959 biggest_valuesize = name_length;
6961 if ( val->size > biggest_datasize )
6962 biggest_datasize = val->size;
6964 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
6965 biggest_datasize));
6968 /* the value is an UNICODE string but real_value_size is the length
6969 in bytes including the trailing 0 */
6971 *out_value_len = 2 * (1+biggest_valuesize);
6972 *out_data_len = biggest_datasize;
6974 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6976 goto done;
6980 * the value len is wrong in NT sp3
6981 * that's the number of bytes not the number of unicode chars
6984 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
6986 if ( !val )
6989 /* out_value should default to "" or else NT4 has
6990 problems unmarshalling the response */
6992 *out_max_value_len = (in_value_len/sizeof(uint16));
6994 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
6996 result = WERR_NOMEM;
6997 goto done;
7000 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7002 /* the data is counted in bytes */
7004 *out_max_data_len = in_data_len;
7005 *out_data_len = in_data_len;
7007 /* only allocate when given a non-zero data_len */
7009 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7011 result = WERR_NOMEM;
7012 goto done;
7015 result = WERR_NO_MORE_ITEMS;
7017 else
7020 * the value is:
7021 * - counted in bytes in the request
7022 * - counted in UNICODE chars in the max reply
7023 * - counted in bytes in the real size
7025 * take a pause *before* coding not *during* coding
7028 /* name */
7029 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7030 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7032 result = WERR_NOMEM;
7033 goto done;
7036 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7038 /* type */
7040 *out_type = regval_type( val );
7042 /* data - counted in bytes */
7044 *out_max_data_len = in_data_len;
7045 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7047 result = WERR_NOMEM;
7048 goto done;
7050 data_len = (size_t)regval_size(val);
7051 memcpy( *data_out, regval_data_p(val), data_len );
7052 *out_data_len = data_len;
7055 done:
7056 free_a_printer(&printer, 2);
7057 return result;
7060 /****************************************************************************
7061 ****************************************************************************/
7063 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7065 POLICY_HND *handle = &q_u->handle;
7066 UNISTR2 *value = &q_u->value;
7067 uint32 type = q_u->type;
7068 uint8 *data = q_u->data;
7069 uint32 real_len = q_u->real_len;
7071 NT_PRINTER_INFO_LEVEL *printer = NULL;
7072 int snum=0;
7073 WERROR status = WERR_OK;
7074 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7075 fstring valuename;
7077 DEBUG(5,("spoolss_setprinterdata\n"));
7079 if (!Printer) {
7080 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7081 return WERR_BADFID;
7084 if (!get_printer_snum(p,handle, &snum))
7085 return WERR_BADFID;
7088 * Access check : NT returns "access denied" if you make a
7089 * SetPrinterData call without the necessary privildge.
7090 * we were originally returning OK if nothing changed
7091 * which made Win2k issue **a lot** of SetPrinterData
7092 * when connecting to a printer --jerry
7095 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7096 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7097 status = WERR_ACCESS_DENIED;
7098 goto done;
7101 status = get_a_printer(&printer, 2, lp_servicename(snum));
7102 if (!W_ERROR_IS_OK(status))
7103 return status;
7105 /* save the registry data */
7107 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7108 delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
7109 add_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename, type, data, real_len );
7111 /* write the **entire** printer out to disk.... :-( */
7113 status = mod_a_printer(*printer, 2);
7115 done:
7116 free_a_printer(&printer, 2);
7118 return status;
7121 /****************************************************************************
7122 ****************************************************************************/
7124 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7126 POLICY_HND *handle = &q_u->handle;
7127 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7128 int snum;
7130 DEBUG(5,("_spoolss_resetprinter\n"));
7133 * All we do is to check to see if the handle and queue is valid.
7134 * This call really doesn't mean anything to us because we only
7135 * support RAW printing. --jerry
7138 if (!Printer) {
7139 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7140 return WERR_BADFID;
7143 if (!get_printer_snum(p,handle, &snum))
7144 return WERR_BADFID;
7147 /* blindly return success */
7148 return WERR_OK;
7152 /****************************************************************************
7153 ****************************************************************************/
7155 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7157 POLICY_HND *handle = &q_u->handle;
7158 UNISTR2 *value = &q_u->valuename;
7160 NT_PRINTER_INFO_LEVEL *printer = NULL;
7161 int snum=0;
7162 WERROR status = WERR_OK;
7163 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7164 pstring valuename;
7166 DEBUG(5,("spoolss_deleteprinterdata\n"));
7168 if (!Printer) {
7169 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7170 return WERR_BADFID;
7173 if (!get_printer_snum(p, handle, &snum))
7174 return WERR_BADFID;
7176 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7177 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7178 return WERR_ACCESS_DENIED;
7181 status = get_a_printer(&printer, 2, lp_servicename(snum));
7182 if (!W_ERROR_IS_OK(status))
7183 return status;
7185 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7187 status = delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
7188 if ( NT_STATUS_IS_OK(status) )
7189 status = mod_a_printer(*printer, 2);
7191 free_a_printer(&printer, 2);
7193 return status;
7196 /****************************************************************************
7197 ****************************************************************************/
7199 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7201 POLICY_HND *handle = &q_u->handle;
7202 FORM *form = &q_u->form;
7203 nt_forms_struct tmpForm;
7204 int snum;
7205 WERROR status = WERR_OK;
7206 NT_PRINTER_INFO_LEVEL *printer = NULL;
7208 int count=0;
7209 nt_forms_struct *list=NULL;
7210 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7212 DEBUG(5,("spoolss_addform\n"));
7214 if (!Printer) {
7215 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7216 return WERR_BADFID;
7219 if (!get_printer_snum(p,handle, &snum))
7220 return WERR_BADFID;
7222 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7223 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7224 status = WERR_ACCESS_DENIED;
7225 goto done;
7228 /* can't add if builtin */
7229 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7230 return WERR_ALREADY_EXISTS;
7233 count=get_ntforms(&list);
7234 if(!add_a_form(&list, form, &count))
7235 return WERR_NOMEM;
7236 write_ntforms(&list, count);
7239 * ChangeID must always be set
7242 status = get_a_printer(&printer, 2, lp_servicename(snum));
7243 if (!W_ERROR_IS_OK(status))
7244 goto done;
7246 status = mod_a_printer(*printer, 2);
7247 if (!W_ERROR_IS_OK(status))
7248 goto done;
7250 done:
7251 free_a_printer(&printer, 2);
7252 SAFE_FREE(list);
7254 return status;
7257 /****************************************************************************
7258 ****************************************************************************/
7260 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7262 POLICY_HND *handle = &q_u->handle;
7263 UNISTR2 *form_name = &q_u->name;
7264 nt_forms_struct tmpForm;
7265 int count=0;
7266 WERROR ret = WERR_OK;
7267 nt_forms_struct *list=NULL;
7268 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7269 int snum;
7270 WERROR status = WERR_OK;
7271 NT_PRINTER_INFO_LEVEL *printer = NULL;
7273 DEBUG(5,("spoolss_deleteform\n"));
7275 if (!Printer) {
7276 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7277 return WERR_BADFID;
7280 if (!get_printer_snum(p, handle, &snum))
7281 return WERR_BADFID;
7283 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7284 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7285 return WERR_ACCESS_DENIED;
7288 /* can't delete if builtin */
7289 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7290 return WERR_INVALID_PARAM;
7293 count = get_ntforms(&list);
7294 if(!delete_a_form(&list, form_name, &count, &ret))
7295 return WERR_INVALID_PARAM;
7298 * ChangeID must always be set
7301 status = get_a_printer(&printer, 2, lp_servicename(snum));
7302 if (!W_ERROR_IS_OK(status))
7303 goto done;
7305 status = mod_a_printer(*printer, 2);
7306 if (!W_ERROR_IS_OK(status))
7307 goto done;
7309 done:
7310 free_a_printer(&printer, 2);
7311 SAFE_FREE(list);
7313 return ret;
7316 /****************************************************************************
7317 ****************************************************************************/
7319 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7321 POLICY_HND *handle = &q_u->handle;
7322 FORM *form = &q_u->form;
7323 nt_forms_struct tmpForm;
7324 int snum;
7325 WERROR status = WERR_OK;
7326 NT_PRINTER_INFO_LEVEL *printer = NULL;
7328 int count=0;
7329 nt_forms_struct *list=NULL;
7330 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7332 DEBUG(5,("spoolss_setform\n"));
7334 if (!Printer) {
7335 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7336 return WERR_BADFID;
7339 if (!get_printer_snum(p, handle, &snum))
7340 return WERR_BADFID;
7342 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7343 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7344 return WERR_ACCESS_DENIED;
7347 /* can't set if builtin */
7348 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7349 return WERR_INVALID_PARAM;
7352 count=get_ntforms(&list);
7353 update_a_form(&list, form, count);
7354 write_ntforms(&list, count);
7357 * ChangeID must always be set
7360 status = get_a_printer(&printer, 2, lp_servicename(snum));
7361 if (!W_ERROR_IS_OK(status))
7362 goto done;
7364 status = mod_a_printer(*printer, 2);
7365 if (!W_ERROR_IS_OK(status))
7366 goto done;
7368 done:
7369 free_a_printer(&printer, 2);
7370 SAFE_FREE(list);
7372 return WERR_OK;
7375 /****************************************************************************
7376 enumprintprocessors level 1.
7377 ****************************************************************************/
7379 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7381 PRINTPROCESSOR_1 *info_1=NULL;
7383 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7384 return WERR_NOMEM;
7386 (*returned) = 0x1;
7388 init_unistr(&info_1->name, "winprint");
7390 *needed += spoolss_size_printprocessor_info_1(info_1);
7392 if (!alloc_buffer_size(buffer, *needed))
7393 return WERR_INSUFFICIENT_BUFFER;
7395 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7397 SAFE_FREE(info_1);
7399 if (*needed > offered) {
7400 *returned=0;
7401 return WERR_INSUFFICIENT_BUFFER;
7404 return WERR_OK;
7407 /****************************************************************************
7408 ****************************************************************************/
7410 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7412 uint32 level = q_u->level;
7413 NEW_BUFFER *buffer = NULL;
7414 uint32 offered = q_u->offered;
7415 uint32 *needed = &r_u->needed;
7416 uint32 *returned = &r_u->returned;
7418 /* that's an [in out] buffer */
7419 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7420 buffer = r_u->buffer;
7422 DEBUG(5,("spoolss_enumprintprocessors\n"));
7425 * Enumerate the print processors ...
7427 * Just reply with "winprint", to keep NT happy
7428 * and I can use my nice printer checker.
7431 *returned=0;
7432 *needed=0;
7434 switch (level) {
7435 case 1:
7436 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7437 default:
7438 return WERR_UNKNOWN_LEVEL;
7442 /****************************************************************************
7443 enumprintprocdatatypes level 1.
7444 ****************************************************************************/
7446 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7448 PRINTPROCDATATYPE_1 *info_1=NULL;
7450 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7451 return WERR_NOMEM;
7453 (*returned) = 0x1;
7455 init_unistr(&info_1->name, "RAW");
7457 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7459 if (!alloc_buffer_size(buffer, *needed))
7460 return WERR_INSUFFICIENT_BUFFER;
7462 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7464 SAFE_FREE(info_1);
7466 if (*needed > offered) {
7467 *returned=0;
7468 return WERR_INSUFFICIENT_BUFFER;
7471 return WERR_OK;
7474 /****************************************************************************
7475 ****************************************************************************/
7477 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7479 uint32 level = q_u->level;
7480 NEW_BUFFER *buffer = NULL;
7481 uint32 offered = q_u->offered;
7482 uint32 *needed = &r_u->needed;
7483 uint32 *returned = &r_u->returned;
7485 /* that's an [in out] buffer */
7486 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7487 buffer = r_u->buffer;
7489 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7491 *returned=0;
7492 *needed=0;
7494 switch (level) {
7495 case 1:
7496 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7497 default:
7498 return WERR_UNKNOWN_LEVEL;
7502 /****************************************************************************
7503 enumprintmonitors level 1.
7504 ****************************************************************************/
7506 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7508 PRINTMONITOR_1 *info_1=NULL;
7510 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7511 return WERR_NOMEM;
7513 (*returned) = 0x1;
7515 init_unistr(&info_1->name, "Local Port");
7517 *needed += spoolss_size_printmonitor_info_1(info_1);
7519 if (!alloc_buffer_size(buffer, *needed))
7520 return WERR_INSUFFICIENT_BUFFER;
7522 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7524 SAFE_FREE(info_1);
7526 if (*needed > offered) {
7527 *returned=0;
7528 return WERR_INSUFFICIENT_BUFFER;
7531 return WERR_OK;
7534 /****************************************************************************
7535 enumprintmonitors level 2.
7536 ****************************************************************************/
7538 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7540 PRINTMONITOR_2 *info_2=NULL;
7542 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7543 return WERR_NOMEM;
7545 (*returned) = 0x1;
7547 init_unistr(&info_2->name, "Local Port");
7548 init_unistr(&info_2->environment, "Windows NT X86");
7549 init_unistr(&info_2->dll_name, "localmon.dll");
7551 *needed += spoolss_size_printmonitor_info_2(info_2);
7553 if (!alloc_buffer_size(buffer, *needed))
7554 return WERR_INSUFFICIENT_BUFFER;
7556 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7558 SAFE_FREE(info_2);
7560 if (*needed > offered) {
7561 *returned=0;
7562 return WERR_INSUFFICIENT_BUFFER;
7565 return WERR_OK;
7568 /****************************************************************************
7569 ****************************************************************************/
7571 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7573 uint32 level = q_u->level;
7574 NEW_BUFFER *buffer = NULL;
7575 uint32 offered = q_u->offered;
7576 uint32 *needed = &r_u->needed;
7577 uint32 *returned = &r_u->returned;
7579 /* that's an [in out] buffer */
7580 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7581 buffer = r_u->buffer;
7583 DEBUG(5,("spoolss_enumprintmonitors\n"));
7586 * Enumerate the print monitors ...
7588 * Just reply with "Local Port", to keep NT happy
7589 * and I can use my nice printer checker.
7592 *returned=0;
7593 *needed=0;
7595 switch (level) {
7596 case 1:
7597 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7598 case 2:
7599 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7600 default:
7601 return WERR_UNKNOWN_LEVEL;
7605 /****************************************************************************
7606 ****************************************************************************/
7608 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7610 int i=0;
7611 BOOL found=False;
7612 JOB_INFO_1 *info_1=NULL;
7614 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7616 if (info_1 == NULL) {
7617 SAFE_FREE(queue);
7618 return WERR_NOMEM;
7621 for (i=0; i<count && found==False; i++) {
7622 if (queue[i].job==(int)jobid)
7623 found=True;
7626 if (found==False) {
7627 SAFE_FREE(queue);
7628 SAFE_FREE(info_1);
7629 /* NT treats not found as bad param... yet another bad choice */
7630 return WERR_INVALID_PARAM;
7633 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7635 SAFE_FREE(queue);
7637 *needed += spoolss_size_job_info_1(info_1);
7639 if (!alloc_buffer_size(buffer, *needed)) {
7640 SAFE_FREE(info_1);
7641 return WERR_INSUFFICIENT_BUFFER;
7644 smb_io_job_info_1("", buffer, info_1, 0);
7646 SAFE_FREE(info_1);
7648 if (*needed > offered)
7649 return WERR_INSUFFICIENT_BUFFER;
7651 return WERR_OK;
7654 /****************************************************************************
7655 ****************************************************************************/
7657 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7659 int i=0;
7660 BOOL found=False;
7661 JOB_INFO_2 *info_2;
7662 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7663 WERROR ret;
7664 DEVICEMODE *devmode = NULL;
7666 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7668 ZERO_STRUCTP(info_2);
7670 if (info_2 == NULL) {
7671 ret = WERR_NOMEM;
7672 goto done;
7675 for (i=0; i<count && found==False; i++) {
7676 if (queue[i].job==(int)jobid)
7677 found=True;
7680 if (found==False) {
7681 /* NT treats not found as bad param... yet another bad
7682 choice */
7683 ret = WERR_INVALID_PARAM;
7684 goto done;
7687 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7688 if (!W_ERROR_IS_OK(ret))
7689 goto done;
7690 if (construct_dev_mode(snum) == NULL) {
7691 ret = WERR_NOMEM;
7692 goto done;
7695 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7697 *needed += spoolss_size_job_info_2(info_2);
7699 if (!alloc_buffer_size(buffer, *needed)) {
7700 ret = WERR_INSUFFICIENT_BUFFER;
7701 goto done;
7704 smb_io_job_info_2("", buffer, info_2, 0);
7706 if (*needed > offered) {
7707 ret = WERR_INSUFFICIENT_BUFFER;
7708 goto done;
7711 ret = WERR_OK;
7713 done:
7714 /* Cleanup allocated memory */
7716 SAFE_FREE(queue);
7717 free_job_info_2(info_2); /* Also frees devmode */
7718 SAFE_FREE(info_2);
7719 free_a_printer(&ntprinter, 2);
7721 return ret;
7724 /****************************************************************************
7725 ****************************************************************************/
7727 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7729 POLICY_HND *handle = &q_u->handle;
7730 uint32 jobid = q_u->jobid;
7731 uint32 level = q_u->level;
7732 NEW_BUFFER *buffer = NULL;
7733 uint32 offered = q_u->offered;
7734 uint32 *needed = &r_u->needed;
7736 int snum;
7737 int count;
7738 print_queue_struct *queue=NULL;
7739 print_status_struct prt_status;
7741 /* that's an [in out] buffer */
7742 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7743 buffer = r_u->buffer;
7745 DEBUG(5,("spoolss_getjob\n"));
7747 *needed=0;
7749 if (!get_printer_snum(p, handle, &snum))
7750 return WERR_BADFID;
7752 count = print_queue_status(snum, &queue, &prt_status);
7754 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7755 count, prt_status.status, prt_status.message));
7757 switch (level) {
7758 case 1:
7759 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7760 case 2:
7761 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7762 default:
7763 SAFE_FREE(queue);
7764 return WERR_UNKNOWN_LEVEL;
7768 /********************************************************************
7769 * spoolss_getprinterdataex
7770 ********************************************************************/
7772 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7774 POLICY_HND *handle = &q_u->handle;
7775 uint32 in_size = q_u->size;
7776 uint32 *type = &r_u->type;
7777 uint32 *out_size = &r_u->size;
7778 uint8 **data = &r_u->data;
7779 uint32 *needed = &r_u->needed;
7781 fstring key, value;
7782 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7783 BOOL found = False;
7785 DEBUG(4,("_spoolss_getprinterdataex\n"));
7787 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7788 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7790 /* in case of problem, return some default values */
7791 *needed=0;
7792 *type=0;
7793 *out_size=0;
7796 if (!Printer) {
7797 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7798 return WERR_NOMEM;
7799 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7800 return WERR_BADFID;
7804 /* Is the handle to a printer or to the server? */
7806 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7808 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7809 return WERR_INVALID_PARAM;
7811 else
7814 * From MSDN documentation of GetPrinterDataEx: pass request
7815 * to GetPrinterData if key is "PrinterDriverData". This is
7816 * the only key we really support. Other keys to implement:
7817 * (a) DsDriver
7818 * (b) DsSpooler
7819 * (c) PnPData
7820 * (d) DsUser
7823 if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
7824 return WERR_BADFILE;
7826 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7827 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7828 type, data, needed, in_size);
7832 if (!found) {
7833 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7835 /* reply this param doesn't exist */
7836 if (*out_size) {
7837 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7838 return WERR_NOMEM;
7839 } else {
7840 *data = NULL;
7843 return WERR_INVALID_PARAM;
7846 if (*needed > *out_size)
7847 return WERR_MORE_DATA;
7848 else
7849 return WERR_OK;
7852 /********************************************************************
7853 * spoolss_setprinterdata
7854 ********************************************************************/
7856 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7858 SPOOL_Q_SETPRINTERDATA q_u_local;
7859 SPOOL_R_SETPRINTERDATA r_u_local;
7860 fstring key;
7862 DEBUG(4,("_spoolss_setprinterdataex\n"));
7864 /* From MSDN documentation of SetPrinterDataEx: pass request to
7865 SetPrinterData if key is "PrinterDriverData" */
7867 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7869 if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
7870 return WERR_INVALID_PARAM;
7872 ZERO_STRUCT(q_u_local);
7873 ZERO_STRUCT(r_u_local);
7875 /* make a copy to call _spoolss_setprinterdata() */
7877 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7878 copy_unistr2(&q_u_local.value, &q_u->value);
7879 q_u_local.type = q_u->type;
7880 q_u_local.max_len = q_u->max_len;
7881 q_u_local.data = q_u->data;
7882 q_u_local.real_len = q_u->real_len;
7883 q_u_local.numeric_data = q_u->numeric_data;
7885 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7889 /********************************************************************
7890 * spoolss_deleteprinterdataex
7891 ********************************************************************/
7893 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
7895 SPOOL_Q_DELETEPRINTERDATA q_u_local;
7896 SPOOL_R_DELETEPRINTERDATA r_u_local;
7897 fstring key;
7899 /* From MSDN documentation of SetPrinterDataEx: pass request to
7900 SetPrinterData if key is "PrinterDriverData" */
7902 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7904 if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
7905 return WERR_INVALID_PARAM;
7907 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7908 copy_unistr2(&q_u_local.valuename, &q_u->valuename);
7910 return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
7916 /********************************************************************
7917 * spoolss_enumprinterkey
7918 ********************************************************************/
7920 /* constants for EnumPrinterKey() */
7921 #define ENUMERATED_KEY_SIZE 19
7923 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7925 fstring key;
7926 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
7927 char* ptr = NULL;
7928 int i;
7929 char *PrinterKey = SPOOL_PRINTERDATA_KEY;
7931 DEBUG(4,("_spoolss_enumprinterkey\n"));
7933 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7936 * we only support enumating all keys (key == "")
7937 * Of course, the only key we support is the "PrinterDriverData"
7938 * key
7940 if (strlen(key) == 0)
7942 r_u->needed = ENUMERATED_KEY_SIZE *2;
7943 if (q_u->size < r_u->needed)
7944 return WERR_MORE_DATA;
7946 ptr = PrinterKey;
7947 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7949 enumkeys[i] = (uint16)(*ptr);
7950 ptr++;
7953 /* tag of with 2 '\0's */
7954 enumkeys[i++] = '\0';
7955 enumkeys[i] = '\0';
7957 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7958 return WERR_BADFILE;
7960 return WERR_OK;
7963 /* The "PrinterDriverData" key should have no subkeys */
7964 if (strcmp(key, PrinterKey) == 0)
7966 r_u-> needed = 2;
7967 if (q_u->size < r_u->needed)
7968 return WERR_MORE_DATA;
7969 enumkeys[0] = 0x0;
7970 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7971 return WERR_BADFILE;
7973 return WERR_OK;
7977 /* The return value for an unknown key is documented in MSDN
7978 EnumPrinterKey description */
7979 return WERR_BADFILE;
7982 /********************************************************************
7983 * spoolss_deleteprinterkey
7984 ********************************************************************/
7986 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
7988 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
7989 fstring key;
7991 if (!Printer) {
7992 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
7993 return WERR_BADFID;
7996 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7998 if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
7999 return WERR_INVALID_PARAM;
8002 * this is what 2k returns when you try to delete the "PrinterDriverData"
8003 * key
8006 return WERR_ACCESS_DENIED;
8010 /********************************************************************
8011 * spoolss_enumprinterdataex
8012 ********************************************************************/
8014 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8016 POLICY_HND *handle = &q_u->handle;
8017 uint32 in_size = q_u->size;
8018 uint32 num_entries,
8019 needed;
8020 NT_PRINTER_INFO_LEVEL *printer = NULL;
8021 PRINTER_ENUM_VALUES *enum_values = NULL;
8022 NT_PRINTER_DATA *p_data;
8023 fstring key;
8024 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8025 int snum;
8026 WERROR result;
8027 int key_index;
8028 int i;
8029 REGISTRY_VALUE *val;
8030 char *value_name;
8031 int data_len;
8034 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8036 if (!Printer) {
8037 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8038 return WERR_BADFID;
8042 /* first get the printer off of disk */
8044 if (!get_printer_snum(p,handle, &snum))
8045 return WERR_BADFID;
8047 ZERO_STRUCT(printer);
8048 result = get_a_printer(&printer, 2, lp_servicename(snum));
8049 if (!W_ERROR_IS_OK(result))
8050 return result;
8052 /* now look for a match on the key name */
8054 p_data = &printer->info_2->data;
8056 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8057 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8059 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8060 result = WERR_INVALID_PARAM;
8061 goto done;
8064 result = WERR_OK;
8065 needed = 0;
8067 /* allocate the memory for the array of pointers -- if necessary */
8069 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8070 if ( num_entries )
8072 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8074 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8075 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8076 result = WERR_NOMEM;
8077 goto done;
8080 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8084 * loop through all params and build the array to pass
8085 * back to the client
8088 for ( i=0; i<num_entries; i++ )
8090 /* lookup the registry value */
8092 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8093 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8095 /* copy the data */
8097 value_name = regval_name( val );
8098 init_unistr( &enum_values[i].valuename, value_name );
8099 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8100 enum_values[i].type = regval_type( val );
8102 data_len = regval_size( val );
8103 if ( data_len ) {
8104 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8106 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8107 data_len ));
8108 result = WERR_NOMEM;
8109 goto done;
8112 enum_values[i].data_len = data_len;
8114 /* keep track of the size of the array in bytes */
8116 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
8119 r_u->needed = needed;
8120 r_u->returned = num_entries;
8122 if (needed > in_size) {
8123 result = WERR_MORE_DATA;
8124 goto done;
8127 /* copy data into the reply */
8129 r_u->ctr.size = r_u->needed;
8130 r_u->ctr.size_of_array = r_u->returned;
8131 r_u->ctr.values = enum_values;
8135 done:
8136 free_a_printer(&printer, 2);
8138 return result;
8141 /****************************************************************************
8142 ****************************************************************************/
8144 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8146 init_unistr(&info->name, name);
8149 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8150 UNISTR2 *environment,
8151 NEW_BUFFER *buffer,
8152 uint32 offered,
8153 uint32 *needed)
8155 pstring path;
8156 pstring long_archi;
8157 pstring short_archi;
8158 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8160 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8162 if (get_short_archi(short_archi, long_archi)==False)
8163 return WERR_INVALID_ENVIRONMENT;
8165 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8166 return WERR_NOMEM;
8168 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8170 fill_printprocessordirectory_1(info, path);
8172 *needed += spoolss_size_printprocessordirectory_info_1(info);
8174 if (!alloc_buffer_size(buffer, *needed)) {
8175 safe_free(info);
8176 return WERR_INSUFFICIENT_BUFFER;
8179 smb_io_printprocessordirectory_1("", buffer, info, 0);
8181 safe_free(info);
8183 if (*needed > offered)
8184 return WERR_INSUFFICIENT_BUFFER;
8185 else
8186 return WERR_OK;
8189 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8191 uint32 level = q_u->level;
8192 NEW_BUFFER *buffer = NULL;
8193 uint32 offered = q_u->offered;
8194 uint32 *needed = &r_u->needed;
8195 WERROR result;
8197 /* that's an [in out] buffer */
8198 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8199 buffer = r_u->buffer;
8201 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8203 *needed=0;
8205 switch(level) {
8206 case 1:
8207 result = getprintprocessordirectory_level_1
8208 (&q_u->name, &q_u->environment, buffer, offered, needed);
8209 default:
8210 result = WERR_UNKNOWN_LEVEL;
8213 return result;
8216 #if 0
8218 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8219 SPOOL_R_REPLYOPENPRINTER *r_u)
8221 DEBUG(5,("_spoolss_replyopenprinter\n"));
8223 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8225 return WERR_OK;
8228 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8229 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8231 DEBUG(5,("_spoolss_replycloseprinter\n"));
8232 return WERR_OK;
8235 #endif