added parsing routines for SPOOLSS_ADDPRINTERDRIVEREX and
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobd66c023ba69021e9e9a20311dcccef0a4befc627
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001,
8 * Copyright (C) Gerald Carter 2000-2001,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 #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 int 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 cli;
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(&cli, 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(&cli);
196 cli_ulogoff(&cli);
197 cli_shutdown(&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", NULL },
672 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", NULL },
673 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", NULL },
674 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", NULL },
675 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", NULL },
676 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", NULL },
677 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", NULL },
678 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
679 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", NULL },
680 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", NULL },
681 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
682 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", NULL },
683 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
684 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", NULL },
685 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", NULL },
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 for (p = printers_list; p; p = p->next) {
730 SPOOL_NOTIFY_INFO_DATA *data;
731 uint32 data_len = 1;
732 uint32 id;
734 /* Is there notification on this handle? */
736 if (!p->notify.client_connected)
737 continue;
739 /* For this printer? Print servers always receive
740 notifications. */
742 if (p->printer_type == PRINTER_HANDLE_IS_PRINTER &&
743 !strequal(msg->printer, p->dev.handlename))
744 continue;
746 /* Are we monitoring this event? */
748 if (!is_monitoring_event(p, msg->type, msg->field))
749 continue;
751 /* OK - send the event to the client */
753 data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA));
755 ZERO_STRUCTP(data);
757 /* Convert unix jobid to smb jobid */
759 id = msg->id;
761 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
763 id = sysjob_to_jobid(msg->id);
765 if (id == -1) {
766 DEBUG(3, ("no such unix jobid %d\n", msg->id));
767 goto done;
771 construct_info_data(data, msg->type, msg->field, id);
773 switch(msg->type) {
774 case PRINTER_NOTIFY_TYPE:
775 if (printer_notify_table[msg->field].fn)
776 printer_notify_table[msg->field].fn(
777 msg, data, mem_ctx);
778 else
779 goto done;
780 break;
781 case JOB_NOTIFY_TYPE:
782 if (job_notify_table[msg->field].fn)
783 job_notify_table[msg->field].fn(
784 msg, data, mem_ctx);
785 else
786 goto done;
787 break;
788 default:
789 DEBUG(5, ("Unknown notification type %d\n",
790 msg->type));
791 goto done;
794 if (!p->notify.flags)
795 cli_spoolss_rrpcn(
796 &cli, mem_ctx, &p->notify.client_hnd,
797 data_len, data, p->notify.change, 0);
798 else {
799 NT_PRINTER_INFO_LEVEL *printer = NULL;
801 get_a_printer(&printer, 2, msg->printer);
803 if (!printer) {
804 DEBUG(5, ("unable to load info2 for %s\n",
805 msg->printer));
806 goto done;
809 /* XXX: This needs to be updated for
810 PRINTER_CHANGE_SET_PRINTER_DRIVER. */
812 cli_spoolss_routerreplyprinter(
813 &cli, mem_ctx, &p->notify.client_hnd,
814 0, printer->info_2->changeid);
816 free_a_printer(&printer, 2);
819 done:
820 return;
823 /* Receive a notify2 message */
825 static void receive_notify2_message(int msg_type, pid_t src, void *buf,
826 size_t len)
828 struct spoolss_notify_msg msg;
829 int offset = 0;
830 TALLOC_CTX *mem_ctx = talloc_init();
832 /* Unpack message */
834 ZERO_STRUCT(msg);
836 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
837 msg.printer);
839 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
840 &msg.type, &msg.field, &msg.id, &msg.len, &msg.flags);
842 if (msg.len == 0)
843 tdb_unpack((char *)buf + offset, len - offset, "dd",
844 &msg.notify.value[0], &msg.notify.value[1]);
845 else
846 tdb_unpack((char *)buf + offset, len - offset, "B",
847 &msg.len, &msg.notify.data);
849 DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
850 msg.type, msg.field, msg.flags));
852 if (msg.len == 0)
853 DEBUG(3, ("value1 = %d, value2 = %d\n", msg.notify.value[0],
854 msg.notify.value[1]));
855 else
856 dump_data(3, msg.notify.data, msg.len);
858 /* Process message */
860 process_notify2_message(&msg, mem_ctx);
862 /* Free message */
864 if (msg.len > 0)
865 free(msg.notify.data);
867 talloc_destroy(mem_ctx);
870 /***************************************************************************
871 Server wrapper for cli_spoolss_routerreplyprinter() since the client
872 function can only send a single change notification at a time.
874 FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
875 --jerry
876 **************************************************************************/
878 static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
879 POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
880 NT_PRINTER_INFO_LEVEL *printer)
882 WERROR result;
883 uint32 condition = 0x0;
885 if (info->flags & PRINTER_MESSAGE_DRIVER)
886 condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
888 result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
889 printer->info_2->changeid);
891 return result;
894 /********************************************************************
895 Send a message to ourself about new driver being installed
896 so we can upgrade the information for each printer bound to this
897 driver
898 ********************************************************************/
900 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
902 int len = strlen(drivername);
904 if (!len)
905 return False;
907 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
908 drivername));
910 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
912 return True;
915 /**********************************************************************
916 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
917 over all printers, upgrading ones as neessary
918 **********************************************************************/
920 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
922 fstring drivername;
923 int snum;
924 int n_services = lp_numservices();
926 len = MIN(len,sizeof(drivername)-1);
927 strncpy(drivername, buf, len);
929 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
931 /* Iterate the printer list */
933 for (snum=0; snum<n_services; snum++)
935 if (lp_snum_ok(snum) && lp_print_ok(snum) )
937 WERROR result;
938 NT_PRINTER_INFO_LEVEL *printer = NULL;
940 result = get_a_printer(&printer, 2, lp_servicename(snum));
941 if (!W_ERROR_IS_OK(result))
942 continue;
944 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
946 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
948 /* all we care about currently is the change_id */
950 result = mod_a_printer(*printer, 2);
951 if (!W_ERROR_IS_OK(result)) {
952 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
953 dos_errstr(result)));
957 free_a_printer(&printer, 2);
961 /* all done */
964 /********************************************************************
965 Copy routines used by convert_to_openprinterex()
966 *******************************************************************/
968 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
970 DEVICEMODE *d;
971 int len;
973 if (!devmode)
974 return NULL;
976 DEBUG (8,("dup_devmode\n"));
978 /* bulk copy first */
980 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
981 if (!d)
982 return NULL;
984 /* dup the pointer members separately */
986 len = unistrlen(devmode->devicename.buffer);
987 if (len != -1) {
988 d->devicename.buffer = talloc(ctx, len*2);
989 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
990 return NULL;
994 len = unistrlen(devmode->formname.buffer);
995 if (len != -1) {
996 d->devicename.buffer = talloc(ctx, len*2);
997 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
998 return NULL;
1001 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1003 return d;
1006 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1008 if (!new_ctr || !ctr)
1009 return;
1011 DEBUG(8,("copy_devmode_ctr\n"));
1013 new_ctr->size = ctr->size;
1014 new_ctr->devmode_ptr = ctr->devmode_ptr;
1016 if(ctr->devmode_ptr)
1017 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1020 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1022 if (!new_def || !def)
1023 return;
1025 DEBUG(8,("copy_printer_defaults\n"));
1027 new_def->datatype_ptr = def->datatype_ptr;
1029 if (def->datatype_ptr)
1030 copy_unistr2(&new_def->datatype, &def->datatype);
1032 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1034 new_def->access_required = def->access_required;
1037 /********************************************************************
1038 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1039 * SPOOL_Q_OPEN_PRINTER_EX structure
1040 ********************************************************************/
1042 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1044 if (!q_u_ex || !q_u)
1045 return;
1047 DEBUG(8,("convert_to_openprinterex\n"));
1049 q_u_ex->printername_ptr = q_u->printername_ptr;
1051 if (q_u->printername_ptr)
1052 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1054 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1057 /********************************************************************
1058 * spoolss_open_printer
1060 * called from the spoolss dispatcher
1061 ********************************************************************/
1063 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1065 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1066 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1068 if (!q_u || !r_u)
1069 return WERR_NOMEM;
1071 ZERO_STRUCT(q_u_ex);
1072 ZERO_STRUCT(r_u_ex);
1074 /* convert the OpenPrinter() call to OpenPrinterEx() */
1076 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1078 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1080 /* convert back to OpenPrinter() */
1082 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1084 return r_u->status;
1087 /********************************************************************
1088 * spoolss_open_printer
1090 * called from the spoolss dispatcher
1091 ********************************************************************/
1093 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1095 UNISTR2 *printername = NULL;
1096 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1097 /* uint32 user_switch = q_u->user_switch; - notused */
1098 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
1099 POLICY_HND *handle = &r_u->handle;
1101 fstring name;
1102 int snum;
1103 struct current_user user;
1104 Printer_entry *Printer=NULL;
1106 if (q_u->printername_ptr != 0)
1107 printername = &q_u->printername;
1109 if (printername == NULL)
1110 return WERR_INVALID_PRINTER_NAME;
1112 /* some sanity check because you can open a printer or a print server */
1113 /* aka: \\server\printer or \\server */
1114 unistr2_to_ascii(name, printername, sizeof(name)-1);
1116 DEBUGADD(3,("checking name: %s\n",name));
1118 if (!open_printer_hnd(p, handle, name, 0))
1119 return WERR_INVALID_PRINTER_NAME;
1121 Printer=find_printer_index_by_hnd(p, handle);
1122 if (!Printer) {
1123 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1124 Can't find printer handle we created for printer %s\n", name ));
1125 close_printer_handle(p,handle);
1126 return WERR_INVALID_PRINTER_NAME;
1130 First case: the user is opening the print server:
1132 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1133 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1135 Then both Win2k and WinNT clients try an OpenPrinterEx with
1136 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1137 or if the user is listed in the smb.conf printer admin parameter.
1139 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1140 client view printer folder, but does not show the MSAPW.
1142 Note: this test needs code to check access rights here too. Jeremy
1143 could you look at this?
1146 Second case: the user is opening a printer:
1147 NT doesn't let us connect to a printer if the connecting user
1148 doesn't have print permission.
1152 get_current_user(&user, p);
1154 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
1156 /* Printserver handles use global struct... */
1158 snum = -1;
1160 /* Map standard access rights to object specific access
1161 rights */
1163 se_map_standard(&printer_default->access_required,
1164 &printserver_std_mapping);
1166 /* Deny any object specific bits that don't apply to print
1167 servers (i.e printer and job specific bits) */
1169 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1171 if (printer_default->access_required &
1172 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1173 DEBUG(3, ("access DENIED for non-printserver bits"));
1174 close_printer_handle(p, handle);
1175 return WERR_ACCESS_DENIED;
1178 /* Allow admin access */
1180 if (printer_default->access_required &
1181 SERVER_ACCESS_ADMINISTER) {
1183 if (!lp_ms_add_printer_wizard()) {
1184 close_printer_handle(p, handle);
1185 return WERR_ACCESS_DENIED;
1188 if (user.uid == 0 ||
1189 user_in_list(uidtoname(user.uid),
1190 lp_printer_admin(snum)))
1191 return WERR_OK;
1193 close_printer_handle(p, handle);
1194 return WERR_ACCESS_DENIED;
1197 /* We fall through to return WERR_OK */
1200 else
1202 /* NT doesn't let us connect to a printer if the connecting user
1203 doesn't have print permission. */
1205 if (!get_printer_snum(p, handle, &snum))
1206 return WERR_BADFID;
1208 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1210 /* map an empty access mask to the minimum access mask */
1211 if (printer_default->access_required == 0x0)
1212 printer_default->access_required = PRINTER_ACCESS_USE;
1215 * If we are not serving the printer driver for this printer,
1216 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1217 * will keep NT clients happy --jerry
1220 if (lp_use_client_driver(snum)
1221 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1223 printer_default->access_required = PRINTER_ACCESS_USE;
1226 /* check smb.conf parameters and the the sec_desc */
1228 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1229 DEBUG(3, ("access DENIED for printer open\n"));
1230 close_printer_handle(p, handle);
1231 return WERR_ACCESS_DENIED;
1234 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1235 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1236 close_printer_handle(p, handle);
1237 return WERR_ACCESS_DENIED;
1240 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1241 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1242 else
1243 printer_default->access_required = PRINTER_ACCESS_USE;
1245 DEBUG(4,("Setting printer access=%x\n", printer_default->access_required));
1246 Printer->access_granted = printer_default->access_required;
1249 * If we have a default device pointer in the
1250 * printer_default struct, then we need to get
1251 * the printer info from the tdb and if there is
1252 * no default devicemode there then we do a *SET*
1253 * here ! This is insanity.... JRA.
1257 * If the openprinterex rpc call contains a devmode,
1258 * it's a per-user one. This per-user devmode is derivated
1259 * from the global devmode. Openprinterex() contains a per-user
1260 * devmode for when you do EMF printing and spooling.
1261 * In the EMF case, the NT workstation is only doing half the job
1262 * of rendering the page. The other half is done by running the printer
1263 * driver on the server.
1264 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1265 * The EMF file only contains what is to be printed on the page.
1266 * So in order for the server to know how to print, the NT client sends
1267 * a devicemode attached to the openprinterex call.
1268 * But this devicemode is short lived, it's only valid for the current print job.
1270 * If Samba would have supported EMF spooling, this devicemode would
1271 * have been attached to the handle, to sent it to the driver to correctly
1272 * rasterize the EMF file.
1274 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1275 * we just act as a pass-thru between windows and the printer.
1277 * In order to know that Samba supports only RAW spooling, NT has to call
1278 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1279 * and until NT sends a RAW job, we refuse it.
1281 * But to call getprinter() or startdoc(), you first need a valid handle,
1282 * and to get an handle you have to call openprintex(). Hence why you have
1283 * a devicemode in the openprinterex() call.
1286 * Differences between NT4 and NT 2000.
1287 * NT4:
1288 * ---
1289 * On NT4, you only have a global devicemode. This global devicemode can be changed
1290 * by the administrator (or by a user with enough privs). Everytime a user
1291 * wants to print, the devicemode is resetted to the default. In Word, everytime
1292 * you print, the printer's characteristics are always reset to the global devicemode.
1294 * NT 2000:
1295 * -------
1296 * In W2K, there is the notion of per-user devicemode. The first time you use
1297 * a printer, a per-user devicemode is build from the global devicemode.
1298 * If you change your per-user devicemode, it is saved in the registry, under the
1299 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1300 * printer preferences available.
1302 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1303 * on the General Tab of the printer properties windows.
1305 * To change the global devicemode: it's the "Printing Defaults..." button
1306 * on the Advanced Tab of the printer properties window.
1308 * JFM.
1313 #if 0
1314 if (printer_default->devmode_cont.devmode != NULL) {
1315 result = printer_write_default_dev( snum, printer_default);
1316 if (result != 0) {
1317 close_printer_handle(p, handle);
1318 return result;
1321 #endif
1324 return WERR_OK;
1327 /****************************************************************************
1328 ****************************************************************************/
1330 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1331 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1333 BOOL ret = True;
1335 switch (level) {
1336 case 2:
1337 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1338 break;
1339 default:
1340 break;
1343 return ret;
1346 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1347 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1349 BOOL result = True;
1351 switch (level) {
1352 case 3:
1353 printer->info_3=NULL;
1354 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1355 result = False;
1356 break;
1357 case 6:
1358 printer->info_6=NULL;
1359 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1360 result = False;
1361 break;
1362 default:
1363 break;
1366 return result;
1369 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1370 NT_DEVICEMODE **pp_nt_devmode)
1372 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1375 * Ensure nt_devmode is a valid pointer
1376 * as we will be overwriting it.
1379 if (nt_devmode == NULL) {
1380 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1381 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1382 return False;
1385 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1386 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1388 nt_devmode->specversion=devmode->specversion;
1389 nt_devmode->driverversion=devmode->driverversion;
1390 nt_devmode->size=devmode->size;
1391 nt_devmode->fields=devmode->fields;
1392 nt_devmode->orientation=devmode->orientation;
1393 nt_devmode->papersize=devmode->papersize;
1394 nt_devmode->paperlength=devmode->paperlength;
1395 nt_devmode->paperwidth=devmode->paperwidth;
1396 nt_devmode->scale=devmode->scale;
1397 nt_devmode->copies=devmode->copies;
1398 nt_devmode->defaultsource=devmode->defaultsource;
1399 nt_devmode->printquality=devmode->printquality;
1400 nt_devmode->color=devmode->color;
1401 nt_devmode->duplex=devmode->duplex;
1402 nt_devmode->yresolution=devmode->yresolution;
1403 nt_devmode->ttoption=devmode->ttoption;
1404 nt_devmode->collate=devmode->collate;
1406 nt_devmode->logpixels=devmode->logpixels;
1407 nt_devmode->bitsperpel=devmode->bitsperpel;
1408 nt_devmode->pelswidth=devmode->pelswidth;
1409 nt_devmode->pelsheight=devmode->pelsheight;
1410 nt_devmode->displayflags=devmode->displayflags;
1411 nt_devmode->displayfrequency=devmode->displayfrequency;
1412 nt_devmode->icmmethod=devmode->icmmethod;
1413 nt_devmode->icmintent=devmode->icmintent;
1414 nt_devmode->mediatype=devmode->mediatype;
1415 nt_devmode->dithertype=devmode->dithertype;
1416 nt_devmode->reserved1=devmode->reserved1;
1417 nt_devmode->reserved2=devmode->reserved2;
1418 nt_devmode->panningwidth=devmode->panningwidth;
1419 nt_devmode->panningheight=devmode->panningheight;
1422 * Only change private and driverextra if the incoming devmode
1423 * has a new one. JRA.
1426 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1427 SAFE_FREE(nt_devmode->private);
1428 nt_devmode->driverextra=devmode->driverextra;
1429 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1430 return False;
1431 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1434 *pp_nt_devmode = nt_devmode;
1436 return True;
1439 /********************************************************************
1440 * _spoolss_enddocprinter_internal.
1441 ********************************************************************/
1443 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1445 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1447 if (!Printer) {
1448 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1449 return WERR_BADFID;
1452 Printer->document_started=False;
1453 print_job_end(Printer->jobid,True);
1454 /* error codes unhandled so far ... */
1456 return WERR_OK;
1459 /********************************************************************
1460 * api_spoolss_closeprinter
1461 ********************************************************************/
1463 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1465 POLICY_HND *handle = &q_u->handle;
1467 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1469 if (Printer && Printer->document_started)
1470 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1472 if (!close_printer_handle(p, handle))
1473 return WERR_BADFID;
1475 /* clear the returned printer handle. Observed behavior
1476 from Win2k server. Don't think this really matters.
1477 Previous code just copied the value of the closed
1478 handle. --jerry */
1480 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1482 return WERR_OK;
1485 /********************************************************************
1486 * api_spoolss_deleteprinter
1488 ********************************************************************/
1490 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1492 POLICY_HND *handle = &q_u->handle;
1493 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1494 WERROR result;
1496 if (Printer && Printer->document_started)
1497 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1499 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1501 result = delete_printer_handle(p, handle);
1503 update_c_setprinter(False);
1505 return result;
1508 /*******************************************************************
1509 * static function to lookup the version id corresponding to an
1510 * long architecture string
1511 ******************************************************************/
1513 static int get_version_id (char * arch)
1515 int i;
1516 struct table_node archi_table[]= {
1518 {"Windows 4.0", "WIN40", 0 },
1519 {"Windows NT x86", "W32X86", 2 },
1520 {"Windows NT R4000", "W32MIPS", 2 },
1521 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1522 {"Windows NT PowerPC", "W32PPC", 2 },
1523 {NULL, "", -1 }
1526 for (i=0; archi_table[i].long_archi != NULL; i++)
1528 if (strcmp(arch, archi_table[i].long_archi) == 0)
1529 return (archi_table[i].version);
1532 return -1;
1535 /********************************************************************
1536 * _spoolss_deleteprinterdriver
1538 * We currently delete the driver for the architecture only.
1539 * This can leave the driver for other archtectures. However,
1540 * since every printer associates a "Windows NT x86" driver name
1541 * and we cannot delete that one while it is in use, **and** since
1542 * it is impossible to assign a driver to a Samba printer without
1543 * having the "Windows NT x86" driver installed,...
1545 * ....we should not get into trouble here.
1547 * --jerry
1548 ********************************************************************/
1550 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1552 fstring driver;
1553 fstring arch;
1554 NT_PRINTER_DRIVER_INFO_LEVEL info;
1555 int version;
1557 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1558 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1560 /* check that we have a valid driver name first */
1561 if ((version=get_version_id(arch)) == -1) {
1562 /* this is what NT returns */
1563 return WERR_INVALID_ENVIRONMENT;
1566 ZERO_STRUCT(info);
1567 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1568 return WERR_UNKNOWN_PRINTER_DRIVER;
1571 if (printer_driver_in_use(arch, driver))
1572 return WERR_PRINTER_DRIVER_IN_USE;
1574 return delete_printer_driver(info.info_3);
1577 /********************************************************************
1578 * spoolss_deleteprinterdriverex
1579 ********************************************************************/
1581 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1583 fstring driver;
1584 fstring arch;
1585 NT_PRINTER_DRIVER_INFO_LEVEL info;
1586 int version;
1588 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1589 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1591 /* check that we have a valid driver name first */
1592 if ((version=get_version_id(arch)) == -1) {
1593 /* this is what NT returns */
1594 return WERR_INVALID_ENVIRONMENT;
1597 if (q_u->delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1598 version = q_u->version;
1600 ZERO_STRUCT(info);
1601 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1602 return WERR_UNKNOWN_PRINTER_DRIVER;
1605 if (printer_driver_in_use(arch, driver))
1606 return WERR_PRINTER_DRIVER_IN_USE;
1608 return delete_printer_driver(info.info_3);
1612 /********************************************************************
1613 GetPrinterData on a printer server Handle.
1614 ********************************************************************/
1616 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1618 int i;
1620 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1622 if (!strcmp(value, "W3SvcInstalled")) {
1623 *type = 0x4;
1624 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1625 return False;
1626 *needed = 0x4;
1627 return True;
1630 if (!strcmp(value, "BeepEnabled")) {
1631 *type = 0x4;
1632 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1633 return False;
1634 SIVAL(*data, 0, 0x00);
1635 *needed = 0x4;
1636 return True;
1639 if (!strcmp(value, "EventLog")) {
1640 *type = 0x4;
1641 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1642 return False;
1643 /* formally was 0x1b */
1644 SIVAL(*data, 0, 0x0);
1645 *needed = 0x4;
1646 return True;
1649 if (!strcmp(value, "NetPopup")) {
1650 *type = 0x4;
1651 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1652 return False;
1653 SIVAL(*data, 0, 0x00);
1654 *needed = 0x4;
1655 return True;
1658 if (!strcmp(value, "MajorVersion")) {
1659 *type = 0x4;
1660 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1661 return False;
1662 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1663 SIVAL(*data, 0, 2);
1664 #else
1665 SIVAL(*data, 0, 3);
1666 #endif
1667 *needed = 0x4;
1668 return True;
1671 if (!strcmp(value, "DefaultSpoolDirectory")) {
1672 fstring string;
1674 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1675 *type = 0x1;
1676 *needed = 2*(strlen(string)+1);
1677 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1678 return False;
1679 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1681 /* it's done by hand ready to go on the wire */
1682 for (i=0; i<strlen(string); i++) {
1683 (*data)[2*i]=string[i];
1684 (*data)[2*i+1]='\0';
1686 return True;
1689 if (!strcmp(value, "Architecture")) {
1690 pstring string="Windows NT x86";
1691 *type = 0x1;
1692 *needed = 2*(strlen(string)+1);
1693 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1694 return False;
1695 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1696 for (i=0; i<strlen(string); i++) {
1697 (*data)[2*i]=string[i];
1698 (*data)[2*i+1]='\0';
1700 return True;
1703 return False;
1706 /********************************************************************
1707 GetPrinterData on a printer Handle.
1708 ********************************************************************/
1710 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1711 fstring value, uint32 *type,
1712 uint8 **data, uint32 *needed, uint32 in_size )
1714 NT_PRINTER_INFO_LEVEL *printer = NULL;
1715 int snum=0;
1716 uint8 *idata=NULL;
1717 uint32 len;
1718 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1720 DEBUG(5,("getprinterdata_printer\n"));
1722 if (!Printer) {
1723 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1724 return False;
1727 if(!get_printer_snum(p, handle, &snum))
1728 return False;
1730 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1731 return False;
1733 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1734 free_a_printer(&printer, 2);
1735 return False;
1738 free_a_printer(&printer, 2);
1740 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1742 if (in_size) {
1743 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1744 return False;
1747 memset(*data, 0, in_size *sizeof(uint8));
1748 /* copy the min(in_size, len) */
1749 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1750 } else {
1751 *data = NULL;
1754 *needed = len;
1756 DEBUG(5,("getprinterdata_printer:copy done\n"));
1758 SAFE_FREE(idata);
1760 return True;
1763 /********************************************************************
1764 * spoolss_getprinterdata
1765 ********************************************************************/
1767 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1769 POLICY_HND *handle = &q_u->handle;
1770 UNISTR2 *valuename = &q_u->valuename;
1771 uint32 in_size = q_u->size;
1772 uint32 *type = &r_u->type;
1773 uint32 *out_size = &r_u->size;
1774 uint8 **data = &r_u->data;
1775 uint32 *needed = &r_u->needed;
1777 fstring value;
1778 BOOL found=False;
1779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1782 * Reminder: when it's a string, the length is in BYTES
1783 * even if UNICODE is negociated.
1785 * JFM, 4/19/1999
1788 *out_size=in_size;
1790 /* in case of problem, return some default values */
1791 *needed=0;
1792 *type=0;
1794 DEBUG(4,("_spoolss_getprinterdata\n"));
1796 if (!Printer) {
1797 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1798 return WERR_NOMEM;
1799 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1800 return WERR_BADFID;
1803 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1805 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1806 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1807 else
1808 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1810 if (found==False) {
1811 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1812 /* reply this param doesn't exist */
1813 if (*out_size) {
1814 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1815 return WERR_NOMEM;
1816 } else {
1817 *data = NULL;
1820 /* error depends on handle type */
1822 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1823 return WERR_INVALID_PARAM;
1824 else
1825 return WERR_BADFILE;
1828 if (*needed > *out_size)
1829 return WERR_MORE_DATA;
1830 else
1831 return WERR_OK;
1834 /*********************************************************
1835 Connect to the client machine.
1836 **********************************************************/
1838 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
1840 extern pstring global_myname;
1842 ZERO_STRUCTP(the_cli);
1843 if(cli_initialise(the_cli) == NULL) {
1844 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
1845 return False;
1848 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
1849 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
1850 cli_shutdown(the_cli);
1851 return False;
1854 if (ismyip(the_cli->dest_ip)) {
1855 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
1856 cli_shutdown(the_cli);
1857 return False;
1860 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
1861 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1862 cli_shutdown(the_cli);
1863 return False;
1866 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
1867 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
1868 remote_machine));
1869 return False;
1872 the_cli->protocol = PROTOCOL_NT1;
1874 if (!cli_negprot(the_cli)) {
1875 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1876 cli_shutdown(the_cli);
1877 return False;
1880 if (the_cli->protocol != PROTOCOL_NT1) {
1881 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
1882 cli_shutdown(the_cli);
1883 return False;
1887 * Do an anonymous session setup.
1890 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
1891 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1892 cli_shutdown(the_cli);
1893 return False;
1896 if (!(the_cli->sec_mode & 1)) {
1897 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
1898 cli_shutdown(the_cli);
1899 return False;
1902 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
1903 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1904 cli_shutdown(the_cli);
1905 return False;
1909 * Ok - we have an anonymous connection to the IPC$ share.
1910 * Now start the NT Domain stuff :-).
1913 if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
1914 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)));
1915 cli_nt_session_close(the_cli);
1916 cli_ulogoff(the_cli);
1917 cli_shutdown(the_cli);
1918 return False;
1921 return True;
1924 /***************************************************************************
1925 Connect to the client.
1926 ****************************************************************************/
1928 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1930 WERROR result;
1933 * If it's the first connection, contact the client
1934 * and connect to the IPC$ share anonumously
1936 if (smb_connections==0) {
1937 fstring unix_printer;
1939 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1941 if(!spoolss_connect_to_client(&cli, unix_printer))
1942 return False;
1944 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
1947 smb_connections++;
1949 result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
1950 type, handle);
1952 if (!W_ERROR_IS_OK(result))
1953 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1954 dos_errstr(result)));
1956 return (W_ERROR_IS_OK(result));
1959 /********************************************************************
1960 * _spoolss_rffpcnex
1961 * ReplyFindFirstPrinterChangeNotifyEx
1963 * before replying OK: status=0 a rpc call is made to the workstation
1964 * asking ReplyOpenPrinter
1966 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1967 * called from api_spoolss_rffpcnex
1968 ********************************************************************/
1970 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1972 POLICY_HND *handle = &q_u->handle;
1973 uint32 flags = q_u->flags;
1974 uint32 options = q_u->options;
1975 UNISTR2 *localmachine = &q_u->localmachine;
1976 uint32 printerlocal = q_u->printerlocal;
1977 SPOOL_NOTIFY_OPTION *option = q_u->option;
1979 /* store the notify value in the printer struct */
1981 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1983 if (!Printer) {
1984 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1985 return WERR_BADFID;
1988 Printer->notify.flags=flags;
1989 Printer->notify.options=options;
1990 Printer->notify.printerlocal=printerlocal;
1992 if (Printer->notify.option)
1993 free_spool_notify_option(&Printer->notify.option);
1995 Printer->notify.option=dup_spool_notify_option(option);
1997 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
1998 sizeof(Printer->notify.localmachine)-1);
2000 /* Connect to the client machine and send a ReplyOpenPrinter */
2002 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
2003 Printer->notify.printerlocal, 1,
2004 &Printer->notify.client_hnd))
2005 return WERR_SERVER_UNAVAILABLE;
2007 Printer->notify.client_connected=True;
2009 return WERR_OK;
2012 /*******************************************************************
2013 * fill a notify_info_data with the servername
2014 ********************************************************************/
2016 void spoolss_notify_server_name(int snum,
2017 SPOOL_NOTIFY_INFO_DATA *data,
2018 print_queue_struct *queue,
2019 NT_PRINTER_INFO_LEVEL *printer,
2020 TALLOC_CTX *mem_ctx)
2022 pstring temp_name, temp;
2023 uint32 len;
2025 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2027 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2029 data->notify_data.data.length = len;
2030 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2032 if (!data->notify_data.data.string) {
2033 data->notify_data.data.length = 0;
2034 return;
2037 memcpy(data->notify_data.data.string, temp, len);
2040 /*******************************************************************
2041 * fill a notify_info_data with the printername (not including the servername).
2042 ********************************************************************/
2044 void spoolss_notify_printer_name(int snum,
2045 SPOOL_NOTIFY_INFO_DATA *data,
2046 print_queue_struct *queue,
2047 NT_PRINTER_INFO_LEVEL *printer,
2048 TALLOC_CTX *mem_ctx)
2050 pstring temp;
2051 uint32 len;
2053 /* the notify name should not contain the \\server\ part */
2054 char *p = strrchr(printer->info_2->printername, '\\');
2056 if (!p) {
2057 p = printer->info_2->printername;
2058 } else {
2059 p++;
2062 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2064 data->notify_data.data.length = len;
2065 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2067 if (!data->notify_data.data.string) {
2068 data->notify_data.data.length = 0;
2069 return;
2072 memcpy(data->notify_data.data.string, temp, len);
2075 /*******************************************************************
2076 * fill a notify_info_data with the servicename
2077 ********************************************************************/
2079 void spoolss_notify_share_name(int snum,
2080 SPOOL_NOTIFY_INFO_DATA *data,
2081 print_queue_struct *queue,
2082 NT_PRINTER_INFO_LEVEL *printer,
2083 TALLOC_CTX *mem_ctx)
2085 pstring temp;
2086 uint32 len;
2088 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2090 data->notify_data.data.length = len;
2091 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2093 if (!data->notify_data.data.string) {
2094 data->notify_data.data.length = 0;
2095 return;
2098 memcpy(data->notify_data.data.string, temp, len);
2101 /*******************************************************************
2102 * fill a notify_info_data with the port name
2103 ********************************************************************/
2105 void spoolss_notify_port_name(int snum,
2106 SPOOL_NOTIFY_INFO_DATA *data,
2107 print_queue_struct *queue,
2108 NT_PRINTER_INFO_LEVEL *printer,
2109 TALLOC_CTX *mem_ctx)
2111 pstring temp;
2112 uint32 len;
2114 /* even if it's strange, that's consistant in all the code */
2116 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2118 data->notify_data.data.length = len;
2119 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2121 if (!data->notify_data.data.string) {
2122 data->notify_data.data.length = 0;
2123 return;
2126 memcpy(data->notify_data.data.string, temp, len);
2129 /*******************************************************************
2130 * fill a notify_info_data with the printername
2131 * but it doesn't exist, have to see what to do
2132 ********************************************************************/
2134 void spoolss_notify_driver_name(int snum,
2135 SPOOL_NOTIFY_INFO_DATA *data,
2136 print_queue_struct *queue,
2137 NT_PRINTER_INFO_LEVEL *printer,
2138 TALLOC_CTX *mem_ctx)
2140 pstring temp;
2141 uint32 len;
2143 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2145 data->notify_data.data.length = len;
2146 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2148 if (!data->notify_data.data.string) {
2149 data->notify_data.data.length = 0;
2150 return;
2153 memcpy(data->notify_data.data.string, temp, len);
2156 /*******************************************************************
2157 * fill a notify_info_data with the comment
2158 ********************************************************************/
2160 void spoolss_notify_comment(int snum,
2161 SPOOL_NOTIFY_INFO_DATA *data,
2162 print_queue_struct *queue,
2163 NT_PRINTER_INFO_LEVEL *printer,
2164 TALLOC_CTX *mem_ctx)
2166 pstring temp;
2167 uint32 len;
2169 if (*printer->info_2->comment == '\0')
2170 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2171 else
2172 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2174 data->notify_data.data.length = len;
2175 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2177 if (!data->notify_data.data.string) {
2178 data->notify_data.data.length = 0;
2179 return;
2182 memcpy(data->notify_data.data.string, temp, len);
2185 /*******************************************************************
2186 * fill a notify_info_data with the comment
2187 * location = "Room 1, floor 2, building 3"
2188 ********************************************************************/
2190 void spoolss_notify_location(int snum,
2191 SPOOL_NOTIFY_INFO_DATA *data,
2192 print_queue_struct *queue,
2193 NT_PRINTER_INFO_LEVEL *printer,
2194 TALLOC_CTX *mem_ctx)
2196 pstring temp;
2197 uint32 len;
2199 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2201 data->notify_data.data.length = len;
2202 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2204 if (!data->notify_data.data.string) {
2205 data->notify_data.data.length = 0;
2206 return;
2209 memcpy(data->notify_data.data.string, temp, len);
2212 /*******************************************************************
2213 * fill a notify_info_data with the device mode
2214 * jfm:xxxx don't to it for know but that's a real problem !!!
2215 ********************************************************************/
2217 static void spoolss_notify_devmode(int snum,
2218 SPOOL_NOTIFY_INFO_DATA *data,
2219 print_queue_struct *queue,
2220 NT_PRINTER_INFO_LEVEL *printer,
2221 TALLOC_CTX *mem_ctx)
2225 /*******************************************************************
2226 * fill a notify_info_data with the separator file name
2227 ********************************************************************/
2229 void spoolss_notify_sepfile(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->sepfile, 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 print processor
2253 * jfm:xxxx return always winprint to indicate we don't do anything to it
2254 ********************************************************************/
2256 void spoolss_notify_print_processor(int snum,
2257 SPOOL_NOTIFY_INFO_DATA *data,
2258 print_queue_struct *queue,
2259 NT_PRINTER_INFO_LEVEL *printer,
2260 TALLOC_CTX *mem_ctx)
2262 pstring temp;
2263 uint32 len;
2265 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2267 data->notify_data.data.length = len;
2268 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2270 if (!data->notify_data.data.string) {
2271 data->notify_data.data.length = 0;
2272 return;
2275 memcpy(data->notify_data.data.string, temp, len);
2278 /*******************************************************************
2279 * fill a notify_info_data with the print processor options
2280 * jfm:xxxx send an empty string
2281 ********************************************************************/
2283 void spoolss_notify_parameters(int snum,
2284 SPOOL_NOTIFY_INFO_DATA *data,
2285 print_queue_struct *queue,
2286 NT_PRINTER_INFO_LEVEL *printer,
2287 TALLOC_CTX *mem_ctx)
2289 pstring temp;
2290 uint32 len;
2292 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2294 data->notify_data.data.length = len;
2295 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2297 if (!data->notify_data.data.string) {
2298 data->notify_data.data.length = 0;
2299 return;
2302 memcpy(data->notify_data.data.string, temp, len);
2305 /*******************************************************************
2306 * fill a notify_info_data with the data type
2307 * jfm:xxxx always send RAW as data type
2308 ********************************************************************/
2310 void spoolss_notify_datatype(int snum,
2311 SPOOL_NOTIFY_INFO_DATA *data,
2312 print_queue_struct *queue,
2313 NT_PRINTER_INFO_LEVEL *printer,
2314 TALLOC_CTX *mem_ctx)
2316 pstring temp;
2317 uint32 len;
2319 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2321 data->notify_data.data.length = len;
2322 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2324 if (!data->notify_data.data.string) {
2325 data->notify_data.data.length = 0;
2326 return;
2329 memcpy(data->notify_data.data.string, temp, len);
2332 /*******************************************************************
2333 * fill a notify_info_data with the security descriptor
2334 * jfm:xxxx send an null pointer to say no security desc
2335 * have to implement security before !
2336 ********************************************************************/
2338 static void spoolss_notify_security_desc(int snum,
2339 SPOOL_NOTIFY_INFO_DATA *data,
2340 print_queue_struct *queue,
2341 NT_PRINTER_INFO_LEVEL *printer,
2342 TALLOC_CTX *mem_ctx)
2344 data->notify_data.data.length=0;
2345 data->notify_data.data.string = NULL;
2348 /*******************************************************************
2349 * fill a notify_info_data with the attributes
2350 * jfm:xxxx a samba printer is always shared
2351 ********************************************************************/
2353 void spoolss_notify_attributes(int snum,
2354 SPOOL_NOTIFY_INFO_DATA *data,
2355 print_queue_struct *queue,
2356 NT_PRINTER_INFO_LEVEL *printer,
2357 TALLOC_CTX *mem_ctx)
2359 data->notify_data.value[0] = printer->info_2->attributes;
2360 data->notify_data.value[1] = 0;
2363 /*******************************************************************
2364 * fill a notify_info_data with the priority
2365 ********************************************************************/
2367 static void spoolss_notify_priority(int snum,
2368 SPOOL_NOTIFY_INFO_DATA *data,
2369 print_queue_struct *queue,
2370 NT_PRINTER_INFO_LEVEL *printer,
2371 TALLOC_CTX *mem_ctx)
2373 data->notify_data.value[0] = printer->info_2->priority;
2374 data->notify_data.value[1] = 0;
2377 /*******************************************************************
2378 * fill a notify_info_data with the default priority
2379 ********************************************************************/
2381 static void spoolss_notify_default_priority(int snum,
2382 SPOOL_NOTIFY_INFO_DATA *data,
2383 print_queue_struct *queue,
2384 NT_PRINTER_INFO_LEVEL *printer,
2385 TALLOC_CTX *mem_ctx)
2387 data->notify_data.value[0] = printer->info_2->default_priority;
2388 data->notify_data.value[1] = 0;
2391 /*******************************************************************
2392 * fill a notify_info_data with the start time
2393 ********************************************************************/
2395 static void spoolss_notify_start_time(int snum,
2396 SPOOL_NOTIFY_INFO_DATA *data,
2397 print_queue_struct *queue,
2398 NT_PRINTER_INFO_LEVEL *printer,
2399 TALLOC_CTX *mem_ctx)
2401 data->notify_data.value[0] = printer->info_2->starttime;
2402 data->notify_data.value[1] = 0;
2405 /*******************************************************************
2406 * fill a notify_info_data with the until time
2407 ********************************************************************/
2409 static void spoolss_notify_until_time(int snum,
2410 SPOOL_NOTIFY_INFO_DATA *data,
2411 print_queue_struct *queue,
2412 NT_PRINTER_INFO_LEVEL *printer,
2413 TALLOC_CTX *mem_ctx)
2415 data->notify_data.value[0] = printer->info_2->untiltime;
2416 data->notify_data.value[1] = 0;
2419 /*******************************************************************
2420 * fill a notify_info_data with the status
2421 ********************************************************************/
2423 static void spoolss_notify_status(int snum,
2424 SPOOL_NOTIFY_INFO_DATA *data,
2425 print_queue_struct *queue,
2426 NT_PRINTER_INFO_LEVEL *printer,
2427 TALLOC_CTX *mem_ctx)
2429 print_status_struct status;
2431 print_queue_length(snum, &status);
2432 data->notify_data.value[0]=(uint32) status.status;
2433 data->notify_data.value[1] = 0;
2436 /*******************************************************************
2437 * fill a notify_info_data with the number of jobs queued
2438 ********************************************************************/
2440 void spoolss_notify_cjobs(int snum,
2441 SPOOL_NOTIFY_INFO_DATA *data,
2442 print_queue_struct *queue,
2443 NT_PRINTER_INFO_LEVEL *printer,
2444 TALLOC_CTX *mem_ctx)
2446 data->notify_data.value[0] = print_queue_length(snum, NULL);
2447 data->notify_data.value[1] = 0;
2450 /*******************************************************************
2451 * fill a notify_info_data with the average ppm
2452 ********************************************************************/
2454 static void spoolss_notify_average_ppm(int snum,
2455 SPOOL_NOTIFY_INFO_DATA *data,
2456 print_queue_struct *queue,
2457 NT_PRINTER_INFO_LEVEL *printer,
2458 TALLOC_CTX *mem_ctx)
2460 /* always respond 8 pages per minutes */
2461 /* a little hard ! */
2462 data->notify_data.value[0] = printer->info_2->averageppm;
2463 data->notify_data.value[1] = 0;
2466 /*******************************************************************
2467 * fill a notify_info_data with username
2468 ********************************************************************/
2470 static void spoolss_notify_username(int snum,
2471 SPOOL_NOTIFY_INFO_DATA *data,
2472 print_queue_struct *queue,
2473 NT_PRINTER_INFO_LEVEL *printer,
2474 TALLOC_CTX *mem_ctx)
2476 pstring temp;
2477 uint32 len;
2479 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2481 data->notify_data.data.length = len;
2482 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2484 if (!data->notify_data.data.string) {
2485 data->notify_data.data.length = 0;
2486 return;
2489 memcpy(data->notify_data.data.string, temp, len);
2492 /*******************************************************************
2493 * fill a notify_info_data with job status
2494 ********************************************************************/
2496 static void spoolss_notify_job_status(int snum,
2497 SPOOL_NOTIFY_INFO_DATA *data,
2498 print_queue_struct *queue,
2499 NT_PRINTER_INFO_LEVEL *printer,
2500 TALLOC_CTX *mem_ctx)
2502 data->notify_data.value[0]=nt_printj_status(queue->status);
2503 data->notify_data.value[1] = 0;
2506 /*******************************************************************
2507 * fill a notify_info_data with job name
2508 ********************************************************************/
2510 static void spoolss_notify_job_name(int snum,
2511 SPOOL_NOTIFY_INFO_DATA *data,
2512 print_queue_struct *queue,
2513 NT_PRINTER_INFO_LEVEL *printer,
2514 TALLOC_CTX *mem_ctx)
2516 pstring temp;
2517 uint32 len;
2519 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2521 data->notify_data.data.length = len;
2522 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2524 if (!data->notify_data.data.string) {
2525 data->notify_data.data.length = 0;
2526 return;
2529 memcpy(data->notify_data.data.string, temp, len);
2532 /*******************************************************************
2533 * fill a notify_info_data with job status
2534 ********************************************************************/
2536 static void spoolss_notify_job_status_string(int snum,
2537 SPOOL_NOTIFY_INFO_DATA *data,
2538 print_queue_struct *queue,
2539 NT_PRINTER_INFO_LEVEL *printer,
2540 TALLOC_CTX *mem_ctx)
2543 * Now we're returning job status codes we just return a "" here. JRA.
2546 char *p = "";
2547 pstring temp;
2548 uint32 len;
2550 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2551 p = "unknown";
2553 switch (queue->status) {
2554 case LPQ_QUEUED:
2555 p = "Queued";
2556 break;
2557 case LPQ_PAUSED:
2558 p = ""; /* NT provides the paused string */
2559 break;
2560 case LPQ_SPOOLING:
2561 p = "Spooling";
2562 break;
2563 case LPQ_PRINTING:
2564 p = "Printing";
2565 break;
2567 #endif /* NO LONGER NEEDED. */
2569 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2571 data->notify_data.data.length = len;
2572 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2574 if (!data->notify_data.data.string) {
2575 data->notify_data.data.length = 0;
2576 return;
2579 memcpy(data->notify_data.data.string, temp, len);
2582 /*******************************************************************
2583 * fill a notify_info_data with job time
2584 ********************************************************************/
2586 static void spoolss_notify_job_time(int snum,
2587 SPOOL_NOTIFY_INFO_DATA *data,
2588 print_queue_struct *queue,
2589 NT_PRINTER_INFO_LEVEL *printer,
2590 TALLOC_CTX *mem_ctx)
2592 data->notify_data.value[0]=0x0;
2593 data->notify_data.value[1]=0;
2596 /*******************************************************************
2597 * fill a notify_info_data with job size
2598 ********************************************************************/
2600 static void spoolss_notify_job_size(int snum,
2601 SPOOL_NOTIFY_INFO_DATA *data,
2602 print_queue_struct *queue,
2603 NT_PRINTER_INFO_LEVEL *printer,
2604 TALLOC_CTX *mem_ctx)
2606 data->notify_data.value[0]=queue->size;
2607 data->notify_data.value[1]=0;
2610 /*******************************************************************
2611 * fill a notify_info_data with page info
2612 ********************************************************************/
2613 static void spoolss_notify_total_pages(int snum,
2614 SPOOL_NOTIFY_INFO_DATA *data,
2615 print_queue_struct *queue,
2616 NT_PRINTER_INFO_LEVEL *printer,
2617 TALLOC_CTX *mem_ctx)
2619 data->notify_data.value[0]=queue->page_count;
2620 data->notify_data.value[1]=0;
2623 /*******************************************************************
2624 * fill a notify_info_data with pages printed info.
2625 ********************************************************************/
2626 static void spoolss_notify_pages_printed(int snum,
2627 SPOOL_NOTIFY_INFO_DATA *data,
2628 print_queue_struct *queue,
2629 NT_PRINTER_INFO_LEVEL *printer,
2630 TALLOC_CTX *mem_ctx)
2632 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2633 data->notify_data.value[1]=0;
2636 /*******************************************************************
2637 Fill a notify_info_data with job position.
2638 ********************************************************************/
2640 static void spoolss_notify_job_position(int snum,
2641 SPOOL_NOTIFY_INFO_DATA *data,
2642 print_queue_struct *queue,
2643 NT_PRINTER_INFO_LEVEL *printer,
2644 TALLOC_CTX *mem_ctx)
2646 data->notify_data.value[0]=queue->job;
2647 data->notify_data.value[1]=0;
2650 /*******************************************************************
2651 Fill a notify_info_data with submitted time.
2652 ********************************************************************/
2654 static void spoolss_notify_submitted_time(int snum,
2655 SPOOL_NOTIFY_INFO_DATA *data,
2656 print_queue_struct *queue,
2657 NT_PRINTER_INFO_LEVEL *printer,
2658 TALLOC_CTX *mem_ctx)
2660 struct tm *t;
2661 uint32 len;
2662 SYSTEMTIME st;
2663 char *p;
2665 t=gmtime(&queue->time);
2667 len = sizeof(SYSTEMTIME);
2669 data->notify_data.data.length = len;
2670 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2672 if (!data->notify_data.data.string) {
2673 data->notify_data.data.length = 0;
2674 return;
2677 make_systemtime(&st, t);
2680 * Systemtime must be linearized as a set of UINT16's.
2681 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2684 p = (char *)data->notify_data.data.string;
2685 SSVAL(p, 0, st.year);
2686 SSVAL(p, 2, st.month);
2687 SSVAL(p, 4, st.dayofweek);
2688 SSVAL(p, 6, st.day);
2689 SSVAL(p, 8, st.hour);
2690 SSVAL(p, 10, st.minute);
2691 SSVAL(p, 12, st.second);
2692 SSVAL(p, 14, st.milliseconds);
2695 struct s_notify_info_data_table
2697 uint16 type;
2698 uint16 field;
2699 char *name;
2700 uint32 size;
2701 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2702 print_queue_struct *queue,
2703 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2706 /* A table describing the various print notification constants and
2707 whether the notification data is a pointer to a variable sized
2708 buffer, a one value uint32 or a two value uint32. */
2710 struct s_notify_info_data_table notify_info_data_table[] =
2712 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2713 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2714 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
2715 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2716 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2717 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
2718 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
2719 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2720 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
2721 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2722 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2723 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2724 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, spoolss_notify_security_desc },
2725 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
2726 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2727 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
2728 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2729 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2730 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
2731 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
2732 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
2733 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
2734 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
2735 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
2736 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
2737 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
2738 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2739 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2740 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2741 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
2742 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
2743 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2744 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2745 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2746 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2747 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2748 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
2749 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
2750 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
2751 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
2752 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2753 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
2754 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
2755 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2756 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2757 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
2758 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
2759 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
2760 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
2763 /*******************************************************************
2764 Return the size of info_data structure.
2765 ********************************************************************/
2767 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2769 int i=0;
2771 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2772 if (notify_info_data_table[i].type == type &&
2773 notify_info_data_table[i].field == field) {
2774 switch(notify_info_data_table[i].size) {
2775 case NOTIFY_ONE_VALUE:
2776 case NOTIFY_TWO_VALUE:
2777 return 1;
2778 case NOTIFY_STRING:
2779 return 2;
2781 /* The only pointer notify data I have seen on
2782 the wire is the submitted time and this has
2783 the notify size set to 4. -tpot */
2785 case NOTIFY_POINTER:
2786 return 4;
2791 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2793 return 0;
2796 /*******************************************************************
2797 Return the type of notify_info_data.
2798 ********************************************************************/
2800 static int type_of_notify_info_data(uint16 type, uint16 field)
2802 int i=0;
2804 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2805 if (notify_info_data_table[i].type == type &&
2806 notify_info_data_table[i].field == field)
2807 return notify_info_data_table[i].size;
2810 return False;
2813 /****************************************************************************
2814 ****************************************************************************/
2816 static int search_notify(uint16 type, uint16 field, int *value)
2818 int i;
2820 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2821 if (notify_info_data_table[i].type == type &&
2822 notify_info_data_table[i].field == field &&
2823 notify_info_data_table[i].fn != NULL) {
2824 *value = i;
2825 return True;
2829 return False;
2832 /****************************************************************************
2833 ****************************************************************************/
2835 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2837 info_data->type = type;
2838 info_data->field = field;
2839 info_data->reserved = 0;
2841 if (type == JOB_NOTIFY_TYPE)
2842 info_data->id = id;
2843 else
2844 info_data->id = 0;
2846 info_data->size = size_of_notify_info_data(type, field);
2847 info_data->enc_type = type_of_notify_info_data(type, field);
2851 /*******************************************************************
2853 * fill a notify_info struct with info asked
2855 ********************************************************************/
2857 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2858 snum, SPOOL_NOTIFY_OPTION_TYPE
2859 *option_type, uint32 id,
2860 TALLOC_CTX *mem_ctx)
2862 int field_num,j;
2863 uint16 type;
2864 uint16 field;
2866 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2867 NT_PRINTER_INFO_LEVEL *printer = NULL;
2868 print_queue_struct *queue=NULL;
2870 type=option_type->type;
2872 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2873 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2874 option_type->count, lp_servicename(snum)));
2876 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2877 return False;
2879 for(field_num=0; field_num<option_type->count; field_num++) {
2880 field = option_type->fields[field_num];
2881 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2883 if (!search_notify(type, field, &j) )
2884 continue;
2886 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2887 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2888 return False;
2890 else info->data = tid;
2892 current_data=&info->data[info->count];
2894 construct_info_data(current_data, type, field, id);
2896 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2897 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2899 notify_info_data_table[j].fn(snum, current_data, queue,
2900 printer, mem_ctx);
2902 info->count++;
2905 free_a_printer(&printer, 2);
2906 return True;
2909 /*******************************************************************
2911 * fill a notify_info struct with info asked
2913 ********************************************************************/
2915 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2916 SPOOL_NOTIFY_INFO *info,
2917 NT_PRINTER_INFO_LEVEL *printer,
2918 int snum, SPOOL_NOTIFY_OPTION_TYPE
2919 *option_type, uint32 id,
2920 TALLOC_CTX *mem_ctx)
2922 int field_num,j;
2923 uint16 type;
2924 uint16 field;
2926 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2928 DEBUG(4,("construct_notify_jobs_info\n"));
2930 type = option_type->type;
2932 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2933 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2934 option_type->count));
2936 for(field_num=0; field_num<option_type->count; field_num++) {
2937 field = option_type->fields[field_num];
2939 if (!search_notify(type, field, &j) )
2940 continue;
2942 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2943 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2944 return False;
2946 else info->data = tid;
2948 current_data=&(info->data[info->count]);
2950 construct_info_data(current_data, type, field, id);
2951 notify_info_data_table[j].fn(snum, current_data, queue,
2952 printer, mem_ctx);
2953 info->count++;
2956 return True;
2960 * JFM: The enumeration is not that simple, it's even non obvious.
2962 * let's take an example: I want to monitor the PRINTER SERVER for
2963 * the printer's name and the number of jobs currently queued.
2964 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2965 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2967 * I have 3 printers on the back of my server.
2969 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2970 * structures.
2971 * Number Data Id
2972 * 1 printer 1 name 1
2973 * 2 printer 1 cjob 1
2974 * 3 printer 2 name 2
2975 * 4 printer 2 cjob 2
2976 * 5 printer 3 name 3
2977 * 6 printer 3 name 3
2979 * that's the print server case, the printer case is even worse.
2982 /*******************************************************************
2984 * enumerate all printers on the printserver
2985 * fill a notify_info struct with info asked
2987 ********************************************************************/
2989 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2990 SPOOL_NOTIFY_INFO *info,
2991 TALLOC_CTX *mem_ctx)
2993 int snum;
2994 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2995 int n_services=lp_numservices();
2996 int i;
2997 uint32 id;
2998 SPOOL_NOTIFY_OPTION *option;
2999 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3001 DEBUG(4,("printserver_notify_info\n"));
3003 if (!Printer)
3004 return WERR_BADFID;
3006 option=Printer->notify.option;
3007 id=1;
3008 info->version=2;
3009 info->data=NULL;
3010 info->count=0;
3012 for (i=0; i<option->count; i++) {
3013 option_type=&(option->ctr.type[i]);
3015 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3016 continue;
3018 for (snum=0; snum<n_services; snum++)
3019 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3020 if (construct_notify_printer_info
3021 (info, snum, option_type, id, mem_ctx))
3022 id++;
3026 * Debugging information, don't delete.
3029 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3030 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3031 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3033 for (i=0; i<info->count; i++) {
3034 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3035 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3036 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3040 return WERR_OK;
3043 /*******************************************************************
3045 * fill a notify_info struct with info asked
3047 ********************************************************************/
3049 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3050 TALLOC_CTX *mem_ctx)
3052 int snum;
3053 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3054 int i;
3055 uint32 id;
3056 SPOOL_NOTIFY_OPTION *option;
3057 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3058 int count,j;
3059 print_queue_struct *queue=NULL;
3060 print_status_struct status;
3062 DEBUG(4,("printer_notify_info\n"));
3064 if (!Printer)
3065 return WERR_BADFID;
3067 option=Printer->notify.option;
3068 id = 0x0;
3069 info->version=2;
3070 info->data=NULL;
3071 info->count=0;
3073 get_printer_snum(p, hnd, &snum);
3075 for (i=0; i<option->count; i++) {
3076 option_type=&option->ctr.type[i];
3078 switch ( option_type->type ) {
3079 case PRINTER_NOTIFY_TYPE:
3080 if(construct_notify_printer_info(info, snum,
3081 option_type, id,
3082 mem_ctx))
3083 id--;
3084 break;
3086 case JOB_NOTIFY_TYPE: {
3087 NT_PRINTER_INFO_LEVEL *printer = NULL;
3089 count = print_queue_status(snum, &queue, &status);
3091 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3092 lp_servicename(snum))))
3093 goto done;
3095 for (j=0; j<count; j++) {
3096 construct_notify_jobs_info(&queue[j], info,
3097 printer, snum,
3098 option_type,
3099 queue[j].job,
3100 mem_ctx);
3103 free_a_printer(&printer, 2);
3105 done:
3106 SAFE_FREE(queue);
3107 break;
3113 * Debugging information, don't delete.
3116 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3117 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3118 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3120 for (i=0; i<info->count; i++) {
3121 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3122 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3123 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3126 return WERR_OK;
3129 /********************************************************************
3130 * spoolss_rfnpcnex
3131 ********************************************************************/
3133 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3135 POLICY_HND *handle = &q_u->handle;
3136 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
3137 SPOOL_NOTIFY_INFO *info = &r_u->info;
3139 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3140 WERROR result = WERR_BADFID;
3142 /* we always have a NOTIFY_INFO struct */
3143 r_u->info_ptr=0x1;
3145 if (!Printer) {
3146 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3147 OUR_HANDLE(handle)));
3148 goto done;
3151 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3154 * We are now using the change value, and
3155 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3156 * I don't have a global notification system, I'm sending back all the
3157 * informations even when _NOTHING_ has changed.
3160 /* We need to keep track of the change value to send back in
3161 RRPCN replies otherwise our updates are ignored. */
3163 if (Printer->notify.client_connected)
3164 Printer->notify.change = q_u->change;
3166 /* just ignore the SPOOL_NOTIFY_OPTION */
3168 switch (Printer->printer_type) {
3169 case PRINTER_HANDLE_IS_PRINTSERVER:
3170 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3171 break;
3173 case PRINTER_HANDLE_IS_PRINTER:
3174 result = printer_notify_info(p, handle, info, p->mem_ctx);
3175 break;
3178 done:
3179 return result;
3182 /********************************************************************
3183 * construct_printer_info_0
3184 * fill a printer_info_0 struct
3185 ********************************************************************/
3187 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3189 pstring chaine;
3190 int count;
3191 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3192 counter_printer_0 *session_counter;
3193 uint32 global_counter;
3194 struct tm *t;
3195 time_t setuptime;
3196 print_status_struct status;
3198 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3199 return False;
3201 count = print_queue_length(snum, &status);
3203 /* check if we already have a counter for this printer */
3204 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3206 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3207 if (session_counter->snum == snum)
3208 break;
3211 /* it's the first time, add it to the list */
3212 if (session_counter==NULL) {
3213 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3214 free_a_printer(&ntprinter, 2);
3215 return False;
3217 ZERO_STRUCTP(session_counter);
3218 session_counter->snum=snum;
3219 session_counter->counter=0;
3220 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3223 /* increment it */
3224 session_counter->counter++;
3226 /* JFM:
3227 * the global_counter should be stored in a TDB as it's common to all the clients
3228 * and should be zeroed on samba startup
3230 global_counter=session_counter->counter;
3232 pstrcpy(chaine,ntprinter->info_2->printername);
3234 init_unistr(&printer->printername, chaine);
3236 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3237 init_unistr(&printer->servername, chaine);
3239 printer->cjobs = count;
3240 printer->total_jobs = 0;
3241 printer->total_bytes = 0;
3243 setuptime = (time_t)ntprinter->info_2->setuptime;
3244 t=gmtime(&setuptime);
3246 printer->year = t->tm_year+1900;
3247 printer->month = t->tm_mon+1;
3248 printer->dayofweek = t->tm_wday;
3249 printer->day = t->tm_mday;
3250 printer->hour = t->tm_hour;
3251 printer->minute = t->tm_min;
3252 printer->second = t->tm_sec;
3253 printer->milliseconds = 0;
3255 printer->global_counter = global_counter;
3256 printer->total_pages = 0;
3257 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3258 printer->major_version = 0x0004; /* NT 4 */
3259 printer->build_version = 0x0565; /* build 1381 */
3260 #else
3261 printer->major_version = 0x0005; /* NT 5 */
3262 printer->build_version = 0x0893; /* build 2195 */
3263 #endif
3264 printer->unknown7 = 0x1;
3265 printer->unknown8 = 0x0;
3266 printer->unknown9 = 0x0;
3267 printer->session_counter = session_counter->counter;
3268 printer->unknown11 = 0x0;
3269 printer->printer_errors = 0x0; /* number of print failure */
3270 printer->unknown13 = 0x0;
3271 printer->unknown14 = 0x1;
3272 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3273 printer->unknown16 = 0x0;
3274 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3275 printer->unknown18 = 0x0;
3276 printer->status = nt_printq_status(status.status);
3277 printer->unknown20 = 0x0;
3278 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3279 printer->unknown22 = 0x0;
3280 printer->unknown23 = 0x6; /* 6 ???*/
3281 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3282 printer->unknown25 = 0;
3283 printer->unknown26 = 0;
3284 printer->unknown27 = 0;
3285 printer->unknown28 = 0;
3286 printer->unknown29 = 0;
3288 free_a_printer(&ntprinter,2);
3289 return (True);
3292 /********************************************************************
3293 * construct_printer_info_1
3294 * fill a printer_info_1 struct
3295 ********************************************************************/
3296 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3298 pstring chaine;
3299 pstring chaine2;
3300 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3302 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3303 return False;
3305 printer->flags=flags;
3307 if (*ntprinter->info_2->comment == '\0') {
3308 init_unistr(&printer->comment, lp_comment(snum));
3309 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3310 ntprinter->info_2->drivername, lp_comment(snum));
3312 else {
3313 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3314 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3315 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3318 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3320 init_unistr(&printer->description, chaine);
3321 init_unistr(&printer->name, chaine2);
3323 free_a_printer(&ntprinter,2);
3325 return True;
3328 /****************************************************************************
3329 Free a DEVMODE struct.
3330 ****************************************************************************/
3332 static void free_dev_mode(DEVICEMODE *dev)
3334 if (dev == NULL)
3335 return;
3337 SAFE_FREE(dev->private);
3338 SAFE_FREE(dev);
3341 /****************************************************************************
3342 Create a DEVMODE struct. Returns malloced memory.
3343 ****************************************************************************/
3345 static DEVICEMODE *construct_dev_mode(int snum)
3347 char adevice[32];
3348 char aform[32];
3349 NT_PRINTER_INFO_LEVEL *printer = NULL;
3350 NT_DEVICEMODE *ntdevmode = NULL;
3351 DEVICEMODE *devmode = NULL;
3353 DEBUG(7,("construct_dev_mode\n"));
3355 DEBUGADD(8,("getting printer characteristics\n"));
3357 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3358 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3359 return NULL;
3362 ZERO_STRUCTP(devmode);
3364 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3365 goto fail;
3367 if (printer->info_2->devmode)
3368 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3370 if (ntdevmode == NULL) {
3371 DEBUG(5, ("BONG! There was no device mode!\n"));
3372 goto fail;
3375 DEBUGADD(8,("loading DEVICEMODE\n"));
3377 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3378 init_unistr(&devmode->devicename, adevice);
3380 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3381 init_unistr(&devmode->formname, aform);
3383 devmode->specversion = ntdevmode->specversion;
3384 devmode->driverversion = ntdevmode->driverversion;
3385 devmode->size = ntdevmode->size;
3386 devmode->driverextra = ntdevmode->driverextra;
3387 devmode->fields = ntdevmode->fields;
3389 devmode->orientation = ntdevmode->orientation;
3390 devmode->papersize = ntdevmode->papersize;
3391 devmode->paperlength = ntdevmode->paperlength;
3392 devmode->paperwidth = ntdevmode->paperwidth;
3393 devmode->scale = ntdevmode->scale;
3394 devmode->copies = ntdevmode->copies;
3395 devmode->defaultsource = ntdevmode->defaultsource;
3396 devmode->printquality = ntdevmode->printquality;
3397 devmode->color = ntdevmode->color;
3398 devmode->duplex = ntdevmode->duplex;
3399 devmode->yresolution = ntdevmode->yresolution;
3400 devmode->ttoption = ntdevmode->ttoption;
3401 devmode->collate = ntdevmode->collate;
3402 devmode->icmmethod = ntdevmode->icmmethod;
3403 devmode->icmintent = ntdevmode->icmintent;
3404 devmode->mediatype = ntdevmode->mediatype;
3405 devmode->dithertype = ntdevmode->dithertype;
3407 if (ntdevmode->private != NULL) {
3408 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3409 goto fail;
3412 free_nt_devicemode(&ntdevmode);
3413 free_a_printer(&printer,2);
3415 return devmode;
3417 fail:
3419 if (ntdevmode)
3420 free_nt_devicemode(&ntdevmode);
3421 if (printer)
3422 free_a_printer(&printer,2);
3423 free_dev_mode(devmode);
3425 return NULL;
3428 /********************************************************************
3429 * construct_printer_info_2
3430 * fill a printer_info_2 struct
3431 ********************************************************************/
3433 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3435 int count;
3436 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3438 print_status_struct status;
3440 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3441 return False;
3443 count = print_queue_length(snum, &status);
3445 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3446 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3447 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3448 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3449 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3451 if (*ntprinter->info_2->comment == '\0')
3452 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3453 else
3454 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3456 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3457 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3458 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3459 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3460 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3462 printer->attributes = ntprinter->info_2->attributes;
3464 printer->priority = ntprinter->info_2->priority; /* priority */
3465 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3466 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3467 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3468 printer->status = nt_printq_status(status.status); /* status */
3469 printer->cjobs = count; /* jobs */
3470 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3472 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3473 DEBUG(8, ("Returning NULL Devicemode!\n"));
3476 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3477 /* steal the printer info sec_desc structure. [badly done]. */
3478 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3479 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3480 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3481 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3483 else {
3484 printer->secdesc = NULL;
3487 free_a_printer(&ntprinter, 2);
3488 return True;
3491 /********************************************************************
3492 * construct_printer_info_3
3493 * fill a printer_info_3 struct
3494 ********************************************************************/
3496 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3498 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3499 PRINTER_INFO_3 *printer = NULL;
3501 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3502 return False;
3504 *pp_printer = NULL;
3505 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3506 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3507 return False;
3510 ZERO_STRUCTP(printer);
3512 printer->flags = 4; /* These are the components of the SD we are returning. */
3513 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3514 /* steal the printer info sec_desc structure. [badly done]. */
3515 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3517 #if 0
3519 * Set the flags for the components we are returning.
3522 if (printer->secdesc->owner_sid)
3523 printer->flags |= OWNER_SECURITY_INFORMATION;
3525 if (printer->secdesc->grp_sid)
3526 printer->flags |= GROUP_SECURITY_INFORMATION;
3528 if (printer->secdesc->dacl)
3529 printer->flags |= DACL_SECURITY_INFORMATION;
3531 if (printer->secdesc->sacl)
3532 printer->flags |= SACL_SECURITY_INFORMATION;
3533 #endif
3535 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3536 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3537 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3540 free_a_printer(&ntprinter, 2);
3542 *pp_printer = printer;
3543 return True;
3546 /********************************************************************
3547 * construct_printer_info_4
3548 * fill a printer_info_4 struct
3549 ********************************************************************/
3551 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3553 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3555 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3556 return False;
3558 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3559 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3560 printer->attributes = ntprinter->info_2->attributes;
3562 free_a_printer(&ntprinter, 2);
3563 return True;
3566 /********************************************************************
3567 * construct_printer_info_5
3568 * fill a printer_info_5 struct
3569 ********************************************************************/
3571 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3573 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3575 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3576 return False;
3578 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3579 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3580 printer->attributes = ntprinter->info_2->attributes;
3581 printer->device_not_selected_timeout = 0x3a98;
3582 printer->transmission_retry_timeout = 0xafc8;
3584 free_a_printer(&ntprinter, 2);
3585 return True;
3588 /********************************************************************
3589 Spoolss_enumprinters.
3590 ********************************************************************/
3592 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3594 int snum;
3595 int i;
3596 int n_services=lp_numservices();
3597 PRINTER_INFO_1 *tp, *printers=NULL;
3598 PRINTER_INFO_1 current_prt;
3600 DEBUG(4,("enum_all_printers_info_1\n"));
3602 for (snum=0; snum<n_services; snum++) {
3603 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3604 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3606 if (construct_printer_info_1(flags, &current_prt, snum)) {
3607 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3608 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3609 SAFE_FREE(printers);
3610 *returned=0;
3611 return WERR_NOMEM;
3613 else printers = tp;
3614 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3616 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
3617 (*returned)++;
3622 /* check the required size. */
3623 for (i=0; i<*returned; i++)
3624 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3626 if (!alloc_buffer_size(buffer, *needed))
3627 return WERR_INSUFFICIENT_BUFFER;
3629 /* fill the buffer with the structures */
3630 for (i=0; i<*returned; i++)
3631 smb_io_printer_info_1("", buffer, &printers[i], 0);
3633 /* clear memory */
3634 SAFE_FREE(printers);
3636 if (*needed > offered) {
3637 *returned=0;
3638 return WERR_INSUFFICIENT_BUFFER;
3640 else
3641 return WERR_OK;
3644 /********************************************************************
3645 enum_all_printers_info_1_local.
3646 *********************************************************************/
3648 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3650 DEBUG(4,("enum_all_printers_info_1_local\n"));
3652 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3655 /********************************************************************
3656 enum_all_printers_info_1_name.
3657 *********************************************************************/
3659 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3661 char *s = name;
3663 DEBUG(4,("enum_all_printers_info_1_name\n"));
3665 if ((name[0] == '\\') && (name[1] == '\\'))
3666 s = name + 2;
3668 if (is_myname_or_ipaddr(s)) {
3669 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3671 else
3672 return WERR_INVALID_NAME;
3675 /********************************************************************
3676 enum_all_printers_info_1_remote.
3677 *********************************************************************/
3679 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3681 PRINTER_INFO_1 *printer;
3682 fstring printername;
3683 fstring desc;
3684 fstring comment;
3685 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3687 /* JFM: currently it's more a place holder than anything else.
3688 * In the spooler world there is a notion of server registration.
3689 * the print servers are registring (sp ?) on the PDC (in the same domain)
3691 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3694 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3695 return WERR_NOMEM;
3697 *returned=1;
3699 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3700 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3701 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3703 init_unistr(&printer->description, desc);
3704 init_unistr(&printer->name, printername);
3705 init_unistr(&printer->comment, comment);
3706 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3708 /* check the required size. */
3709 *needed += spoolss_size_printer_info_1(printer);
3711 if (!alloc_buffer_size(buffer, *needed)) {
3712 SAFE_FREE(printer);
3713 return WERR_INSUFFICIENT_BUFFER;
3716 /* fill the buffer with the structures */
3717 smb_io_printer_info_1("", buffer, printer, 0);
3719 /* clear memory */
3720 SAFE_FREE(printer);
3722 if (*needed > offered) {
3723 *returned=0;
3724 return WERR_INSUFFICIENT_BUFFER;
3726 else
3727 return WERR_OK;
3730 /********************************************************************
3731 enum_all_printers_info_1_network.
3732 *********************************************************************/
3734 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3736 char *s = name;
3738 DEBUG(4,("enum_all_printers_info_1_network\n"));
3740 /* If we respond to a enum_printers level 1 on our name with flags
3741 set to PRINTER_ENUM_REMOTE with a list of printers then these
3742 printers incorrectly appear in the APW browse list.
3743 Specifically the printers for the server appear at the workgroup
3744 level where all the other servers in the domain are
3745 listed. Windows responds to this call with a
3746 WERR_CAN_NOT_COMPLETE so we should do the same. */
3748 if (name[0] == '\\' && name[1] == '\\')
3749 s = name + 2;
3751 if (is_myname_or_ipaddr(s))
3752 return WERR_CAN_NOT_COMPLETE;
3754 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3757 /********************************************************************
3758 * api_spoolss_enumprinters
3760 * called from api_spoolss_enumprinters (see this to understand)
3761 ********************************************************************/
3763 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3765 int snum;
3766 int i;
3767 int n_services=lp_numservices();
3768 PRINTER_INFO_2 *tp, *printers=NULL;
3769 PRINTER_INFO_2 current_prt;
3771 for (snum=0; snum<n_services; snum++) {
3772 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3773 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3775 if (construct_printer_info_2(&current_prt, snum)) {
3776 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3777 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3778 SAFE_FREE(printers);
3779 *returned = 0;
3780 return WERR_NOMEM;
3782 else printers = tp;
3783 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3784 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3785 (*returned)++;
3790 /* check the required size. */
3791 for (i=0; i<*returned; i++)
3792 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3794 if (!alloc_buffer_size(buffer, *needed)) {
3795 for (i=0; i<*returned; i++) {
3796 free_devmode(printers[i].devmode);
3798 SAFE_FREE(printers);
3799 return WERR_INSUFFICIENT_BUFFER;
3802 /* fill the buffer with the structures */
3803 for (i=0; i<*returned; i++)
3804 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3806 /* clear memory */
3807 for (i=0; i<*returned; i++) {
3808 free_devmode(printers[i].devmode);
3810 SAFE_FREE(printers);
3812 if (*needed > offered) {
3813 *returned=0;
3814 return WERR_INSUFFICIENT_BUFFER;
3816 else
3817 return WERR_OK;
3820 /********************************************************************
3821 * handle enumeration of printers at level 1
3822 ********************************************************************/
3824 static WERROR enumprinters_level1( uint32 flags, fstring name,
3825 NEW_BUFFER *buffer, uint32 offered,
3826 uint32 *needed, uint32 *returned)
3828 /* Not all the flags are equals */
3830 if (flags & PRINTER_ENUM_LOCAL)
3831 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3833 if (flags & PRINTER_ENUM_NAME)
3834 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3836 if (flags & PRINTER_ENUM_REMOTE)
3837 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3839 if (flags & PRINTER_ENUM_NETWORK)
3840 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
3842 return WERR_OK; /* NT4sp5 does that */
3845 /********************************************************************
3846 * handle enumeration of printers at level 2
3847 ********************************************************************/
3849 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3850 NEW_BUFFER *buffer, uint32 offered,
3851 uint32 *needed, uint32 *returned)
3853 char *s = servername;
3855 if (flags & PRINTER_ENUM_LOCAL) {
3856 return enum_all_printers_info_2(buffer, offered, needed, returned);
3859 if (flags & PRINTER_ENUM_NAME) {
3860 if ((servername[0] == '\\') && (servername[1] == '\\'))
3861 s = servername + 2;
3862 if (is_myname_or_ipaddr(s))
3863 return enum_all_printers_info_2(buffer, offered, needed, returned);
3864 else
3865 return WERR_INVALID_NAME;
3868 if (flags & PRINTER_ENUM_REMOTE)
3869 return WERR_UNKNOWN_LEVEL;
3871 return WERR_OK;
3874 /********************************************************************
3875 * handle enumeration of printers at level 5
3876 ********************************************************************/
3878 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3879 NEW_BUFFER *buffer, uint32 offered,
3880 uint32 *needed, uint32 *returned)
3882 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3883 return WERR_OK;
3886 /********************************************************************
3887 * api_spoolss_enumprinters
3889 * called from api_spoolss_enumprinters (see this to understand)
3890 ********************************************************************/
3892 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3894 uint32 flags = q_u->flags;
3895 UNISTR2 *servername = &q_u->servername;
3896 uint32 level = q_u->level;
3897 NEW_BUFFER *buffer = NULL;
3898 uint32 offered = q_u->offered;
3899 uint32 *needed = &r_u->needed;
3900 uint32 *returned = &r_u->returned;
3902 fstring name;
3904 /* that's an [in out] buffer */
3905 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3906 buffer = r_u->buffer;
3908 DEBUG(4,("_spoolss_enumprinters\n"));
3910 *needed=0;
3911 *returned=0;
3914 * Level 1:
3915 * flags==PRINTER_ENUM_NAME
3916 * if name=="" then enumerates all printers
3917 * if name!="" then enumerate the printer
3918 * flags==PRINTER_ENUM_REMOTE
3919 * name is NULL, enumerate printers
3920 * Level 2: name!="" enumerates printers, name can't be NULL
3921 * Level 3: doesn't exist
3922 * Level 4: does a local registry lookup
3923 * Level 5: same as Level 2
3926 unistr2_to_ascii(name, servername, sizeof(name)-1);
3927 strupper(name);
3929 switch (level) {
3930 case 1:
3931 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3932 case 2:
3933 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3934 case 5:
3935 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3936 case 3:
3937 case 4:
3938 break;
3940 return WERR_UNKNOWN_LEVEL;
3943 /****************************************************************************
3944 ****************************************************************************/
3946 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3948 PRINTER_INFO_0 *printer=NULL;
3950 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3951 return WERR_NOMEM;
3953 construct_printer_info_0(printer, snum);
3955 /* check the required size. */
3956 *needed += spoolss_size_printer_info_0(printer);
3958 if (!alloc_buffer_size(buffer, *needed)) {
3959 SAFE_FREE(printer);
3960 return WERR_INSUFFICIENT_BUFFER;
3963 /* fill the buffer with the structures */
3964 smb_io_printer_info_0("", buffer, printer, 0);
3966 /* clear memory */
3967 SAFE_FREE(printer);
3969 if (*needed > offered) {
3970 return WERR_INSUFFICIENT_BUFFER;
3973 return WERR_OK;
3976 /****************************************************************************
3977 ****************************************************************************/
3979 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3981 PRINTER_INFO_1 *printer=NULL;
3983 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3984 return WERR_NOMEM;
3986 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3988 /* check the required size. */
3989 *needed += spoolss_size_printer_info_1(printer);
3991 if (!alloc_buffer_size(buffer, *needed)) {
3992 SAFE_FREE(printer);
3993 return WERR_INSUFFICIENT_BUFFER;
3996 /* fill the buffer with the structures */
3997 smb_io_printer_info_1("", buffer, printer, 0);
3999 /* clear memory */
4000 SAFE_FREE(printer);
4002 if (*needed > offered) {
4003 return WERR_INSUFFICIENT_BUFFER;
4006 return WERR_OK;
4009 /****************************************************************************
4010 ****************************************************************************/
4012 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4014 PRINTER_INFO_2 *printer=NULL;
4016 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4017 return WERR_NOMEM;
4019 construct_printer_info_2(printer, snum);
4021 /* check the required size. */
4022 *needed += spoolss_size_printer_info_2(printer);
4024 if (!alloc_buffer_size(buffer, *needed)) {
4025 free_printer_info_2(printer);
4026 return WERR_INSUFFICIENT_BUFFER;
4029 /* fill the buffer with the structures */
4030 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4031 free_printer_info_2(printer);
4032 return WERR_NOMEM;
4035 /* clear memory */
4036 free_printer_info_2(printer);
4038 if (*needed > offered) {
4039 return WERR_INSUFFICIENT_BUFFER;
4042 return WERR_OK;
4045 /****************************************************************************
4046 ****************************************************************************/
4048 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4050 PRINTER_INFO_3 *printer=NULL;
4052 if (!construct_printer_info_3(&printer, snum))
4053 return WERR_NOMEM;
4055 /* check the required size. */
4056 *needed += spoolss_size_printer_info_3(printer);
4058 if (!alloc_buffer_size(buffer, *needed)) {
4059 free_printer_info_3(printer);
4060 return WERR_INSUFFICIENT_BUFFER;
4063 /* fill the buffer with the structures */
4064 smb_io_printer_info_3("", buffer, printer, 0);
4066 /* clear memory */
4067 free_printer_info_3(printer);
4069 if (*needed > offered) {
4070 return WERR_INSUFFICIENT_BUFFER;
4073 return WERR_OK;
4076 /****************************************************************************
4077 ****************************************************************************/
4079 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4081 PRINTER_INFO_4 *printer=NULL;
4083 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4084 return WERR_NOMEM;
4086 if (!construct_printer_info_4(printer, snum))
4087 return WERR_NOMEM;
4089 /* check the required size. */
4090 *needed += spoolss_size_printer_info_4(printer);
4092 if (!alloc_buffer_size(buffer, *needed)) {
4093 free_printer_info_4(printer);
4094 return WERR_INSUFFICIENT_BUFFER;
4097 /* fill the buffer with the structures */
4098 smb_io_printer_info_4("", buffer, printer, 0);
4100 /* clear memory */
4101 free_printer_info_4(printer);
4103 if (*needed > offered) {
4104 return WERR_INSUFFICIENT_BUFFER;
4107 return WERR_OK;
4110 /****************************************************************************
4111 ****************************************************************************/
4113 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4115 PRINTER_INFO_5 *printer=NULL;
4117 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4118 return WERR_NOMEM;
4120 if (!construct_printer_info_5(printer, snum))
4121 return WERR_NOMEM;
4123 /* check the required size. */
4124 *needed += spoolss_size_printer_info_5(printer);
4126 if (!alloc_buffer_size(buffer, *needed)) {
4127 free_printer_info_5(printer);
4128 return WERR_INSUFFICIENT_BUFFER;
4131 /* fill the buffer with the structures */
4132 smb_io_printer_info_5("", buffer, printer, 0);
4134 /* clear memory */
4135 free_printer_info_5(printer);
4137 if (*needed > offered) {
4138 return WERR_INSUFFICIENT_BUFFER;
4141 return WERR_OK;
4144 /****************************************************************************
4145 ****************************************************************************/
4147 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4149 POLICY_HND *handle = &q_u->handle;
4150 uint32 level = q_u->level;
4151 NEW_BUFFER *buffer = NULL;
4152 uint32 offered = q_u->offered;
4153 uint32 *needed = &r_u->needed;
4155 int snum;
4157 /* that's an [in out] buffer */
4158 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4159 buffer = r_u->buffer;
4161 *needed=0;
4163 if (!get_printer_snum(p, handle, &snum))
4164 return WERR_BADFID;
4166 switch (level) {
4167 case 0:
4168 return getprinter_level_0(snum, buffer, offered, needed);
4169 case 1:
4170 return getprinter_level_1(snum, buffer, offered, needed);
4171 case 2:
4172 return getprinter_level_2(snum, buffer, offered, needed);
4173 case 3:
4174 return getprinter_level_3(snum, buffer, offered, needed);
4175 case 4:
4176 return getprinter_level_4(snum, buffer, offered, needed);
4177 case 5:
4178 return getprinter_level_5(snum, buffer, offered, needed);
4180 return WERR_UNKNOWN_LEVEL;
4183 /********************************************************************
4184 * fill a DRIVER_INFO_1 struct
4185 ********************************************************************/
4187 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4189 init_unistr( &info->name, driver.info_3->name);
4192 /********************************************************************
4193 * construct_printer_driver_info_1
4194 ********************************************************************/
4196 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4198 NT_PRINTER_INFO_LEVEL *printer = NULL;
4199 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4201 ZERO_STRUCT(driver);
4203 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4204 return WERR_INVALID_PRINTER_NAME;
4206 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4207 return WERR_UNKNOWN_PRINTER_DRIVER;
4209 fill_printer_driver_info_1(info, driver, servername, architecture);
4211 free_a_printer(&printer,2);
4213 return WERR_OK;
4216 /********************************************************************
4217 * construct_printer_driver_info_2
4218 * fill a printer_info_2 struct
4219 ********************************************************************/
4221 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4223 pstring temp;
4225 info->version=driver.info_3->cversion;
4227 init_unistr( &info->name, driver.info_3->name );
4228 init_unistr( &info->architecture, driver.info_3->environment );
4231 if (strlen(driver.info_3->driverpath)) {
4232 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4233 init_unistr( &info->driverpath, temp );
4234 } else
4235 init_unistr( &info->driverpath, "" );
4237 if (strlen(driver.info_3->datafile)) {
4238 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4239 init_unistr( &info->datafile, temp );
4240 } else
4241 init_unistr( &info->datafile, "" );
4243 if (strlen(driver.info_3->configfile)) {
4244 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4245 init_unistr( &info->configfile, temp );
4246 } else
4247 init_unistr( &info->configfile, "" );
4250 /********************************************************************
4251 * construct_printer_driver_info_2
4252 * fill a printer_info_2 struct
4253 ********************************************************************/
4255 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4257 NT_PRINTER_INFO_LEVEL *printer = NULL;
4258 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4260 ZERO_STRUCT(printer);
4261 ZERO_STRUCT(driver);
4263 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4264 return WERR_INVALID_PRINTER_NAME;
4266 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4267 return WERR_UNKNOWN_PRINTER_DRIVER;
4269 fill_printer_driver_info_2(info, driver, servername);
4271 free_a_printer(&printer,2);
4273 return WERR_OK;
4276 /********************************************************************
4277 * copy a strings array and convert to UNICODE
4279 * convert an array of ascii string to a UNICODE string
4280 ********************************************************************/
4282 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4284 int i=0;
4285 int j=0;
4286 char *v;
4287 pstring line;
4288 uint16 *tuary;
4290 DEBUG(6,("init_unistr_array\n"));
4291 *uni_array=NULL;
4293 while (1) {
4294 if (char_array == NULL)
4295 v = "";
4296 else {
4297 v = char_array[i];
4298 if (!v) v = ""; /* hack to handle null lists */
4300 if (strlen(v) == 0) break;
4301 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
4302 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4303 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
4304 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4305 return;
4306 } else
4307 *uni_array = tuary;
4308 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
4309 i++;
4312 if (*uni_array) {
4313 (*uni_array)[j]=0x0000;
4316 DEBUGADD(6,("last one:done\n"));
4319 /********************************************************************
4320 * construct_printer_info_3
4321 * fill a printer_info_3 struct
4322 ********************************************************************/
4324 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4326 pstring temp;
4328 ZERO_STRUCTP(info);
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 );
4335 if (strlen(driver.info_3->driverpath)) {
4336 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4337 init_unistr( &info->driverpath, temp );
4338 } else
4339 init_unistr( &info->driverpath, "" );
4341 if (strlen(driver.info_3->datafile)) {
4342 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4343 init_unistr( &info->datafile, temp );
4344 } else
4345 init_unistr( &info->datafile, "" );
4347 if (strlen(driver.info_3->configfile)) {
4348 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4349 init_unistr( &info->configfile, temp );
4350 } else
4351 init_unistr( &info->configfile, "" );
4353 if (strlen(driver.info_3->helpfile)) {
4354 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4355 init_unistr( &info->helpfile, temp );
4356 } else
4357 init_unistr( &info->helpfile, "" );
4359 init_unistr( &info->monitorname, driver.info_3->monitorname );
4360 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4362 info->dependentfiles=NULL;
4363 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4366 /********************************************************************
4367 * construct_printer_info_3
4368 * fill a printer_info_3 struct
4369 ********************************************************************/
4371 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4373 NT_PRINTER_INFO_LEVEL *printer = NULL;
4374 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4375 WERROR status;
4376 ZERO_STRUCT(driver);
4378 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4379 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4380 if (!W_ERROR_IS_OK(status))
4381 return WERR_INVALID_PRINTER_NAME;
4383 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4384 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4386 #if 0 /* JERRY */
4389 * I put this code in during testing. Helpful when commenting out the
4390 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4391 * as win2k always queries the driver using an infor level of 6.
4392 * I've left it in (but ifdef'd out) because I'll probably
4393 * use it in experimentation again in the future. --jerry 22/01/2002
4396 if (!W_ERROR_IS_OK(status)) {
4398 * Is this a W2k client ?
4400 if (version == 3) {
4401 /* Yes - try again with a WinNT driver. */
4402 version = 2;
4403 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4404 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4406 #endif
4408 if (!W_ERROR_IS_OK(status)) {
4409 free_a_printer(&printer,2);
4410 return WERR_UNKNOWN_PRINTER_DRIVER;
4413 #if 0 /* JERRY */
4415 #endif
4418 fill_printer_driver_info_3(info, driver, servername);
4420 free_a_printer(&printer,2);
4422 return WERR_OK;
4425 /********************************************************************
4426 * construct_printer_info_6
4427 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4428 ********************************************************************/
4430 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4432 pstring temp;
4433 fstring nullstr;
4435 ZERO_STRUCTP(info);
4436 memset(&nullstr, '\0', sizeof(fstring));
4438 info->version=driver.info_3->cversion;
4440 init_unistr( &info->name, driver.info_3->name );
4441 init_unistr( &info->architecture, driver.info_3->environment );
4443 if (strlen(driver.info_3->driverpath)) {
4444 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4445 init_unistr( &info->driverpath, temp );
4446 } else
4447 init_unistr( &info->driverpath, "" );
4449 if (strlen(driver.info_3->datafile)) {
4450 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4451 init_unistr( &info->datafile, temp );
4452 } else
4453 init_unistr( &info->datafile, "" );
4455 if (strlen(driver.info_3->configfile)) {
4456 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4457 init_unistr( &info->configfile, temp );
4458 } else
4459 init_unistr( &info->configfile, "" );
4461 if (strlen(driver.info_3->helpfile)) {
4462 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4463 init_unistr( &info->helpfile, temp );
4464 } else
4465 init_unistr( &info->helpfile, "" );
4467 init_unistr( &info->monitorname, driver.info_3->monitorname );
4468 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4470 info->dependentfiles=NULL;
4471 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4473 info->previousdrivernames=NULL;
4474 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4476 info->driver_date.low=0;
4477 info->driver_date.high=0;
4479 info->padding=0;
4480 info->driver_version_low=0;
4481 info->driver_version_high=0;
4483 init_unistr( &info->mfgname, "");
4484 init_unistr( &info->oem_url, "");
4485 init_unistr( &info->hardware_id, "");
4486 init_unistr( &info->provider, "");
4489 /********************************************************************
4490 * construct_printer_info_6
4491 * fill a printer_info_6 struct
4492 ********************************************************************/
4494 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4496 NT_PRINTER_INFO_LEVEL *printer = NULL;
4497 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4498 WERROR status;
4499 ZERO_STRUCT(driver);
4501 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4502 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4503 if (!W_ERROR_IS_OK(status))
4504 return WERR_INVALID_PRINTER_NAME;
4506 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4507 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4508 if (!W_ERROR_IS_OK(status)) {
4510 * Is this a W2k client ?
4513 if (version < 3) {
4514 free_a_printer(&printer,2);
4515 return WERR_UNKNOWN_PRINTER_DRIVER;
4518 /* Yes - try again with a WinNT driver. */
4519 version = 2;
4520 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4521 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4522 if (!W_ERROR_IS_OK(status)) {
4523 free_a_printer(&printer,2);
4524 return WERR_UNKNOWN_PRINTER_DRIVER;
4528 fill_printer_driver_info_6(info, driver, servername);
4530 free_a_printer(&printer,2);
4532 return WERR_OK;
4535 /****************************************************************************
4536 ****************************************************************************/
4538 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4540 SAFE_FREE(info->dependentfiles);
4543 /****************************************************************************
4544 ****************************************************************************/
4546 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4548 SAFE_FREE(info->dependentfiles);
4552 /****************************************************************************
4553 ****************************************************************************/
4555 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4557 DRIVER_INFO_1 *info=NULL;
4558 WERROR status;
4560 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4561 return WERR_NOMEM;
4563 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4564 if (!W_ERROR_IS_OK(status)) {
4565 SAFE_FREE(info);
4566 return status;
4569 /* check the required size. */
4570 *needed += spoolss_size_printer_driver_info_1(info);
4572 if (!alloc_buffer_size(buffer, *needed)) {
4573 SAFE_FREE(info);
4574 return WERR_INSUFFICIENT_BUFFER;
4577 /* fill the buffer with the structures */
4578 smb_io_printer_driver_info_1("", buffer, info, 0);
4580 /* clear memory */
4581 SAFE_FREE(info);
4583 if (*needed > offered)
4584 return WERR_INSUFFICIENT_BUFFER;
4586 return WERR_OK;
4589 /****************************************************************************
4590 ****************************************************************************/
4592 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4594 DRIVER_INFO_2 *info=NULL;
4595 WERROR status;
4597 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4598 return WERR_NOMEM;
4600 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4601 if (!W_ERROR_IS_OK(status)) {
4602 SAFE_FREE(info);
4603 return status;
4606 /* check the required size. */
4607 *needed += spoolss_size_printer_driver_info_2(info);
4609 if (!alloc_buffer_size(buffer, *needed)) {
4610 SAFE_FREE(info);
4611 return WERR_INSUFFICIENT_BUFFER;
4614 /* fill the buffer with the structures */
4615 smb_io_printer_driver_info_2("", buffer, info, 0);
4617 /* clear memory */
4618 SAFE_FREE(info);
4620 if (*needed > offered)
4621 return WERR_INSUFFICIENT_BUFFER;
4623 return WERR_OK;
4626 /****************************************************************************
4627 ****************************************************************************/
4629 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4631 DRIVER_INFO_3 info;
4632 WERROR status;
4634 ZERO_STRUCT(info);
4636 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4637 if (!W_ERROR_IS_OK(status)) {
4638 return status;
4641 /* check the required size. */
4642 *needed += spoolss_size_printer_driver_info_3(&info);
4644 if (!alloc_buffer_size(buffer, *needed)) {
4645 free_printer_driver_info_3(&info);
4646 return WERR_INSUFFICIENT_BUFFER;
4649 /* fill the buffer with the structures */
4650 smb_io_printer_driver_info_3("", buffer, &info, 0);
4652 free_printer_driver_info_3(&info);
4654 if (*needed > offered)
4655 return WERR_INSUFFICIENT_BUFFER;
4657 return WERR_OK;
4660 /****************************************************************************
4661 ****************************************************************************/
4663 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4665 DRIVER_INFO_6 info;
4666 WERROR status;
4668 ZERO_STRUCT(info);
4670 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4671 if (!W_ERROR_IS_OK(status)) {
4672 return status;
4675 /* check the required size. */
4676 *needed += spoolss_size_printer_driver_info_6(&info);
4678 if (!alloc_buffer_size(buffer, *needed)) {
4679 free_printer_driver_info_6(&info);
4680 return WERR_INSUFFICIENT_BUFFER;
4683 /* fill the buffer with the structures */
4684 smb_io_printer_driver_info_6("", buffer, &info, 0);
4686 free_printer_driver_info_6(&info);
4688 if (*needed > offered)
4689 return WERR_INSUFFICIENT_BUFFER;
4691 return WERR_OK;
4694 /****************************************************************************
4695 ****************************************************************************/
4697 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4699 POLICY_HND *handle = &q_u->handle;
4700 UNISTR2 *uni_arch = &q_u->architecture;
4701 uint32 level = q_u->level;
4702 uint32 clientmajorversion = q_u->clientmajorversion;
4703 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4704 NEW_BUFFER *buffer = NULL;
4705 uint32 offered = q_u->offered;
4706 uint32 *needed = &r_u->needed;
4707 uint32 *servermajorversion = &r_u->servermajorversion;
4708 uint32 *serverminorversion = &r_u->serverminorversion;
4710 fstring servername;
4711 fstring architecture;
4712 int snum;
4714 /* that's an [in out] buffer */
4715 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4716 buffer = r_u->buffer;
4718 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4720 *needed=0;
4721 *servermajorversion=0;
4722 *serverminorversion=0;
4724 pstrcpy(servername, get_called_name());
4725 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4727 if (!get_printer_snum(p, handle, &snum))
4728 return WERR_BADFID;
4730 switch (level) {
4731 case 1:
4732 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4733 case 2:
4734 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4735 case 3:
4736 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4737 case 6:
4738 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4741 return WERR_UNKNOWN_LEVEL;
4744 /****************************************************************************
4745 ****************************************************************************/
4747 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4749 POLICY_HND *handle = &q_u->handle;
4751 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4753 if (!Printer) {
4754 DEBUG(3,("Error in startpageprinter printer handle\n"));
4755 return WERR_BADFID;
4758 Printer->page_started=True;
4759 return WERR_OK;
4762 /****************************************************************************
4763 ****************************************************************************/
4765 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4767 POLICY_HND *handle = &q_u->handle;
4769 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4771 if (!Printer) {
4772 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4773 return WERR_BADFID;
4776 Printer->page_started=False;
4777 print_job_endpage(Printer->jobid);
4779 return WERR_OK;
4782 /********************************************************************
4783 * api_spoolss_getprinter
4784 * called from the spoolss dispatcher
4786 ********************************************************************/
4788 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4790 POLICY_HND *handle = &q_u->handle;
4791 /* uint32 level = q_u->doc_info_container.level; - notused. */
4792 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4793 uint32 *jobid = &r_u->jobid;
4795 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4796 int snum;
4797 pstring jobname;
4798 fstring datatype;
4799 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4800 struct current_user user;
4802 if (!Printer) {
4803 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4804 return WERR_BADFID;
4807 get_current_user(&user, p);
4810 * a nice thing with NT is it doesn't listen to what you tell it.
4811 * when asked to send _only_ RAW datas, it tries to send datas
4812 * in EMF format.
4814 * So I add checks like in NT Server ...
4816 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4817 * there's a bug in NT client-side code, so we'll fix it in the
4818 * server-side code. *nnnnnggggh!*
4821 if (info_1->p_datatype != 0) {
4822 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4823 if (strcmp(datatype, "RAW") != 0) {
4824 (*jobid)=0;
4825 return WERR_INVALID_DATATYPE;
4829 /* get the share number of the printer */
4830 if (!get_printer_snum(p, handle, &snum)) {
4831 return WERR_BADFID;
4834 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4836 Printer->jobid = print_job_start(&user, snum, jobname);
4838 /* An error occured in print_job_start() so return an appropriate
4839 NT error code. */
4841 if (Printer->jobid == -1) {
4842 return map_werror_from_unix(errno);
4845 Printer->document_started=True;
4846 (*jobid) = Printer->jobid;
4848 return WERR_OK;
4851 /********************************************************************
4852 * api_spoolss_getprinter
4853 * called from the spoolss dispatcher
4855 ********************************************************************/
4857 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4859 POLICY_HND *handle = &q_u->handle;
4861 return _spoolss_enddocprinter_internal(p, handle);
4864 /****************************************************************************
4865 ****************************************************************************/
4867 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4869 POLICY_HND *handle = &q_u->handle;
4870 uint32 buffer_size = q_u->buffer_size;
4871 uint8 *buffer = q_u->buffer;
4872 uint32 *buffer_written = &q_u->buffer_size2;
4874 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4876 if (!Printer) {
4877 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4878 r_u->buffer_written = q_u->buffer_size2;
4879 return WERR_BADFID;
4882 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4885 r_u->buffer_written = q_u->buffer_size2;
4887 return WERR_OK;
4890 /********************************************************************
4891 * api_spoolss_getprinter
4892 * called from the spoolss dispatcher
4894 ********************************************************************/
4896 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4897 pipes_struct *p)
4899 struct current_user user;
4900 int snum;
4901 WERROR errcode = WERR_BADFUNC;
4902 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4904 get_current_user(&user, p);
4906 if (!Printer) {
4907 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4908 return WERR_BADFID;
4911 if (!get_printer_snum(p, handle, &snum))
4912 return WERR_BADFID;
4914 switch (command) {
4915 case PRINTER_CONTROL_PAUSE:
4916 if (print_queue_pause(&user, snum, &errcode)) {
4917 errcode = WERR_OK;
4919 break;
4920 case PRINTER_CONTROL_RESUME:
4921 case PRINTER_CONTROL_UNPAUSE:
4922 if (print_queue_resume(&user, snum, &errcode)) {
4923 errcode = WERR_OK;
4925 break;
4926 case PRINTER_CONTROL_PURGE:
4927 if (print_queue_purge(&user, snum, &errcode)) {
4928 errcode = WERR_OK;
4930 break;
4931 default:
4932 return WERR_UNKNOWN_LEVEL;
4935 return errcode;
4938 /********************************************************************
4939 * api_spoolss_abortprinter
4940 ********************************************************************/
4942 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4944 POLICY_HND *handle = &q_u->handle;
4946 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4949 /********************************************************************
4950 * called by spoolss_api_setprinter
4951 * when updating a printer description
4952 ********************************************************************/
4954 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4955 const SPOOL_PRINTER_INFO_LEVEL *info,
4956 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4958 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4959 struct current_user user;
4960 WERROR result;
4961 int snum;
4963 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4965 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4966 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4967 OUR_HANDLE(handle)));
4969 result = WERR_BADFID;
4970 goto done;
4973 /* NT seems to like setting the security descriptor even though
4974 nothing may have actually changed. This causes annoying
4975 dialog boxes when the user doesn't have permission to change
4976 the security descriptor. */
4978 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4980 if (DEBUGLEVEL >= 10) {
4981 SEC_ACL *the_acl;
4982 int i;
4984 the_acl = old_secdesc_ctr->sec->dacl;
4985 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4986 PRINTERNAME(snum), the_acl->num_aces));
4988 for (i = 0; i < the_acl->num_aces; i++) {
4989 fstring sid_str;
4991 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4993 DEBUG(10, ("%s 0x%08x\n", sid_str,
4994 the_acl->ace[i].info.mask));
4997 the_acl = secdesc_ctr->sec->dacl;
4999 if (the_acl) {
5000 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5001 PRINTERNAME(snum), the_acl->num_aces));
5003 for (i = 0; i < the_acl->num_aces; i++) {
5004 fstring sid_str;
5006 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5008 DEBUG(10, ("%s 0x%08x\n", sid_str,
5009 the_acl->ace[i].info.mask));
5011 } else {
5012 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5016 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5018 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5019 result = WERR_OK;
5020 goto done;
5023 /* Work out which user is performing the operation */
5025 get_current_user(&user, p);
5027 /* Check the user has permissions to change the security
5028 descriptor. By experimentation with two NT machines, the user
5029 requires Full Access to the printer to change security
5030 information. */
5032 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5033 result = WERR_ACCESS_DENIED;
5034 goto done;
5037 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5039 done:
5041 return result;
5044 /********************************************************************
5045 Do Samba sanity checks on a printer info struct.
5046 this has changed purpose: it now "canonicalises" printer
5047 info from a client rather than just checking it is correct
5048 ********************************************************************/
5050 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5052 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5053 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5055 /* we force some elements to "correct" values */
5056 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5057 fstrcpy(info->sharename, lp_servicename(snum));
5058 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5059 get_called_name(), info->sharename);
5060 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5062 return True;
5065 /****************************************************************************
5066 ****************************************************************************/
5068 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5070 extern userdom_struct current_user_info;
5071 char *cmd = lp_addprinter_cmd();
5072 char **qlines;
5073 pstring command;
5074 pstring driverlocation;
5075 int numlines;
5076 int ret;
5077 int fd;
5078 fstring remote_machine = "%m";
5080 /* build driver path... only 9X architecture is needed for legacy reasons */
5081 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5082 get_called_name());
5083 /* change \ to \\ for the shell */
5084 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5085 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5087 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5088 cmd, printer->info_2->printername, printer->info_2->sharename,
5089 printer->info_2->portname, printer->info_2->drivername,
5090 printer->info_2->location, driverlocation, remote_machine);
5092 DEBUG(10,("Running [%s]\n", command));
5093 ret = smbrun(command, &fd);
5094 DEBUGADD(10,("returned [%d]\n", ret));
5096 if ( ret != 0 ) {
5097 if (fd != -1)
5098 close(fd);
5099 return False;
5102 numlines = 0;
5103 /* Get lines and convert them back to dos-codepage */
5104 qlines = fd_lines_load(fd, &numlines);
5105 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5106 close(fd);
5108 if(numlines) {
5109 /* Set the portname to what the script says the portname should be. */
5110 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5111 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5113 /* Send SIGHUP to process group... is there a better way? */
5114 kill(0, SIGHUP);
5115 add_all_printers();
5118 file_lines_free(qlines);
5119 return True;
5122 #if 0 /* JERRY */
5124 /* Return true if two devicemodes are equal */
5126 #define DEVMODE_CHECK_INT(field) \
5127 if (d1->field != d2->field) { \
5128 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
5129 d1->field, d2->field)); \
5130 return False; \
5133 /************************************************************************
5134 Handy, but currently unused functions
5135 ***********************************************************************/
5137 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
5139 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
5141 if (!d1 ^ !d2) {
5142 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
5143 return False; /* if either is exclusively NULL are not equal */
5146 if (!strequal(d1->devicename, d2->devicename)) {
5147 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
5148 return False;
5151 if (!strequal(d1->formname, d2->formname)) {
5152 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
5153 return False;
5156 DEVMODE_CHECK_INT(specversion);
5157 DEVMODE_CHECK_INT(driverversion);
5158 DEVMODE_CHECK_INT(driverextra);
5159 DEVMODE_CHECK_INT(orientation);
5160 DEVMODE_CHECK_INT(papersize);
5161 DEVMODE_CHECK_INT(paperlength);
5162 DEVMODE_CHECK_INT(paperwidth);
5163 DEVMODE_CHECK_INT(scale);
5164 DEVMODE_CHECK_INT(copies);
5165 DEVMODE_CHECK_INT(defaultsource);
5166 DEVMODE_CHECK_INT(printquality);
5167 DEVMODE_CHECK_INT(color);
5168 DEVMODE_CHECK_INT(duplex);
5169 DEVMODE_CHECK_INT(yresolution);
5170 DEVMODE_CHECK_INT(ttoption);
5171 DEVMODE_CHECK_INT(collate);
5172 DEVMODE_CHECK_INT(logpixels);
5174 DEVMODE_CHECK_INT(fields);
5175 DEVMODE_CHECK_INT(bitsperpel);
5176 DEVMODE_CHECK_INT(pelswidth);
5177 DEVMODE_CHECK_INT(pelsheight);
5178 DEVMODE_CHECK_INT(displayflags);
5179 DEVMODE_CHECK_INT(displayfrequency);
5180 DEVMODE_CHECK_INT(icmmethod);
5181 DEVMODE_CHECK_INT(icmintent);
5182 DEVMODE_CHECK_INT(mediatype);
5183 DEVMODE_CHECK_INT(dithertype);
5184 DEVMODE_CHECK_INT(reserved1);
5185 DEVMODE_CHECK_INT(reserved2);
5186 DEVMODE_CHECK_INT(panningwidth);
5187 DEVMODE_CHECK_INT(panningheight);
5189 /* compare the private data if it exists */
5190 if (!d1->driverextra && !d2->driverextra) goto equal;
5193 DEVMODE_CHECK_INT(driverextra);
5195 if (memcmp(d1->private, d2->private, d1->driverextra)) {
5196 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
5197 return False;
5200 equal:
5201 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
5202 return True;
5205 /* Return true if two NT_PRINTER_PARAM structures are equal */
5207 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
5208 NT_PRINTER_PARAM *p2)
5210 if (!p1 && !p2) goto equal;
5212 if ((!p1 && p2) || (p1 && !p2)) {
5213 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
5214 return False;
5217 /* Compare lists of printer parameters */
5219 while (p1) {
5220 BOOL found = False;
5221 NT_PRINTER_PARAM *q = p1;
5223 /* Find the parameter in the second structure */
5225 while(q) {
5227 if (strequal(p1->value, q->value)) {
5229 if (p1->type != q->type) {
5230 DEBUG(10, ("nt_printer_param_equal():"
5231 "types for %s differ (%d != %d)\n",
5232 p1->value, p1->type,
5233 q->type));
5234 break;
5237 if (p1->data_len != q->data_len) {
5238 DEBUG(10, ("nt_printer_param_equal():"
5239 "len for %s differs (%d != %d)\n",
5240 p1->value, p1->data_len,
5241 q->data_len));
5242 break;
5245 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
5246 found = True;
5247 } else {
5248 DEBUG(10, ("nt_printer_param_equal():"
5249 "data for %s differs\n", p1->value));
5252 break;
5255 q = q->next;
5258 if (!found) {
5259 DEBUG(10, ("nt_printer_param_equal(): param %s "
5260 "does not exist\n", p1->value));
5261 return False;
5264 p1 = p1->next;
5267 equal:
5269 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
5270 return True;
5273 /********************************************************************
5274 * Called by update_printer when trying to work out whether to
5275 * actually update printer info.
5276 ********************************************************************/
5278 #define PI_CHECK_INT(field) \
5279 if (pi1->field != pi2->field) { \
5280 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
5281 pi1->field, pi2->field)); \
5282 return False; \
5285 #define PI_CHECK_STR(field) \
5286 if (!strequal(pi1->field, pi2->field)) { \
5287 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
5288 pi1->field, pi2->field)); \
5289 return False; \
5292 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
5293 NT_PRINTER_INFO_LEVEL *p2)
5295 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
5297 /* Trivial conditions */
5299 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
5300 goto equal;
5303 if ((!p1 && p2) || (p1 && !p2) ||
5304 (!p1->info_2 && p2->info_2) ||
5305 (p1->info_2 && !p2->info_2)) {
5306 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
5307 "differ\n"));
5308 return False;
5311 /* Compare two nt_printer_info_level structures. Don't compare
5312 status or cjobs as they seem to have something to do with the
5313 printer queue. */
5315 pi1 = p1->info_2;
5316 pi2 = p2->info_2;
5318 /* Don't check the attributes as we stomp on the value in
5319 check_printer_ok() anyway. */
5321 #if 0
5322 PI_CHECK_INT(attributes);
5323 #endif
5325 PI_CHECK_INT(priority);
5326 PI_CHECK_INT(default_priority);
5327 PI_CHECK_INT(starttime);
5328 PI_CHECK_INT(untiltime);
5329 PI_CHECK_INT(averageppm);
5331 /* Yuck - don't check the printername or servername as the
5332 mod_a_printer() code plays games with them. You can't
5333 change the printername or the sharename through this interface
5334 in Samba. */
5336 PI_CHECK_STR(sharename);
5337 PI_CHECK_STR(portname);
5338 PI_CHECK_STR(drivername);
5339 PI_CHECK_STR(comment);
5340 PI_CHECK_STR(location);
5342 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
5343 return False;
5346 PI_CHECK_STR(sepfile);
5347 PI_CHECK_STR(printprocessor);
5348 PI_CHECK_STR(datatype);
5349 PI_CHECK_STR(parameters);
5351 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
5352 return False;
5355 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
5356 return False;
5359 PI_CHECK_INT(changeid);
5360 PI_CHECK_INT(c_setprinter);
5361 PI_CHECK_INT(setuptime);
5363 equal:
5364 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5365 return True;
5368 #endif
5370 /********************************************************************
5371 * Called by spoolss_api_setprinter
5372 * when updating a printer description.
5373 ********************************************************************/
5375 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5376 const SPOOL_PRINTER_INFO_LEVEL *info,
5377 DEVICEMODE *devmode)
5379 int snum;
5380 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5381 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5382 WERROR result;
5384 DEBUG(8,("update_printer\n"));
5386 result = WERR_OK;
5388 if (level!=2) {
5389 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5390 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5391 result = WERR_UNKNOWN_LEVEL;
5392 goto done;
5395 if (!Printer) {
5396 result = WERR_BADFID;
5397 goto done;
5400 if (!get_printer_snum(p, handle, &snum)) {
5401 result = WERR_BADFID;
5402 goto done;
5405 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5406 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5407 result = WERR_BADFID;
5408 goto done;
5411 DEBUGADD(8,("Converting info_2 struct\n"));
5414 * convert_printer_info converts the incoming
5415 * info from the client and overwrites the info
5416 * just read from the tdb in the pointer 'printer'.
5419 if (!convert_printer_info(info, printer, level)) {
5420 result = WERR_NOMEM;
5421 goto done;
5424 if (devmode) {
5425 /* we have a valid devmode
5426 convert it and link it*/
5428 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5429 if (!convert_devicemode(printer->info_2->printername, devmode,
5430 &printer->info_2->devmode)) {
5431 result = WERR_NOMEM;
5432 goto done;
5436 /* Do sanity check on the requested changes for Samba */
5438 if (!check_printer_ok(printer->info_2, snum)) {
5439 result = WERR_INVALID_PARAM;
5440 goto done;
5443 #if 0 /* JERRY */
5446 * Another one of those historical misunderstandings...
5447 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5448 * I'm leaving it here as a reminder. --jerry
5451 if (nt_printer_info_level_equal(printer, old_printer)) {
5452 DEBUG(3, ("update_printer: printer info has not changed\n"));
5453 result = WERR_OK;
5454 goto done;
5457 #endif
5459 /* Check calling user has permission to update printer description */
5461 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5462 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5463 result = WERR_ACCESS_DENIED;
5464 goto done;
5467 /* Call addprinter hook */
5469 if (*lp_addprinter_cmd()) {
5470 if ( !add_printer_hook(printer) ) {
5471 result = WERR_ACCESS_DENIED;
5472 goto done;
5477 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5478 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5479 * requires Win32 client code (see other notes elsewhere in the code).
5481 if (printer->info_2->devmode &&
5482 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5484 DEBUG(10,("update_printer: Save printer driver init data\n"));
5485 printer->info_2->devmode->displayfrequency = 0;
5487 if (update_driver_init(*printer, 2)!=0) {
5488 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5489 result = WERR_ACCESS_DENIED;
5490 goto done;
5492 } else {
5494 * When a *new* driver is bound to a printer, the drivername is used to
5495 * lookup previously saved driver initialization info, which is then
5496 * bound to the printer, simulating what happens in the Windows arch.
5498 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5499 if (!set_driver_init(printer, 2)) {
5500 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5501 printer->info_2->drivername));
5503 notify_printer_driver(snum, printer->info_2->drivername);
5507 /* Update printer info */
5508 result = mod_a_printer(*printer, 2);
5510 /* flag which changes actually occured. This is a small subset of
5511 all the possible changes */
5513 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5514 notify_printer_comment(snum, printer->info_2->comment);
5516 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5517 notify_printer_sharename(snum, printer->info_2->sharename);
5519 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5520 notify_printer_port(snum, printer->info_2->portname);
5522 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5523 notify_printer_location(snum, printer->info_2->location);
5525 done:
5526 free_a_printer(&printer, 2);
5527 free_a_printer(&old_printer, 2);
5530 return result;
5533 /****************************************************************************
5534 ****************************************************************************/
5536 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5538 POLICY_HND *handle = &q_u->handle;
5539 uint32 level = q_u->level;
5540 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5541 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5542 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5543 uint32 command = q_u->command;
5545 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5547 if (!Printer) {
5548 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5549 return WERR_BADFID;
5552 /* check the level */
5553 switch (level) {
5554 case 0:
5555 return control_printer(handle, command, p);
5556 case 2:
5557 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5558 case 3:
5559 return update_printer_sec(handle, level, info, p,
5560 secdesc_ctr);
5561 default:
5562 return WERR_UNKNOWN_LEVEL;
5566 /****************************************************************************
5567 ****************************************************************************/
5569 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5571 POLICY_HND *handle = &q_u->handle;
5573 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5575 if (!Printer) {
5576 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5577 return WERR_BADFID;
5580 if (Printer->notify.client_connected==True)
5581 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5583 Printer->notify.flags=0;
5584 Printer->notify.options=0;
5585 Printer->notify.localmachine[0]='\0';
5586 Printer->notify.printerlocal=0;
5587 if (Printer->notify.option)
5588 free_spool_notify_option(&Printer->notify.option);
5589 Printer->notify.client_connected=False;
5591 return WERR_OK;
5594 /****************************************************************************
5595 ****************************************************************************/
5597 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5599 /* that's an [in out] buffer (despite appearences to the contrary) */
5600 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5602 r_u->needed = 0;
5603 return WERR_INVALID_PARAM; /* this is what a NT server
5604 returns for AddJob. AddJob
5605 must fail on non-local
5606 printers */
5609 /****************************************************************************
5610 ****************************************************************************/
5612 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5613 int position, int snum)
5615 pstring temp_name;
5617 struct tm *t;
5619 t=gmtime(&queue->time);
5620 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5622 job_info->jobid=queue->job;
5623 init_unistr(&job_info->printername, lp_servicename(snum));
5624 init_unistr(&job_info->machinename, temp_name);
5625 init_unistr(&job_info->username, queue->fs_user);
5626 init_unistr(&job_info->document, queue->fs_file);
5627 init_unistr(&job_info->datatype, "RAW");
5628 init_unistr(&job_info->text_status, "");
5629 job_info->status=nt_printj_status(queue->status);
5630 job_info->priority=queue->priority;
5631 job_info->position=position;
5632 job_info->totalpages=queue->page_count;
5633 job_info->pagesprinted=0;
5635 make_systemtime(&job_info->submitted, t);
5638 /****************************************************************************
5639 ****************************************************************************/
5641 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5642 int position, int snum,
5643 NT_PRINTER_INFO_LEVEL *ntprinter,
5644 DEVICEMODE *devmode)
5646 pstring temp_name;
5647 pstring chaine;
5648 struct tm *t;
5650 t=gmtime(&queue->time);
5651 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5653 job_info->jobid=queue->job;
5655 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5657 init_unistr(&job_info->printername, chaine);
5659 init_unistr(&job_info->machinename, temp_name);
5660 init_unistr(&job_info->username, queue->fs_user);
5661 init_unistr(&job_info->document, queue->fs_file);
5662 init_unistr(&job_info->notifyname, queue->fs_user);
5663 init_unistr(&job_info->datatype, "RAW");
5664 init_unistr(&job_info->printprocessor, "winprint");
5665 init_unistr(&job_info->parameters, "");
5666 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5667 init_unistr(&job_info->text_status, "");
5669 /* and here the security descriptor */
5671 job_info->status=nt_printj_status(queue->status);
5672 job_info->priority=queue->priority;
5673 job_info->position=position;
5674 job_info->starttime=0;
5675 job_info->untiltime=0;
5676 job_info->totalpages=queue->page_count;
5677 job_info->size=queue->size;
5678 make_systemtime(&(job_info->submitted), t);
5679 job_info->timeelapsed=0;
5680 job_info->pagesprinted=0;
5682 job_info->devmode = devmode;
5684 return (True);
5687 /****************************************************************************
5688 Enumjobs at level 1.
5689 ****************************************************************************/
5691 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5692 NEW_BUFFER *buffer, uint32 offered,
5693 uint32 *needed, uint32 *returned)
5695 JOB_INFO_1 *info;
5696 int i;
5698 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5699 if (info==NULL) {
5700 SAFE_FREE(queue);
5701 *returned=0;
5702 return WERR_NOMEM;
5705 for (i=0; i<*returned; i++)
5706 fill_job_info_1(&info[i], &queue[i], i, snum);
5708 SAFE_FREE(queue);
5710 /* check the required size. */
5711 for (i=0; i<*returned; i++)
5712 (*needed) += spoolss_size_job_info_1(&info[i]);
5714 if (!alloc_buffer_size(buffer, *needed)) {
5715 SAFE_FREE(info);
5716 return WERR_INSUFFICIENT_BUFFER;
5719 /* fill the buffer with the structures */
5720 for (i=0; i<*returned; i++)
5721 smb_io_job_info_1("", buffer, &info[i], 0);
5723 /* clear memory */
5724 SAFE_FREE(info);
5726 if (*needed > offered) {
5727 *returned=0;
5728 return WERR_INSUFFICIENT_BUFFER;
5731 return WERR_OK;
5734 /****************************************************************************
5735 Enumjobs at level 2.
5736 ****************************************************************************/
5738 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5739 NEW_BUFFER *buffer, uint32 offered,
5740 uint32 *needed, uint32 *returned)
5742 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5743 JOB_INFO_2 *info = NULL;
5744 int i;
5745 WERROR result;
5746 DEVICEMODE *devmode = NULL;
5748 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5749 if (info==NULL) {
5750 *returned=0;
5751 result = WERR_NOMEM;
5752 goto done;
5755 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5756 if (!W_ERROR_IS_OK(result)) {
5757 *returned = 0;
5758 goto done;
5761 if (!(devmode = construct_dev_mode(snum))) {
5762 *returned = 0;
5763 result = WERR_NOMEM;
5764 goto done;
5767 for (i=0; i<*returned; i++)
5768 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5769 devmode);
5771 free_a_printer(&ntprinter, 2);
5772 SAFE_FREE(queue);
5774 /* check the required size. */
5775 for (i=0; i<*returned; i++)
5776 (*needed) += spoolss_size_job_info_2(&info[i]);
5778 if (*needed > offered) {
5779 *returned=0;
5780 result = WERR_INSUFFICIENT_BUFFER;
5781 goto done;
5784 if (!alloc_buffer_size(buffer, *needed)) {
5785 SAFE_FREE(info);
5786 result = WERR_INSUFFICIENT_BUFFER;
5787 goto done;
5790 /* fill the buffer with the structures */
5791 for (i=0; i<*returned; i++)
5792 smb_io_job_info_2("", buffer, &info[i], 0);
5794 result = WERR_OK;
5796 done:
5797 free_a_printer(&ntprinter, 2);
5798 free_devmode(devmode);
5799 SAFE_FREE(queue);
5800 SAFE_FREE(info);
5802 return result;
5806 /****************************************************************************
5807 Enumjobs.
5808 ****************************************************************************/
5810 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5812 POLICY_HND *handle = &q_u->handle;
5813 /* uint32 firstjob = q_u->firstjob; - notused. */
5814 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5815 uint32 level = q_u->level;
5816 NEW_BUFFER *buffer = NULL;
5817 uint32 offered = q_u->offered;
5818 uint32 *needed = &r_u->needed;
5819 uint32 *returned = &r_u->returned;
5821 int snum;
5822 print_status_struct prt_status;
5823 print_queue_struct *queue=NULL;
5825 /* that's an [in out] buffer */
5826 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5827 buffer = r_u->buffer;
5829 DEBUG(4,("_spoolss_enumjobs\n"));
5831 *needed=0;
5832 *returned=0;
5834 if (!get_printer_snum(p, handle, &snum))
5835 return WERR_BADFID;
5837 *returned = print_queue_status(snum, &queue, &prt_status);
5838 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5840 if (*returned == 0) {
5841 SAFE_FREE(queue);
5842 return WERR_OK;
5845 switch (level) {
5846 case 1:
5847 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5848 case 2:
5849 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5850 default:
5851 SAFE_FREE(queue);
5852 *returned=0;
5853 return WERR_UNKNOWN_LEVEL;
5857 /****************************************************************************
5858 ****************************************************************************/
5860 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5862 return WERR_OK;
5865 /****************************************************************************
5866 ****************************************************************************/
5868 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5870 POLICY_HND *handle = &q_u->handle;
5871 uint32 jobid = q_u->jobid;
5872 /* uint32 level = q_u->level; - notused. */
5873 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5874 uint32 command = q_u->command;
5876 struct current_user user;
5877 int snum;
5878 WERROR errcode = WERR_BADFUNC;
5880 if (!get_printer_snum(p, handle, &snum)) {
5881 return WERR_BADFID;
5884 if (!print_job_exists(jobid)) {
5885 return WERR_INVALID_PRINTER_NAME;
5888 get_current_user(&user, p);
5890 switch (command) {
5891 case JOB_CONTROL_CANCEL:
5892 case JOB_CONTROL_DELETE:
5893 if (print_job_delete(&user, jobid, &errcode)) {
5894 errcode = WERR_OK;
5896 break;
5897 case JOB_CONTROL_PAUSE:
5898 if (print_job_pause(&user, jobid, &errcode)) {
5899 errcode = WERR_OK;
5901 break;
5902 case JOB_CONTROL_RESTART:
5903 case JOB_CONTROL_RESUME:
5904 if (print_job_resume(&user, jobid, &errcode)) {
5905 errcode = WERR_OK;
5907 break;
5908 default:
5909 return WERR_UNKNOWN_LEVEL;
5912 return errcode;
5915 /****************************************************************************
5916 Enumerates all printer drivers at level 1.
5917 ****************************************************************************/
5919 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5921 int i;
5922 int ndrivers;
5923 uint32 version;
5924 fstring *list = NULL;
5926 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5927 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5929 *returned=0;
5931 #define MAX_VERSION 4
5933 for (version=0; version<MAX_VERSION; version++) {
5934 list=NULL;
5935 ndrivers=get_ntdrivers(&list, architecture, version);
5936 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5938 if(ndrivers == -1)
5939 return WERR_NOMEM;
5941 if(ndrivers != 0) {
5942 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5943 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5944 SAFE_FREE(driver_info_1);
5945 SAFE_FREE(list);
5946 return WERR_NOMEM;
5948 else driver_info_1 = tdi1;
5951 for (i=0; i<ndrivers; i++) {
5952 WERROR status;
5953 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5954 ZERO_STRUCT(driver);
5955 status = get_a_printer_driver(&driver, 3, list[i],
5956 architecture, version);
5957 if (!W_ERROR_IS_OK(status)) {
5958 SAFE_FREE(list);
5959 return status;
5961 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5962 free_a_printer_driver(driver, 3);
5965 *returned+=ndrivers;
5966 SAFE_FREE(list);
5969 /* check the required size. */
5970 for (i=0; i<*returned; i++) {
5971 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5972 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5975 if (!alloc_buffer_size(buffer, *needed)) {
5976 SAFE_FREE(driver_info_1);
5977 return WERR_INSUFFICIENT_BUFFER;
5980 /* fill the buffer with the driver structures */
5981 for (i=0; i<*returned; i++) {
5982 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5983 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5986 SAFE_FREE(driver_info_1);
5988 if (*needed > offered) {
5989 *returned=0;
5990 return WERR_INSUFFICIENT_BUFFER;
5993 return WERR_OK;
5996 /****************************************************************************
5997 Enumerates all printer drivers at level 2.
5998 ****************************************************************************/
6000 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6002 int i;
6003 int ndrivers;
6004 uint32 version;
6005 fstring *list = NULL;
6007 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6008 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6010 *returned=0;
6012 #define MAX_VERSION 4
6014 for (version=0; version<MAX_VERSION; version++) {
6015 list=NULL;
6016 ndrivers=get_ntdrivers(&list, architecture, version);
6017 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6019 if(ndrivers == -1)
6020 return WERR_NOMEM;
6022 if(ndrivers != 0) {
6023 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6024 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6025 SAFE_FREE(driver_info_2);
6026 SAFE_FREE(list);
6027 return WERR_NOMEM;
6029 else driver_info_2 = tdi2;
6032 for (i=0; i<ndrivers; i++) {
6033 WERROR status;
6035 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6036 ZERO_STRUCT(driver);
6037 status = get_a_printer_driver(&driver, 3, list[i],
6038 architecture, version);
6039 if (!W_ERROR_IS_OK(status)) {
6040 SAFE_FREE(list);
6041 return status;
6043 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6044 free_a_printer_driver(driver, 3);
6047 *returned+=ndrivers;
6048 SAFE_FREE(list);
6051 /* check the required size. */
6052 for (i=0; i<*returned; i++) {
6053 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6054 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6057 if (!alloc_buffer_size(buffer, *needed)) {
6058 SAFE_FREE(driver_info_2);
6059 return WERR_INSUFFICIENT_BUFFER;
6062 /* fill the buffer with the form structures */
6063 for (i=0; i<*returned; i++) {
6064 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6065 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6068 SAFE_FREE(driver_info_2);
6070 if (*needed > offered) {
6071 *returned=0;
6072 return WERR_INSUFFICIENT_BUFFER;
6075 return WERR_OK;
6078 /****************************************************************************
6079 Enumerates all printer drivers at level 3.
6080 ****************************************************************************/
6082 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6084 int i;
6085 int ndrivers;
6086 uint32 version;
6087 fstring *list = NULL;
6089 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6090 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6092 *returned=0;
6094 #define MAX_VERSION 4
6096 for (version=0; version<MAX_VERSION; version++) {
6097 list=NULL;
6098 ndrivers=get_ntdrivers(&list, architecture, version);
6099 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6101 if(ndrivers == -1)
6102 return WERR_NOMEM;
6104 if(ndrivers != 0) {
6105 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6106 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6107 SAFE_FREE(driver_info_3);
6108 SAFE_FREE(list);
6109 return WERR_NOMEM;
6111 else driver_info_3 = tdi3;
6114 for (i=0; i<ndrivers; i++) {
6115 WERROR status;
6117 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6118 ZERO_STRUCT(driver);
6119 status = get_a_printer_driver(&driver, 3, list[i],
6120 architecture, version);
6121 if (!W_ERROR_IS_OK(status)) {
6122 SAFE_FREE(list);
6123 return status;
6125 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6126 free_a_printer_driver(driver, 3);
6129 *returned+=ndrivers;
6130 SAFE_FREE(list);
6133 /* check the required size. */
6134 for (i=0; i<*returned; i++) {
6135 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6136 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6139 if (!alloc_buffer_size(buffer, *needed)) {
6140 SAFE_FREE(driver_info_3);
6141 return WERR_INSUFFICIENT_BUFFER;
6144 /* fill the buffer with the driver structures */
6145 for (i=0; i<*returned; i++) {
6146 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6147 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6150 for (i=0; i<*returned; i++)
6151 SAFE_FREE(driver_info_3[i].dependentfiles);
6153 SAFE_FREE(driver_info_3);
6155 if (*needed > offered) {
6156 *returned=0;
6157 return WERR_INSUFFICIENT_BUFFER;
6160 return WERR_OK;
6163 /****************************************************************************
6164 Enumerates all printer drivers.
6165 ****************************************************************************/
6167 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6169 /* UNISTR2 *name = &q_u->name; - notused. */
6170 UNISTR2 *environment = &q_u->environment;
6171 uint32 level = q_u->level;
6172 NEW_BUFFER *buffer = NULL;
6173 uint32 offered = q_u->offered;
6174 uint32 *needed = &r_u->needed;
6175 uint32 *returned = &r_u->returned;
6177 fstring *list = NULL;
6178 fstring servername;
6179 fstring architecture;
6181 /* that's an [in out] buffer */
6182 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6183 buffer = r_u->buffer;
6185 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6186 fstrcpy(servername, get_called_name());
6187 *needed=0;
6188 *returned=0;
6190 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6192 switch (level) {
6193 case 1:
6194 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6195 case 2:
6196 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6197 case 3:
6198 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6199 default:
6200 *returned=0;
6201 SAFE_FREE(list);
6202 return WERR_UNKNOWN_LEVEL;
6206 /****************************************************************************
6207 ****************************************************************************/
6209 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6211 form->flag=list->flag;
6212 init_unistr(&form->name, list->name);
6213 form->width=list->width;
6214 form->length=list->length;
6215 form->left=list->left;
6216 form->top=list->top;
6217 form->right=list->right;
6218 form->bottom=list->bottom;
6221 /****************************************************************************
6222 ****************************************************************************/
6224 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6226 /* POLICY_HND *handle = &q_u->handle; - notused. */
6227 uint32 level = q_u->level;
6228 NEW_BUFFER *buffer = NULL;
6229 uint32 offered = q_u->offered;
6230 uint32 *needed = &r_u->needed;
6231 uint32 *numofforms = &r_u->numofforms;
6232 uint32 numbuiltinforms;
6234 nt_forms_struct *list=NULL;
6235 nt_forms_struct *builtinlist=NULL;
6236 FORM_1 *forms_1;
6237 int buffer_size=0;
6238 int i;
6240 /* that's an [in out] buffer */
6241 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6242 buffer = r_u->buffer;
6244 DEBUG(4,("_spoolss_enumforms\n"));
6245 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6246 DEBUGADD(5,("Info level [%d]\n", level));
6248 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6249 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6250 *numofforms = get_ntforms(&list);
6251 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6252 *numofforms += numbuiltinforms;
6254 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6256 switch (level) {
6257 case 1:
6258 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6259 *numofforms=0;
6260 return WERR_NOMEM;
6263 /* construct the list of form structures */
6264 for (i=0; i<numbuiltinforms; i++) {
6265 DEBUGADD(6,("Filling form number [%d]\n",i));
6266 fill_form_1(&forms_1[i], &builtinlist[i]);
6269 SAFE_FREE(builtinlist);
6271 for (; i<*numofforms; i++) {
6272 DEBUGADD(6,("Filling form number [%d]\n",i));
6273 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6276 SAFE_FREE(list);
6278 /* check the required size. */
6279 for (i=0; i<numbuiltinforms; i++) {
6280 DEBUGADD(6,("adding form [%d]'s size\n",i));
6281 buffer_size += spoolss_size_form_1(&forms_1[i]);
6283 for (; i<*numofforms; i++) {
6284 DEBUGADD(6,("adding form [%d]'s size\n",i));
6285 buffer_size += spoolss_size_form_1(&forms_1[i]);
6288 *needed=buffer_size;
6290 if (!alloc_buffer_size(buffer, buffer_size)){
6291 SAFE_FREE(forms_1);
6292 return WERR_INSUFFICIENT_BUFFER;
6295 /* fill the buffer with the form structures */
6296 for (i=0; i<numbuiltinforms; i++) {
6297 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6298 smb_io_form_1("", buffer, &forms_1[i], 0);
6300 for (; i<*numofforms; i++) {
6301 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6302 smb_io_form_1("", buffer, &forms_1[i], 0);
6305 SAFE_FREE(forms_1);
6307 if (*needed > offered) {
6308 *numofforms=0;
6309 return WERR_INSUFFICIENT_BUFFER;
6311 else
6312 return WERR_OK;
6314 default:
6315 SAFE_FREE(list);
6316 SAFE_FREE(builtinlist);
6317 return WERR_UNKNOWN_LEVEL;
6322 /****************************************************************************
6323 ****************************************************************************/
6325 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6327 /* POLICY_HND *handle = &q_u->handle; - notused. */
6328 uint32 level = q_u->level;
6329 UNISTR2 *uni_formname = &q_u->formname;
6330 NEW_BUFFER *buffer = NULL;
6331 uint32 offered = q_u->offered;
6332 uint32 *needed = &r_u->needed;
6334 nt_forms_struct *list=NULL;
6335 nt_forms_struct builtin_form;
6336 BOOL foundBuiltin;
6337 FORM_1 form_1;
6338 fstring form_name;
6339 int buffer_size=0;
6340 int numofforms=0, i=0;
6342 /* that's an [in out] buffer */
6343 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6344 buffer = r_u->buffer;
6346 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6348 DEBUG(4,("_spoolss_getform\n"));
6349 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6350 DEBUGADD(5,("Info level [%d]\n", level));
6352 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6353 if (!foundBuiltin) {
6354 numofforms = get_ntforms(&list);
6355 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6357 if (numofforms == 0)
6358 return WERR_BADFID;
6361 switch (level) {
6362 case 1:
6363 if (foundBuiltin) {
6364 fill_form_1(&form_1, &builtin_form);
6365 } else {
6367 /* Check if the requested name is in the list of form structures */
6368 for (i=0; i<numofforms; i++) {
6370 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6372 if (strequal(form_name, list[i].name)) {
6373 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6374 fill_form_1(&form_1, &list[i]);
6375 break;
6379 SAFE_FREE(list);
6380 if (i == numofforms) {
6381 return WERR_BADFID;
6384 /* check the required size. */
6386 *needed=spoolss_size_form_1(&form_1);
6388 if (!alloc_buffer_size(buffer, buffer_size)){
6389 return WERR_INSUFFICIENT_BUFFER;
6392 if (*needed > offered) {
6393 return WERR_INSUFFICIENT_BUFFER;
6396 /* fill the buffer with the form structures */
6397 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6398 smb_io_form_1("", buffer, &form_1, 0);
6400 return WERR_OK;
6402 default:
6403 SAFE_FREE(list);
6404 return WERR_UNKNOWN_LEVEL;
6408 /****************************************************************************
6409 ****************************************************************************/
6411 static void fill_port_1(PORT_INFO_1 *port, char *name)
6413 init_unistr(&port->port_name, name);
6416 /****************************************************************************
6417 ****************************************************************************/
6419 static void fill_port_2(PORT_INFO_2 *port, char *name)
6421 init_unistr(&port->port_name, name);
6422 init_unistr(&port->monitor_name, "Local Monitor");
6423 init_unistr(&port->description, "Local Port");
6424 #define PORT_TYPE_WRITE 1
6425 port->port_type=PORT_TYPE_WRITE;
6426 port->reserved=0x0;
6429 /****************************************************************************
6430 enumports level 1.
6431 ****************************************************************************/
6433 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6435 PORT_INFO_1 *ports=NULL;
6436 int i=0;
6438 if (*lp_enumports_cmd()) {
6439 char *cmd = lp_enumports_cmd();
6440 char **qlines;
6441 pstring command;
6442 int numlines;
6443 int ret;
6444 int fd;
6446 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6448 DEBUG(10,("Running [%s]\n", command));
6449 ret = smbrun(command, &fd);
6450 DEBUG(10,("Returned [%d]\n", ret));
6451 if (ret != 0) {
6452 if (fd != -1)
6453 close(fd);
6454 /* Is this the best error to return here? */
6455 return WERR_ACCESS_DENIED;
6458 numlines = 0;
6459 qlines = fd_lines_load(fd, &numlines);
6460 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6461 close(fd);
6463 if(numlines) {
6464 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6465 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6466 dos_errstr(WERR_NOMEM)));
6467 file_lines_free(qlines);
6468 return WERR_NOMEM;
6471 for (i=0; i<numlines; i++) {
6472 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6473 fill_port_1(&ports[i], qlines[i]);
6476 file_lines_free(qlines);
6479 *returned = numlines;
6481 } else {
6482 *returned = 1; /* Sole Samba port returned. */
6484 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6485 return WERR_NOMEM;
6487 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6489 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6492 /* check the required size. */
6493 for (i=0; i<*returned; i++) {
6494 DEBUGADD(6,("adding port [%d]'s size\n", i));
6495 *needed += spoolss_size_port_info_1(&ports[i]);
6498 if (!alloc_buffer_size(buffer, *needed)) {
6499 SAFE_FREE(ports);
6500 return WERR_INSUFFICIENT_BUFFER;
6503 /* fill the buffer with the ports structures */
6504 for (i=0; i<*returned; i++) {
6505 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6506 smb_io_port_1("", buffer, &ports[i], 0);
6509 SAFE_FREE(ports);
6511 if (*needed > offered) {
6512 *returned=0;
6513 return WERR_INSUFFICIENT_BUFFER;
6516 return WERR_OK;
6519 /****************************************************************************
6520 enumports level 2.
6521 ****************************************************************************/
6523 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6525 PORT_INFO_2 *ports=NULL;
6526 int i=0;
6528 if (*lp_enumports_cmd()) {
6529 char *cmd = lp_enumports_cmd();
6530 char *path;
6531 char **qlines;
6532 pstring tmp_file;
6533 pstring command;
6534 int numlines;
6535 int ret;
6536 int fd;
6538 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6539 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6540 else
6541 path = lp_lockdir();
6543 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6544 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6546 unlink(tmp_file);
6547 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6548 ret = smbrun(command, &fd);
6549 DEBUGADD(10,("returned [%d]\n", ret));
6550 if (ret != 0) {
6551 if (fd != -1)
6552 close(fd);
6553 /* Is this the best error to return here? */
6554 return WERR_ACCESS_DENIED;
6557 numlines = 0;
6558 qlines = fd_lines_load(fd, &numlines);
6559 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6560 close(fd);
6562 if(numlines) {
6563 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6564 file_lines_free(qlines);
6565 return WERR_NOMEM;
6568 for (i=0; i<numlines; i++) {
6569 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6570 fill_port_2(&(ports[i]), qlines[i]);
6573 file_lines_free(qlines);
6576 *returned = numlines;
6578 } else {
6580 *returned = 1;
6582 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6583 return WERR_NOMEM;
6585 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6587 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6590 /* check the required size. */
6591 for (i=0; i<*returned; i++) {
6592 DEBUGADD(6,("adding port [%d]'s size\n", i));
6593 *needed += spoolss_size_port_info_2(&ports[i]);
6596 if (!alloc_buffer_size(buffer, *needed)) {
6597 SAFE_FREE(ports);
6598 return WERR_INSUFFICIENT_BUFFER;
6601 /* fill the buffer with the ports structures */
6602 for (i=0; i<*returned; i++) {
6603 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6604 smb_io_port_2("", buffer, &ports[i], 0);
6607 SAFE_FREE(ports);
6609 if (*needed > offered) {
6610 *returned=0;
6611 return WERR_INSUFFICIENT_BUFFER;
6614 return WERR_OK;
6617 /****************************************************************************
6618 enumports.
6619 ****************************************************************************/
6621 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6623 /* UNISTR2 *name = &q_u->name; - notused. */
6624 uint32 level = q_u->level;
6625 NEW_BUFFER *buffer = NULL;
6626 uint32 offered = q_u->offered;
6627 uint32 *needed = &r_u->needed;
6628 uint32 *returned = &r_u->returned;
6630 /* that's an [in out] buffer */
6631 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6632 buffer = r_u->buffer;
6634 DEBUG(4,("_spoolss_enumports\n"));
6636 *returned=0;
6637 *needed=0;
6639 switch (level) {
6640 case 1:
6641 return enumports_level_1(buffer, offered, needed, returned);
6642 case 2:
6643 return enumports_level_2(buffer, offered, needed, returned);
6644 default:
6645 return WERR_UNKNOWN_LEVEL;
6649 /****************************************************************************
6650 ****************************************************************************/
6652 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6653 const SPOOL_PRINTER_INFO_LEVEL *info,
6654 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6655 uint32 user_switch, const SPOOL_USER_CTR *user,
6656 POLICY_HND *handle)
6658 NT_PRINTER_INFO_LEVEL *printer = NULL;
6659 fstring name;
6660 int snum;
6661 WERROR err = WERR_OK;
6663 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6664 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6665 return WERR_NOMEM;
6668 ZERO_STRUCTP(printer);
6670 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6671 if (!convert_printer_info(info, printer, 2)) {
6672 free_a_printer(&printer, 2);
6673 return WERR_NOMEM;
6676 /* check to see if the printer already exists */
6678 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6679 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6680 printer->info_2->sharename));
6681 free_a_printer(&printer, 2);
6682 return WERR_PRINTER_ALREADY_EXISTS;
6685 if (*lp_addprinter_cmd() )
6686 if ( !add_printer_hook(printer) ) {
6687 free_a_printer(&printer,2);
6688 return WERR_ACCESS_DENIED;
6691 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6692 printer->info_2->sharename);
6694 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6695 free_a_printer(&printer,2);
6696 return WERR_ACCESS_DENIED;
6699 /* you must be a printer admin to add a new printer */
6700 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6701 free_a_printer(&printer,2);
6702 return WERR_ACCESS_DENIED;
6706 * Do sanity check on the requested changes for Samba.
6709 if (!check_printer_ok(printer->info_2, snum)) {
6710 free_a_printer(&printer,2);
6711 return WERR_INVALID_PARAM;
6715 * When a printer is created, the drivername bound to the printer is used
6716 * to lookup previously saved driver initialization info, which is then
6717 * bound to the new printer, simulating what happens in the Windows arch.
6720 if (!devmode)
6721 set_driver_init(printer, 2);
6722 else {
6723 /* A valid devmode was included, convert and link it
6725 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6727 if (!convert_devicemode(printer->info_2->printername, devmode,
6728 &printer->info_2->devmode))
6729 return WERR_NOMEM;
6732 set_driver_init(printer, 2);
6734 /* write the ASCII on disk */
6735 err = mod_a_printer(*printer, 2);
6736 if (!W_ERROR_IS_OK(err)) {
6737 free_a_printer(&printer,2);
6738 return err;
6741 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6742 /* Handle open failed - remove addition. */
6743 del_a_printer(printer->info_2->sharename);
6744 free_a_printer(&printer,2);
6745 return WERR_ACCESS_DENIED;
6748 update_c_setprinter(False);
6749 free_a_printer(&printer,2);
6751 return WERR_OK;
6754 /****************************************************************************
6755 ****************************************************************************/
6757 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6759 UNISTR2 *uni_srv_name = &q_u->server_name;
6760 uint32 level = q_u->level;
6761 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6762 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6763 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6764 uint32 user_switch = q_u->user_switch;
6765 SPOOL_USER_CTR *user = &q_u->user_ctr;
6766 POLICY_HND *handle = &r_u->handle;
6768 switch (level) {
6769 case 1:
6770 /* we don't handle yet */
6771 /* but I know what to do ... */
6772 return WERR_UNKNOWN_LEVEL;
6773 case 2:
6774 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6775 devmode, sdb,
6776 user_switch, user, handle);
6777 default:
6778 return WERR_UNKNOWN_LEVEL;
6782 /****************************************************************************
6783 ****************************************************************************/
6785 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6787 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6788 uint32 level = q_u->level;
6789 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6790 WERROR err = WERR_OK;
6791 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6792 struct current_user user;
6793 fstring driver_name;
6794 uint32 version;
6796 ZERO_STRUCT(driver);
6798 get_current_user(&user, p);
6800 if (!convert_printer_driver_info(info, &driver, level)) {
6801 err = WERR_NOMEM;
6802 goto done;
6805 DEBUG(5,("Cleaning driver's information\n"));
6806 err = clean_up_driver_struct(driver, level, &user);
6807 if (!W_ERROR_IS_OK(err))
6808 goto done;
6810 DEBUG(5,("Moving driver to final destination\n"));
6811 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6812 if (W_ERROR_IS_OK(err))
6813 err = WERR_ACCESS_DENIED;
6814 goto done;
6817 if (add_a_printer_driver(driver, level)!=0) {
6818 err = WERR_ACCESS_DENIED;
6819 goto done;
6822 /* BEGIN_ADMIN_LOG */
6823 switch(level) {
6824 case 3:
6825 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6826 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6827 fstrcpy(driver_name, driver.info_3->name);
6828 break;
6829 case 6:
6830 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6831 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6832 fstrcpy(driver_name, driver.info_6->name);
6833 break;
6835 /* END_ADMIN_LOG */
6838 * I think this is where he DrvUpgradePrinter() hook would be
6839 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6840 * server. Right now, we just need to send ourselves a message
6841 * to update each printer bound to this driver. --jerry
6844 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6845 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6846 driver_name));
6850 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6851 * decide if the driver init data should be deleted. The rules are:
6852 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6853 * 2) delete init data only if there is no 2k/Xp driver
6854 * 3) always delete init data
6855 * The generalized rule is always use init data from the highest order driver.
6856 * It is necessary to follow the driver install by an initialization step to
6857 * finish off this process.
6859 if (level == 3)
6860 version = driver.info_3->cversion;
6861 else if (level == 6)
6862 version = driver.info_6->version;
6863 else
6864 version = -1;
6865 switch (version) {
6867 * 9x printer driver - never delete init data
6869 case 0:
6870 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6871 driver_name));
6872 break;
6875 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6876 * there is no 2k/Xp driver init data for this driver name.
6878 case 2:
6880 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
6882 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
6884 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6886 if (!del_driver_init(driver_name))
6887 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
6888 } else {
6890 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6892 free_a_printer_driver(driver1,3);
6893 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6894 driver_name));
6897 break;
6900 * 2k or Xp printer driver - always delete init data
6902 case 3:
6903 if (!del_driver_init(driver_name))
6904 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
6905 break;
6907 default:
6908 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
6909 break;
6913 done:
6914 free_a_printer_driver(driver, level);
6915 return err;
6918 /********************************************************************
6919 * spoolss_addprinterdriverex
6920 ********************************************************************/
6922 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
6924 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
6925 SPOOL_R_ADDPRINTERDRIVER r_u_local;
6928 * we only support the semantics of AddPrinterDriver()
6929 * i.e. only copy files that are newer than existing ones
6932 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
6933 return WERR_ACCESS_DENIED;
6935 /* just pass the information off to _spoolss_addprinterdriver() */
6936 q_u_local.server_name_ptr = q_u->server_name_ptr;
6937 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
6938 q_u_local.level = q_u->level;
6939 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
6941 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
6944 /****************************************************************************
6945 ****************************************************************************/
6947 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6949 init_unistr(&info->name, name);
6952 /****************************************************************************
6953 ****************************************************************************/
6955 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6957 pstring path;
6958 pstring long_archi;
6959 pstring short_archi;
6960 DRIVER_DIRECTORY_1 *info=NULL;
6962 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6964 if (get_short_archi(short_archi, long_archi)==False)
6965 return WERR_INVALID_ENVIRONMENT;
6967 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6968 return WERR_NOMEM;
6970 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6972 DEBUG(4,("printer driver directory: [%s]\n", path));
6974 fill_driverdir_1(info, path);
6976 *needed += spoolss_size_driverdir_info_1(info);
6978 if (!alloc_buffer_size(buffer, *needed)) {
6979 SAFE_FREE(info);
6980 return WERR_INSUFFICIENT_BUFFER;
6983 smb_io_driverdir_1("", buffer, info, 0);
6985 SAFE_FREE(info);
6987 if (*needed > offered)
6988 return WERR_INSUFFICIENT_BUFFER;
6990 return WERR_OK;
6993 /****************************************************************************
6994 ****************************************************************************/
6996 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6998 UNISTR2 *name = &q_u->name;
6999 UNISTR2 *uni_environment = &q_u->environment;
7000 uint32 level = q_u->level;
7001 NEW_BUFFER *buffer = NULL;
7002 uint32 offered = q_u->offered;
7003 uint32 *needed = &r_u->needed;
7005 /* that's an [in out] buffer */
7006 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7007 buffer = r_u->buffer;
7009 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7011 *needed=0;
7013 switch(level) {
7014 case 1:
7015 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7016 default:
7017 return WERR_UNKNOWN_LEVEL;
7021 /****************************************************************************
7022 ****************************************************************************/
7024 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7026 POLICY_HND *handle = &q_u->handle;
7027 uint32 idx = q_u->index;
7028 uint32 in_value_len = q_u->valuesize;
7029 uint32 in_data_len = q_u->datasize;
7030 uint32 *out_max_value_len = &r_u->valuesize;
7031 uint16 **out_value = &r_u->value;
7032 uint32 *out_value_len = &r_u->realvaluesize;
7033 uint32 *out_type = &r_u->type;
7034 uint32 *out_max_data_len = &r_u->datasize;
7035 uint8 **data_out = &r_u->data;
7036 uint32 *out_data_len = &r_u->realdatasize;
7038 NT_PRINTER_INFO_LEVEL *printer = NULL;
7040 fstring value;
7042 uint32 param_index;
7043 uint32 biggest_valuesize;
7044 uint32 biggest_datasize;
7045 uint32 data_len;
7046 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7047 int snum;
7048 uint8 *data=NULL;
7049 uint32 type;
7050 WERROR result;
7052 ZERO_STRUCT(printer);
7054 *out_type=0;
7056 *out_max_data_len=0;
7057 *data_out=NULL;
7058 *out_data_len=0;
7060 DEBUG(5,("spoolss_enumprinterdata\n"));
7062 if (!Printer) {
7063 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7064 return WERR_BADFID;
7067 if (!get_printer_snum(p,handle, &snum))
7068 return WERR_BADFID;
7070 result = get_a_printer(&printer, 2, lp_servicename(snum));
7071 if (!W_ERROR_IS_OK(result))
7072 return result;
7075 * The NT machine wants to know the biggest size of value and data
7077 * cf: MSDN EnumPrinterData remark section
7079 if ( (in_value_len==0) && (in_data_len==0) ) {
7080 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7082 SAFE_FREE(data);
7084 param_index=0;
7085 biggest_valuesize=0;
7086 biggest_datasize=0;
7088 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
7089 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
7090 if (data_len > biggest_datasize) biggest_datasize=data_len;
7092 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
7094 SAFE_FREE(data);
7095 param_index++;
7098 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
7099 *out_value_len=2*(1+biggest_valuesize);
7100 *out_data_len=biggest_datasize;
7102 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7104 free_a_printer(&printer, 2);
7105 return WERR_OK;
7109 * the value len is wrong in NT sp3
7110 * that's the number of bytes not the number of unicode chars
7113 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
7115 SAFE_FREE(data);
7116 free_a_printer(&printer, 2);
7118 /* out_value should default to "" or else NT4 has
7119 problems unmarshalling the response */
7121 *out_max_value_len=(in_value_len/sizeof(uint16));
7122 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7123 return WERR_NOMEM;
7125 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7127 /* the data is counted in bytes */
7128 *out_max_data_len = in_data_len;
7129 *out_data_len = in_data_len;
7130 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7131 return WERR_NOMEM;
7133 return WERR_NO_MORE_ITEMS;
7136 free_a_printer(&printer, 2);
7139 * the value is:
7140 * - counted in bytes in the request
7141 * - counted in UNICODE chars in the max reply
7142 * - counted in bytes in the real size
7144 * take a pause *before* coding not *during* coding
7147 *out_max_value_len=(in_value_len/sizeof(uint16));
7148 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
7149 SAFE_FREE(data);
7150 return WERR_NOMEM;
7153 *out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0);
7155 *out_type=type;
7157 /* the data is counted in bytes */
7158 *out_max_data_len=in_data_len;
7159 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
7160 SAFE_FREE(data);
7161 return WERR_NOMEM;
7164 memcpy(*data_out, data, (size_t)data_len);
7165 *out_data_len=data_len;
7167 SAFE_FREE(data);
7169 return WERR_OK;
7172 /****************************************************************************
7173 ****************************************************************************/
7175 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7177 POLICY_HND *handle = &q_u->handle;
7178 UNISTR2 *value = &q_u->value;
7179 uint32 type = q_u->type;
7180 uint8 *data = q_u->data;
7181 uint32 real_len = q_u->real_len;
7183 NT_PRINTER_INFO_LEVEL *printer = NULL;
7184 NT_PRINTER_PARAM *param = NULL, old_param;
7185 int snum=0;
7186 WERROR status = WERR_OK;
7187 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7189 DEBUG(5,("spoolss_setprinterdata\n"));
7191 if (!Printer) {
7192 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7193 return WERR_BADFID;
7196 if (!get_printer_snum(p,handle, &snum))
7197 return WERR_BADFID;
7199 ZERO_STRUCT(old_param);
7202 * Access check : NT returns "access denied" if you make a
7203 * SetPrinterData call without the necessary privildge.
7204 * we were originally returning OK if nothing changed
7205 * which made Win2k issue **a lot** of SetPrinterData
7206 * when connecting to a printer --jerry
7209 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7210 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7211 status = WERR_ACCESS_DENIED;
7212 goto done;
7215 /* Check if we are making any changes or not. Return true if
7216 nothing is actually changing. This is not needed anymore but
7217 has been left in as an optimization to keep from from
7218 writing to disk as often --jerry */
7220 status = get_a_printer(&printer, 2, lp_servicename(snum));
7221 if (!W_ERROR_IS_OK(status))
7222 return status;
7224 convert_specific_param(&param, value , type, data, real_len);
7226 unlink_specific_param_if_exist(printer->info_2, param);
7229 * When client side code sets a magic printer data key, detect it and save
7230 * the current printer data and the magic key's data (its the DEVMODE) for
7231 * future printer/driver initializations.
7233 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
7235 * Set devmode and printer initialization info
7237 status = save_driver_init(printer, 2, param);
7239 else {
7240 add_a_specific_param(printer->info_2, &param);
7241 status = mod_a_printer(*printer, 2);
7244 done:
7245 free_a_printer(&printer, 2);
7246 if (param)
7247 free_nt_printer_param(&param);
7248 SAFE_FREE(old_param.data);
7250 return status;
7253 /****************************************************************************
7254 ****************************************************************************/
7256 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7258 POLICY_HND *handle = &q_u->handle;
7259 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7260 int snum;
7262 DEBUG(5,("_spoolss_resetprinter\n"));
7265 * All we do is to check to see if the handle and queue is valid.
7266 * This call really doesn't mean anything to us because we only
7267 * support RAW printing. --jerry
7270 if (!Printer) {
7271 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7272 return WERR_BADFID;
7275 if (!get_printer_snum(p,handle, &snum))
7276 return WERR_BADFID;
7279 /* blindly return success */
7280 return WERR_OK;
7284 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7286 POLICY_HND *handle = &q_u->handle;
7287 UNISTR2 *value = &q_u->valuename;
7289 NT_PRINTER_INFO_LEVEL *printer = NULL;
7290 NT_PRINTER_PARAM param;
7291 int snum=0;
7292 WERROR status = WERR_OK;
7293 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7295 DEBUG(5,("spoolss_deleteprinterdata\n"));
7297 if (!Printer) {
7298 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7299 return WERR_BADFID;
7302 if (!get_printer_snum(p, handle, &snum))
7303 return WERR_BADFID;
7305 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7306 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7307 return WERR_ACCESS_DENIED;
7310 status = get_a_printer(&printer, 2, lp_servicename(snum));
7311 if (!W_ERROR_IS_OK(status))
7312 return status;
7314 ZERO_STRUCTP(&param);
7315 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
7317 if(!unlink_specific_param_if_exist(printer->info_2, &param))
7318 status = WERR_INVALID_PARAM;
7319 else
7320 status = mod_a_printer(*printer, 2);
7322 free_a_printer(&printer, 2);
7323 return status;
7326 /****************************************************************************
7327 ****************************************************************************/
7329 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7331 POLICY_HND *handle = &q_u->handle;
7332 /* uint32 level = q_u->level; - notused. */
7333 FORM *form = &q_u->form;
7334 nt_forms_struct tmpForm;
7335 int snum;
7336 WERROR status = WERR_OK;
7337 NT_PRINTER_INFO_LEVEL *printer = NULL;
7339 int count=0;
7340 nt_forms_struct *list=NULL;
7341 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7343 DEBUG(5,("spoolss_addform\n"));
7345 if (!Printer) {
7346 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7347 return WERR_BADFID;
7350 if (!get_printer_snum(p,handle, &snum))
7351 return WERR_BADFID;
7353 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7354 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7355 status = WERR_ACCESS_DENIED;
7356 goto done;
7359 /* can't add if builtin */
7360 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7361 return WERR_ALREADY_EXISTS;
7364 count=get_ntforms(&list);
7365 if(!add_a_form(&list, form, &count))
7366 return WERR_NOMEM;
7367 write_ntforms(&list, count);
7370 * ChangeID must always be set
7373 status = get_a_printer(&printer, 2, lp_servicename(snum));
7374 if (!W_ERROR_IS_OK(status))
7375 goto done;
7377 status = mod_a_printer(*printer, 2);
7378 if (!W_ERROR_IS_OK(status))
7379 goto done;
7381 done:
7382 free_a_printer(&printer, 2);
7383 SAFE_FREE(list);
7385 return status;
7388 /****************************************************************************
7389 ****************************************************************************/
7391 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7393 POLICY_HND *handle = &q_u->handle;
7394 UNISTR2 *form_name = &q_u->name;
7395 nt_forms_struct tmpForm;
7396 int count=0;
7397 WERROR ret = WERR_OK;
7398 nt_forms_struct *list=NULL;
7399 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7400 int snum;
7401 WERROR status = WERR_OK;
7402 NT_PRINTER_INFO_LEVEL *printer = NULL;
7404 DEBUG(5,("spoolss_deleteform\n"));
7406 if (!Printer) {
7407 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7408 return WERR_BADFID;
7411 if (!get_printer_snum(p, handle, &snum))
7412 return WERR_BADFID;
7414 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7415 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7416 return WERR_ACCESS_DENIED;
7419 /* can't delete if builtin */
7420 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7421 return WERR_INVALID_PARAM;
7424 count = get_ntforms(&list);
7425 if(!delete_a_form(&list, form_name, &count, &ret))
7426 return WERR_INVALID_PARAM;
7429 * ChangeID must always be set
7432 status = get_a_printer(&printer, 2, lp_servicename(snum));
7433 if (!W_ERROR_IS_OK(status))
7434 goto done;
7436 status = mod_a_printer(*printer, 2);
7437 if (!W_ERROR_IS_OK(status))
7438 goto done;
7440 done:
7441 free_a_printer(&printer, 2);
7442 SAFE_FREE(list);
7444 return ret;
7447 /****************************************************************************
7448 ****************************************************************************/
7450 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7452 POLICY_HND *handle = &q_u->handle;
7453 FORM *form = &q_u->form;
7454 nt_forms_struct tmpForm;
7455 int snum;
7456 WERROR status = WERR_OK;
7457 NT_PRINTER_INFO_LEVEL *printer = NULL;
7459 int count=0;
7460 nt_forms_struct *list=NULL;
7461 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7463 DEBUG(5,("spoolss_setform\n"));
7465 if (!Printer) {
7466 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7467 return WERR_BADFID;
7470 if (!get_printer_snum(p, handle, &snum))
7471 return WERR_BADFID;
7473 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7474 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7475 return WERR_ACCESS_DENIED;
7478 /* can't set if builtin */
7479 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7480 return WERR_INVALID_PARAM;
7483 count=get_ntforms(&list);
7484 update_a_form(&list, form, count);
7485 write_ntforms(&list, count);
7488 * ChangeID must always be set
7491 status = get_a_printer(&printer, 2, lp_servicename(snum));
7492 if (!W_ERROR_IS_OK(status))
7493 goto done;
7495 status = mod_a_printer(*printer, 2);
7496 if (!W_ERROR_IS_OK(status))
7497 goto done;
7499 done:
7500 free_a_printer(&printer, 2);
7501 SAFE_FREE(list);
7503 return WERR_OK;
7506 /****************************************************************************
7507 enumprintprocessors level 1.
7508 ****************************************************************************/
7510 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7512 PRINTPROCESSOR_1 *info_1=NULL;
7514 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7515 return WERR_NOMEM;
7517 (*returned) = 0x1;
7519 init_unistr(&info_1->name, "winprint");
7521 *needed += spoolss_size_printprocessor_info_1(info_1);
7523 if (!alloc_buffer_size(buffer, *needed))
7524 return WERR_INSUFFICIENT_BUFFER;
7526 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7528 SAFE_FREE(info_1);
7530 if (*needed > offered) {
7531 *returned=0;
7532 return WERR_INSUFFICIENT_BUFFER;
7535 return WERR_OK;
7538 /****************************************************************************
7539 ****************************************************************************/
7541 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7543 uint32 level = q_u->level;
7544 NEW_BUFFER *buffer = NULL;
7545 uint32 offered = q_u->offered;
7546 uint32 *needed = &r_u->needed;
7547 uint32 *returned = &r_u->returned;
7549 /* that's an [in out] buffer */
7550 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7551 buffer = r_u->buffer;
7553 DEBUG(5,("spoolss_enumprintprocessors\n"));
7556 * Enumerate the print processors ...
7558 * Just reply with "winprint", to keep NT happy
7559 * and I can use my nice printer checker.
7562 *returned=0;
7563 *needed=0;
7565 switch (level) {
7566 case 1:
7567 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7568 default:
7569 return WERR_UNKNOWN_LEVEL;
7573 /****************************************************************************
7574 enumprintprocdatatypes level 1.
7575 ****************************************************************************/
7577 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7579 PRINTPROCDATATYPE_1 *info_1=NULL;
7581 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7582 return WERR_NOMEM;
7584 (*returned) = 0x1;
7586 init_unistr(&info_1->name, "RAW");
7588 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7590 if (!alloc_buffer_size(buffer, *needed))
7591 return WERR_INSUFFICIENT_BUFFER;
7593 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7595 SAFE_FREE(info_1);
7597 if (*needed > offered) {
7598 *returned=0;
7599 return WERR_INSUFFICIENT_BUFFER;
7602 return WERR_OK;
7605 /****************************************************************************
7606 ****************************************************************************/
7608 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7610 uint32 level = q_u->level;
7611 NEW_BUFFER *buffer = NULL;
7612 uint32 offered = q_u->offered;
7613 uint32 *needed = &r_u->needed;
7614 uint32 *returned = &r_u->returned;
7616 /* that's an [in out] buffer */
7617 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7618 buffer = r_u->buffer;
7620 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7622 *returned=0;
7623 *needed=0;
7625 switch (level) {
7626 case 1:
7627 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7628 default:
7629 return WERR_UNKNOWN_LEVEL;
7633 /****************************************************************************
7634 enumprintmonitors level 1.
7635 ****************************************************************************/
7637 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7639 PRINTMONITOR_1 *info_1=NULL;
7641 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7642 return WERR_NOMEM;
7644 (*returned) = 0x1;
7646 init_unistr(&info_1->name, "Local Port");
7648 *needed += spoolss_size_printmonitor_info_1(info_1);
7650 if (!alloc_buffer_size(buffer, *needed))
7651 return WERR_INSUFFICIENT_BUFFER;
7653 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7655 SAFE_FREE(info_1);
7657 if (*needed > offered) {
7658 *returned=0;
7659 return WERR_INSUFFICIENT_BUFFER;
7662 return WERR_OK;
7665 /****************************************************************************
7666 enumprintmonitors level 2.
7667 ****************************************************************************/
7669 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7671 PRINTMONITOR_2 *info_2=NULL;
7673 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7674 return WERR_NOMEM;
7676 (*returned) = 0x1;
7678 init_unistr(&info_2->name, "Local Port");
7679 init_unistr(&info_2->environment, "Windows NT X86");
7680 init_unistr(&info_2->dll_name, "localmon.dll");
7682 *needed += spoolss_size_printmonitor_info_2(info_2);
7684 if (!alloc_buffer_size(buffer, *needed))
7685 return WERR_INSUFFICIENT_BUFFER;
7687 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7689 SAFE_FREE(info_2);
7691 if (*needed > offered) {
7692 *returned=0;
7693 return WERR_INSUFFICIENT_BUFFER;
7696 return WERR_OK;
7699 /****************************************************************************
7700 ****************************************************************************/
7702 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7704 uint32 level = q_u->level;
7705 NEW_BUFFER *buffer = NULL;
7706 uint32 offered = q_u->offered;
7707 uint32 *needed = &r_u->needed;
7708 uint32 *returned = &r_u->returned;
7710 /* that's an [in out] buffer */
7711 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7712 buffer = r_u->buffer;
7714 DEBUG(5,("spoolss_enumprintmonitors\n"));
7717 * Enumerate the print monitors ...
7719 * Just reply with "Local Port", to keep NT happy
7720 * and I can use my nice printer checker.
7723 *returned=0;
7724 *needed=0;
7726 switch (level) {
7727 case 1:
7728 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7729 case 2:
7730 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7731 default:
7732 return WERR_UNKNOWN_LEVEL;
7736 /****************************************************************************
7737 ****************************************************************************/
7739 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7741 int i=0;
7742 BOOL found=False;
7743 JOB_INFO_1 *info_1=NULL;
7745 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7747 if (info_1 == NULL) {
7748 SAFE_FREE(queue);
7749 return WERR_NOMEM;
7752 for (i=0; i<count && found==False; i++) {
7753 if (queue[i].job==(int)jobid)
7754 found=True;
7757 if (found==False) {
7758 SAFE_FREE(queue);
7759 SAFE_FREE(info_1);
7760 /* NT treats not found as bad param... yet another bad choice */
7761 return WERR_INVALID_PARAM;
7764 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7766 SAFE_FREE(queue);
7768 *needed += spoolss_size_job_info_1(info_1);
7770 if (!alloc_buffer_size(buffer, *needed)) {
7771 SAFE_FREE(info_1);
7772 return WERR_INSUFFICIENT_BUFFER;
7775 smb_io_job_info_1("", buffer, info_1, 0);
7777 SAFE_FREE(info_1);
7779 if (*needed > offered)
7780 return WERR_INSUFFICIENT_BUFFER;
7782 return WERR_OK;
7785 /****************************************************************************
7786 ****************************************************************************/
7788 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7790 int i=0;
7791 BOOL found=False;
7792 JOB_INFO_2 *info_2;
7793 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7794 WERROR ret;
7795 DEVICEMODE *devmode = NULL;
7797 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7799 ZERO_STRUCTP(info_2);
7801 if (info_2 == NULL) {
7802 ret = WERR_NOMEM;
7803 goto done;
7806 for (i=0; i<count && found==False; i++) {
7807 if (queue[i].job==(int)jobid)
7808 found=True;
7811 if (found==False) {
7812 /* NT treats not found as bad param... yet another bad
7813 choice */
7814 ret = WERR_INVALID_PARAM;
7815 goto done;
7818 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7819 if (!W_ERROR_IS_OK(ret))
7820 goto done;
7821 if (construct_dev_mode(snum) == NULL) {
7822 ret = WERR_NOMEM;
7823 goto done;
7826 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7828 *needed += spoolss_size_job_info_2(info_2);
7830 if (!alloc_buffer_size(buffer, *needed)) {
7831 ret = WERR_INSUFFICIENT_BUFFER;
7832 goto done;
7835 smb_io_job_info_2("", buffer, info_2, 0);
7837 if (*needed > offered) {
7838 ret = WERR_INSUFFICIENT_BUFFER;
7839 goto done;
7842 ret = WERR_OK;
7844 done:
7845 /* Cleanup allocated memory */
7847 SAFE_FREE(queue);
7848 free_job_info_2(info_2); /* Also frees devmode */
7849 SAFE_FREE(info_2);
7850 free_a_printer(&ntprinter, 2);
7852 return ret;
7855 /****************************************************************************
7856 ****************************************************************************/
7858 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7860 POLICY_HND *handle = &q_u->handle;
7861 uint32 jobid = q_u->jobid;
7862 uint32 level = q_u->level;
7863 NEW_BUFFER *buffer = NULL;
7864 uint32 offered = q_u->offered;
7865 uint32 *needed = &r_u->needed;
7867 int snum;
7868 int count;
7869 print_queue_struct *queue=NULL;
7870 print_status_struct prt_status;
7872 /* that's an [in out] buffer */
7873 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7874 buffer = r_u->buffer;
7876 DEBUG(5,("spoolss_getjob\n"));
7878 *needed=0;
7880 if (!get_printer_snum(p, handle, &snum))
7881 return WERR_BADFID;
7883 count = print_queue_status(snum, &queue, &prt_status);
7885 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7886 count, prt_status.status, prt_status.message));
7888 switch (level) {
7889 case 1:
7890 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7891 case 2:
7892 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7893 default:
7894 SAFE_FREE(queue);
7895 return WERR_UNKNOWN_LEVEL;
7899 /********************************************************************
7900 * spoolss_getprinterdataex
7901 ********************************************************************/
7903 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7905 POLICY_HND *handle = &q_u->handle;
7906 uint32 in_size = q_u->size;
7907 uint32 *type = &r_u->type;
7908 uint32 *out_size = &r_u->size;
7909 uint8 **data = &r_u->data;
7910 uint32 *needed = &r_u->needed;
7912 fstring key, value;
7913 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7914 BOOL found = False;
7916 DEBUG(4,("_spoolss_getprinterdataex\n"));
7918 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7919 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7921 /* in case of problem, return some default values */
7922 *needed=0;
7923 *type=0;
7924 *out_size=0;
7927 if (!Printer) {
7928 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7929 return WERR_NOMEM;
7930 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7931 return WERR_BADFID;
7935 /* Is the handle to a printer or to the server? */
7937 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7939 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7940 return WERR_INVALID_PARAM;
7942 else
7945 * From MSDN documentation of GetPrinterDataEx: pass request
7946 * to GetPrinterData if key is "PrinterDriverData". This is
7947 * the only key we really support. Other keys to implement:
7948 * (a) DsDriver
7949 * (b) DsSpooler
7950 * (c) PnPData
7953 if (strcmp(key, "PrinterDriverData") != 0)
7954 return WERR_BADFILE;
7956 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7957 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7958 type, data, needed, in_size);
7962 if (!found) {
7963 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7965 /* reply this param doesn't exist */
7966 if (*out_size) {
7967 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7968 return WERR_NOMEM;
7969 } else {
7970 *data = NULL;
7973 return WERR_INVALID_PARAM;
7976 if (*needed > *out_size)
7977 return WERR_MORE_DATA;
7978 else
7979 return WERR_OK;
7982 /********************************************************************
7983 * spoolss_setprinterdata
7984 ********************************************************************/
7986 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7988 SPOOL_Q_SETPRINTERDATA q_u_local;
7989 SPOOL_R_SETPRINTERDATA r_u_local;
7990 fstring key;
7992 DEBUG(4,("_spoolss_setprinterdataex\n"));
7994 /* From MSDN documentation of SetPrinterDataEx: pass request to
7995 SetPrinterData if key is "PrinterDriverData" */
7997 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7999 if (strcmp(key, "PrinterDriverData") != 0)
8000 return WERR_INVALID_PARAM;
8002 ZERO_STRUCT(q_u_local);
8003 ZERO_STRUCT(r_u_local);
8005 /* make a copy to call _spoolss_setprinterdata() */
8007 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
8008 copy_unistr2(&q_u_local.value, &q_u->value);
8009 q_u_local.type = q_u->type;
8010 q_u_local.max_len = q_u->max_len;
8011 q_u_local.data = q_u->data;
8012 q_u_local.real_len = q_u->real_len;
8013 q_u_local.numeric_data = q_u->numeric_data;
8015 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
8019 /********************************************************************
8020 * spoolss_deleteprinterdataex
8021 ********************************************************************/
8023 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8025 SPOOL_Q_DELETEPRINTERDATA q_u_local;
8026 SPOOL_R_DELETEPRINTERDATA r_u_local;
8027 fstring key;
8029 /* From MSDN documentation of SetPrinterDataEx: pass request to
8030 SetPrinterData if key is "PrinterDriverData" */
8032 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8034 if (strcmp(key, "PrinterDriverData") != 0)
8035 return WERR_INVALID_PARAM;
8037 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
8038 copy_unistr2(&q_u_local.valuename, &q_u->valuename);
8040 return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
8046 /********************************************************************
8047 * spoolss_enumprinterkey
8048 ********************************************************************/
8050 /* constants for EnumPrinterKey() */
8051 #define ENUMERATED_KEY_SIZE 19
8053 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8055 fstring key;
8056 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
8057 char* ptr = NULL;
8058 int i;
8059 char *PrinterKey = "PrinterDriverData";
8061 DEBUG(4,("_spoolss_enumprinterkey\n"));
8063 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8066 * we only support enumating all keys (key == "")
8067 * Of course, the only key we support is the "PrinterDriverData"
8068 * key
8070 if (strlen(key) == 0)
8072 r_u->needed = ENUMERATED_KEY_SIZE *2;
8073 if (q_u->size < r_u->needed)
8074 return WERR_MORE_DATA;
8076 ptr = PrinterKey;
8077 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
8079 enumkeys[i] = (uint16)(*ptr);
8080 ptr++;
8083 /* tag of with 2 '\0's */
8084 enumkeys[i++] = '\0';
8085 enumkeys[i] = '\0';
8087 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
8088 return WERR_BADFILE;
8090 return WERR_OK;
8093 /* The "PrinterDriverData" key should have no subkeys */
8094 if (strcmp(key, PrinterKey) == 0)
8096 r_u-> needed = 2;
8097 if (q_u->size < r_u->needed)
8098 return WERR_MORE_DATA;
8099 enumkeys[0] = 0x0;
8100 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
8101 return WERR_BADFILE;
8103 return WERR_OK;
8107 /* The return value for an unknown key is documented in MSDN
8108 EnumPrinterKey description */
8109 return WERR_BADFILE;
8112 /********************************************************************
8113 * spoolss_deleteprinterkey
8114 ********************************************************************/
8116 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8118 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8119 fstring key;
8121 if (!Printer) {
8122 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8123 return WERR_BADFID;
8126 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8128 if (strcmp(key, "PrinterDriverData") != 0)
8129 return WERR_INVALID_PARAM;
8132 * this is what 2k returns when you try to delete the "PrinterDriverData"
8133 * key
8136 return WERR_ACCESS_DENIED;
8140 /********************************************************************
8141 * spoolss_enumprinterdataex
8142 ********************************************************************/
8144 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8146 POLICY_HND *handle = &q_u->handle;
8147 uint32 in_size = q_u->size;
8148 uint32 num_entries,
8149 needed;
8150 NT_PRINTER_INFO_LEVEL *printer = NULL;
8151 PRINTER_ENUM_VALUES *enum_values = NULL;
8152 fstring key, value;
8153 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8154 int snum;
8155 uint32 param_index,
8156 data_len,
8157 type;
8158 WERROR result;
8159 uint8 *data=NULL;
8162 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8164 if (!Printer) {
8165 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8166 return WERR_BADFID;
8171 * The only key we support is "PrinterDriverData". This should return
8172 > an array of all the key/value pairs returned by EnumPrinterDataSee
8173 * _spoolss_getprinterdataex() for details --jerry
8176 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8177 if (strcmp(key, "PrinterDriverData") != 0)
8179 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8180 return WERR_INVALID_PARAM;
8184 if (!get_printer_snum(p,handle, &snum))
8185 return WERR_BADFID;
8187 ZERO_STRUCT(printer);
8188 result = get_a_printer(&printer, 2, lp_servicename(snum));
8189 if (!W_ERROR_IS_OK(result))
8190 return result;
8194 * loop through all params and build the array to pass
8195 * back to the client
8197 result = WERR_OK;
8198 param_index = 0;
8199 needed = 0;
8200 num_entries = 0;
8202 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
8204 PRINTER_ENUM_VALUES *ptr;
8205 uint32 add_len = 0;
8207 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
8209 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
8211 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
8212 result = WERR_NOMEM;
8213 goto done;
8215 enum_values = ptr;
8217 /* copy the data */
8218 init_unistr(&enum_values[num_entries].valuename, value);
8219 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
8220 enum_values[num_entries].type = type;
8222 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
8223 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
8224 result = WERR_NOMEM;
8225 goto done;
8227 memcpy(enum_values[num_entries].data, data, data_len);
8228 enum_values[num_entries].data_len = data_len + add_len;
8230 /* keep track of the size of the array in bytes */
8232 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
8234 num_entries++;
8235 param_index++;
8238 r_u->needed = needed;
8239 r_u->returned = num_entries;
8241 if (needed > in_size) {
8242 result = WERR_MORE_DATA;
8243 goto done;
8246 /* copy data into the reply */
8248 r_u->ctr.size = r_u->needed;
8249 r_u->ctr.size_of_array = r_u->returned;
8250 r_u->ctr.values = enum_values;
8254 done:
8255 free_a_printer(&printer, 2);
8257 return result;
8260 /****************************************************************************
8261 ****************************************************************************/
8263 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8265 init_unistr(&info->name, name);
8268 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8269 UNISTR2 *environment,
8270 NEW_BUFFER *buffer,
8271 uint32 offered,
8272 uint32 *needed)
8274 pstring path;
8275 pstring long_archi;
8276 pstring short_archi;
8277 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8279 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8281 if (get_short_archi(short_archi, long_archi)==False)
8282 return WERR_INVALID_ENVIRONMENT;
8284 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8285 return WERR_NOMEM;
8287 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8289 fill_printprocessordirectory_1(info, path);
8291 *needed += spoolss_size_printprocessordirectory_info_1(info);
8293 if (!alloc_buffer_size(buffer, *needed)) {
8294 safe_free(info);
8295 return WERR_INSUFFICIENT_BUFFER;
8298 smb_io_printprocessordirectory_1("", buffer, info, 0);
8300 safe_free(info);
8302 if (*needed > offered)
8303 return WERR_INSUFFICIENT_BUFFER;
8304 else
8305 return WERR_OK;
8308 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8310 uint32 level = q_u->level;
8311 NEW_BUFFER *buffer = NULL;
8312 uint32 offered = q_u->offered;
8313 uint32 *needed = &r_u->needed;
8314 WERROR result;
8316 /* that's an [in out] buffer */
8317 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8318 buffer = r_u->buffer;
8320 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8322 *needed=0;
8324 switch(level) {
8325 case 1:
8326 result = getprintprocessordirectory_level_1
8327 (&q_u->name, &q_u->environment, buffer, offered, needed);
8328 default:
8329 result = WERR_UNKNOWN_LEVEL;
8332 return result;