* the printing code should now be back to the working state it was
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob7aceaa548f29000bb4b1d5e9d55887ecb6b4cb2c
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 (True)
4400 if (char_array == NULL)
4401 v = "";
4402 else {
4403 v = char_array[i];
4404 if (!v) v = ""; /* hack to handle null lists */
4407 if ( !strlen(v) )
4408 break;
4410 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
4412 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4414 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
4415 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4416 return;
4417 } else
4418 *uni_array = tuary;
4420 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4421 i++;
4424 if (*uni_array) {
4425 (*uni_array)[j]=0x0000;
4428 DEBUGADD(6,("last one:done\n"));
4431 /********************************************************************
4432 * construct_printer_info_3
4433 * fill a printer_info_3 struct
4434 ********************************************************************/
4436 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4438 pstring temp;
4440 ZERO_STRUCTP(info);
4442 info->version=driver.info_3->cversion;
4444 init_unistr( &info->name, driver.info_3->name );
4445 init_unistr( &info->architecture, driver.info_3->environment );
4447 if (strlen(driver.info_3->driverpath)) {
4448 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4449 init_unistr( &info->driverpath, temp );
4450 } else
4451 init_unistr( &info->driverpath, "" );
4453 if (strlen(driver.info_3->datafile)) {
4454 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4455 init_unistr( &info->datafile, temp );
4456 } else
4457 init_unistr( &info->datafile, "" );
4459 if (strlen(driver.info_3->configfile)) {
4460 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4461 init_unistr( &info->configfile, temp );
4462 } else
4463 init_unistr( &info->configfile, "" );
4465 if (strlen(driver.info_3->helpfile)) {
4466 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4467 init_unistr( &info->helpfile, temp );
4468 } else
4469 init_unistr( &info->helpfile, "" );
4471 init_unistr( &info->monitorname, driver.info_3->monitorname );
4472 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4474 info->dependentfiles=NULL;
4475 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4478 /********************************************************************
4479 * construct_printer_info_3
4480 * fill a printer_info_3 struct
4481 ********************************************************************/
4483 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4485 NT_PRINTER_INFO_LEVEL *printer = NULL;
4486 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4487 WERROR status;
4488 ZERO_STRUCT(driver);
4490 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4491 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4492 if (!W_ERROR_IS_OK(status))
4493 return WERR_INVALID_PRINTER_NAME;
4495 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4496 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4498 #if 0 /* JERRY */
4501 * I put this code in during testing. Helpful when commenting out the
4502 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4503 * as win2k always queries the driver using an infor level of 6.
4504 * I've left it in (but ifdef'd out) because I'll probably
4505 * use it in experimentation again in the future. --jerry 22/01/2002
4508 if (!W_ERROR_IS_OK(status)) {
4510 * Is this a W2k client ?
4512 if (version == 3) {
4513 /* Yes - try again with a WinNT driver. */
4514 version = 2;
4515 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4516 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4518 #endif
4520 if (!W_ERROR_IS_OK(status)) {
4521 free_a_printer(&printer,2);
4522 return WERR_UNKNOWN_PRINTER_DRIVER;
4525 #if 0 /* JERRY */
4527 #endif
4530 fill_printer_driver_info_3(info, driver, servername);
4532 free_a_printer(&printer,2);
4534 return WERR_OK;
4537 /********************************************************************
4538 * construct_printer_info_6
4539 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4540 ********************************************************************/
4542 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4544 pstring temp;
4545 fstring nullstr;
4547 ZERO_STRUCTP(info);
4548 memset(&nullstr, '\0', sizeof(fstring));
4550 info->version=driver.info_3->cversion;
4552 init_unistr( &info->name, driver.info_3->name );
4553 init_unistr( &info->architecture, driver.info_3->environment );
4555 if (strlen(driver.info_3->driverpath)) {
4556 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4557 init_unistr( &info->driverpath, temp );
4558 } else
4559 init_unistr( &info->driverpath, "" );
4561 if (strlen(driver.info_3->datafile)) {
4562 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4563 init_unistr( &info->datafile, temp );
4564 } else
4565 init_unistr( &info->datafile, "" );
4567 if (strlen(driver.info_3->configfile)) {
4568 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4569 init_unistr( &info->configfile, temp );
4570 } else
4571 init_unistr( &info->configfile, "" );
4573 if (strlen(driver.info_3->helpfile)) {
4574 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4575 init_unistr( &info->helpfile, temp );
4576 } else
4577 init_unistr( &info->helpfile, "" );
4579 init_unistr( &info->monitorname, driver.info_3->monitorname );
4580 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4582 info->dependentfiles = NULL;
4583 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
4585 info->previousdrivernames=NULL;
4586 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4588 info->driver_date.low=0;
4589 info->driver_date.high=0;
4591 info->padding=0;
4592 info->driver_version_low=0;
4593 info->driver_version_high=0;
4595 init_unistr( &info->mfgname, "");
4596 init_unistr( &info->oem_url, "");
4597 init_unistr( &info->hardware_id, "");
4598 init_unistr( &info->provider, "");
4601 /********************************************************************
4602 * construct_printer_info_6
4603 * fill a printer_info_6 struct
4604 ********************************************************************/
4606 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
4607 fstring servername, fstring architecture, uint32 version)
4609 NT_PRINTER_INFO_LEVEL *printer = NULL;
4610 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4611 WERROR status;
4613 ZERO_STRUCT(driver);
4615 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4617 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4619 if (!W_ERROR_IS_OK(status))
4620 return WERR_INVALID_PRINTER_NAME;
4622 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4624 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4626 if (!W_ERROR_IS_OK(status))
4629 * Is this a W2k client ?
4632 if (version < 3) {
4633 free_a_printer(&printer,2);
4634 return WERR_UNKNOWN_PRINTER_DRIVER;
4637 /* Yes - try again with a WinNT driver. */
4638 version = 2;
4639 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4640 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4641 if (!W_ERROR_IS_OK(status)) {
4642 free_a_printer(&printer,2);
4643 return WERR_UNKNOWN_PRINTER_DRIVER;
4647 fill_printer_driver_info_6(info, driver, servername);
4649 free_a_printer(&printer,2);
4651 return WERR_OK;
4654 /****************************************************************************
4655 ****************************************************************************/
4657 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4659 SAFE_FREE(info->dependentfiles);
4662 /****************************************************************************
4663 ****************************************************************************/
4665 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4667 SAFE_FREE(info->dependentfiles);
4671 /****************************************************************************
4672 ****************************************************************************/
4674 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4676 DRIVER_INFO_1 *info=NULL;
4677 WERROR status;
4679 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4680 return WERR_NOMEM;
4682 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4683 if (!W_ERROR_IS_OK(status)) {
4684 SAFE_FREE(info);
4685 return status;
4688 /* check the required size. */
4689 *needed += spoolss_size_printer_driver_info_1(info);
4691 if (!alloc_buffer_size(buffer, *needed)) {
4692 SAFE_FREE(info);
4693 return WERR_INSUFFICIENT_BUFFER;
4696 /* fill the buffer with the structures */
4697 smb_io_printer_driver_info_1("", buffer, info, 0);
4699 /* clear memory */
4700 SAFE_FREE(info);
4702 if (*needed > offered)
4703 return WERR_INSUFFICIENT_BUFFER;
4705 return WERR_OK;
4708 /****************************************************************************
4709 ****************************************************************************/
4711 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4713 DRIVER_INFO_2 *info=NULL;
4714 WERROR status;
4716 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4717 return WERR_NOMEM;
4719 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4720 if (!W_ERROR_IS_OK(status)) {
4721 SAFE_FREE(info);
4722 return status;
4725 /* check the required size. */
4726 *needed += spoolss_size_printer_driver_info_2(info);
4728 if (!alloc_buffer_size(buffer, *needed)) {
4729 SAFE_FREE(info);
4730 return WERR_INSUFFICIENT_BUFFER;
4733 /* fill the buffer with the structures */
4734 smb_io_printer_driver_info_2("", buffer, info, 0);
4736 /* clear memory */
4737 SAFE_FREE(info);
4739 if (*needed > offered)
4740 return WERR_INSUFFICIENT_BUFFER;
4742 return WERR_OK;
4745 /****************************************************************************
4746 ****************************************************************************/
4748 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4750 DRIVER_INFO_3 info;
4751 WERROR status;
4753 ZERO_STRUCT(info);
4755 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4756 if (!W_ERROR_IS_OK(status)) {
4757 return status;
4760 /* check the required size. */
4761 *needed += spoolss_size_printer_driver_info_3(&info);
4763 if (!alloc_buffer_size(buffer, *needed)) {
4764 free_printer_driver_info_3(&info);
4765 return WERR_INSUFFICIENT_BUFFER;
4768 /* fill the buffer with the structures */
4769 smb_io_printer_driver_info_3("", buffer, &info, 0);
4771 free_printer_driver_info_3(&info);
4773 if (*needed > offered)
4774 return WERR_INSUFFICIENT_BUFFER;
4776 return WERR_OK;
4779 /****************************************************************************
4780 ****************************************************************************/
4782 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4784 DRIVER_INFO_6 info;
4785 WERROR status;
4787 ZERO_STRUCT(info);
4789 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4790 if (!W_ERROR_IS_OK(status)) {
4791 return status;
4794 /* check the required size. */
4795 *needed += spoolss_size_printer_driver_info_6(&info);
4797 if (!alloc_buffer_size(buffer, *needed)) {
4798 free_printer_driver_info_6(&info);
4799 return WERR_INSUFFICIENT_BUFFER;
4802 /* fill the buffer with the structures */
4803 smb_io_printer_driver_info_6("", buffer, &info, 0);
4805 free_printer_driver_info_6(&info);
4807 if (*needed > offered)
4808 return WERR_INSUFFICIENT_BUFFER;
4810 return WERR_OK;
4813 /****************************************************************************
4814 ****************************************************************************/
4816 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4818 POLICY_HND *handle = &q_u->handle;
4819 UNISTR2 *uni_arch = &q_u->architecture;
4820 uint32 level = q_u->level;
4821 uint32 clientmajorversion = q_u->clientmajorversion;
4822 NEW_BUFFER *buffer = NULL;
4823 uint32 offered = q_u->offered;
4824 uint32 *needed = &r_u->needed;
4825 uint32 *servermajorversion = &r_u->servermajorversion;
4826 uint32 *serverminorversion = &r_u->serverminorversion;
4828 fstring servername;
4829 fstring architecture;
4830 int snum;
4832 /* that's an [in out] buffer */
4833 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4834 buffer = r_u->buffer;
4836 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4838 *needed = 0;
4839 *servermajorversion = 0;
4840 *serverminorversion = 0;
4842 pstrcpy(servername, get_called_name());
4843 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4845 if (!get_printer_snum(p, handle, &snum))
4846 return WERR_BADFID;
4848 switch (level) {
4849 case 1:
4850 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4851 case 2:
4852 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4853 case 3:
4854 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4855 case 6:
4856 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4859 return WERR_UNKNOWN_LEVEL;
4862 /****************************************************************************
4863 ****************************************************************************/
4865 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4867 POLICY_HND *handle = &q_u->handle;
4869 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4871 if (!Printer) {
4872 DEBUG(3,("Error in startpageprinter printer handle\n"));
4873 return WERR_BADFID;
4876 Printer->page_started=True;
4877 return WERR_OK;
4880 /****************************************************************************
4881 ****************************************************************************/
4883 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4885 POLICY_HND *handle = &q_u->handle;
4886 int snum;
4888 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4890 if (!Printer) {
4891 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4892 return WERR_BADFID;
4895 if (!get_printer_snum(p, handle, &snum))
4896 return WERR_BADFID;
4898 Printer->page_started=False;
4899 print_job_endpage(snum, Printer->jobid);
4901 return WERR_OK;
4904 /********************************************************************
4905 * api_spoolss_getprinter
4906 * called from the spoolss dispatcher
4908 ********************************************************************/
4910 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4912 POLICY_HND *handle = &q_u->handle;
4913 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4914 uint32 *jobid = &r_u->jobid;
4916 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4917 int snum;
4918 pstring jobname;
4919 fstring datatype;
4920 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4921 struct current_user user;
4923 if (!Printer) {
4924 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4925 return WERR_BADFID;
4928 get_current_user(&user, p);
4931 * a nice thing with NT is it doesn't listen to what you tell it.
4932 * when asked to send _only_ RAW datas, it tries to send datas
4933 * in EMF format.
4935 * So I add checks like in NT Server ...
4937 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4938 * there's a bug in NT client-side code, so we'll fix it in the
4939 * server-side code. *nnnnnggggh!*
4942 if (info_1->p_datatype != 0) {
4943 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4944 if (strcmp(datatype, "RAW") != 0) {
4945 (*jobid)=0;
4946 return WERR_INVALID_DATATYPE;
4950 /* get the share number of the printer */
4951 if (!get_printer_snum(p, handle, &snum)) {
4952 return WERR_BADFID;
4955 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4957 Printer->jobid = print_job_start(&user, snum, jobname);
4959 /* An error occured in print_job_start() so return an appropriate
4960 NT error code. */
4962 if (Printer->jobid == -1) {
4963 return map_werror_from_unix(errno);
4966 Printer->document_started=True;
4967 (*jobid) = Printer->jobid;
4969 return WERR_OK;
4972 /********************************************************************
4973 * api_spoolss_getprinter
4974 * called from the spoolss dispatcher
4976 ********************************************************************/
4978 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4980 POLICY_HND *handle = &q_u->handle;
4982 return _spoolss_enddocprinter_internal(p, handle);
4985 /****************************************************************************
4986 ****************************************************************************/
4988 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4990 POLICY_HND *handle = &q_u->handle;
4991 uint32 buffer_size = q_u->buffer_size;
4992 uint8 *buffer = q_u->buffer;
4993 uint32 *buffer_written = &q_u->buffer_size2;
4994 int snum;
4995 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4997 if (!Printer) {
4998 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4999 r_u->buffer_written = q_u->buffer_size2;
5000 return WERR_BADFID;
5003 if (!get_printer_snum(p, handle, &snum))
5004 return WERR_BADFID;
5006 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5008 r_u->buffer_written = q_u->buffer_size2;
5010 return WERR_OK;
5013 /********************************************************************
5014 * api_spoolss_getprinter
5015 * called from the spoolss dispatcher
5017 ********************************************************************/
5019 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5020 pipes_struct *p)
5022 struct current_user user;
5023 int snum;
5024 WERROR errcode = WERR_BADFUNC;
5025 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5027 get_current_user(&user, p);
5029 if (!Printer) {
5030 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5031 return WERR_BADFID;
5034 if (!get_printer_snum(p, handle, &snum))
5035 return WERR_BADFID;
5037 switch (command) {
5038 case PRINTER_CONTROL_PAUSE:
5039 if (print_queue_pause(&user, snum, &errcode)) {
5040 errcode = WERR_OK;
5042 break;
5043 case PRINTER_CONTROL_RESUME:
5044 case PRINTER_CONTROL_UNPAUSE:
5045 if (print_queue_resume(&user, snum, &errcode)) {
5046 errcode = WERR_OK;
5048 break;
5049 case PRINTER_CONTROL_PURGE:
5050 if (print_queue_purge(&user, snum, &errcode)) {
5051 errcode = WERR_OK;
5053 break;
5054 default:
5055 return WERR_UNKNOWN_LEVEL;
5058 return errcode;
5061 /********************************************************************
5062 * api_spoolss_abortprinter
5063 ********************************************************************/
5065 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5067 POLICY_HND *handle = &q_u->handle;
5069 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
5072 /********************************************************************
5073 * called by spoolss_api_setprinter
5074 * when updating a printer description
5075 ********************************************************************/
5077 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5078 const SPOOL_PRINTER_INFO_LEVEL *info,
5079 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5081 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5082 struct current_user user;
5083 WERROR result;
5084 int snum;
5086 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5088 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5089 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5090 OUR_HANDLE(handle)));
5092 result = WERR_BADFID;
5093 goto done;
5096 /* NT seems to like setting the security descriptor even though
5097 nothing may have actually changed. This causes annoying
5098 dialog boxes when the user doesn't have permission to change
5099 the security descriptor. */
5101 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5103 if (DEBUGLEVEL >= 10) {
5104 SEC_ACL *the_acl;
5105 int i;
5107 the_acl = old_secdesc_ctr->sec->dacl;
5108 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5109 PRINTERNAME(snum), the_acl->num_aces));
5111 for (i = 0; i < the_acl->num_aces; i++) {
5112 fstring sid_str;
5114 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5116 DEBUG(10, ("%s 0x%08x\n", sid_str,
5117 the_acl->ace[i].info.mask));
5120 the_acl = secdesc_ctr->sec->dacl;
5122 if (the_acl) {
5123 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5124 PRINTERNAME(snum), the_acl->num_aces));
5126 for (i = 0; i < the_acl->num_aces; i++) {
5127 fstring sid_str;
5129 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5131 DEBUG(10, ("%s 0x%08x\n", sid_str,
5132 the_acl->ace[i].info.mask));
5134 } else {
5135 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5139 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5141 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5142 result = WERR_OK;
5143 goto done;
5146 /* Work out which user is performing the operation */
5148 get_current_user(&user, p);
5150 /* Check the user has permissions to change the security
5151 descriptor. By experimentation with two NT machines, the user
5152 requires Full Access to the printer to change security
5153 information. */
5155 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5156 result = WERR_ACCESS_DENIED;
5157 goto done;
5160 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5162 done:
5164 return result;
5167 /********************************************************************
5168 Do Samba sanity checks on a printer info struct.
5169 this has changed purpose: it now "canonicalises" printer
5170 info from a client rather than just checking it is correct
5171 ********************************************************************/
5173 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5175 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5176 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5178 /* we force some elements to "correct" values */
5179 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5180 fstrcpy(info->sharename, lp_servicename(snum));
5181 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5182 get_called_name(), info->sharename);
5183 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5185 return True;
5188 /****************************************************************************
5189 ****************************************************************************/
5191 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5193 extern userdom_struct current_user_info;
5194 char *cmd = lp_addprinter_cmd();
5195 char **qlines;
5196 pstring command;
5197 pstring driverlocation;
5198 int numlines;
5199 int ret;
5200 int fd;
5201 fstring remote_machine = "%m";
5203 /* build driver path... only 9X architecture is needed for legacy reasons */
5204 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5205 get_called_name());
5206 /* change \ to \\ for the shell */
5207 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5208 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5210 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5211 cmd, printer->info_2->printername, printer->info_2->sharename,
5212 printer->info_2->portname, printer->info_2->drivername,
5213 printer->info_2->location, driverlocation, remote_machine);
5215 DEBUG(10,("Running [%s]\n", command));
5216 ret = smbrun(command, &fd);
5217 DEBUGADD(10,("returned [%d]\n", ret));
5219 if ( ret != 0 ) {
5220 if (fd != -1)
5221 close(fd);
5222 return False;
5225 numlines = 0;
5226 /* Get lines and convert them back to dos-codepage */
5227 qlines = fd_lines_load(fd, &numlines);
5228 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5229 close(fd);
5231 if(numlines) {
5232 /* Set the portname to what the script says the portname should be. */
5233 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5234 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5236 /* Send SIGHUP to process group... is there a better way? */
5237 kill(0, SIGHUP);
5238 add_all_printers();
5241 file_lines_free(qlines);
5242 return True;
5245 /********************************************************************
5246 * Called by spoolss_api_setprinter
5247 * when updating a printer description.
5248 ********************************************************************/
5250 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5251 const SPOOL_PRINTER_INFO_LEVEL *info,
5252 DEVICEMODE *devmode)
5254 int snum;
5255 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5256 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5257 WERROR result;
5259 DEBUG(8,("update_printer\n"));
5261 result = WERR_OK;
5263 if (level!=2) {
5264 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5265 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5266 result = WERR_UNKNOWN_LEVEL;
5267 goto done;
5270 if (!Printer) {
5271 result = WERR_BADFID;
5272 goto done;
5275 if (!get_printer_snum(p, handle, &snum)) {
5276 result = WERR_BADFID;
5277 goto done;
5280 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5281 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5282 result = WERR_BADFID;
5283 goto done;
5286 DEBUGADD(8,("Converting info_2 struct\n"));
5289 * convert_printer_info converts the incoming
5290 * info from the client and overwrites the info
5291 * just read from the tdb in the pointer 'printer'.
5294 if (!convert_printer_info(info, printer, level)) {
5295 result = WERR_NOMEM;
5296 goto done;
5299 if (devmode) {
5300 /* we have a valid devmode
5301 convert it and link it*/
5303 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5304 if (!convert_devicemode(printer->info_2->printername, devmode,
5305 &printer->info_2->devmode)) {
5306 result = WERR_NOMEM;
5307 goto done;
5311 /* Do sanity check on the requested changes for Samba */
5313 if (!check_printer_ok(printer->info_2, snum)) {
5314 result = WERR_INVALID_PARAM;
5315 goto done;
5318 #if 0 /* JERRY */
5321 * Another one of those historical misunderstandings...
5322 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5323 * I'm leaving it here as a reminder. --jerry
5326 if (nt_printer_info_level_equal(printer, old_printer)) {
5327 DEBUG(3, ("update_printer: printer info has not changed\n"));
5328 result = WERR_OK;
5329 goto done;
5332 #endif
5334 /* Check calling user has permission to update printer description */
5336 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5337 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5338 result = WERR_ACCESS_DENIED;
5339 goto done;
5342 /* Call addprinter hook */
5344 if (*lp_addprinter_cmd()) {
5345 if ( !add_printer_hook(printer) ) {
5346 result = WERR_ACCESS_DENIED;
5347 goto done;
5352 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5353 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5354 * requires Win32 client code (see other notes elsewhere in the code).
5356 if (printer->info_2->devmode &&
5357 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY)
5360 DEBUG(10,("update_printer: Save printer driver init data\n"));
5361 printer->info_2->devmode->displayfrequency = 0;
5363 if (update_driver_init(*printer, 2)!=0) {
5364 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5365 result = WERR_ACCESS_DENIED;
5366 goto done;
5369 /* we need to reset all driver init data for all printers
5370 bound to this driver */
5372 srv_spoolss_reset_printerdata( printer->info_2->drivername );
5375 else
5378 * When a *new* driver is bound to a printer, the drivername is used to
5379 * lookup previously saved driver initialization info, which is then
5380 * bound to the printer, simulating what happens in the Windows arch.
5382 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5384 if (!set_driver_init(printer, 2))
5386 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5387 printer->info_2->drivername));
5390 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5391 printer->info_2->drivername));
5393 notify_printer_driver(snum, printer->info_2->drivername);
5397 /* Update printer info */
5398 result = mod_a_printer(*printer, 2);
5400 /* flag which changes actually occured. This is a small subset of
5401 all the possible changes */
5403 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5404 notify_printer_comment(snum, printer->info_2->comment);
5406 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5407 notify_printer_sharename(snum, printer->info_2->sharename);
5409 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5410 notify_printer_port(snum, printer->info_2->portname);
5412 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5413 notify_printer_location(snum, printer->info_2->location);
5415 done:
5416 free_a_printer(&printer, 2);
5417 free_a_printer(&old_printer, 2);
5420 return result;
5423 /****************************************************************************
5424 ****************************************************************************/
5426 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5428 POLICY_HND *handle = &q_u->handle;
5429 uint32 level = q_u->level;
5430 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5431 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5432 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5433 uint32 command = q_u->command;
5435 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5437 if (!Printer) {
5438 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5439 return WERR_BADFID;
5442 /* check the level */
5443 switch (level) {
5444 case 0:
5445 return control_printer(handle, command, p);
5446 case 2:
5447 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5448 case 3:
5449 return update_printer_sec(handle, level, info, p,
5450 secdesc_ctr);
5451 default:
5452 return WERR_UNKNOWN_LEVEL;
5456 /****************************************************************************
5457 ****************************************************************************/
5459 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5461 POLICY_HND *handle = &q_u->handle;
5463 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5465 if (!Printer) {
5466 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5467 return WERR_BADFID;
5470 if (Printer->notify.client_connected==True)
5471 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5473 Printer->notify.flags=0;
5474 Printer->notify.options=0;
5475 Printer->notify.localmachine[0]='\0';
5476 Printer->notify.printerlocal=0;
5477 if (Printer->notify.option)
5478 free_spool_notify_option(&Printer->notify.option);
5479 Printer->notify.client_connected=False;
5481 return WERR_OK;
5484 /****************************************************************************
5485 ****************************************************************************/
5487 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5489 /* that's an [in out] buffer (despite appearences to the contrary) */
5490 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5492 r_u->needed = 0;
5493 return WERR_INVALID_PARAM; /* this is what a NT server
5494 returns for AddJob. AddJob
5495 must fail on non-local
5496 printers */
5499 /****************************************************************************
5500 ****************************************************************************/
5502 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5503 int position, int snum)
5505 pstring temp_name;
5507 struct tm *t;
5509 t=gmtime(&queue->time);
5510 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5512 job_info->jobid=queue->job;
5513 init_unistr(&job_info->printername, lp_servicename(snum));
5514 init_unistr(&job_info->machinename, temp_name);
5515 init_unistr(&job_info->username, queue->fs_user);
5516 init_unistr(&job_info->document, queue->fs_file);
5517 init_unistr(&job_info->datatype, "RAW");
5518 init_unistr(&job_info->text_status, "");
5519 job_info->status=nt_printj_status(queue->status);
5520 job_info->priority=queue->priority;
5521 job_info->position=position;
5522 job_info->totalpages=queue->page_count;
5523 job_info->pagesprinted=0;
5525 make_systemtime(&job_info->submitted, t);
5528 /****************************************************************************
5529 ****************************************************************************/
5531 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5532 int position, int snum,
5533 NT_PRINTER_INFO_LEVEL *ntprinter,
5534 DEVICEMODE *devmode)
5536 pstring temp_name;
5537 pstring chaine;
5538 struct tm *t;
5540 t=gmtime(&queue->time);
5541 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5543 job_info->jobid=queue->job;
5545 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5547 init_unistr(&job_info->printername, chaine);
5549 init_unistr(&job_info->machinename, temp_name);
5550 init_unistr(&job_info->username, queue->fs_user);
5551 init_unistr(&job_info->document, queue->fs_file);
5552 init_unistr(&job_info->notifyname, queue->fs_user);
5553 init_unistr(&job_info->datatype, "RAW");
5554 init_unistr(&job_info->printprocessor, "winprint");
5555 init_unistr(&job_info->parameters, "");
5556 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5557 init_unistr(&job_info->text_status, "");
5559 /* and here the security descriptor */
5561 job_info->status=nt_printj_status(queue->status);
5562 job_info->priority=queue->priority;
5563 job_info->position=position;
5564 job_info->starttime=0;
5565 job_info->untiltime=0;
5566 job_info->totalpages=queue->page_count;
5567 job_info->size=queue->size;
5568 make_systemtime(&(job_info->submitted), t);
5569 job_info->timeelapsed=0;
5570 job_info->pagesprinted=0;
5572 job_info->devmode = devmode;
5574 return (True);
5577 /****************************************************************************
5578 Enumjobs at level 1.
5579 ****************************************************************************/
5581 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5582 NEW_BUFFER *buffer, uint32 offered,
5583 uint32 *needed, uint32 *returned)
5585 JOB_INFO_1 *info;
5586 int i;
5588 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5589 if (info==NULL) {
5590 SAFE_FREE(queue);
5591 *returned=0;
5592 return WERR_NOMEM;
5595 for (i=0; i<*returned; i++)
5596 fill_job_info_1(&info[i], &queue[i], i, snum);
5598 SAFE_FREE(queue);
5600 /* check the required size. */
5601 for (i=0; i<*returned; i++)
5602 (*needed) += spoolss_size_job_info_1(&info[i]);
5604 if (!alloc_buffer_size(buffer, *needed)) {
5605 SAFE_FREE(info);
5606 return WERR_INSUFFICIENT_BUFFER;
5609 /* fill the buffer with the structures */
5610 for (i=0; i<*returned; i++)
5611 smb_io_job_info_1("", buffer, &info[i], 0);
5613 /* clear memory */
5614 SAFE_FREE(info);
5616 if (*needed > offered) {
5617 *returned=0;
5618 return WERR_INSUFFICIENT_BUFFER;
5621 return WERR_OK;
5624 /****************************************************************************
5625 Enumjobs at level 2.
5626 ****************************************************************************/
5628 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5629 NEW_BUFFER *buffer, uint32 offered,
5630 uint32 *needed, uint32 *returned)
5632 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5633 JOB_INFO_2 *info = NULL;
5634 int i;
5635 WERROR result;
5636 DEVICEMODE *devmode = NULL;
5638 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5639 if (info==NULL) {
5640 *returned=0;
5641 result = WERR_NOMEM;
5642 goto done;
5645 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5646 if (!W_ERROR_IS_OK(result)) {
5647 *returned = 0;
5648 goto done;
5651 if (!(devmode = construct_dev_mode(snum))) {
5652 *returned = 0;
5653 result = WERR_NOMEM;
5654 goto done;
5657 for (i=0; i<*returned; i++)
5658 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5659 devmode);
5661 free_a_printer(&ntprinter, 2);
5662 SAFE_FREE(queue);
5664 /* check the required size. */
5665 for (i=0; i<*returned; i++)
5666 (*needed) += spoolss_size_job_info_2(&info[i]);
5668 if (*needed > offered) {
5669 *returned=0;
5670 result = WERR_INSUFFICIENT_BUFFER;
5671 goto done;
5674 if (!alloc_buffer_size(buffer, *needed)) {
5675 SAFE_FREE(info);
5676 result = WERR_INSUFFICIENT_BUFFER;
5677 goto done;
5680 /* fill the buffer with the structures */
5681 for (i=0; i<*returned; i++)
5682 smb_io_job_info_2("", buffer, &info[i], 0);
5684 result = WERR_OK;
5686 done:
5687 free_a_printer(&ntprinter, 2);
5688 free_devmode(devmode);
5689 SAFE_FREE(queue);
5690 SAFE_FREE(info);
5692 return result;
5696 /****************************************************************************
5697 Enumjobs.
5698 ****************************************************************************/
5700 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5702 POLICY_HND *handle = &q_u->handle;
5703 uint32 level = q_u->level;
5704 NEW_BUFFER *buffer = NULL;
5705 uint32 offered = q_u->offered;
5706 uint32 *needed = &r_u->needed;
5707 uint32 *returned = &r_u->returned;
5709 int snum;
5710 print_status_struct prt_status;
5711 print_queue_struct *queue=NULL;
5713 /* that's an [in out] buffer */
5714 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5715 buffer = r_u->buffer;
5717 DEBUG(4,("_spoolss_enumjobs\n"));
5719 *needed=0;
5720 *returned=0;
5722 if (!get_printer_snum(p, handle, &snum))
5723 return WERR_BADFID;
5725 *returned = print_queue_status(snum, &queue, &prt_status);
5726 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5728 if (*returned == 0) {
5729 SAFE_FREE(queue);
5730 return WERR_OK;
5733 switch (level) {
5734 case 1:
5735 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5736 case 2:
5737 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5738 default:
5739 SAFE_FREE(queue);
5740 *returned=0;
5741 return WERR_UNKNOWN_LEVEL;
5745 /****************************************************************************
5746 ****************************************************************************/
5748 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5750 return WERR_OK;
5753 /****************************************************************************
5754 ****************************************************************************/
5756 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5758 POLICY_HND *handle = &q_u->handle;
5759 uint32 jobid = q_u->jobid;
5760 uint32 command = q_u->command;
5762 struct current_user user;
5763 int snum;
5764 WERROR errcode = WERR_BADFUNC;
5766 if (!get_printer_snum(p, handle, &snum)) {
5767 return WERR_BADFID;
5770 if (!print_job_exists(snum, jobid)) {
5771 return WERR_INVALID_PRINTER_NAME;
5774 get_current_user(&user, p);
5776 switch (command) {
5777 case JOB_CONTROL_CANCEL:
5778 case JOB_CONTROL_DELETE:
5779 if (print_job_delete(&user, snum, jobid, &errcode)) {
5780 errcode = WERR_OK;
5782 break;
5783 case JOB_CONTROL_PAUSE:
5784 if (print_job_pause(&user, snum, jobid, &errcode)) {
5785 errcode = WERR_OK;
5787 break;
5788 case JOB_CONTROL_RESTART:
5789 case JOB_CONTROL_RESUME:
5790 if (print_job_resume(&user, snum, jobid, &errcode)) {
5791 errcode = WERR_OK;
5793 break;
5794 default:
5795 return WERR_UNKNOWN_LEVEL;
5798 return errcode;
5801 /****************************************************************************
5802 Enumerates all printer drivers at level 1.
5803 ****************************************************************************/
5805 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5807 int i;
5808 int ndrivers;
5809 uint32 version;
5810 fstring *list = NULL;
5812 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5813 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5815 *returned=0;
5817 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5818 list=NULL;
5819 ndrivers=get_ntdrivers(&list, architecture, version);
5820 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5822 if(ndrivers == -1)
5823 return WERR_NOMEM;
5825 if(ndrivers != 0) {
5826 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5827 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5828 SAFE_FREE(driver_info_1);
5829 SAFE_FREE(list);
5830 return WERR_NOMEM;
5832 else driver_info_1 = tdi1;
5835 for (i=0; i<ndrivers; i++) {
5836 WERROR status;
5837 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5838 ZERO_STRUCT(driver);
5839 status = get_a_printer_driver(&driver, 3, list[i],
5840 architecture, version);
5841 if (!W_ERROR_IS_OK(status)) {
5842 SAFE_FREE(list);
5843 return status;
5845 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5846 free_a_printer_driver(driver, 3);
5849 *returned+=ndrivers;
5850 SAFE_FREE(list);
5853 /* check the required size. */
5854 for (i=0; i<*returned; i++) {
5855 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5856 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5859 if (!alloc_buffer_size(buffer, *needed)) {
5860 SAFE_FREE(driver_info_1);
5861 return WERR_INSUFFICIENT_BUFFER;
5864 /* fill the buffer with the driver structures */
5865 for (i=0; i<*returned; i++) {
5866 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5867 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5870 SAFE_FREE(driver_info_1);
5872 if (*needed > offered) {
5873 *returned=0;
5874 return WERR_INSUFFICIENT_BUFFER;
5877 return WERR_OK;
5880 /****************************************************************************
5881 Enumerates all printer drivers at level 2.
5882 ****************************************************************************/
5884 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5886 int i;
5887 int ndrivers;
5888 uint32 version;
5889 fstring *list = NULL;
5891 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5892 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5894 *returned=0;
5896 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5897 list=NULL;
5898 ndrivers=get_ntdrivers(&list, architecture, version);
5899 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5901 if(ndrivers == -1)
5902 return WERR_NOMEM;
5904 if(ndrivers != 0) {
5905 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5906 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5907 SAFE_FREE(driver_info_2);
5908 SAFE_FREE(list);
5909 return WERR_NOMEM;
5911 else driver_info_2 = tdi2;
5914 for (i=0; i<ndrivers; i++) {
5915 WERROR status;
5917 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5918 ZERO_STRUCT(driver);
5919 status = get_a_printer_driver(&driver, 3, list[i],
5920 architecture, version);
5921 if (!W_ERROR_IS_OK(status)) {
5922 SAFE_FREE(list);
5923 return status;
5925 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5926 free_a_printer_driver(driver, 3);
5929 *returned+=ndrivers;
5930 SAFE_FREE(list);
5933 /* check the required size. */
5934 for (i=0; i<*returned; i++) {
5935 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5936 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5939 if (!alloc_buffer_size(buffer, *needed)) {
5940 SAFE_FREE(driver_info_2);
5941 return WERR_INSUFFICIENT_BUFFER;
5944 /* fill the buffer with the form structures */
5945 for (i=0; i<*returned; i++) {
5946 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5947 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5950 SAFE_FREE(driver_info_2);
5952 if (*needed > offered) {
5953 *returned=0;
5954 return WERR_INSUFFICIENT_BUFFER;
5957 return WERR_OK;
5960 /****************************************************************************
5961 Enumerates all printer drivers at level 3.
5962 ****************************************************************************/
5964 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5966 int i;
5967 int ndrivers;
5968 uint32 version;
5969 fstring *list = NULL;
5971 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5972 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5974 *returned=0;
5976 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5977 list=NULL;
5978 ndrivers=get_ntdrivers(&list, architecture, version);
5979 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5981 if(ndrivers == -1)
5982 return WERR_NOMEM;
5984 if(ndrivers != 0) {
5985 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5986 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5987 SAFE_FREE(driver_info_3);
5988 SAFE_FREE(list);
5989 return WERR_NOMEM;
5991 else driver_info_3 = tdi3;
5994 for (i=0; i<ndrivers; i++) {
5995 WERROR status;
5997 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5998 ZERO_STRUCT(driver);
5999 status = get_a_printer_driver(&driver, 3, list[i],
6000 architecture, version);
6001 if (!W_ERROR_IS_OK(status)) {
6002 SAFE_FREE(list);
6003 return status;
6005 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6006 free_a_printer_driver(driver, 3);
6009 *returned+=ndrivers;
6010 SAFE_FREE(list);
6013 /* check the required size. */
6014 for (i=0; i<*returned; i++) {
6015 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6016 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6019 if (!alloc_buffer_size(buffer, *needed)) {
6020 SAFE_FREE(driver_info_3);
6021 return WERR_INSUFFICIENT_BUFFER;
6024 /* fill the buffer with the driver structures */
6025 for (i=0; i<*returned; i++) {
6026 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6027 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6030 for (i=0; i<*returned; i++)
6031 SAFE_FREE(driver_info_3[i].dependentfiles);
6033 SAFE_FREE(driver_info_3);
6035 if (*needed > offered) {
6036 *returned=0;
6037 return WERR_INSUFFICIENT_BUFFER;
6040 return WERR_OK;
6043 /****************************************************************************
6044 Enumerates all printer drivers.
6045 ****************************************************************************/
6047 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6049 UNISTR2 *environment = &q_u->environment;
6050 uint32 level = q_u->level;
6051 NEW_BUFFER *buffer = NULL;
6052 uint32 offered = q_u->offered;
6053 uint32 *needed = &r_u->needed;
6054 uint32 *returned = &r_u->returned;
6056 fstring *list = NULL;
6057 fstring servername;
6058 fstring architecture;
6060 /* that's an [in out] buffer */
6061 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6062 buffer = r_u->buffer;
6064 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6065 fstrcpy(servername, get_called_name());
6066 *needed=0;
6067 *returned=0;
6069 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6071 switch (level) {
6072 case 1:
6073 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6074 case 2:
6075 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6076 case 3:
6077 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6078 default:
6079 *returned=0;
6080 SAFE_FREE(list);
6081 return WERR_UNKNOWN_LEVEL;
6085 /****************************************************************************
6086 ****************************************************************************/
6088 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6090 form->flag=list->flag;
6091 init_unistr(&form->name, list->name);
6092 form->width=list->width;
6093 form->length=list->length;
6094 form->left=list->left;
6095 form->top=list->top;
6096 form->right=list->right;
6097 form->bottom=list->bottom;
6100 /****************************************************************************
6101 ****************************************************************************/
6103 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6105 uint32 level = q_u->level;
6106 NEW_BUFFER *buffer = NULL;
6107 uint32 offered = q_u->offered;
6108 uint32 *needed = &r_u->needed;
6109 uint32 *numofforms = &r_u->numofforms;
6110 uint32 numbuiltinforms;
6112 nt_forms_struct *list=NULL;
6113 nt_forms_struct *builtinlist=NULL;
6114 FORM_1 *forms_1;
6115 int buffer_size=0;
6116 int i;
6118 /* that's an [in out] buffer */
6119 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6120 buffer = r_u->buffer;
6122 DEBUG(4,("_spoolss_enumforms\n"));
6123 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6124 DEBUGADD(5,("Info level [%d]\n", level));
6126 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6127 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6128 *numofforms = get_ntforms(&list);
6129 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6130 *numofforms += numbuiltinforms;
6132 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6134 switch (level) {
6135 case 1:
6136 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6137 *numofforms=0;
6138 return WERR_NOMEM;
6141 /* construct the list of form structures */
6142 for (i=0; i<numbuiltinforms; i++) {
6143 DEBUGADD(6,("Filling form number [%d]\n",i));
6144 fill_form_1(&forms_1[i], &builtinlist[i]);
6147 SAFE_FREE(builtinlist);
6149 for (; i<*numofforms; i++) {
6150 DEBUGADD(6,("Filling form number [%d]\n",i));
6151 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6154 SAFE_FREE(list);
6156 /* check the required size. */
6157 for (i=0; i<numbuiltinforms; i++) {
6158 DEBUGADD(6,("adding form [%d]'s size\n",i));
6159 buffer_size += spoolss_size_form_1(&forms_1[i]);
6161 for (; i<*numofforms; i++) {
6162 DEBUGADD(6,("adding form [%d]'s size\n",i));
6163 buffer_size += spoolss_size_form_1(&forms_1[i]);
6166 *needed=buffer_size;
6168 if (!alloc_buffer_size(buffer, buffer_size)){
6169 SAFE_FREE(forms_1);
6170 return WERR_INSUFFICIENT_BUFFER;
6173 /* fill the buffer with the form structures */
6174 for (i=0; i<numbuiltinforms; i++) {
6175 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6176 smb_io_form_1("", buffer, &forms_1[i], 0);
6178 for (; i<*numofforms; i++) {
6179 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6180 smb_io_form_1("", buffer, &forms_1[i], 0);
6183 SAFE_FREE(forms_1);
6185 if (*needed > offered) {
6186 *numofforms=0;
6187 return WERR_INSUFFICIENT_BUFFER;
6189 else
6190 return WERR_OK;
6192 default:
6193 SAFE_FREE(list);
6194 SAFE_FREE(builtinlist);
6195 return WERR_UNKNOWN_LEVEL;
6200 /****************************************************************************
6201 ****************************************************************************/
6203 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6205 uint32 level = q_u->level;
6206 UNISTR2 *uni_formname = &q_u->formname;
6207 NEW_BUFFER *buffer = NULL;
6208 uint32 offered = q_u->offered;
6209 uint32 *needed = &r_u->needed;
6211 nt_forms_struct *list=NULL;
6212 nt_forms_struct builtin_form;
6213 BOOL foundBuiltin;
6214 FORM_1 form_1;
6215 fstring form_name;
6216 int buffer_size=0;
6217 int numofforms=0, i=0;
6219 /* that's an [in out] buffer */
6220 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6221 buffer = r_u->buffer;
6223 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6225 DEBUG(4,("_spoolss_getform\n"));
6226 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6227 DEBUGADD(5,("Info level [%d]\n", level));
6229 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6230 if (!foundBuiltin) {
6231 numofforms = get_ntforms(&list);
6232 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6234 if (numofforms == 0)
6235 return WERR_BADFID;
6238 switch (level) {
6239 case 1:
6240 if (foundBuiltin) {
6241 fill_form_1(&form_1, &builtin_form);
6242 } else {
6244 /* Check if the requested name is in the list of form structures */
6245 for (i=0; i<numofforms; i++) {
6247 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6249 if (strequal(form_name, list[i].name)) {
6250 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6251 fill_form_1(&form_1, &list[i]);
6252 break;
6256 SAFE_FREE(list);
6257 if (i == numofforms) {
6258 return WERR_BADFID;
6261 /* check the required size. */
6263 *needed=spoolss_size_form_1(&form_1);
6265 if (!alloc_buffer_size(buffer, buffer_size)){
6266 return WERR_INSUFFICIENT_BUFFER;
6269 if (*needed > offered) {
6270 return WERR_INSUFFICIENT_BUFFER;
6273 /* fill the buffer with the form structures */
6274 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6275 smb_io_form_1("", buffer, &form_1, 0);
6277 return WERR_OK;
6279 default:
6280 SAFE_FREE(list);
6281 return WERR_UNKNOWN_LEVEL;
6285 /****************************************************************************
6286 ****************************************************************************/
6288 static void fill_port_1(PORT_INFO_1 *port, char *name)
6290 init_unistr(&port->port_name, name);
6293 /****************************************************************************
6294 ****************************************************************************/
6296 static void fill_port_2(PORT_INFO_2 *port, char *name)
6298 init_unistr(&port->port_name, name);
6299 init_unistr(&port->monitor_name, "Local Monitor");
6300 init_unistr(&port->description, "Local Port");
6301 #define PORT_TYPE_WRITE 1
6302 port->port_type=PORT_TYPE_WRITE;
6303 port->reserved=0x0;
6306 /****************************************************************************
6307 enumports level 1.
6308 ****************************************************************************/
6310 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6312 PORT_INFO_1 *ports=NULL;
6313 int i=0;
6315 if (*lp_enumports_cmd()) {
6316 char *cmd = lp_enumports_cmd();
6317 char **qlines;
6318 pstring command;
6319 int numlines;
6320 int ret;
6321 int fd;
6323 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6325 DEBUG(10,("Running [%s]\n", command));
6326 ret = smbrun(command, &fd);
6327 DEBUG(10,("Returned [%d]\n", ret));
6328 if (ret != 0) {
6329 if (fd != -1)
6330 close(fd);
6331 /* Is this the best error to return here? */
6332 return WERR_ACCESS_DENIED;
6335 numlines = 0;
6336 qlines = fd_lines_load(fd, &numlines);
6337 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6338 close(fd);
6340 if(numlines) {
6341 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6342 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6343 dos_errstr(WERR_NOMEM)));
6344 file_lines_free(qlines);
6345 return WERR_NOMEM;
6348 for (i=0; i<numlines; i++) {
6349 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6350 fill_port_1(&ports[i], qlines[i]);
6353 file_lines_free(qlines);
6356 *returned = numlines;
6358 } else {
6359 *returned = 1; /* Sole Samba port returned. */
6361 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6362 return WERR_NOMEM;
6364 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6366 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6369 /* check the required size. */
6370 for (i=0; i<*returned; i++) {
6371 DEBUGADD(6,("adding port [%d]'s size\n", i));
6372 *needed += spoolss_size_port_info_1(&ports[i]);
6375 if (!alloc_buffer_size(buffer, *needed)) {
6376 SAFE_FREE(ports);
6377 return WERR_INSUFFICIENT_BUFFER;
6380 /* fill the buffer with the ports structures */
6381 for (i=0; i<*returned; i++) {
6382 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6383 smb_io_port_1("", buffer, &ports[i], 0);
6386 SAFE_FREE(ports);
6388 if (*needed > offered) {
6389 *returned=0;
6390 return WERR_INSUFFICIENT_BUFFER;
6393 return WERR_OK;
6396 /****************************************************************************
6397 enumports level 2.
6398 ****************************************************************************/
6400 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6402 PORT_INFO_2 *ports=NULL;
6403 int i=0;
6405 if (*lp_enumports_cmd()) {
6406 char *cmd = lp_enumports_cmd();
6407 char *path;
6408 char **qlines;
6409 pstring tmp_file;
6410 pstring command;
6411 int numlines;
6412 int ret;
6413 int fd;
6415 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6416 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6417 else
6418 path = lp_lockdir();
6420 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6421 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6423 unlink(tmp_file);
6424 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6425 ret = smbrun(command, &fd);
6426 DEBUGADD(10,("returned [%d]\n", ret));
6427 if (ret != 0) {
6428 if (fd != -1)
6429 close(fd);
6430 /* Is this the best error to return here? */
6431 return WERR_ACCESS_DENIED;
6434 numlines = 0;
6435 qlines = fd_lines_load(fd, &numlines);
6436 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6437 close(fd);
6439 if(numlines) {
6440 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6441 file_lines_free(qlines);
6442 return WERR_NOMEM;
6445 for (i=0; i<numlines; i++) {
6446 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6447 fill_port_2(&(ports[i]), qlines[i]);
6450 file_lines_free(qlines);
6453 *returned = numlines;
6455 } else {
6457 *returned = 1;
6459 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6460 return WERR_NOMEM;
6462 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6464 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6467 /* check the required size. */
6468 for (i=0; i<*returned; i++) {
6469 DEBUGADD(6,("adding port [%d]'s size\n", i));
6470 *needed += spoolss_size_port_info_2(&ports[i]);
6473 if (!alloc_buffer_size(buffer, *needed)) {
6474 SAFE_FREE(ports);
6475 return WERR_INSUFFICIENT_BUFFER;
6478 /* fill the buffer with the ports structures */
6479 for (i=0; i<*returned; i++) {
6480 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6481 smb_io_port_2("", buffer, &ports[i], 0);
6484 SAFE_FREE(ports);
6486 if (*needed > offered) {
6487 *returned=0;
6488 return WERR_INSUFFICIENT_BUFFER;
6491 return WERR_OK;
6494 /****************************************************************************
6495 enumports.
6496 ****************************************************************************/
6498 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6500 uint32 level = q_u->level;
6501 NEW_BUFFER *buffer = NULL;
6502 uint32 offered = q_u->offered;
6503 uint32 *needed = &r_u->needed;
6504 uint32 *returned = &r_u->returned;
6506 /* that's an [in out] buffer */
6507 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6508 buffer = r_u->buffer;
6510 DEBUG(4,("_spoolss_enumports\n"));
6512 *returned=0;
6513 *needed=0;
6515 switch (level) {
6516 case 1:
6517 return enumports_level_1(buffer, offered, needed, returned);
6518 case 2:
6519 return enumports_level_2(buffer, offered, needed, returned);
6520 default:
6521 return WERR_UNKNOWN_LEVEL;
6525 /****************************************************************************
6526 ****************************************************************************/
6528 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6529 const SPOOL_PRINTER_INFO_LEVEL *info,
6530 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6531 uint32 user_switch, const SPOOL_USER_CTR *user,
6532 POLICY_HND *handle)
6534 NT_PRINTER_INFO_LEVEL *printer = NULL;
6535 fstring name;
6536 int snum;
6537 WERROR err = WERR_OK;
6539 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6540 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6541 return WERR_NOMEM;
6544 ZERO_STRUCTP(printer);
6546 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6547 if (!convert_printer_info(info, printer, 2)) {
6548 free_a_printer(&printer, 2);
6549 return WERR_NOMEM;
6552 /* check to see if the printer already exists */
6554 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6555 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6556 printer->info_2->sharename));
6557 free_a_printer(&printer, 2);
6558 return WERR_PRINTER_ALREADY_EXISTS;
6561 if (*lp_addprinter_cmd() )
6562 if ( !add_printer_hook(printer) ) {
6563 free_a_printer(&printer,2);
6564 return WERR_ACCESS_DENIED;
6567 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6568 printer->info_2->sharename);
6570 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6571 free_a_printer(&printer,2);
6572 return WERR_ACCESS_DENIED;
6575 /* you must be a printer admin to add a new printer */
6576 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6577 free_a_printer(&printer,2);
6578 return WERR_ACCESS_DENIED;
6582 * Do sanity check on the requested changes for Samba.
6585 if (!check_printer_ok(printer->info_2, snum)) {
6586 free_a_printer(&printer,2);
6587 return WERR_INVALID_PARAM;
6591 * When a printer is created, the drivername bound to the printer is used
6592 * to lookup previously saved driver initialization info, which is then
6593 * bound to the new printer, simulating what happens in the Windows arch.
6596 if (!devmode)
6597 set_driver_init(printer, 2);
6598 else {
6599 /* A valid devmode was included, convert and link it
6601 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6603 if (!convert_devicemode(printer->info_2->printername, devmode,
6604 &printer->info_2->devmode))
6605 return WERR_NOMEM;
6608 set_driver_init(printer, 2);
6610 /* write the ASCII on disk */
6611 err = mod_a_printer(*printer, 2);
6612 if (!W_ERROR_IS_OK(err)) {
6613 free_a_printer(&printer,2);
6614 return err;
6617 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6618 /* Handle open failed - remove addition. */
6619 del_a_printer(printer->info_2->sharename);
6620 free_a_printer(&printer,2);
6621 return WERR_ACCESS_DENIED;
6624 update_c_setprinter(False);
6625 free_a_printer(&printer,2);
6627 return WERR_OK;
6630 /****************************************************************************
6631 ****************************************************************************/
6633 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6635 UNISTR2 *uni_srv_name = &q_u->server_name;
6636 uint32 level = q_u->level;
6637 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6638 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6639 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6640 uint32 user_switch = q_u->user_switch;
6641 SPOOL_USER_CTR *user = &q_u->user_ctr;
6642 POLICY_HND *handle = &r_u->handle;
6644 switch (level) {
6645 case 1:
6646 /* we don't handle yet */
6647 /* but I know what to do ... */
6648 return WERR_UNKNOWN_LEVEL;
6649 case 2:
6650 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6651 devmode, sdb,
6652 user_switch, user, handle);
6653 default:
6654 return WERR_UNKNOWN_LEVEL;
6658 /****************************************************************************
6659 ****************************************************************************/
6661 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6663 uint32 level = q_u->level;
6664 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6665 WERROR err = WERR_OK;
6666 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6667 struct current_user user;
6668 fstring driver_name;
6669 uint32 version;
6671 ZERO_STRUCT(driver);
6673 get_current_user(&user, p);
6675 if (!convert_printer_driver_info(info, &driver, level)) {
6676 err = WERR_NOMEM;
6677 goto done;
6680 DEBUG(5,("Cleaning driver's information\n"));
6681 err = clean_up_driver_struct(driver, level, &user);
6682 if (!W_ERROR_IS_OK(err))
6683 goto done;
6685 DEBUG(5,("Moving driver to final destination\n"));
6686 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6687 if (W_ERROR_IS_OK(err))
6688 err = WERR_ACCESS_DENIED;
6689 goto done;
6692 if (add_a_printer_driver(driver, level)!=0) {
6693 err = WERR_ACCESS_DENIED;
6694 goto done;
6697 /* BEGIN_ADMIN_LOG */
6698 switch(level) {
6699 case 3:
6700 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6701 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6702 fstrcpy(driver_name, driver.info_3->name);
6703 break;
6704 case 6:
6705 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6706 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6707 fstrcpy(driver_name, driver.info_6->name);
6708 break;
6710 /* END_ADMIN_LOG */
6713 * I think this is where he DrvUpgradePrinter() hook would be
6714 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6715 * server. Right now, we just need to send ourselves a message
6716 * to update each printer bound to this driver. --jerry
6719 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6720 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6721 driver_name));
6725 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6726 * decide if the driver init data should be deleted. The rules are:
6727 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6728 * 2) delete init data only if there is no 2k/Xp driver
6729 * 3) always delete init data
6730 * The generalized rule is always use init data from the highest order driver.
6731 * It is necessary to follow the driver install by an initialization step to
6732 * finish off this process.
6734 if (level == 3)
6735 version = driver.info_3->cversion;
6736 else if (level == 6)
6737 version = driver.info_6->version;
6738 else
6739 version = -1;
6740 switch (version) {
6742 * 9x printer driver - never delete init data
6744 case 0:
6745 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6746 driver_name));
6747 break;
6750 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6751 * there is no 2k/Xp driver init data for this driver name.
6753 case 2:
6755 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
6757 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
6759 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6761 if (!del_driver_init(driver_name))
6762 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
6763 } else {
6765 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6767 free_a_printer_driver(driver1,3);
6768 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6769 driver_name));
6772 break;
6775 * 2k or Xp printer driver - always delete init data
6777 case 3:
6778 if (!del_driver_init(driver_name))
6779 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
6780 break;
6782 default:
6783 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
6784 break;
6788 done:
6789 free_a_printer_driver(driver, level);
6790 return err;
6793 /********************************************************************
6794 * spoolss_addprinterdriverex
6795 ********************************************************************/
6797 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
6799 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
6800 SPOOL_R_ADDPRINTERDRIVER r_u_local;
6803 * we only support the semantics of AddPrinterDriver()
6804 * i.e. only copy files that are newer than existing ones
6807 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
6808 return WERR_ACCESS_DENIED;
6810 ZERO_STRUCT(q_u_local);
6811 ZERO_STRUCT(r_u_local);
6813 /* just pass the information off to _spoolss_addprinterdriver() */
6814 q_u_local.server_name_ptr = q_u->server_name_ptr;
6815 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
6816 q_u_local.level = q_u->level;
6817 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
6819 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
6822 /****************************************************************************
6823 ****************************************************************************/
6825 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6827 init_unistr(&info->name, name);
6830 /****************************************************************************
6831 ****************************************************************************/
6833 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6835 pstring path;
6836 pstring long_archi;
6837 pstring short_archi;
6838 DRIVER_DIRECTORY_1 *info=NULL;
6840 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6842 if (get_short_archi(short_archi, long_archi)==False)
6843 return WERR_INVALID_ENVIRONMENT;
6845 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6846 return WERR_NOMEM;
6848 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6850 DEBUG(4,("printer driver directory: [%s]\n", path));
6852 fill_driverdir_1(info, path);
6854 *needed += spoolss_size_driverdir_info_1(info);
6856 if (!alloc_buffer_size(buffer, *needed)) {
6857 SAFE_FREE(info);
6858 return WERR_INSUFFICIENT_BUFFER;
6861 smb_io_driverdir_1("", buffer, info, 0);
6863 SAFE_FREE(info);
6865 if (*needed > offered)
6866 return WERR_INSUFFICIENT_BUFFER;
6868 return WERR_OK;
6871 /****************************************************************************
6872 ****************************************************************************/
6874 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6876 UNISTR2 *name = &q_u->name;
6877 UNISTR2 *uni_environment = &q_u->environment;
6878 uint32 level = q_u->level;
6879 NEW_BUFFER *buffer = NULL;
6880 uint32 offered = q_u->offered;
6881 uint32 *needed = &r_u->needed;
6883 /* that's an [in out] buffer */
6884 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6885 buffer = r_u->buffer;
6887 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6889 *needed=0;
6891 switch(level) {
6892 case 1:
6893 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6894 default:
6895 return WERR_UNKNOWN_LEVEL;
6899 /****************************************************************************
6900 ****************************************************************************/
6902 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6904 POLICY_HND *handle = &q_u->handle;
6905 uint32 idx = q_u->index;
6906 uint32 in_value_len = q_u->valuesize;
6907 uint32 in_data_len = q_u->datasize;
6908 uint32 *out_max_value_len= &r_u->valuesize;
6909 uint16 **out_value = &r_u->value;
6910 uint32 *out_value_len = &r_u->realvaluesize;
6911 uint32 *out_type = &r_u->type;
6912 uint32 *out_max_data_len = &r_u->datasize;
6913 uint8 **data_out = &r_u->data;
6914 uint32 *out_data_len = &r_u->realdatasize;
6916 NT_PRINTER_INFO_LEVEL *printer = NULL;
6918 uint32 param_index;
6919 uint32 biggest_valuesize;
6920 uint32 biggest_datasize;
6921 uint32 data_len;
6922 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6923 int snum;
6924 WERROR result;
6925 REGISTRY_VALUE *val;
6926 NT_PRINTER_DATA *p_data;
6927 int i, key_index, num_values;
6928 int name_length;
6930 ZERO_STRUCT( printer );
6932 *out_type = 0;
6934 *out_max_data_len = 0;
6935 *data_out = NULL;
6936 *out_data_len = 0;
6938 DEBUG(5,("spoolss_enumprinterdata\n"));
6940 if (!Printer) {
6941 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6942 return WERR_BADFID;
6945 if (!get_printer_snum(p,handle, &snum))
6946 return WERR_BADFID;
6948 result = get_a_printer(&printer, 2, lp_servicename(snum));
6949 if (!W_ERROR_IS_OK(result))
6950 return result;
6952 p_data = &printer->info_2->data;
6953 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
6955 result = WERR_OK;
6958 * The NT machine wants to know the biggest size of value and data
6960 * cf: MSDN EnumPrinterData remark section
6963 if ( !in_value_len && !in_data_len )
6965 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6967 param_index = 0;
6968 biggest_valuesize = 0;
6969 biggest_datasize = 0;
6971 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
6973 for ( i=0; i<num_values; i++ )
6975 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
6977 name_length = strlen(val->valuename);
6978 if ( strlen(val->valuename) > biggest_valuesize )
6979 biggest_valuesize = name_length;
6981 if ( val->size > biggest_datasize )
6982 biggest_datasize = val->size;
6984 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
6985 biggest_datasize));
6988 /* the value is an UNICODE string but real_value_size is the length
6989 in bytes including the trailing 0 */
6991 *out_value_len = 2 * (1+biggest_valuesize);
6992 *out_data_len = biggest_datasize;
6994 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6996 goto done;
7000 * the value len is wrong in NT sp3
7001 * that's the number of bytes not the number of unicode chars
7004 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7006 if ( !val )
7009 /* out_value should default to "" or else NT4 has
7010 problems unmarshalling the response */
7012 *out_max_value_len = (in_value_len/sizeof(uint16));
7014 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7016 result = WERR_NOMEM;
7017 goto done;
7020 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7022 /* the data is counted in bytes */
7024 *out_max_data_len = in_data_len;
7025 *out_data_len = in_data_len;
7027 /* only allocate when given a non-zero data_len */
7029 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7031 result = WERR_NOMEM;
7032 goto done;
7035 result = WERR_NO_MORE_ITEMS;
7037 else
7040 * the value is:
7041 * - counted in bytes in the request
7042 * - counted in UNICODE chars in the max reply
7043 * - counted in bytes in the real size
7045 * take a pause *before* coding not *during* coding
7048 /* name */
7049 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7050 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7052 result = WERR_NOMEM;
7053 goto done;
7056 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7058 /* type */
7060 *out_type = regval_type( val );
7062 /* data - counted in bytes */
7064 *out_max_data_len = in_data_len;
7065 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7067 result = WERR_NOMEM;
7068 goto done;
7070 data_len = (size_t)regval_size(val);
7071 memcpy( *data_out, regval_data_p(val), data_len );
7072 *out_data_len = data_len;
7075 done:
7076 free_a_printer(&printer, 2);
7077 return result;
7080 /****************************************************************************
7081 ****************************************************************************/
7083 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7085 POLICY_HND *handle = &q_u->handle;
7086 UNISTR2 *value = &q_u->value;
7087 uint32 type = q_u->type;
7088 uint8 *data = q_u->data;
7089 uint32 real_len = q_u->real_len;
7091 NT_PRINTER_INFO_LEVEL *printer = NULL;
7092 int snum=0;
7093 WERROR status = WERR_OK;
7094 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7095 fstring valuename;
7097 DEBUG(5,("spoolss_setprinterdata\n"));
7099 if (!Printer) {
7100 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7101 return WERR_BADFID;
7104 if (!get_printer_snum(p,handle, &snum))
7105 return WERR_BADFID;
7108 * Access check : NT returns "access denied" if you make a
7109 * SetPrinterData call without the necessary privildge.
7110 * we were originally returning OK if nothing changed
7111 * which made Win2k issue **a lot** of SetPrinterData
7112 * when connecting to a printer --jerry
7115 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7116 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7117 status = WERR_ACCESS_DENIED;
7118 goto done;
7121 status = get_a_printer(&printer, 2, lp_servicename(snum));
7122 if (!W_ERROR_IS_OK(status))
7123 return status;
7125 /* save the registry data */
7127 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7128 delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
7129 add_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename, type, data, real_len );
7131 /* write the **entire** printer out to disk.... :-( */
7133 status = mod_a_printer(*printer, 2);
7135 done:
7136 free_a_printer(&printer, 2);
7138 return status;
7141 /****************************************************************************
7142 ****************************************************************************/
7144 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7146 POLICY_HND *handle = &q_u->handle;
7147 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7148 int snum;
7150 DEBUG(5,("_spoolss_resetprinter\n"));
7153 * All we do is to check to see if the handle and queue is valid.
7154 * This call really doesn't mean anything to us because we only
7155 * support RAW printing. --jerry
7158 if (!Printer) {
7159 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7160 return WERR_BADFID;
7163 if (!get_printer_snum(p,handle, &snum))
7164 return WERR_BADFID;
7167 /* blindly return success */
7168 return WERR_OK;
7172 /****************************************************************************
7173 ****************************************************************************/
7175 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7177 POLICY_HND *handle = &q_u->handle;
7178 UNISTR2 *value = &q_u->valuename;
7180 NT_PRINTER_INFO_LEVEL *printer = NULL;
7181 int snum=0;
7182 WERROR status = WERR_OK;
7183 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7184 pstring valuename;
7186 DEBUG(5,("spoolss_deleteprinterdata\n"));
7188 if (!Printer) {
7189 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7190 return WERR_BADFID;
7193 if (!get_printer_snum(p, handle, &snum))
7194 return WERR_BADFID;
7196 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7197 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7198 return WERR_ACCESS_DENIED;
7201 status = get_a_printer(&printer, 2, lp_servicename(snum));
7202 if (!W_ERROR_IS_OK(status))
7203 return status;
7205 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7207 status = delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
7208 if ( NT_STATUS_IS_OK(status) )
7209 status = mod_a_printer(*printer, 2);
7211 free_a_printer(&printer, 2);
7213 return status;
7216 /****************************************************************************
7217 ****************************************************************************/
7219 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7221 POLICY_HND *handle = &q_u->handle;
7222 FORM *form = &q_u->form;
7223 nt_forms_struct tmpForm;
7224 int snum;
7225 WERROR status = WERR_OK;
7226 NT_PRINTER_INFO_LEVEL *printer = NULL;
7228 int count=0;
7229 nt_forms_struct *list=NULL;
7230 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7232 DEBUG(5,("spoolss_addform\n"));
7234 if (!Printer) {
7235 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7236 return WERR_BADFID;
7239 if (!get_printer_snum(p,handle, &snum))
7240 return WERR_BADFID;
7242 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7243 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7244 status = WERR_ACCESS_DENIED;
7245 goto done;
7248 /* can't add if builtin */
7249 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7250 return WERR_ALREADY_EXISTS;
7253 count=get_ntforms(&list);
7254 if(!add_a_form(&list, form, &count))
7255 return WERR_NOMEM;
7256 write_ntforms(&list, count);
7259 * ChangeID must always be set
7262 status = get_a_printer(&printer, 2, lp_servicename(snum));
7263 if (!W_ERROR_IS_OK(status))
7264 goto done;
7266 status = mod_a_printer(*printer, 2);
7267 if (!W_ERROR_IS_OK(status))
7268 goto done;
7270 done:
7271 free_a_printer(&printer, 2);
7272 SAFE_FREE(list);
7274 return status;
7277 /****************************************************************************
7278 ****************************************************************************/
7280 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7282 POLICY_HND *handle = &q_u->handle;
7283 UNISTR2 *form_name = &q_u->name;
7284 nt_forms_struct tmpForm;
7285 int count=0;
7286 WERROR ret = WERR_OK;
7287 nt_forms_struct *list=NULL;
7288 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7289 int snum;
7290 WERROR status = WERR_OK;
7291 NT_PRINTER_INFO_LEVEL *printer = NULL;
7293 DEBUG(5,("spoolss_deleteform\n"));
7295 if (!Printer) {
7296 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7297 return WERR_BADFID;
7300 if (!get_printer_snum(p, handle, &snum))
7301 return WERR_BADFID;
7303 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7304 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7305 return WERR_ACCESS_DENIED;
7308 /* can't delete if builtin */
7309 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7310 return WERR_INVALID_PARAM;
7313 count = get_ntforms(&list);
7314 if(!delete_a_form(&list, form_name, &count, &ret))
7315 return WERR_INVALID_PARAM;
7318 * ChangeID must always be set
7321 status = get_a_printer(&printer, 2, lp_servicename(snum));
7322 if (!W_ERROR_IS_OK(status))
7323 goto done;
7325 status = mod_a_printer(*printer, 2);
7326 if (!W_ERROR_IS_OK(status))
7327 goto done;
7329 done:
7330 free_a_printer(&printer, 2);
7331 SAFE_FREE(list);
7333 return ret;
7336 /****************************************************************************
7337 ****************************************************************************/
7339 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7341 POLICY_HND *handle = &q_u->handle;
7342 FORM *form = &q_u->form;
7343 nt_forms_struct tmpForm;
7344 int snum;
7345 WERROR status = WERR_OK;
7346 NT_PRINTER_INFO_LEVEL *printer = NULL;
7348 int count=0;
7349 nt_forms_struct *list=NULL;
7350 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7352 DEBUG(5,("spoolss_setform\n"));
7354 if (!Printer) {
7355 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7356 return WERR_BADFID;
7359 if (!get_printer_snum(p, handle, &snum))
7360 return WERR_BADFID;
7362 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7363 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7364 return WERR_ACCESS_DENIED;
7367 /* can't set if builtin */
7368 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7369 return WERR_INVALID_PARAM;
7372 count=get_ntforms(&list);
7373 update_a_form(&list, form, count);
7374 write_ntforms(&list, count);
7377 * ChangeID must always be set
7380 status = get_a_printer(&printer, 2, lp_servicename(snum));
7381 if (!W_ERROR_IS_OK(status))
7382 goto done;
7384 status = mod_a_printer(*printer, 2);
7385 if (!W_ERROR_IS_OK(status))
7386 goto done;
7388 done:
7389 free_a_printer(&printer, 2);
7390 SAFE_FREE(list);
7392 return WERR_OK;
7395 /****************************************************************************
7396 enumprintprocessors level 1.
7397 ****************************************************************************/
7399 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7401 PRINTPROCESSOR_1 *info_1=NULL;
7403 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7404 return WERR_NOMEM;
7406 (*returned) = 0x1;
7408 init_unistr(&info_1->name, "winprint");
7410 *needed += spoolss_size_printprocessor_info_1(info_1);
7412 if (!alloc_buffer_size(buffer, *needed))
7413 return WERR_INSUFFICIENT_BUFFER;
7415 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7417 SAFE_FREE(info_1);
7419 if (*needed > offered) {
7420 *returned=0;
7421 return WERR_INSUFFICIENT_BUFFER;
7424 return WERR_OK;
7427 /****************************************************************************
7428 ****************************************************************************/
7430 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7432 uint32 level = q_u->level;
7433 NEW_BUFFER *buffer = NULL;
7434 uint32 offered = q_u->offered;
7435 uint32 *needed = &r_u->needed;
7436 uint32 *returned = &r_u->returned;
7438 /* that's an [in out] buffer */
7439 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7440 buffer = r_u->buffer;
7442 DEBUG(5,("spoolss_enumprintprocessors\n"));
7445 * Enumerate the print processors ...
7447 * Just reply with "winprint", to keep NT happy
7448 * and I can use my nice printer checker.
7451 *returned=0;
7452 *needed=0;
7454 switch (level) {
7455 case 1:
7456 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7457 default:
7458 return WERR_UNKNOWN_LEVEL;
7462 /****************************************************************************
7463 enumprintprocdatatypes level 1.
7464 ****************************************************************************/
7466 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7468 PRINTPROCDATATYPE_1 *info_1=NULL;
7470 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7471 return WERR_NOMEM;
7473 (*returned) = 0x1;
7475 init_unistr(&info_1->name, "RAW");
7477 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7479 if (!alloc_buffer_size(buffer, *needed))
7480 return WERR_INSUFFICIENT_BUFFER;
7482 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7484 SAFE_FREE(info_1);
7486 if (*needed > offered) {
7487 *returned=0;
7488 return WERR_INSUFFICIENT_BUFFER;
7491 return WERR_OK;
7494 /****************************************************************************
7495 ****************************************************************************/
7497 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7499 uint32 level = q_u->level;
7500 NEW_BUFFER *buffer = NULL;
7501 uint32 offered = q_u->offered;
7502 uint32 *needed = &r_u->needed;
7503 uint32 *returned = &r_u->returned;
7505 /* that's an [in out] buffer */
7506 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7507 buffer = r_u->buffer;
7509 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7511 *returned=0;
7512 *needed=0;
7514 switch (level) {
7515 case 1:
7516 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7517 default:
7518 return WERR_UNKNOWN_LEVEL;
7522 /****************************************************************************
7523 enumprintmonitors level 1.
7524 ****************************************************************************/
7526 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7528 PRINTMONITOR_1 *info_1=NULL;
7530 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7531 return WERR_NOMEM;
7533 (*returned) = 0x1;
7535 init_unistr(&info_1->name, "Local Port");
7537 *needed += spoolss_size_printmonitor_info_1(info_1);
7539 if (!alloc_buffer_size(buffer, *needed))
7540 return WERR_INSUFFICIENT_BUFFER;
7542 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7544 SAFE_FREE(info_1);
7546 if (*needed > offered) {
7547 *returned=0;
7548 return WERR_INSUFFICIENT_BUFFER;
7551 return WERR_OK;
7554 /****************************************************************************
7555 enumprintmonitors level 2.
7556 ****************************************************************************/
7558 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7560 PRINTMONITOR_2 *info_2=NULL;
7562 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7563 return WERR_NOMEM;
7565 (*returned) = 0x1;
7567 init_unistr(&info_2->name, "Local Port");
7568 init_unistr(&info_2->environment, "Windows NT X86");
7569 init_unistr(&info_2->dll_name, "localmon.dll");
7571 *needed += spoolss_size_printmonitor_info_2(info_2);
7573 if (!alloc_buffer_size(buffer, *needed))
7574 return WERR_INSUFFICIENT_BUFFER;
7576 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7578 SAFE_FREE(info_2);
7580 if (*needed > offered) {
7581 *returned=0;
7582 return WERR_INSUFFICIENT_BUFFER;
7585 return WERR_OK;
7588 /****************************************************************************
7589 ****************************************************************************/
7591 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7593 uint32 level = q_u->level;
7594 NEW_BUFFER *buffer = NULL;
7595 uint32 offered = q_u->offered;
7596 uint32 *needed = &r_u->needed;
7597 uint32 *returned = &r_u->returned;
7599 /* that's an [in out] buffer */
7600 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7601 buffer = r_u->buffer;
7603 DEBUG(5,("spoolss_enumprintmonitors\n"));
7606 * Enumerate the print monitors ...
7608 * Just reply with "Local Port", to keep NT happy
7609 * and I can use my nice printer checker.
7612 *returned=0;
7613 *needed=0;
7615 switch (level) {
7616 case 1:
7617 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7618 case 2:
7619 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7620 default:
7621 return WERR_UNKNOWN_LEVEL;
7625 /****************************************************************************
7626 ****************************************************************************/
7628 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7630 int i=0;
7631 BOOL found=False;
7632 JOB_INFO_1 *info_1=NULL;
7634 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7636 if (info_1 == NULL) {
7637 SAFE_FREE(queue);
7638 return WERR_NOMEM;
7641 for (i=0; i<count && found==False; i++) {
7642 if (queue[i].job==(int)jobid)
7643 found=True;
7646 if (found==False) {
7647 SAFE_FREE(queue);
7648 SAFE_FREE(info_1);
7649 /* NT treats not found as bad param... yet another bad choice */
7650 return WERR_INVALID_PARAM;
7653 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7655 SAFE_FREE(queue);
7657 *needed += spoolss_size_job_info_1(info_1);
7659 if (!alloc_buffer_size(buffer, *needed)) {
7660 SAFE_FREE(info_1);
7661 return WERR_INSUFFICIENT_BUFFER;
7664 smb_io_job_info_1("", buffer, info_1, 0);
7666 SAFE_FREE(info_1);
7668 if (*needed > offered)
7669 return WERR_INSUFFICIENT_BUFFER;
7671 return WERR_OK;
7674 /****************************************************************************
7675 ****************************************************************************/
7677 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7679 int i=0;
7680 BOOL found=False;
7681 JOB_INFO_2 *info_2;
7682 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7683 WERROR ret;
7684 DEVICEMODE *devmode = NULL;
7686 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7688 ZERO_STRUCTP(info_2);
7690 if (info_2 == NULL) {
7691 ret = WERR_NOMEM;
7692 goto done;
7695 for (i=0; i<count && found==False; i++) {
7696 if (queue[i].job==(int)jobid)
7697 found=True;
7700 if (found==False) {
7701 /* NT treats not found as bad param... yet another bad
7702 choice */
7703 ret = WERR_INVALID_PARAM;
7704 goto done;
7707 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7708 if (!W_ERROR_IS_OK(ret))
7709 goto done;
7710 if (construct_dev_mode(snum) == NULL) {
7711 ret = WERR_NOMEM;
7712 goto done;
7715 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7717 *needed += spoolss_size_job_info_2(info_2);
7719 if (!alloc_buffer_size(buffer, *needed)) {
7720 ret = WERR_INSUFFICIENT_BUFFER;
7721 goto done;
7724 smb_io_job_info_2("", buffer, info_2, 0);
7726 if (*needed > offered) {
7727 ret = WERR_INSUFFICIENT_BUFFER;
7728 goto done;
7731 ret = WERR_OK;
7733 done:
7734 /* Cleanup allocated memory */
7736 SAFE_FREE(queue);
7737 free_job_info_2(info_2); /* Also frees devmode */
7738 SAFE_FREE(info_2);
7739 free_a_printer(&ntprinter, 2);
7741 return ret;
7744 /****************************************************************************
7745 ****************************************************************************/
7747 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7749 POLICY_HND *handle = &q_u->handle;
7750 uint32 jobid = q_u->jobid;
7751 uint32 level = q_u->level;
7752 NEW_BUFFER *buffer = NULL;
7753 uint32 offered = q_u->offered;
7754 uint32 *needed = &r_u->needed;
7756 int snum;
7757 int count;
7758 print_queue_struct *queue=NULL;
7759 print_status_struct prt_status;
7761 /* that's an [in out] buffer */
7762 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7763 buffer = r_u->buffer;
7765 DEBUG(5,("spoolss_getjob\n"));
7767 *needed=0;
7769 if (!get_printer_snum(p, handle, &snum))
7770 return WERR_BADFID;
7772 count = print_queue_status(snum, &queue, &prt_status);
7774 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7775 count, prt_status.status, prt_status.message));
7777 switch (level) {
7778 case 1:
7779 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7780 case 2:
7781 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7782 default:
7783 SAFE_FREE(queue);
7784 return WERR_UNKNOWN_LEVEL;
7788 /********************************************************************
7789 * spoolss_getprinterdataex
7790 ********************************************************************/
7792 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7794 POLICY_HND *handle = &q_u->handle;
7795 uint32 in_size = q_u->size;
7796 uint32 *type = &r_u->type;
7797 uint32 *out_size = &r_u->size;
7798 uint8 **data = &r_u->data;
7799 uint32 *needed = &r_u->needed;
7801 fstring key, value;
7802 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7803 BOOL found = False;
7805 DEBUG(4,("_spoolss_getprinterdataex\n"));
7807 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7808 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7810 /* in case of problem, return some default values */
7811 *needed=0;
7812 *type=0;
7813 *out_size=0;
7816 if (!Printer) {
7817 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7818 return WERR_NOMEM;
7819 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7820 return WERR_BADFID;
7824 /* Is the handle to a printer or to the server? */
7826 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7828 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7829 return WERR_INVALID_PARAM;
7831 else
7834 * From MSDN documentation of GetPrinterDataEx: pass request
7835 * to GetPrinterData if key is "PrinterDriverData". This is
7836 * the only key we really support. Other keys to implement:
7837 * (a) DsDriver
7838 * (b) DsSpooler
7839 * (c) PnPData
7840 * (d) DsUser
7843 if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
7844 return WERR_BADFILE;
7846 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7847 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7848 type, data, needed, in_size);
7852 if (!found) {
7853 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7855 /* reply this param doesn't exist */
7856 if (*out_size) {
7857 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7858 return WERR_NOMEM;
7859 } else {
7860 *data = NULL;
7863 return WERR_INVALID_PARAM;
7866 if (*needed > *out_size)
7867 return WERR_MORE_DATA;
7868 else
7869 return WERR_OK;
7872 /********************************************************************
7873 * spoolss_setprinterdata
7874 ********************************************************************/
7876 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7878 SPOOL_Q_SETPRINTERDATA q_u_local;
7879 SPOOL_R_SETPRINTERDATA r_u_local;
7880 fstring key;
7882 DEBUG(4,("_spoolss_setprinterdataex\n"));
7884 /* From MSDN documentation of SetPrinterDataEx: pass request to
7885 SetPrinterData if key is "PrinterDriverData" */
7887 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7889 if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
7890 return WERR_INVALID_PARAM;
7892 ZERO_STRUCT(q_u_local);
7893 ZERO_STRUCT(r_u_local);
7895 /* make a copy to call _spoolss_setprinterdata() */
7897 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7898 copy_unistr2(&q_u_local.value, &q_u->value);
7899 q_u_local.type = q_u->type;
7900 q_u_local.max_len = q_u->max_len;
7901 q_u_local.data = q_u->data;
7902 q_u_local.real_len = q_u->real_len;
7903 q_u_local.numeric_data = q_u->numeric_data;
7905 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7909 /********************************************************************
7910 * spoolss_deleteprinterdataex
7911 ********************************************************************/
7913 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
7915 SPOOL_Q_DELETEPRINTERDATA q_u_local;
7916 SPOOL_R_DELETEPRINTERDATA r_u_local;
7917 fstring key;
7919 /* From MSDN documentation of SetPrinterDataEx: pass request to
7920 SetPrinterData if key is "PrinterDriverData" */
7922 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7924 if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
7925 return WERR_INVALID_PARAM;
7927 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7928 copy_unistr2(&q_u_local.valuename, &q_u->valuename);
7930 return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
7936 /********************************************************************
7937 * spoolss_enumprinterkey
7938 ********************************************************************/
7941 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7943 fstring key;
7944 uint16 *enumkeys = NULL;
7945 char* ptr = NULL;
7946 int i;
7947 int printerkey_len = strlen(SPOOL_PRINTERDATA_KEY)+1;
7949 DEBUG(4,("_spoolss_enumprinterkey\n"));
7951 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
7954 * we only support enumating all keys (key == "")
7955 * Of course, the only key we support is the "PrinterDriverData"
7956 * key
7959 if ( !strlen( key ) )
7961 r_u->needed = printerkey_len*2;
7963 if ( q_u->size < r_u->needed )
7964 return WERR_MORE_DATA;
7966 if ( !(enumkeys = talloc( p->mem_ctx, printerkey_len*2 )) ) {
7967 DEBUG(0,("_spoolss_enumprinterkey: talloc() failed for [%d] bytes!\n",
7968 printerkey_len));
7969 return WERR_NOMEM;
7972 ptr = SPOOL_PRINTERDATA_KEY;
7973 for ( i=0; i<(printerkey_len-1); i++ )
7975 enumkeys[i] = (uint16)(*ptr);
7976 ptr++;
7979 /* tag of '\0's */
7981 enumkeys[i] = 0x0;
7983 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys))
7984 return WERR_BADFILE;
7986 return WERR_OK;
7989 /* The "PrinterDriverData" key should have no subkeys */
7990 if ( strcmp(key, SPOOL_PRINTERDATA_KEY) == 0 )
7992 uint16 dummy_key = 0;
7994 r_u->needed = 2;
7996 if (q_u->size < r_u->needed)
7997 return WERR_MORE_DATA;
7999 if ( !make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, &dummy_key ) )
8000 return WERR_BADFILE;
8002 return WERR_OK;
8006 /* The return value for an unknown key is documented in MSDN
8007 EnumPrinterKey description */
8009 return WERR_BADFILE;
8012 /********************************************************************
8013 * spoolss_deleteprinterkey
8014 ********************************************************************/
8016 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8018 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8019 fstring key;
8021 if (!Printer) {
8022 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
8023 return WERR_BADFID;
8026 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8028 if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
8029 return WERR_INVALID_PARAM;
8032 * this is what 2k returns when you try to delete the "PrinterDriverData"
8033 * key
8036 return WERR_ACCESS_DENIED;
8040 /********************************************************************
8041 * spoolss_enumprinterdataex
8042 ********************************************************************/
8044 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8046 POLICY_HND *handle = &q_u->handle;
8047 uint32 in_size = q_u->size;
8048 uint32 num_entries,
8049 needed;
8050 NT_PRINTER_INFO_LEVEL *printer = NULL;
8051 PRINTER_ENUM_VALUES *enum_values = NULL;
8052 NT_PRINTER_DATA *p_data;
8053 fstring key;
8054 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8055 int snum;
8056 WERROR result;
8057 int key_index;
8058 int i;
8059 REGISTRY_VALUE *val;
8060 char *value_name;
8061 int data_len;
8064 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8066 if (!Printer) {
8067 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8068 return WERR_BADFID;
8072 /* first get the printer off of disk */
8074 if (!get_printer_snum(p,handle, &snum))
8075 return WERR_BADFID;
8077 ZERO_STRUCT(printer);
8078 result = get_a_printer(&printer, 2, lp_servicename(snum));
8079 if (!W_ERROR_IS_OK(result))
8080 return result;
8082 /* now look for a match on the key name */
8084 p_data = &printer->info_2->data;
8086 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8087 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8089 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8090 result = WERR_INVALID_PARAM;
8091 goto done;
8094 result = WERR_OK;
8095 needed = 0;
8097 /* allocate the memory for the array of pointers -- if necessary */
8099 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8100 if ( num_entries )
8102 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8104 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8105 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8106 result = WERR_NOMEM;
8107 goto done;
8110 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8114 * loop through all params and build the array to pass
8115 * back to the client
8118 for ( i=0; i<num_entries; i++ )
8120 /* lookup the registry value */
8122 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8123 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8125 /* copy the data */
8127 value_name = regval_name( val );
8128 init_unistr( &enum_values[i].valuename, value_name );
8129 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8130 enum_values[i].type = regval_type( val );
8132 data_len = regval_size( val );
8133 if ( data_len ) {
8134 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8136 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8137 data_len ));
8138 result = WERR_NOMEM;
8139 goto done;
8142 enum_values[i].data_len = data_len;
8144 /* keep track of the size of the array in bytes */
8146 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8149 /* housekeeping information in the reply */
8151 r_u->needed = needed;
8152 r_u->returned = num_entries;
8154 if (needed > in_size) {
8155 result = WERR_MORE_DATA;
8156 goto done;
8159 /* copy data into the reply */
8161 r_u->ctr.size = r_u->needed;
8162 r_u->ctr.size_of_array = r_u->returned;
8163 r_u->ctr.values = enum_values;
8167 done:
8168 free_a_printer(&printer, 2);
8170 return result;
8173 /****************************************************************************
8174 ****************************************************************************/
8176 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8178 init_unistr(&info->name, name);
8181 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8182 UNISTR2 *environment,
8183 NEW_BUFFER *buffer,
8184 uint32 offered,
8185 uint32 *needed)
8187 pstring path;
8188 pstring long_archi;
8189 pstring short_archi;
8190 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8192 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8194 if (get_short_archi(short_archi, long_archi)==False)
8195 return WERR_INVALID_ENVIRONMENT;
8197 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8198 return WERR_NOMEM;
8200 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8202 fill_printprocessordirectory_1(info, path);
8204 *needed += spoolss_size_printprocessordirectory_info_1(info);
8206 if (!alloc_buffer_size(buffer, *needed)) {
8207 safe_free(info);
8208 return WERR_INSUFFICIENT_BUFFER;
8211 smb_io_printprocessordirectory_1("", buffer, info, 0);
8213 safe_free(info);
8215 if (*needed > offered)
8216 return WERR_INSUFFICIENT_BUFFER;
8217 else
8218 return WERR_OK;
8221 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8223 uint32 level = q_u->level;
8224 NEW_BUFFER *buffer = NULL;
8225 uint32 offered = q_u->offered;
8226 uint32 *needed = &r_u->needed;
8227 WERROR result;
8229 /* that's an [in out] buffer */
8230 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8231 buffer = r_u->buffer;
8233 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8235 *needed=0;
8237 switch(level) {
8238 case 1:
8239 result = getprintprocessordirectory_level_1
8240 (&q_u->name, &q_u->environment, buffer, offered, needed);
8241 default:
8242 result = WERR_UNKNOWN_LEVEL;
8245 return result;
8248 #if 0
8250 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8251 SPOOL_R_REPLYOPENPRINTER *r_u)
8253 DEBUG(5,("_spoolss_replyopenprinter\n"));
8255 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8257 return WERR_OK;
8260 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8261 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8263 DEBUG(5,("_spoolss_replycloseprinter\n"));
8264 return WERR_OK;
8267 #endif