* basic implementation of SPOOLSS_DELETEPRINTERDATAEX and
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob0e209c60643bc8bb60732efa0707a6a7af80f6d7
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,
1551 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1553 fstring driver;
1554 fstring arch;
1555 NT_PRINTER_DRIVER_INFO_LEVEL info;
1556 int version;
1558 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1559 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1561 /* check that we have a valid driver name first */
1562 if ((version=get_version_id(arch)) == -1) {
1563 /* this is what NT returns */
1564 return WERR_INVALID_ENVIRONMENT;
1567 ZERO_STRUCT(info);
1568 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1569 return WERR_UNKNOWN_PRINTER_DRIVER;
1573 if (printer_driver_in_use(arch, driver))
1575 return WERR_PRINTER_DRIVER_IN_USE;
1578 return delete_printer_driver(info.info_3);
1581 /********************************************************************
1582 GetPrinterData on a printer server Handle.
1583 ********************************************************************/
1585 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1587 int i;
1589 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1591 if (!strcmp(value, "W3SvcInstalled")) {
1592 *type = 0x4;
1593 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1594 return False;
1595 *needed = 0x4;
1596 return True;
1599 if (!strcmp(value, "BeepEnabled")) {
1600 *type = 0x4;
1601 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1602 return False;
1603 SIVAL(*data, 0, 0x00);
1604 *needed = 0x4;
1605 return True;
1608 if (!strcmp(value, "EventLog")) {
1609 *type = 0x4;
1610 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1611 return False;
1612 /* formally was 0x1b */
1613 SIVAL(*data, 0, 0x0);
1614 *needed = 0x4;
1615 return True;
1618 if (!strcmp(value, "NetPopup")) {
1619 *type = 0x4;
1620 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1621 return False;
1622 SIVAL(*data, 0, 0x00);
1623 *needed = 0x4;
1624 return True;
1627 if (!strcmp(value, "MajorVersion")) {
1628 *type = 0x4;
1629 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1630 return False;
1631 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1632 SIVAL(*data, 0, 2);
1633 #else
1634 SIVAL(*data, 0, 3);
1635 #endif
1636 *needed = 0x4;
1637 return True;
1640 if (!strcmp(value, "DefaultSpoolDirectory")) {
1641 fstring string;
1643 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1644 *type = 0x1;
1645 *needed = 2*(strlen(string)+1);
1646 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1647 return False;
1648 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1650 /* it's done by hand ready to go on the wire */
1651 for (i=0; i<strlen(string); i++) {
1652 (*data)[2*i]=string[i];
1653 (*data)[2*i+1]='\0';
1655 return True;
1658 if (!strcmp(value, "Architecture")) {
1659 pstring string="Windows NT x86";
1660 *type = 0x1;
1661 *needed = 2*(strlen(string)+1);
1662 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1663 return False;
1664 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1665 for (i=0; i<strlen(string); i++) {
1666 (*data)[2*i]=string[i];
1667 (*data)[2*i+1]='\0';
1669 return True;
1672 return False;
1675 /********************************************************************
1676 GetPrinterData on a printer Handle.
1677 ********************************************************************/
1679 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1680 fstring value, uint32 *type,
1681 uint8 **data, uint32 *needed, uint32 in_size )
1683 NT_PRINTER_INFO_LEVEL *printer = NULL;
1684 int snum=0;
1685 uint8 *idata=NULL;
1686 uint32 len;
1687 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1689 DEBUG(5,("getprinterdata_printer\n"));
1691 if (!Printer) {
1692 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1693 return False;
1696 if(!get_printer_snum(p, handle, &snum))
1697 return False;
1699 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1700 return False;
1702 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1703 free_a_printer(&printer, 2);
1704 return False;
1707 free_a_printer(&printer, 2);
1709 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1711 if (in_size) {
1712 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1713 return False;
1716 memset(*data, 0, in_size *sizeof(uint8));
1717 /* copy the min(in_size, len) */
1718 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1719 } else {
1720 *data = NULL;
1723 *needed = len;
1725 DEBUG(5,("getprinterdata_printer:copy done\n"));
1727 SAFE_FREE(idata);
1729 return True;
1732 /********************************************************************
1733 * spoolss_getprinterdata
1734 ********************************************************************/
1736 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1738 POLICY_HND *handle = &q_u->handle;
1739 UNISTR2 *valuename = &q_u->valuename;
1740 uint32 in_size = q_u->size;
1741 uint32 *type = &r_u->type;
1742 uint32 *out_size = &r_u->size;
1743 uint8 **data = &r_u->data;
1744 uint32 *needed = &r_u->needed;
1746 fstring value;
1747 BOOL found=False;
1748 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1751 * Reminder: when it's a string, the length is in BYTES
1752 * even if UNICODE is negociated.
1754 * JFM, 4/19/1999
1757 *out_size=in_size;
1759 /* in case of problem, return some default values */
1760 *needed=0;
1761 *type=0;
1763 DEBUG(4,("_spoolss_getprinterdata\n"));
1765 if (!Printer) {
1766 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1767 return WERR_NOMEM;
1768 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1769 return WERR_BADFID;
1772 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1774 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1775 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1776 else
1777 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1779 if (found==False) {
1780 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1781 /* reply this param doesn't exist */
1782 if (*out_size) {
1783 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1784 return WERR_NOMEM;
1785 } else {
1786 *data = NULL;
1789 /* error depends on handle type */
1791 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1792 return WERR_INVALID_PARAM;
1793 else
1794 return WERR_BADFILE;
1797 if (*needed > *out_size)
1798 return WERR_MORE_DATA;
1799 else
1800 return WERR_OK;
1803 /*********************************************************
1804 Connect to the client machine.
1805 **********************************************************/
1807 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
1809 extern pstring global_myname;
1811 ZERO_STRUCTP(the_cli);
1812 if(cli_initialise(the_cli) == NULL) {
1813 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
1814 return False;
1817 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
1818 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
1819 cli_shutdown(the_cli);
1820 return False;
1823 if (ismyip(the_cli->dest_ip)) {
1824 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
1825 cli_shutdown(the_cli);
1826 return False;
1829 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
1830 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1831 cli_shutdown(the_cli);
1832 return False;
1835 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
1836 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
1837 remote_machine));
1838 return False;
1841 the_cli->protocol = PROTOCOL_NT1;
1843 if (!cli_negprot(the_cli)) {
1844 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1845 cli_shutdown(the_cli);
1846 return False;
1849 if (the_cli->protocol != PROTOCOL_NT1) {
1850 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
1851 cli_shutdown(the_cli);
1852 return False;
1856 * Do an anonymous session setup.
1859 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
1860 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1861 cli_shutdown(the_cli);
1862 return False;
1865 if (!(the_cli->sec_mode & 1)) {
1866 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
1867 cli_shutdown(the_cli);
1868 return False;
1871 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
1872 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1873 cli_shutdown(the_cli);
1874 return False;
1878 * Ok - we have an anonymous connection to the IPC$ share.
1879 * Now start the NT Domain stuff :-).
1882 if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
1883 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)));
1884 cli_nt_session_close(the_cli);
1885 cli_ulogoff(the_cli);
1886 cli_shutdown(the_cli);
1887 return False;
1890 return True;
1893 /***************************************************************************
1894 Connect to the client.
1895 ****************************************************************************/
1897 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1899 WERROR result;
1902 * If it's the first connection, contact the client
1903 * and connect to the IPC$ share anonumously
1905 if (smb_connections==0) {
1906 fstring unix_printer;
1908 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1910 if(!spoolss_connect_to_client(&cli, unix_printer))
1911 return False;
1913 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
1916 smb_connections++;
1918 result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
1919 type, handle);
1921 if (!W_ERROR_IS_OK(result))
1922 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1923 dos_errstr(result)));
1925 return (W_ERROR_IS_OK(result));
1928 /********************************************************************
1929 * _spoolss_rffpcnex
1930 * ReplyFindFirstPrinterChangeNotifyEx
1932 * before replying OK: status=0 a rpc call is made to the workstation
1933 * asking ReplyOpenPrinter
1935 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1936 * called from api_spoolss_rffpcnex
1937 ********************************************************************/
1939 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1941 POLICY_HND *handle = &q_u->handle;
1942 uint32 flags = q_u->flags;
1943 uint32 options = q_u->options;
1944 UNISTR2 *localmachine = &q_u->localmachine;
1945 uint32 printerlocal = q_u->printerlocal;
1946 SPOOL_NOTIFY_OPTION *option = q_u->option;
1948 /* store the notify value in the printer struct */
1950 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1952 if (!Printer) {
1953 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1954 return WERR_BADFID;
1957 Printer->notify.flags=flags;
1958 Printer->notify.options=options;
1959 Printer->notify.printerlocal=printerlocal;
1961 if (Printer->notify.option)
1962 free_spool_notify_option(&Printer->notify.option);
1964 Printer->notify.option=dup_spool_notify_option(option);
1966 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
1967 sizeof(Printer->notify.localmachine)-1);
1969 /* Connect to the client machine and send a ReplyOpenPrinter */
1971 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1972 Printer->notify.printerlocal, 1,
1973 &Printer->notify.client_hnd))
1974 return WERR_SERVER_UNAVAILABLE;
1976 Printer->notify.client_connected=True;
1978 return WERR_OK;
1981 /*******************************************************************
1982 * fill a notify_info_data with the servername
1983 ********************************************************************/
1985 void spoolss_notify_server_name(int snum,
1986 SPOOL_NOTIFY_INFO_DATA *data,
1987 print_queue_struct *queue,
1988 NT_PRINTER_INFO_LEVEL *printer,
1989 TALLOC_CTX *mem_ctx)
1991 pstring temp_name, temp;
1992 uint32 len;
1994 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1996 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1998 data->notify_data.data.length = len;
1999 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2001 if (!data->notify_data.data.string) {
2002 data->notify_data.data.length = 0;
2003 return;
2006 memcpy(data->notify_data.data.string, temp, len);
2009 /*******************************************************************
2010 * fill a notify_info_data with the printername (not including the servername).
2011 ********************************************************************/
2013 void spoolss_notify_printer_name(int snum,
2014 SPOOL_NOTIFY_INFO_DATA *data,
2015 print_queue_struct *queue,
2016 NT_PRINTER_INFO_LEVEL *printer,
2017 TALLOC_CTX *mem_ctx)
2019 pstring temp;
2020 uint32 len;
2022 /* the notify name should not contain the \\server\ part */
2023 char *p = strrchr(printer->info_2->printername, '\\');
2025 if (!p) {
2026 p = printer->info_2->printername;
2027 } else {
2028 p++;
2031 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2033 data->notify_data.data.length = len;
2034 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2036 if (!data->notify_data.data.string) {
2037 data->notify_data.data.length = 0;
2038 return;
2041 memcpy(data->notify_data.data.string, temp, len);
2044 /*******************************************************************
2045 * fill a notify_info_data with the servicename
2046 ********************************************************************/
2048 void spoolss_notify_share_name(int snum,
2049 SPOOL_NOTIFY_INFO_DATA *data,
2050 print_queue_struct *queue,
2051 NT_PRINTER_INFO_LEVEL *printer,
2052 TALLOC_CTX *mem_ctx)
2054 pstring temp;
2055 uint32 len;
2057 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2059 data->notify_data.data.length = len;
2060 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2062 if (!data->notify_data.data.string) {
2063 data->notify_data.data.length = 0;
2064 return;
2067 memcpy(data->notify_data.data.string, temp, len);
2070 /*******************************************************************
2071 * fill a notify_info_data with the port name
2072 ********************************************************************/
2074 void spoolss_notify_port_name(int snum,
2075 SPOOL_NOTIFY_INFO_DATA *data,
2076 print_queue_struct *queue,
2077 NT_PRINTER_INFO_LEVEL *printer,
2078 TALLOC_CTX *mem_ctx)
2080 pstring temp;
2081 uint32 len;
2083 /* even if it's strange, that's consistant in all the code */
2085 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2087 data->notify_data.data.length = len;
2088 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2090 if (!data->notify_data.data.string) {
2091 data->notify_data.data.length = 0;
2092 return;
2095 memcpy(data->notify_data.data.string, temp, len);
2098 /*******************************************************************
2099 * fill a notify_info_data with the printername
2100 * but it doesn't exist, have to see what to do
2101 ********************************************************************/
2103 void spoolss_notify_driver_name(int snum,
2104 SPOOL_NOTIFY_INFO_DATA *data,
2105 print_queue_struct *queue,
2106 NT_PRINTER_INFO_LEVEL *printer,
2107 TALLOC_CTX *mem_ctx)
2109 pstring temp;
2110 uint32 len;
2112 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2114 data->notify_data.data.length = len;
2115 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2117 if (!data->notify_data.data.string) {
2118 data->notify_data.data.length = 0;
2119 return;
2122 memcpy(data->notify_data.data.string, temp, len);
2125 /*******************************************************************
2126 * fill a notify_info_data with the comment
2127 ********************************************************************/
2129 void spoolss_notify_comment(int snum,
2130 SPOOL_NOTIFY_INFO_DATA *data,
2131 print_queue_struct *queue,
2132 NT_PRINTER_INFO_LEVEL *printer,
2133 TALLOC_CTX *mem_ctx)
2135 pstring temp;
2136 uint32 len;
2138 if (*printer->info_2->comment == '\0')
2139 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2140 else
2141 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2143 data->notify_data.data.length = len;
2144 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2146 if (!data->notify_data.data.string) {
2147 data->notify_data.data.length = 0;
2148 return;
2151 memcpy(data->notify_data.data.string, temp, len);
2154 /*******************************************************************
2155 * fill a notify_info_data with the comment
2156 * location = "Room 1, floor 2, building 3"
2157 ********************************************************************/
2159 void spoolss_notify_location(int snum,
2160 SPOOL_NOTIFY_INFO_DATA *data,
2161 print_queue_struct *queue,
2162 NT_PRINTER_INFO_LEVEL *printer,
2163 TALLOC_CTX *mem_ctx)
2165 pstring temp;
2166 uint32 len;
2168 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2170 data->notify_data.data.length = len;
2171 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2173 if (!data->notify_data.data.string) {
2174 data->notify_data.data.length = 0;
2175 return;
2178 memcpy(data->notify_data.data.string, temp, len);
2181 /*******************************************************************
2182 * fill a notify_info_data with the device mode
2183 * jfm:xxxx don't to it for know but that's a real problem !!!
2184 ********************************************************************/
2186 static void spoolss_notify_devmode(int snum,
2187 SPOOL_NOTIFY_INFO_DATA *data,
2188 print_queue_struct *queue,
2189 NT_PRINTER_INFO_LEVEL *printer,
2190 TALLOC_CTX *mem_ctx)
2194 /*******************************************************************
2195 * fill a notify_info_data with the separator file name
2196 ********************************************************************/
2198 void spoolss_notify_sepfile(int snum,
2199 SPOOL_NOTIFY_INFO_DATA *data,
2200 print_queue_struct *queue,
2201 NT_PRINTER_INFO_LEVEL *printer,
2202 TALLOC_CTX *mem_ctx)
2204 pstring temp;
2205 uint32 len;
2207 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2209 data->notify_data.data.length = len;
2210 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2212 if (!data->notify_data.data.string) {
2213 data->notify_data.data.length = 0;
2214 return;
2217 memcpy(data->notify_data.data.string, temp, len);
2220 /*******************************************************************
2221 * fill a notify_info_data with the print processor
2222 * jfm:xxxx return always winprint to indicate we don't do anything to it
2223 ********************************************************************/
2225 void spoolss_notify_print_processor(int snum,
2226 SPOOL_NOTIFY_INFO_DATA *data,
2227 print_queue_struct *queue,
2228 NT_PRINTER_INFO_LEVEL *printer,
2229 TALLOC_CTX *mem_ctx)
2231 pstring temp;
2232 uint32 len;
2234 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2236 data->notify_data.data.length = len;
2237 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2239 if (!data->notify_data.data.string) {
2240 data->notify_data.data.length = 0;
2241 return;
2244 memcpy(data->notify_data.data.string, temp, len);
2247 /*******************************************************************
2248 * fill a notify_info_data with the print processor options
2249 * jfm:xxxx send an empty string
2250 ********************************************************************/
2252 void spoolss_notify_parameters(int snum,
2253 SPOOL_NOTIFY_INFO_DATA *data,
2254 print_queue_struct *queue,
2255 NT_PRINTER_INFO_LEVEL *printer,
2256 TALLOC_CTX *mem_ctx)
2258 pstring temp;
2259 uint32 len;
2261 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2263 data->notify_data.data.length = len;
2264 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2266 if (!data->notify_data.data.string) {
2267 data->notify_data.data.length = 0;
2268 return;
2271 memcpy(data->notify_data.data.string, temp, len);
2274 /*******************************************************************
2275 * fill a notify_info_data with the data type
2276 * jfm:xxxx always send RAW as data type
2277 ********************************************************************/
2279 void spoolss_notify_datatype(int snum,
2280 SPOOL_NOTIFY_INFO_DATA *data,
2281 print_queue_struct *queue,
2282 NT_PRINTER_INFO_LEVEL *printer,
2283 TALLOC_CTX *mem_ctx)
2285 pstring temp;
2286 uint32 len;
2288 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2290 data->notify_data.data.length = len;
2291 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2293 if (!data->notify_data.data.string) {
2294 data->notify_data.data.length = 0;
2295 return;
2298 memcpy(data->notify_data.data.string, temp, len);
2301 /*******************************************************************
2302 * fill a notify_info_data with the security descriptor
2303 * jfm:xxxx send an null pointer to say no security desc
2304 * have to implement security before !
2305 ********************************************************************/
2307 static void spoolss_notify_security_desc(int snum,
2308 SPOOL_NOTIFY_INFO_DATA *data,
2309 print_queue_struct *queue,
2310 NT_PRINTER_INFO_LEVEL *printer,
2311 TALLOC_CTX *mem_ctx)
2313 data->notify_data.data.length=0;
2314 data->notify_data.data.string = NULL;
2317 /*******************************************************************
2318 * fill a notify_info_data with the attributes
2319 * jfm:xxxx a samba printer is always shared
2320 ********************************************************************/
2322 void spoolss_notify_attributes(int snum,
2323 SPOOL_NOTIFY_INFO_DATA *data,
2324 print_queue_struct *queue,
2325 NT_PRINTER_INFO_LEVEL *printer,
2326 TALLOC_CTX *mem_ctx)
2328 data->notify_data.value[0] = printer->info_2->attributes;
2329 data->notify_data.value[1] = 0;
2332 /*******************************************************************
2333 * fill a notify_info_data with the priority
2334 ********************************************************************/
2336 static void spoolss_notify_priority(int snum,
2337 SPOOL_NOTIFY_INFO_DATA *data,
2338 print_queue_struct *queue,
2339 NT_PRINTER_INFO_LEVEL *printer,
2340 TALLOC_CTX *mem_ctx)
2342 data->notify_data.value[0] = printer->info_2->priority;
2343 data->notify_data.value[1] = 0;
2346 /*******************************************************************
2347 * fill a notify_info_data with the default priority
2348 ********************************************************************/
2350 static void spoolss_notify_default_priority(int snum,
2351 SPOOL_NOTIFY_INFO_DATA *data,
2352 print_queue_struct *queue,
2353 NT_PRINTER_INFO_LEVEL *printer,
2354 TALLOC_CTX *mem_ctx)
2356 data->notify_data.value[0] = printer->info_2->default_priority;
2357 data->notify_data.value[1] = 0;
2360 /*******************************************************************
2361 * fill a notify_info_data with the start time
2362 ********************************************************************/
2364 static void spoolss_notify_start_time(int snum,
2365 SPOOL_NOTIFY_INFO_DATA *data,
2366 print_queue_struct *queue,
2367 NT_PRINTER_INFO_LEVEL *printer,
2368 TALLOC_CTX *mem_ctx)
2370 data->notify_data.value[0] = printer->info_2->starttime;
2371 data->notify_data.value[1] = 0;
2374 /*******************************************************************
2375 * fill a notify_info_data with the until time
2376 ********************************************************************/
2378 static void spoolss_notify_until_time(int snum,
2379 SPOOL_NOTIFY_INFO_DATA *data,
2380 print_queue_struct *queue,
2381 NT_PRINTER_INFO_LEVEL *printer,
2382 TALLOC_CTX *mem_ctx)
2384 data->notify_data.value[0] = printer->info_2->untiltime;
2385 data->notify_data.value[1] = 0;
2388 /*******************************************************************
2389 * fill a notify_info_data with the status
2390 ********************************************************************/
2392 static void spoolss_notify_status(int snum,
2393 SPOOL_NOTIFY_INFO_DATA *data,
2394 print_queue_struct *queue,
2395 NT_PRINTER_INFO_LEVEL *printer,
2396 TALLOC_CTX *mem_ctx)
2398 print_status_struct status;
2400 print_queue_length(snum, &status);
2401 data->notify_data.value[0]=(uint32) status.status;
2402 data->notify_data.value[1] = 0;
2405 /*******************************************************************
2406 * fill a notify_info_data with the number of jobs queued
2407 ********************************************************************/
2409 void spoolss_notify_cjobs(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] = print_queue_length(snum, NULL);
2416 data->notify_data.value[1] = 0;
2419 /*******************************************************************
2420 * fill a notify_info_data with the average ppm
2421 ********************************************************************/
2423 static void spoolss_notify_average_ppm(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 /* always respond 8 pages per minutes */
2430 /* a little hard ! */
2431 data->notify_data.value[0] = printer->info_2->averageppm;
2432 data->notify_data.value[1] = 0;
2435 /*******************************************************************
2436 * fill a notify_info_data with username
2437 ********************************************************************/
2439 static void spoolss_notify_username(int snum,
2440 SPOOL_NOTIFY_INFO_DATA *data,
2441 print_queue_struct *queue,
2442 NT_PRINTER_INFO_LEVEL *printer,
2443 TALLOC_CTX *mem_ctx)
2445 pstring temp;
2446 uint32 len;
2448 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2450 data->notify_data.data.length = len;
2451 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2453 if (!data->notify_data.data.string) {
2454 data->notify_data.data.length = 0;
2455 return;
2458 memcpy(data->notify_data.data.string, temp, len);
2461 /*******************************************************************
2462 * fill a notify_info_data with job status
2463 ********************************************************************/
2465 static void spoolss_notify_job_status(int snum,
2466 SPOOL_NOTIFY_INFO_DATA *data,
2467 print_queue_struct *queue,
2468 NT_PRINTER_INFO_LEVEL *printer,
2469 TALLOC_CTX *mem_ctx)
2471 data->notify_data.value[0]=nt_printj_status(queue->status);
2472 data->notify_data.value[1] = 0;
2475 /*******************************************************************
2476 * fill a notify_info_data with job name
2477 ********************************************************************/
2479 static void spoolss_notify_job_name(int snum,
2480 SPOOL_NOTIFY_INFO_DATA *data,
2481 print_queue_struct *queue,
2482 NT_PRINTER_INFO_LEVEL *printer,
2483 TALLOC_CTX *mem_ctx)
2485 pstring temp;
2486 uint32 len;
2488 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2490 data->notify_data.data.length = len;
2491 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2493 if (!data->notify_data.data.string) {
2494 data->notify_data.data.length = 0;
2495 return;
2498 memcpy(data->notify_data.data.string, temp, len);
2501 /*******************************************************************
2502 * fill a notify_info_data with job status
2503 ********************************************************************/
2505 static void spoolss_notify_job_status_string(int snum,
2506 SPOOL_NOTIFY_INFO_DATA *data,
2507 print_queue_struct *queue,
2508 NT_PRINTER_INFO_LEVEL *printer,
2509 TALLOC_CTX *mem_ctx)
2512 * Now we're returning job status codes we just return a "" here. JRA.
2515 char *p = "";
2516 pstring temp;
2517 uint32 len;
2519 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2520 p = "unknown";
2522 switch (queue->status) {
2523 case LPQ_QUEUED:
2524 p = "Queued";
2525 break;
2526 case LPQ_PAUSED:
2527 p = ""; /* NT provides the paused string */
2528 break;
2529 case LPQ_SPOOLING:
2530 p = "Spooling";
2531 break;
2532 case LPQ_PRINTING:
2533 p = "Printing";
2534 break;
2536 #endif /* NO LONGER NEEDED. */
2538 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2540 data->notify_data.data.length = len;
2541 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2543 if (!data->notify_data.data.string) {
2544 data->notify_data.data.length = 0;
2545 return;
2548 memcpy(data->notify_data.data.string, temp, len);
2551 /*******************************************************************
2552 * fill a notify_info_data with job time
2553 ********************************************************************/
2555 static void spoolss_notify_job_time(int snum,
2556 SPOOL_NOTIFY_INFO_DATA *data,
2557 print_queue_struct *queue,
2558 NT_PRINTER_INFO_LEVEL *printer,
2559 TALLOC_CTX *mem_ctx)
2561 data->notify_data.value[0]=0x0;
2562 data->notify_data.value[1]=0;
2565 /*******************************************************************
2566 * fill a notify_info_data with job size
2567 ********************************************************************/
2569 static void spoolss_notify_job_size(int snum,
2570 SPOOL_NOTIFY_INFO_DATA *data,
2571 print_queue_struct *queue,
2572 NT_PRINTER_INFO_LEVEL *printer,
2573 TALLOC_CTX *mem_ctx)
2575 data->notify_data.value[0]=queue->size;
2576 data->notify_data.value[1]=0;
2579 /*******************************************************************
2580 * fill a notify_info_data with page info
2581 ********************************************************************/
2582 static void spoolss_notify_total_pages(int snum,
2583 SPOOL_NOTIFY_INFO_DATA *data,
2584 print_queue_struct *queue,
2585 NT_PRINTER_INFO_LEVEL *printer,
2586 TALLOC_CTX *mem_ctx)
2588 data->notify_data.value[0]=queue->page_count;
2589 data->notify_data.value[1]=0;
2592 /*******************************************************************
2593 * fill a notify_info_data with pages printed info.
2594 ********************************************************************/
2595 static void spoolss_notify_pages_printed(int snum,
2596 SPOOL_NOTIFY_INFO_DATA *data,
2597 print_queue_struct *queue,
2598 NT_PRINTER_INFO_LEVEL *printer,
2599 TALLOC_CTX *mem_ctx)
2601 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2602 data->notify_data.value[1]=0;
2605 /*******************************************************************
2606 Fill a notify_info_data with job position.
2607 ********************************************************************/
2609 static void spoolss_notify_job_position(int snum,
2610 SPOOL_NOTIFY_INFO_DATA *data,
2611 print_queue_struct *queue,
2612 NT_PRINTER_INFO_LEVEL *printer,
2613 TALLOC_CTX *mem_ctx)
2615 data->notify_data.value[0]=queue->job;
2616 data->notify_data.value[1]=0;
2619 /*******************************************************************
2620 Fill a notify_info_data with submitted time.
2621 ********************************************************************/
2623 static void spoolss_notify_submitted_time(int snum,
2624 SPOOL_NOTIFY_INFO_DATA *data,
2625 print_queue_struct *queue,
2626 NT_PRINTER_INFO_LEVEL *printer,
2627 TALLOC_CTX *mem_ctx)
2629 struct tm *t;
2630 uint32 len;
2631 SYSTEMTIME st;
2632 char *p;
2634 t=gmtime(&queue->time);
2636 len = sizeof(SYSTEMTIME);
2638 data->notify_data.data.length = len;
2639 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2641 if (!data->notify_data.data.string) {
2642 data->notify_data.data.length = 0;
2643 return;
2646 make_systemtime(&st, t);
2649 * Systemtime must be linearized as a set of UINT16's.
2650 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2653 p = (char *)data->notify_data.data.string;
2654 SSVAL(p, 0, st.year);
2655 SSVAL(p, 2, st.month);
2656 SSVAL(p, 4, st.dayofweek);
2657 SSVAL(p, 6, st.day);
2658 SSVAL(p, 8, st.hour);
2659 SSVAL(p, 10, st.minute);
2660 SSVAL(p, 12, st.second);
2661 SSVAL(p, 14, st.milliseconds);
2664 struct s_notify_info_data_table
2666 uint16 type;
2667 uint16 field;
2668 char *name;
2669 uint32 size;
2670 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2671 print_queue_struct *queue,
2672 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2675 /* A table describing the various print notification constants and
2676 whether the notification data is a pointer to a variable sized
2677 buffer, a one value uint32 or a two value uint32. */
2679 struct s_notify_info_data_table notify_info_data_table[] =
2681 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2682 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2683 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
2684 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2685 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2686 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
2687 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
2688 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2689 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
2690 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2691 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2692 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2693 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, spoolss_notify_security_desc },
2694 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
2695 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2696 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
2697 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2698 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2699 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
2700 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
2701 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
2702 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
2703 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
2704 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
2705 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
2706 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
2707 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2708 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2709 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2710 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
2711 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
2712 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2713 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2714 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2715 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2716 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2717 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
2718 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
2719 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
2720 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
2721 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2722 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
2723 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
2724 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2725 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2726 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
2727 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
2728 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
2729 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
2732 /*******************************************************************
2733 Return the size of info_data structure.
2734 ********************************************************************/
2736 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2738 int i=0;
2740 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2741 if (notify_info_data_table[i].type == type &&
2742 notify_info_data_table[i].field == field) {
2743 switch(notify_info_data_table[i].size) {
2744 case NOTIFY_ONE_VALUE:
2745 case NOTIFY_TWO_VALUE:
2746 return 1;
2747 case NOTIFY_STRING:
2748 return 2;
2750 /* The only pointer notify data I have seen on
2751 the wire is the submitted time and this has
2752 the notify size set to 4. -tpot */
2754 case NOTIFY_POINTER:
2755 return 4;
2760 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2762 return 0;
2765 /*******************************************************************
2766 Return the type of notify_info_data.
2767 ********************************************************************/
2769 static int type_of_notify_info_data(uint16 type, uint16 field)
2771 int i=0;
2773 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2774 if (notify_info_data_table[i].type == type &&
2775 notify_info_data_table[i].field == field)
2776 return notify_info_data_table[i].size;
2779 return False;
2782 /****************************************************************************
2783 ****************************************************************************/
2785 static int search_notify(uint16 type, uint16 field, int *value)
2787 int i;
2789 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2790 if (notify_info_data_table[i].type == type &&
2791 notify_info_data_table[i].field == field &&
2792 notify_info_data_table[i].fn != NULL) {
2793 *value = i;
2794 return True;
2798 return False;
2801 /****************************************************************************
2802 ****************************************************************************/
2804 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2806 info_data->type = type;
2807 info_data->field = field;
2808 info_data->reserved = 0;
2810 if (type == JOB_NOTIFY_TYPE)
2811 info_data->id = id;
2812 else
2813 info_data->id = 0;
2815 info_data->size = size_of_notify_info_data(type, field);
2816 info_data->enc_type = type_of_notify_info_data(type, field);
2820 /*******************************************************************
2822 * fill a notify_info struct with info asked
2824 ********************************************************************/
2826 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2827 snum, SPOOL_NOTIFY_OPTION_TYPE
2828 *option_type, uint32 id,
2829 TALLOC_CTX *mem_ctx)
2831 int field_num,j;
2832 uint16 type;
2833 uint16 field;
2835 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2836 NT_PRINTER_INFO_LEVEL *printer = NULL;
2837 print_queue_struct *queue=NULL;
2839 type=option_type->type;
2841 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2842 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2843 option_type->count, lp_servicename(snum)));
2845 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2846 return False;
2848 for(field_num=0; field_num<option_type->count; field_num++) {
2849 field = option_type->fields[field_num];
2850 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2852 if (!search_notify(type, field, &j) )
2853 continue;
2855 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2856 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2857 return False;
2859 else info->data = tid;
2861 current_data=&info->data[info->count];
2863 construct_info_data(current_data, type, field, id);
2865 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2866 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2868 notify_info_data_table[j].fn(snum, current_data, queue,
2869 printer, mem_ctx);
2871 info->count++;
2874 free_a_printer(&printer, 2);
2875 return True;
2878 /*******************************************************************
2880 * fill a notify_info struct with info asked
2882 ********************************************************************/
2884 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2885 SPOOL_NOTIFY_INFO *info,
2886 NT_PRINTER_INFO_LEVEL *printer,
2887 int snum, SPOOL_NOTIFY_OPTION_TYPE
2888 *option_type, uint32 id,
2889 TALLOC_CTX *mem_ctx)
2891 int field_num,j;
2892 uint16 type;
2893 uint16 field;
2895 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2897 DEBUG(4,("construct_notify_jobs_info\n"));
2899 type = option_type->type;
2901 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2902 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2903 option_type->count));
2905 for(field_num=0; field_num<option_type->count; field_num++) {
2906 field = option_type->fields[field_num];
2908 if (!search_notify(type, field, &j) )
2909 continue;
2911 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2912 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2913 return False;
2915 else info->data = tid;
2917 current_data=&(info->data[info->count]);
2919 construct_info_data(current_data, type, field, id);
2920 notify_info_data_table[j].fn(snum, current_data, queue,
2921 printer, mem_ctx);
2922 info->count++;
2925 return True;
2929 * JFM: The enumeration is not that simple, it's even non obvious.
2931 * let's take an example: I want to monitor the PRINTER SERVER for
2932 * the printer's name and the number of jobs currently queued.
2933 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2934 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2936 * I have 3 printers on the back of my server.
2938 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2939 * structures.
2940 * Number Data Id
2941 * 1 printer 1 name 1
2942 * 2 printer 1 cjob 1
2943 * 3 printer 2 name 2
2944 * 4 printer 2 cjob 2
2945 * 5 printer 3 name 3
2946 * 6 printer 3 name 3
2948 * that's the print server case, the printer case is even worse.
2951 /*******************************************************************
2953 * enumerate all printers on the printserver
2954 * fill a notify_info struct with info asked
2956 ********************************************************************/
2958 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2959 SPOOL_NOTIFY_INFO *info,
2960 TALLOC_CTX *mem_ctx)
2962 int snum;
2963 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2964 int n_services=lp_numservices();
2965 int i;
2966 uint32 id;
2967 SPOOL_NOTIFY_OPTION *option;
2968 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2970 DEBUG(4,("printserver_notify_info\n"));
2972 if (!Printer)
2973 return WERR_BADFID;
2975 option=Printer->notify.option;
2976 id=1;
2977 info->version=2;
2978 info->data=NULL;
2979 info->count=0;
2981 for (i=0; i<option->count; i++) {
2982 option_type=&(option->ctr.type[i]);
2984 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2985 continue;
2987 for (snum=0; snum<n_services; snum++)
2988 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2989 if (construct_notify_printer_info
2990 (info, snum, option_type, id, mem_ctx))
2991 id++;
2995 * Debugging information, don't delete.
2998 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2999 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3000 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3002 for (i=0; i<info->count; i++) {
3003 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3004 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3005 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3009 return WERR_OK;
3012 /*******************************************************************
3014 * fill a notify_info struct with info asked
3016 ********************************************************************/
3018 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3019 TALLOC_CTX *mem_ctx)
3021 int snum;
3022 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3023 int i;
3024 uint32 id;
3025 SPOOL_NOTIFY_OPTION *option;
3026 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3027 int count,j;
3028 print_queue_struct *queue=NULL;
3029 print_status_struct status;
3031 DEBUG(4,("printer_notify_info\n"));
3033 if (!Printer)
3034 return WERR_BADFID;
3036 option=Printer->notify.option;
3037 id = 0x0;
3038 info->version=2;
3039 info->data=NULL;
3040 info->count=0;
3042 get_printer_snum(p, hnd, &snum);
3044 for (i=0; i<option->count; i++) {
3045 option_type=&option->ctr.type[i];
3047 switch ( option_type->type ) {
3048 case PRINTER_NOTIFY_TYPE:
3049 if(construct_notify_printer_info(info, snum,
3050 option_type, id,
3051 mem_ctx))
3052 id--;
3053 break;
3055 case JOB_NOTIFY_TYPE: {
3056 NT_PRINTER_INFO_LEVEL *printer = NULL;
3058 count = print_queue_status(snum, &queue, &status);
3060 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3061 lp_servicename(snum))))
3062 goto done;
3064 for (j=0; j<count; j++) {
3065 construct_notify_jobs_info(&queue[j], info,
3066 printer, snum,
3067 option_type,
3068 queue[j].job,
3069 mem_ctx);
3072 free_a_printer(&printer, 2);
3074 done:
3075 SAFE_FREE(queue);
3076 break;
3082 * Debugging information, don't delete.
3085 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3086 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3087 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3089 for (i=0; i<info->count; i++) {
3090 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3091 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3092 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3095 return WERR_OK;
3098 /********************************************************************
3099 * spoolss_rfnpcnex
3100 ********************************************************************/
3102 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3104 POLICY_HND *handle = &q_u->handle;
3105 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
3106 SPOOL_NOTIFY_INFO *info = &r_u->info;
3108 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3109 WERROR result = WERR_BADFID;
3111 /* we always have a NOTIFY_INFO struct */
3112 r_u->info_ptr=0x1;
3114 if (!Printer) {
3115 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3116 OUR_HANDLE(handle)));
3117 goto done;
3120 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3123 * We are now using the change value, and
3124 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3125 * I don't have a global notification system, I'm sending back all the
3126 * informations even when _NOTHING_ has changed.
3129 /* We need to keep track of the change value to send back in
3130 RRPCN replies otherwise our updates are ignored. */
3132 if (Printer->notify.client_connected)
3133 Printer->notify.change = q_u->change;
3135 /* just ignore the SPOOL_NOTIFY_OPTION */
3137 switch (Printer->printer_type) {
3138 case PRINTER_HANDLE_IS_PRINTSERVER:
3139 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3140 break;
3142 case PRINTER_HANDLE_IS_PRINTER:
3143 result = printer_notify_info(p, handle, info, p->mem_ctx);
3144 break;
3147 done:
3148 return result;
3151 /********************************************************************
3152 * construct_printer_info_0
3153 * fill a printer_info_0 struct
3154 ********************************************************************/
3156 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3158 pstring chaine;
3159 int count;
3160 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3161 counter_printer_0 *session_counter;
3162 uint32 global_counter;
3163 struct tm *t;
3164 time_t setuptime;
3165 print_status_struct status;
3167 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3168 return False;
3170 count = print_queue_length(snum, &status);
3172 /* check if we already have a counter for this printer */
3173 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3175 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3176 if (session_counter->snum == snum)
3177 break;
3180 /* it's the first time, add it to the list */
3181 if (session_counter==NULL) {
3182 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3183 free_a_printer(&ntprinter, 2);
3184 return False;
3186 ZERO_STRUCTP(session_counter);
3187 session_counter->snum=snum;
3188 session_counter->counter=0;
3189 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3192 /* increment it */
3193 session_counter->counter++;
3195 /* JFM:
3196 * the global_counter should be stored in a TDB as it's common to all the clients
3197 * and should be zeroed on samba startup
3199 global_counter=session_counter->counter;
3201 pstrcpy(chaine,ntprinter->info_2->printername);
3203 init_unistr(&printer->printername, chaine);
3205 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3206 init_unistr(&printer->servername, chaine);
3208 printer->cjobs = count;
3209 printer->total_jobs = 0;
3210 printer->total_bytes = 0;
3212 setuptime = (time_t)ntprinter->info_2->setuptime;
3213 t=gmtime(&setuptime);
3215 printer->year = t->tm_year+1900;
3216 printer->month = t->tm_mon+1;
3217 printer->dayofweek = t->tm_wday;
3218 printer->day = t->tm_mday;
3219 printer->hour = t->tm_hour;
3220 printer->minute = t->tm_min;
3221 printer->second = t->tm_sec;
3222 printer->milliseconds = 0;
3224 printer->global_counter = global_counter;
3225 printer->total_pages = 0;
3226 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3227 printer->major_version = 0x0004; /* NT 4 */
3228 printer->build_version = 0x0565; /* build 1381 */
3229 #else
3230 printer->major_version = 0x0005; /* NT 5 */
3231 printer->build_version = 0x0893; /* build 2195 */
3232 #endif
3233 printer->unknown7 = 0x1;
3234 printer->unknown8 = 0x0;
3235 printer->unknown9 = 0x0;
3236 printer->session_counter = session_counter->counter;
3237 printer->unknown11 = 0x0;
3238 printer->printer_errors = 0x0; /* number of print failure */
3239 printer->unknown13 = 0x0;
3240 printer->unknown14 = 0x1;
3241 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3242 printer->unknown16 = 0x0;
3243 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3244 printer->unknown18 = 0x0;
3245 printer->status = nt_printq_status(status.status);
3246 printer->unknown20 = 0x0;
3247 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3248 printer->unknown22 = 0x0;
3249 printer->unknown23 = 0x6; /* 6 ???*/
3250 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3251 printer->unknown25 = 0;
3252 printer->unknown26 = 0;
3253 printer->unknown27 = 0;
3254 printer->unknown28 = 0;
3255 printer->unknown29 = 0;
3257 free_a_printer(&ntprinter,2);
3258 return (True);
3261 /********************************************************************
3262 * construct_printer_info_1
3263 * fill a printer_info_1 struct
3264 ********************************************************************/
3265 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3267 pstring chaine;
3268 pstring chaine2;
3269 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3271 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3272 return False;
3274 printer->flags=flags;
3276 if (*ntprinter->info_2->comment == '\0') {
3277 init_unistr(&printer->comment, lp_comment(snum));
3278 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3279 ntprinter->info_2->drivername, lp_comment(snum));
3281 else {
3282 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3283 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3284 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3287 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3289 init_unistr(&printer->description, chaine);
3290 init_unistr(&printer->name, chaine2);
3292 free_a_printer(&ntprinter,2);
3294 return True;
3297 /****************************************************************************
3298 Free a DEVMODE struct.
3299 ****************************************************************************/
3301 static void free_dev_mode(DEVICEMODE *dev)
3303 if (dev == NULL)
3304 return;
3306 SAFE_FREE(dev->private);
3307 SAFE_FREE(dev);
3310 /****************************************************************************
3311 Create a DEVMODE struct. Returns malloced memory.
3312 ****************************************************************************/
3314 static DEVICEMODE *construct_dev_mode(int snum)
3316 char adevice[32];
3317 char aform[32];
3318 NT_PRINTER_INFO_LEVEL *printer = NULL;
3319 NT_DEVICEMODE *ntdevmode = NULL;
3320 DEVICEMODE *devmode = NULL;
3322 DEBUG(7,("construct_dev_mode\n"));
3324 DEBUGADD(8,("getting printer characteristics\n"));
3326 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3327 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3328 return NULL;
3331 ZERO_STRUCTP(devmode);
3333 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3334 goto fail;
3336 if (printer->info_2->devmode)
3337 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3339 if (ntdevmode == NULL) {
3340 DEBUG(5, ("BONG! There was no device mode!\n"));
3341 goto fail;
3344 DEBUGADD(8,("loading DEVICEMODE\n"));
3346 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3347 init_unistr(&devmode->devicename, adevice);
3349 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3350 init_unistr(&devmode->formname, aform);
3352 devmode->specversion = ntdevmode->specversion;
3353 devmode->driverversion = ntdevmode->driverversion;
3354 devmode->size = ntdevmode->size;
3355 devmode->driverextra = ntdevmode->driverextra;
3356 devmode->fields = ntdevmode->fields;
3358 devmode->orientation = ntdevmode->orientation;
3359 devmode->papersize = ntdevmode->papersize;
3360 devmode->paperlength = ntdevmode->paperlength;
3361 devmode->paperwidth = ntdevmode->paperwidth;
3362 devmode->scale = ntdevmode->scale;
3363 devmode->copies = ntdevmode->copies;
3364 devmode->defaultsource = ntdevmode->defaultsource;
3365 devmode->printquality = ntdevmode->printquality;
3366 devmode->color = ntdevmode->color;
3367 devmode->duplex = ntdevmode->duplex;
3368 devmode->yresolution = ntdevmode->yresolution;
3369 devmode->ttoption = ntdevmode->ttoption;
3370 devmode->collate = ntdevmode->collate;
3371 devmode->icmmethod = ntdevmode->icmmethod;
3372 devmode->icmintent = ntdevmode->icmintent;
3373 devmode->mediatype = ntdevmode->mediatype;
3374 devmode->dithertype = ntdevmode->dithertype;
3376 if (ntdevmode->private != NULL) {
3377 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3378 goto fail;
3381 free_nt_devicemode(&ntdevmode);
3382 free_a_printer(&printer,2);
3384 return devmode;
3386 fail:
3388 if (ntdevmode)
3389 free_nt_devicemode(&ntdevmode);
3390 if (printer)
3391 free_a_printer(&printer,2);
3392 free_dev_mode(devmode);
3394 return NULL;
3397 /********************************************************************
3398 * construct_printer_info_2
3399 * fill a printer_info_2 struct
3400 ********************************************************************/
3402 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3404 int count;
3405 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3407 print_status_struct status;
3409 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3410 return False;
3412 count = print_queue_length(snum, &status);
3414 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3415 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3416 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3417 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3418 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3420 if (*ntprinter->info_2->comment == '\0')
3421 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3422 else
3423 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3425 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3426 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3427 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3428 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3429 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3431 printer->attributes = ntprinter->info_2->attributes;
3433 printer->priority = ntprinter->info_2->priority; /* priority */
3434 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3435 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3436 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3437 printer->status = nt_printq_status(status.status); /* status */
3438 printer->cjobs = count; /* jobs */
3439 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3441 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3442 DEBUG(8, ("Returning NULL Devicemode!\n"));
3445 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3446 /* steal the printer info sec_desc structure. [badly done]. */
3447 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3448 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3449 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3450 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3452 else {
3453 printer->secdesc = NULL;
3456 free_a_printer(&ntprinter, 2);
3457 return True;
3460 /********************************************************************
3461 * construct_printer_info_3
3462 * fill a printer_info_3 struct
3463 ********************************************************************/
3465 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3467 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3468 PRINTER_INFO_3 *printer = NULL;
3470 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3471 return False;
3473 *pp_printer = NULL;
3474 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3475 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3476 return False;
3479 ZERO_STRUCTP(printer);
3481 printer->flags = 4; /* These are the components of the SD we are returning. */
3482 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3483 /* steal the printer info sec_desc structure. [badly done]. */
3484 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3486 #if 0
3488 * Set the flags for the components we are returning.
3491 if (printer->secdesc->owner_sid)
3492 printer->flags |= OWNER_SECURITY_INFORMATION;
3494 if (printer->secdesc->grp_sid)
3495 printer->flags |= GROUP_SECURITY_INFORMATION;
3497 if (printer->secdesc->dacl)
3498 printer->flags |= DACL_SECURITY_INFORMATION;
3500 if (printer->secdesc->sacl)
3501 printer->flags |= SACL_SECURITY_INFORMATION;
3502 #endif
3504 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3505 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3506 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3509 free_a_printer(&ntprinter, 2);
3511 *pp_printer = printer;
3512 return True;
3515 /********************************************************************
3516 * construct_printer_info_4
3517 * fill a printer_info_4 struct
3518 ********************************************************************/
3520 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3522 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3524 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3525 return False;
3527 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3528 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3529 printer->attributes = ntprinter->info_2->attributes;
3531 free_a_printer(&ntprinter, 2);
3532 return True;
3535 /********************************************************************
3536 * construct_printer_info_5
3537 * fill a printer_info_5 struct
3538 ********************************************************************/
3540 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3542 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3544 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3545 return False;
3547 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3548 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3549 printer->attributes = ntprinter->info_2->attributes;
3550 printer->device_not_selected_timeout = 0x3a98;
3551 printer->transmission_retry_timeout = 0xafc8;
3553 free_a_printer(&ntprinter, 2);
3554 return True;
3557 /********************************************************************
3558 Spoolss_enumprinters.
3559 ********************************************************************/
3561 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3563 int snum;
3564 int i;
3565 int n_services=lp_numservices();
3566 PRINTER_INFO_1 *tp, *printers=NULL;
3567 PRINTER_INFO_1 current_prt;
3569 DEBUG(4,("enum_all_printers_info_1\n"));
3571 for (snum=0; snum<n_services; snum++) {
3572 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3573 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3575 if (construct_printer_info_1(flags, &current_prt, snum)) {
3576 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3577 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3578 SAFE_FREE(printers);
3579 *returned=0;
3580 return WERR_NOMEM;
3582 else printers = tp;
3583 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3585 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
3586 (*returned)++;
3591 /* check the required size. */
3592 for (i=0; i<*returned; i++)
3593 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3595 if (!alloc_buffer_size(buffer, *needed))
3596 return WERR_INSUFFICIENT_BUFFER;
3598 /* fill the buffer with the structures */
3599 for (i=0; i<*returned; i++)
3600 smb_io_printer_info_1("", buffer, &printers[i], 0);
3602 /* clear memory */
3603 SAFE_FREE(printers);
3605 if (*needed > offered) {
3606 *returned=0;
3607 return WERR_INSUFFICIENT_BUFFER;
3609 else
3610 return WERR_OK;
3613 /********************************************************************
3614 enum_all_printers_info_1_local.
3615 *********************************************************************/
3617 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3619 DEBUG(4,("enum_all_printers_info_1_local\n"));
3621 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3624 /********************************************************************
3625 enum_all_printers_info_1_name.
3626 *********************************************************************/
3628 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3630 char *s = name;
3632 DEBUG(4,("enum_all_printers_info_1_name\n"));
3634 if ((name[0] == '\\') && (name[1] == '\\'))
3635 s = name + 2;
3637 if (is_myname_or_ipaddr(s)) {
3638 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3640 else
3641 return WERR_INVALID_NAME;
3644 /********************************************************************
3645 enum_all_printers_info_1_remote.
3646 *********************************************************************/
3648 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3650 PRINTER_INFO_1 *printer;
3651 fstring printername;
3652 fstring desc;
3653 fstring comment;
3654 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3656 /* JFM: currently it's more a place holder than anything else.
3657 * In the spooler world there is a notion of server registration.
3658 * the print servers are registring (sp ?) on the PDC (in the same domain)
3660 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3663 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3664 return WERR_NOMEM;
3666 *returned=1;
3668 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3669 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3670 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3672 init_unistr(&printer->description, desc);
3673 init_unistr(&printer->name, printername);
3674 init_unistr(&printer->comment, comment);
3675 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3677 /* check the required size. */
3678 *needed += spoolss_size_printer_info_1(printer);
3680 if (!alloc_buffer_size(buffer, *needed)) {
3681 SAFE_FREE(printer);
3682 return WERR_INSUFFICIENT_BUFFER;
3685 /* fill the buffer with the structures */
3686 smb_io_printer_info_1("", buffer, printer, 0);
3688 /* clear memory */
3689 SAFE_FREE(printer);
3691 if (*needed > offered) {
3692 *returned=0;
3693 return WERR_INSUFFICIENT_BUFFER;
3695 else
3696 return WERR_OK;
3699 /********************************************************************
3700 enum_all_printers_info_1_network.
3701 *********************************************************************/
3703 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3705 char *s = name;
3707 DEBUG(4,("enum_all_printers_info_1_network\n"));
3709 /* If we respond to a enum_printers level 1 on our name with flags
3710 set to PRINTER_ENUM_REMOTE with a list of printers then these
3711 printers incorrectly appear in the APW browse list.
3712 Specifically the printers for the server appear at the workgroup
3713 level where all the other servers in the domain are
3714 listed. Windows responds to this call with a
3715 WERR_CAN_NOT_COMPLETE so we should do the same. */
3717 if (name[0] == '\\' && name[1] == '\\')
3718 s = name + 2;
3720 if (is_myname_or_ipaddr(s))
3721 return WERR_CAN_NOT_COMPLETE;
3723 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3726 /********************************************************************
3727 * api_spoolss_enumprinters
3729 * called from api_spoolss_enumprinters (see this to understand)
3730 ********************************************************************/
3732 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3734 int snum;
3735 int i;
3736 int n_services=lp_numservices();
3737 PRINTER_INFO_2 *tp, *printers=NULL;
3738 PRINTER_INFO_2 current_prt;
3740 for (snum=0; snum<n_services; snum++) {
3741 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3742 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3744 if (construct_printer_info_2(&current_prt, snum)) {
3745 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3746 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3747 SAFE_FREE(printers);
3748 *returned = 0;
3749 return WERR_NOMEM;
3751 else printers = tp;
3752 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3753 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3754 (*returned)++;
3759 /* check the required size. */
3760 for (i=0; i<*returned; i++)
3761 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3763 if (!alloc_buffer_size(buffer, *needed)) {
3764 for (i=0; i<*returned; i++) {
3765 free_devmode(printers[i].devmode);
3767 SAFE_FREE(printers);
3768 return WERR_INSUFFICIENT_BUFFER;
3771 /* fill the buffer with the structures */
3772 for (i=0; i<*returned; i++)
3773 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3775 /* clear memory */
3776 for (i=0; i<*returned; i++) {
3777 free_devmode(printers[i].devmode);
3779 SAFE_FREE(printers);
3781 if (*needed > offered) {
3782 *returned=0;
3783 return WERR_INSUFFICIENT_BUFFER;
3785 else
3786 return WERR_OK;
3789 /********************************************************************
3790 * handle enumeration of printers at level 1
3791 ********************************************************************/
3793 static WERROR enumprinters_level1( uint32 flags, fstring name,
3794 NEW_BUFFER *buffer, uint32 offered,
3795 uint32 *needed, uint32 *returned)
3797 /* Not all the flags are equals */
3799 if (flags & PRINTER_ENUM_LOCAL)
3800 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3802 if (flags & PRINTER_ENUM_NAME)
3803 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3805 if (flags & PRINTER_ENUM_REMOTE)
3806 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3808 if (flags & PRINTER_ENUM_NETWORK)
3809 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
3811 return WERR_OK; /* NT4sp5 does that */
3814 /********************************************************************
3815 * handle enumeration of printers at level 2
3816 ********************************************************************/
3818 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3819 NEW_BUFFER *buffer, uint32 offered,
3820 uint32 *needed, uint32 *returned)
3822 char *s = servername;
3824 if (flags & PRINTER_ENUM_LOCAL) {
3825 return enum_all_printers_info_2(buffer, offered, needed, returned);
3828 if (flags & PRINTER_ENUM_NAME) {
3829 if ((servername[0] == '\\') && (servername[1] == '\\'))
3830 s = servername + 2;
3831 if (is_myname_or_ipaddr(s))
3832 return enum_all_printers_info_2(buffer, offered, needed, returned);
3833 else
3834 return WERR_INVALID_NAME;
3837 if (flags & PRINTER_ENUM_REMOTE)
3838 return WERR_UNKNOWN_LEVEL;
3840 return WERR_OK;
3843 /********************************************************************
3844 * handle enumeration of printers at level 5
3845 ********************************************************************/
3847 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3848 NEW_BUFFER *buffer, uint32 offered,
3849 uint32 *needed, uint32 *returned)
3851 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3852 return WERR_OK;
3855 /********************************************************************
3856 * api_spoolss_enumprinters
3858 * called from api_spoolss_enumprinters (see this to understand)
3859 ********************************************************************/
3861 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3863 uint32 flags = q_u->flags;
3864 UNISTR2 *servername = &q_u->servername;
3865 uint32 level = q_u->level;
3866 NEW_BUFFER *buffer = NULL;
3867 uint32 offered = q_u->offered;
3868 uint32 *needed = &r_u->needed;
3869 uint32 *returned = &r_u->returned;
3871 fstring name;
3873 /* that's an [in out] buffer */
3874 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3875 buffer = r_u->buffer;
3877 DEBUG(4,("_spoolss_enumprinters\n"));
3879 *needed=0;
3880 *returned=0;
3883 * Level 1:
3884 * flags==PRINTER_ENUM_NAME
3885 * if name=="" then enumerates all printers
3886 * if name!="" then enumerate the printer
3887 * flags==PRINTER_ENUM_REMOTE
3888 * name is NULL, enumerate printers
3889 * Level 2: name!="" enumerates printers, name can't be NULL
3890 * Level 3: doesn't exist
3891 * Level 4: does a local registry lookup
3892 * Level 5: same as Level 2
3895 unistr2_to_ascii(name, servername, sizeof(name)-1);
3896 strupper(name);
3898 switch (level) {
3899 case 1:
3900 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3901 case 2:
3902 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3903 case 5:
3904 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3905 case 3:
3906 case 4:
3907 break;
3909 return WERR_UNKNOWN_LEVEL;
3912 /****************************************************************************
3913 ****************************************************************************/
3915 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3917 PRINTER_INFO_0 *printer=NULL;
3919 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3920 return WERR_NOMEM;
3922 construct_printer_info_0(printer, snum);
3924 /* check the required size. */
3925 *needed += spoolss_size_printer_info_0(printer);
3927 if (!alloc_buffer_size(buffer, *needed)) {
3928 SAFE_FREE(printer);
3929 return WERR_INSUFFICIENT_BUFFER;
3932 /* fill the buffer with the structures */
3933 smb_io_printer_info_0("", buffer, printer, 0);
3935 /* clear memory */
3936 SAFE_FREE(printer);
3938 if (*needed > offered) {
3939 return WERR_INSUFFICIENT_BUFFER;
3942 return WERR_OK;
3945 /****************************************************************************
3946 ****************************************************************************/
3948 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3950 PRINTER_INFO_1 *printer=NULL;
3952 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3953 return WERR_NOMEM;
3955 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3957 /* check the required size. */
3958 *needed += spoolss_size_printer_info_1(printer);
3960 if (!alloc_buffer_size(buffer, *needed)) {
3961 SAFE_FREE(printer);
3962 return WERR_INSUFFICIENT_BUFFER;
3965 /* fill the buffer with the structures */
3966 smb_io_printer_info_1("", buffer, printer, 0);
3968 /* clear memory */
3969 SAFE_FREE(printer);
3971 if (*needed > offered) {
3972 return WERR_INSUFFICIENT_BUFFER;
3975 return WERR_OK;
3978 /****************************************************************************
3979 ****************************************************************************/
3981 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3983 PRINTER_INFO_2 *printer=NULL;
3985 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3986 return WERR_NOMEM;
3988 construct_printer_info_2(printer, snum);
3990 /* check the required size. */
3991 *needed += spoolss_size_printer_info_2(printer);
3993 if (!alloc_buffer_size(buffer, *needed)) {
3994 free_printer_info_2(printer);
3995 return WERR_INSUFFICIENT_BUFFER;
3998 /* fill the buffer with the structures */
3999 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4000 free_printer_info_2(printer);
4001 return WERR_NOMEM;
4004 /* clear memory */
4005 free_printer_info_2(printer);
4007 if (*needed > offered) {
4008 return WERR_INSUFFICIENT_BUFFER;
4011 return WERR_OK;
4014 /****************************************************************************
4015 ****************************************************************************/
4017 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4019 PRINTER_INFO_3 *printer=NULL;
4021 if (!construct_printer_info_3(&printer, snum))
4022 return WERR_NOMEM;
4024 /* check the required size. */
4025 *needed += spoolss_size_printer_info_3(printer);
4027 if (!alloc_buffer_size(buffer, *needed)) {
4028 free_printer_info_3(printer);
4029 return WERR_INSUFFICIENT_BUFFER;
4032 /* fill the buffer with the structures */
4033 smb_io_printer_info_3("", buffer, printer, 0);
4035 /* clear memory */
4036 free_printer_info_3(printer);
4038 if (*needed > offered) {
4039 return WERR_INSUFFICIENT_BUFFER;
4042 return WERR_OK;
4045 /****************************************************************************
4046 ****************************************************************************/
4048 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4050 PRINTER_INFO_4 *printer=NULL;
4052 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4053 return WERR_NOMEM;
4055 if (!construct_printer_info_4(printer, snum))
4056 return WERR_NOMEM;
4058 /* check the required size. */
4059 *needed += spoolss_size_printer_info_4(printer);
4061 if (!alloc_buffer_size(buffer, *needed)) {
4062 free_printer_info_4(printer);
4063 return WERR_INSUFFICIENT_BUFFER;
4066 /* fill the buffer with the structures */
4067 smb_io_printer_info_4("", buffer, printer, 0);
4069 /* clear memory */
4070 free_printer_info_4(printer);
4072 if (*needed > offered) {
4073 return WERR_INSUFFICIENT_BUFFER;
4076 return WERR_OK;
4079 /****************************************************************************
4080 ****************************************************************************/
4082 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4084 PRINTER_INFO_5 *printer=NULL;
4086 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4087 return WERR_NOMEM;
4089 if (!construct_printer_info_5(printer, snum))
4090 return WERR_NOMEM;
4092 /* check the required size. */
4093 *needed += spoolss_size_printer_info_5(printer);
4095 if (!alloc_buffer_size(buffer, *needed)) {
4096 free_printer_info_5(printer);
4097 return WERR_INSUFFICIENT_BUFFER;
4100 /* fill the buffer with the structures */
4101 smb_io_printer_info_5("", buffer, printer, 0);
4103 /* clear memory */
4104 free_printer_info_5(printer);
4106 if (*needed > offered) {
4107 return WERR_INSUFFICIENT_BUFFER;
4110 return WERR_OK;
4113 /****************************************************************************
4114 ****************************************************************************/
4116 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4118 POLICY_HND *handle = &q_u->handle;
4119 uint32 level = q_u->level;
4120 NEW_BUFFER *buffer = NULL;
4121 uint32 offered = q_u->offered;
4122 uint32 *needed = &r_u->needed;
4124 int snum;
4126 /* that's an [in out] buffer */
4127 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4128 buffer = r_u->buffer;
4130 *needed=0;
4132 if (!get_printer_snum(p, handle, &snum))
4133 return WERR_BADFID;
4135 switch (level) {
4136 case 0:
4137 return getprinter_level_0(snum, buffer, offered, needed);
4138 case 1:
4139 return getprinter_level_1(snum, buffer, offered, needed);
4140 case 2:
4141 return getprinter_level_2(snum, buffer, offered, needed);
4142 case 3:
4143 return getprinter_level_3(snum, buffer, offered, needed);
4144 case 4:
4145 return getprinter_level_4(snum, buffer, offered, needed);
4146 case 5:
4147 return getprinter_level_5(snum, buffer, offered, needed);
4149 return WERR_UNKNOWN_LEVEL;
4152 /********************************************************************
4153 * fill a DRIVER_INFO_1 struct
4154 ********************************************************************/
4156 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4158 init_unistr( &info->name, driver.info_3->name);
4161 /********************************************************************
4162 * construct_printer_driver_info_1
4163 ********************************************************************/
4165 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4167 NT_PRINTER_INFO_LEVEL *printer = NULL;
4168 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4170 ZERO_STRUCT(driver);
4172 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4173 return WERR_INVALID_PRINTER_NAME;
4175 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4176 return WERR_UNKNOWN_PRINTER_DRIVER;
4178 fill_printer_driver_info_1(info, driver, servername, architecture);
4180 free_a_printer(&printer,2);
4182 return WERR_OK;
4185 /********************************************************************
4186 * construct_printer_driver_info_2
4187 * fill a printer_info_2 struct
4188 ********************************************************************/
4190 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4192 pstring temp;
4194 info->version=driver.info_3->cversion;
4196 init_unistr( &info->name, driver.info_3->name );
4197 init_unistr( &info->architecture, driver.info_3->environment );
4200 if (strlen(driver.info_3->driverpath)) {
4201 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4202 init_unistr( &info->driverpath, temp );
4203 } else
4204 init_unistr( &info->driverpath, "" );
4206 if (strlen(driver.info_3->datafile)) {
4207 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4208 init_unistr( &info->datafile, temp );
4209 } else
4210 init_unistr( &info->datafile, "" );
4212 if (strlen(driver.info_3->configfile)) {
4213 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4214 init_unistr( &info->configfile, temp );
4215 } else
4216 init_unistr( &info->configfile, "" );
4219 /********************************************************************
4220 * construct_printer_driver_info_2
4221 * fill a printer_info_2 struct
4222 ********************************************************************/
4224 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4226 NT_PRINTER_INFO_LEVEL *printer = NULL;
4227 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4229 ZERO_STRUCT(printer);
4230 ZERO_STRUCT(driver);
4232 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4233 return WERR_INVALID_PRINTER_NAME;
4235 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4236 return WERR_UNKNOWN_PRINTER_DRIVER;
4238 fill_printer_driver_info_2(info, driver, servername);
4240 free_a_printer(&printer,2);
4242 return WERR_OK;
4245 /********************************************************************
4246 * copy a strings array and convert to UNICODE
4248 * convert an array of ascii string to a UNICODE string
4249 ********************************************************************/
4251 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4253 int i=0;
4254 int j=0;
4255 char *v;
4256 pstring line;
4257 uint16 *tuary;
4259 DEBUG(6,("init_unistr_array\n"));
4260 *uni_array=NULL;
4262 while (1) {
4263 if (char_array == NULL)
4264 v = "";
4265 else {
4266 v = char_array[i];
4267 if (!v) v = ""; /* hack to handle null lists */
4269 if (strlen(v) == 0) break;
4270 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
4271 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4272 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
4273 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4274 return;
4275 } else
4276 *uni_array = tuary;
4277 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
4278 i++;
4281 if (*uni_array) {
4282 (*uni_array)[j]=0x0000;
4285 DEBUGADD(6,("last one:done\n"));
4288 /********************************************************************
4289 * construct_printer_info_3
4290 * fill a printer_info_3 struct
4291 ********************************************************************/
4293 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4295 pstring temp;
4297 ZERO_STRUCTP(info);
4299 info->version=driver.info_3->cversion;
4301 init_unistr( &info->name, driver.info_3->name );
4302 init_unistr( &info->architecture, driver.info_3->environment );
4304 if (strlen(driver.info_3->driverpath)) {
4305 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4306 init_unistr( &info->driverpath, temp );
4307 } else
4308 init_unistr( &info->driverpath, "" );
4310 if (strlen(driver.info_3->datafile)) {
4311 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4312 init_unistr( &info->datafile, temp );
4313 } else
4314 init_unistr( &info->datafile, "" );
4316 if (strlen(driver.info_3->configfile)) {
4317 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4318 init_unistr( &info->configfile, temp );
4319 } else
4320 init_unistr( &info->configfile, "" );
4322 if (strlen(driver.info_3->helpfile)) {
4323 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4324 init_unistr( &info->helpfile, temp );
4325 } else
4326 init_unistr( &info->helpfile, "" );
4328 init_unistr( &info->monitorname, driver.info_3->monitorname );
4329 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4331 info->dependentfiles=NULL;
4332 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4335 /********************************************************************
4336 * construct_printer_info_3
4337 * fill a printer_info_3 struct
4338 ********************************************************************/
4340 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4342 NT_PRINTER_INFO_LEVEL *printer = NULL;
4343 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4344 WERROR status;
4345 ZERO_STRUCT(driver);
4347 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4348 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4349 if (!W_ERROR_IS_OK(status))
4350 return WERR_INVALID_PRINTER_NAME;
4352 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4353 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4355 #if 0 /* JERRY */
4358 * I put this code in during testing. Helpful when commenting out the
4359 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4360 * as win2k always queries the driver using an infor level of 6.
4361 * I've left it in (but ifdef'd out) because I'll probably
4362 * use it in experimentation again in the future. --jerry 22/01/2002
4365 if (!W_ERROR_IS_OK(status)) {
4367 * Is this a W2k client ?
4369 if (version == 3) {
4370 /* Yes - try again with a WinNT driver. */
4371 version = 2;
4372 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4373 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4375 #endif
4377 if (!W_ERROR_IS_OK(status)) {
4378 free_a_printer(&printer,2);
4379 return WERR_UNKNOWN_PRINTER_DRIVER;
4382 #if 0 /* JERRY */
4384 #endif
4387 fill_printer_driver_info_3(info, driver, servername);
4389 free_a_printer(&printer,2);
4391 return WERR_OK;
4394 /********************************************************************
4395 * construct_printer_info_6
4396 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4397 ********************************************************************/
4399 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4401 pstring temp;
4402 fstring nullstr;
4404 ZERO_STRUCTP(info);
4405 memset(&nullstr, '\0', sizeof(fstring));
4407 info->version=driver.info_3->cversion;
4409 init_unistr( &info->name, driver.info_3->name );
4410 init_unistr( &info->architecture, driver.info_3->environment );
4412 if (strlen(driver.info_3->driverpath)) {
4413 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4414 init_unistr( &info->driverpath, temp );
4415 } else
4416 init_unistr( &info->driverpath, "" );
4418 if (strlen(driver.info_3->datafile)) {
4419 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4420 init_unistr( &info->datafile, temp );
4421 } else
4422 init_unistr( &info->datafile, "" );
4424 if (strlen(driver.info_3->configfile)) {
4425 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4426 init_unistr( &info->configfile, temp );
4427 } else
4428 init_unistr( &info->configfile, "" );
4430 if (strlen(driver.info_3->helpfile)) {
4431 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4432 init_unistr( &info->helpfile, temp );
4433 } else
4434 init_unistr( &info->helpfile, "" );
4436 init_unistr( &info->monitorname, driver.info_3->monitorname );
4437 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4439 info->dependentfiles=NULL;
4440 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4442 info->previousdrivernames=NULL;
4443 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4445 info->driver_date.low=0;
4446 info->driver_date.high=0;
4448 info->padding=0;
4449 info->driver_version_low=0;
4450 info->driver_version_high=0;
4452 init_unistr( &info->mfgname, "");
4453 init_unistr( &info->oem_url, "");
4454 init_unistr( &info->hardware_id, "");
4455 init_unistr( &info->provider, "");
4458 /********************************************************************
4459 * construct_printer_info_6
4460 * fill a printer_info_6 struct
4461 ********************************************************************/
4463 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4465 NT_PRINTER_INFO_LEVEL *printer = NULL;
4466 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4467 WERROR status;
4468 ZERO_STRUCT(driver);
4470 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4471 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4472 if (!W_ERROR_IS_OK(status))
4473 return WERR_INVALID_PRINTER_NAME;
4475 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4476 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4477 if (!W_ERROR_IS_OK(status)) {
4479 * Is this a W2k client ?
4482 if (version < 3) {
4483 free_a_printer(&printer,2);
4484 return WERR_UNKNOWN_PRINTER_DRIVER;
4487 /* Yes - try again with a WinNT driver. */
4488 version = 2;
4489 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4490 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4491 if (!W_ERROR_IS_OK(status)) {
4492 free_a_printer(&printer,2);
4493 return WERR_UNKNOWN_PRINTER_DRIVER;
4497 fill_printer_driver_info_6(info, driver, servername);
4499 free_a_printer(&printer,2);
4501 return WERR_OK;
4504 /****************************************************************************
4505 ****************************************************************************/
4507 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4509 SAFE_FREE(info->dependentfiles);
4512 /****************************************************************************
4513 ****************************************************************************/
4515 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4517 SAFE_FREE(info->dependentfiles);
4521 /****************************************************************************
4522 ****************************************************************************/
4524 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4526 DRIVER_INFO_1 *info=NULL;
4527 WERROR status;
4529 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4530 return WERR_NOMEM;
4532 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4533 if (!W_ERROR_IS_OK(status)) {
4534 SAFE_FREE(info);
4535 return status;
4538 /* check the required size. */
4539 *needed += spoolss_size_printer_driver_info_1(info);
4541 if (!alloc_buffer_size(buffer, *needed)) {
4542 SAFE_FREE(info);
4543 return WERR_INSUFFICIENT_BUFFER;
4546 /* fill the buffer with the structures */
4547 smb_io_printer_driver_info_1("", buffer, info, 0);
4549 /* clear memory */
4550 SAFE_FREE(info);
4552 if (*needed > offered)
4553 return WERR_INSUFFICIENT_BUFFER;
4555 return WERR_OK;
4558 /****************************************************************************
4559 ****************************************************************************/
4561 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4563 DRIVER_INFO_2 *info=NULL;
4564 WERROR status;
4566 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4567 return WERR_NOMEM;
4569 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4570 if (!W_ERROR_IS_OK(status)) {
4571 SAFE_FREE(info);
4572 return status;
4575 /* check the required size. */
4576 *needed += spoolss_size_printer_driver_info_2(info);
4578 if (!alloc_buffer_size(buffer, *needed)) {
4579 SAFE_FREE(info);
4580 return WERR_INSUFFICIENT_BUFFER;
4583 /* fill the buffer with the structures */
4584 smb_io_printer_driver_info_2("", buffer, info, 0);
4586 /* clear memory */
4587 SAFE_FREE(info);
4589 if (*needed > offered)
4590 return WERR_INSUFFICIENT_BUFFER;
4592 return WERR_OK;
4595 /****************************************************************************
4596 ****************************************************************************/
4598 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4600 DRIVER_INFO_3 info;
4601 WERROR status;
4603 ZERO_STRUCT(info);
4605 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4606 if (!W_ERROR_IS_OK(status)) {
4607 return status;
4610 /* check the required size. */
4611 *needed += spoolss_size_printer_driver_info_3(&info);
4613 if (!alloc_buffer_size(buffer, *needed)) {
4614 free_printer_driver_info_3(&info);
4615 return WERR_INSUFFICIENT_BUFFER;
4618 /* fill the buffer with the structures */
4619 smb_io_printer_driver_info_3("", buffer, &info, 0);
4621 free_printer_driver_info_3(&info);
4623 if (*needed > offered)
4624 return WERR_INSUFFICIENT_BUFFER;
4626 return WERR_OK;
4629 /****************************************************************************
4630 ****************************************************************************/
4632 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4634 DRIVER_INFO_6 info;
4635 WERROR status;
4637 ZERO_STRUCT(info);
4639 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4640 if (!W_ERROR_IS_OK(status)) {
4641 return status;
4644 /* check the required size. */
4645 *needed += spoolss_size_printer_driver_info_6(&info);
4647 if (!alloc_buffer_size(buffer, *needed)) {
4648 free_printer_driver_info_6(&info);
4649 return WERR_INSUFFICIENT_BUFFER;
4652 /* fill the buffer with the structures */
4653 smb_io_printer_driver_info_6("", buffer, &info, 0);
4655 free_printer_driver_info_6(&info);
4657 if (*needed > offered)
4658 return WERR_INSUFFICIENT_BUFFER;
4660 return WERR_OK;
4663 /****************************************************************************
4664 ****************************************************************************/
4666 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4668 POLICY_HND *handle = &q_u->handle;
4669 UNISTR2 *uni_arch = &q_u->architecture;
4670 uint32 level = q_u->level;
4671 uint32 clientmajorversion = q_u->clientmajorversion;
4672 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4673 NEW_BUFFER *buffer = NULL;
4674 uint32 offered = q_u->offered;
4675 uint32 *needed = &r_u->needed;
4676 uint32 *servermajorversion = &r_u->servermajorversion;
4677 uint32 *serverminorversion = &r_u->serverminorversion;
4679 fstring servername;
4680 fstring architecture;
4681 int snum;
4683 /* that's an [in out] buffer */
4684 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4685 buffer = r_u->buffer;
4687 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4689 *needed=0;
4690 *servermajorversion=0;
4691 *serverminorversion=0;
4693 pstrcpy(servername, get_called_name());
4694 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4696 if (!get_printer_snum(p, handle, &snum))
4697 return WERR_BADFID;
4699 switch (level) {
4700 case 1:
4701 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4702 case 2:
4703 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4704 case 3:
4705 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4706 case 6:
4707 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4710 return WERR_UNKNOWN_LEVEL;
4713 /****************************************************************************
4714 ****************************************************************************/
4716 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4718 POLICY_HND *handle = &q_u->handle;
4720 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4722 if (!Printer) {
4723 DEBUG(3,("Error in startpageprinter printer handle\n"));
4724 return WERR_BADFID;
4727 Printer->page_started=True;
4728 return WERR_OK;
4731 /****************************************************************************
4732 ****************************************************************************/
4734 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4736 POLICY_HND *handle = &q_u->handle;
4738 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4740 if (!Printer) {
4741 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4742 return WERR_BADFID;
4745 Printer->page_started=False;
4746 print_job_endpage(Printer->jobid);
4748 return WERR_OK;
4751 /********************************************************************
4752 * api_spoolss_getprinter
4753 * called from the spoolss dispatcher
4755 ********************************************************************/
4757 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4759 POLICY_HND *handle = &q_u->handle;
4760 /* uint32 level = q_u->doc_info_container.level; - notused. */
4761 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4762 uint32 *jobid = &r_u->jobid;
4764 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4765 int snum;
4766 pstring jobname;
4767 fstring datatype;
4768 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4769 struct current_user user;
4771 if (!Printer) {
4772 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4773 return WERR_BADFID;
4776 get_current_user(&user, p);
4779 * a nice thing with NT is it doesn't listen to what you tell it.
4780 * when asked to send _only_ RAW datas, it tries to send datas
4781 * in EMF format.
4783 * So I add checks like in NT Server ...
4785 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4786 * there's a bug in NT client-side code, so we'll fix it in the
4787 * server-side code. *nnnnnggggh!*
4790 if (info_1->p_datatype != 0) {
4791 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4792 if (strcmp(datatype, "RAW") != 0) {
4793 (*jobid)=0;
4794 return WERR_INVALID_DATATYPE;
4798 /* get the share number of the printer */
4799 if (!get_printer_snum(p, handle, &snum)) {
4800 return WERR_BADFID;
4803 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4805 Printer->jobid = print_job_start(&user, snum, jobname);
4807 /* An error occured in print_job_start() so return an appropriate
4808 NT error code. */
4810 if (Printer->jobid == -1) {
4811 return map_werror_from_unix(errno);
4814 Printer->document_started=True;
4815 (*jobid) = Printer->jobid;
4817 return WERR_OK;
4820 /********************************************************************
4821 * api_spoolss_getprinter
4822 * called from the spoolss dispatcher
4824 ********************************************************************/
4826 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4828 POLICY_HND *handle = &q_u->handle;
4830 return _spoolss_enddocprinter_internal(p, handle);
4833 /****************************************************************************
4834 ****************************************************************************/
4836 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4838 POLICY_HND *handle = &q_u->handle;
4839 uint32 buffer_size = q_u->buffer_size;
4840 uint8 *buffer = q_u->buffer;
4841 uint32 *buffer_written = &q_u->buffer_size2;
4843 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4845 if (!Printer) {
4846 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4847 r_u->buffer_written = q_u->buffer_size2;
4848 return WERR_BADFID;
4851 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4854 r_u->buffer_written = q_u->buffer_size2;
4856 return WERR_OK;
4859 /********************************************************************
4860 * api_spoolss_getprinter
4861 * called from the spoolss dispatcher
4863 ********************************************************************/
4865 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4866 pipes_struct *p)
4868 struct current_user user;
4869 int snum;
4870 WERROR errcode = WERR_BADFUNC;
4871 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4873 get_current_user(&user, p);
4875 if (!Printer) {
4876 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4877 return WERR_BADFID;
4880 if (!get_printer_snum(p, handle, &snum))
4881 return WERR_BADFID;
4883 switch (command) {
4884 case PRINTER_CONTROL_PAUSE:
4885 if (print_queue_pause(&user, snum, &errcode)) {
4886 errcode = WERR_OK;
4888 break;
4889 case PRINTER_CONTROL_RESUME:
4890 case PRINTER_CONTROL_UNPAUSE:
4891 if (print_queue_resume(&user, snum, &errcode)) {
4892 errcode = WERR_OK;
4894 break;
4895 case PRINTER_CONTROL_PURGE:
4896 if (print_queue_purge(&user, snum, &errcode)) {
4897 errcode = WERR_OK;
4899 break;
4900 default:
4901 return WERR_UNKNOWN_LEVEL;
4904 return errcode;
4907 /********************************************************************
4908 * api_spoolss_abortprinter
4909 ********************************************************************/
4911 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4913 POLICY_HND *handle = &q_u->handle;
4915 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4918 /********************************************************************
4919 * called by spoolss_api_setprinter
4920 * when updating a printer description
4921 ********************************************************************/
4923 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4924 const SPOOL_PRINTER_INFO_LEVEL *info,
4925 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4927 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4928 struct current_user user;
4929 WERROR result;
4930 int snum;
4932 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4934 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4935 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4936 OUR_HANDLE(handle)));
4938 result = WERR_BADFID;
4939 goto done;
4942 /* NT seems to like setting the security descriptor even though
4943 nothing may have actually changed. This causes annoying
4944 dialog boxes when the user doesn't have permission to change
4945 the security descriptor. */
4947 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4949 if (DEBUGLEVEL >= 10) {
4950 SEC_ACL *the_acl;
4951 int i;
4953 the_acl = old_secdesc_ctr->sec->dacl;
4954 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4955 PRINTERNAME(snum), the_acl->num_aces));
4957 for (i = 0; i < the_acl->num_aces; i++) {
4958 fstring sid_str;
4960 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4962 DEBUG(10, ("%s 0x%08x\n", sid_str,
4963 the_acl->ace[i].info.mask));
4966 the_acl = secdesc_ctr->sec->dacl;
4968 if (the_acl) {
4969 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4970 PRINTERNAME(snum), the_acl->num_aces));
4972 for (i = 0; i < the_acl->num_aces; i++) {
4973 fstring sid_str;
4975 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4977 DEBUG(10, ("%s 0x%08x\n", sid_str,
4978 the_acl->ace[i].info.mask));
4980 } else {
4981 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4985 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4987 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4988 result = WERR_OK;
4989 goto done;
4992 /* Work out which user is performing the operation */
4994 get_current_user(&user, p);
4996 /* Check the user has permissions to change the security
4997 descriptor. By experimentation with two NT machines, the user
4998 requires Full Access to the printer to change security
4999 information. */
5001 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5002 result = WERR_ACCESS_DENIED;
5003 goto done;
5006 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5008 done:
5010 return result;
5013 /********************************************************************
5014 Do Samba sanity checks on a printer info struct.
5015 this has changed purpose: it now "canonicalises" printer
5016 info from a client rather than just checking it is correct
5017 ********************************************************************/
5019 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5021 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5022 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5024 /* we force some elements to "correct" values */
5025 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5026 fstrcpy(info->sharename, lp_servicename(snum));
5027 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5028 get_called_name(), info->sharename);
5029 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5031 return True;
5034 /****************************************************************************
5035 ****************************************************************************/
5037 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5039 extern userdom_struct current_user_info;
5040 char *cmd = lp_addprinter_cmd();
5041 char **qlines;
5042 pstring command;
5043 pstring driverlocation;
5044 int numlines;
5045 int ret;
5046 int fd;
5047 fstring remote_machine = "%m";
5049 /* build driver path... only 9X architecture is needed for legacy reasons */
5050 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5051 get_called_name());
5052 /* change \ to \\ for the shell */
5053 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5054 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5056 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5057 cmd, printer->info_2->printername, printer->info_2->sharename,
5058 printer->info_2->portname, printer->info_2->drivername,
5059 printer->info_2->location, driverlocation, remote_machine);
5061 DEBUG(10,("Running [%s]\n", command));
5062 ret = smbrun(command, &fd);
5063 DEBUGADD(10,("returned [%d]\n", ret));
5065 if ( ret != 0 ) {
5066 if (fd != -1)
5067 close(fd);
5068 return False;
5071 numlines = 0;
5072 /* Get lines and convert them back to dos-codepage */
5073 qlines = fd_lines_load(fd, &numlines);
5074 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5075 close(fd);
5077 if(numlines) {
5078 /* Set the portname to what the script says the portname should be. */
5079 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5080 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5082 /* Send SIGHUP to process group... is there a better way? */
5083 kill(0, SIGHUP);
5084 add_all_printers();
5087 file_lines_free(qlines);
5088 return True;
5091 #if 0 /* JERRY */
5093 /* Return true if two devicemodes are equal */
5095 #define DEVMODE_CHECK_INT(field) \
5096 if (d1->field != d2->field) { \
5097 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
5098 d1->field, d2->field)); \
5099 return False; \
5102 /************************************************************************
5103 Handy, but currently unused functions
5104 ***********************************************************************/
5106 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
5108 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
5110 if (!d1 ^ !d2) {
5111 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
5112 return False; /* if either is exclusively NULL are not equal */
5115 if (!strequal(d1->devicename, d2->devicename)) {
5116 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
5117 return False;
5120 if (!strequal(d1->formname, d2->formname)) {
5121 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
5122 return False;
5125 DEVMODE_CHECK_INT(specversion);
5126 DEVMODE_CHECK_INT(driverversion);
5127 DEVMODE_CHECK_INT(driverextra);
5128 DEVMODE_CHECK_INT(orientation);
5129 DEVMODE_CHECK_INT(papersize);
5130 DEVMODE_CHECK_INT(paperlength);
5131 DEVMODE_CHECK_INT(paperwidth);
5132 DEVMODE_CHECK_INT(scale);
5133 DEVMODE_CHECK_INT(copies);
5134 DEVMODE_CHECK_INT(defaultsource);
5135 DEVMODE_CHECK_INT(printquality);
5136 DEVMODE_CHECK_INT(color);
5137 DEVMODE_CHECK_INT(duplex);
5138 DEVMODE_CHECK_INT(yresolution);
5139 DEVMODE_CHECK_INT(ttoption);
5140 DEVMODE_CHECK_INT(collate);
5141 DEVMODE_CHECK_INT(logpixels);
5143 DEVMODE_CHECK_INT(fields);
5144 DEVMODE_CHECK_INT(bitsperpel);
5145 DEVMODE_CHECK_INT(pelswidth);
5146 DEVMODE_CHECK_INT(pelsheight);
5147 DEVMODE_CHECK_INT(displayflags);
5148 DEVMODE_CHECK_INT(displayfrequency);
5149 DEVMODE_CHECK_INT(icmmethod);
5150 DEVMODE_CHECK_INT(icmintent);
5151 DEVMODE_CHECK_INT(mediatype);
5152 DEVMODE_CHECK_INT(dithertype);
5153 DEVMODE_CHECK_INT(reserved1);
5154 DEVMODE_CHECK_INT(reserved2);
5155 DEVMODE_CHECK_INT(panningwidth);
5156 DEVMODE_CHECK_INT(panningheight);
5158 /* compare the private data if it exists */
5159 if (!d1->driverextra && !d2->driverextra) goto equal;
5162 DEVMODE_CHECK_INT(driverextra);
5164 if (memcmp(d1->private, d2->private, d1->driverextra)) {
5165 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
5166 return False;
5169 equal:
5170 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
5171 return True;
5174 /* Return true if two NT_PRINTER_PARAM structures are equal */
5176 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
5177 NT_PRINTER_PARAM *p2)
5179 if (!p1 && !p2) goto equal;
5181 if ((!p1 && p2) || (p1 && !p2)) {
5182 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
5183 return False;
5186 /* Compare lists of printer parameters */
5188 while (p1) {
5189 BOOL found = False;
5190 NT_PRINTER_PARAM *q = p1;
5192 /* Find the parameter in the second structure */
5194 while(q) {
5196 if (strequal(p1->value, q->value)) {
5198 if (p1->type != q->type) {
5199 DEBUG(10, ("nt_printer_param_equal():"
5200 "types for %s differ (%d != %d)\n",
5201 p1->value, p1->type,
5202 q->type));
5203 break;
5206 if (p1->data_len != q->data_len) {
5207 DEBUG(10, ("nt_printer_param_equal():"
5208 "len for %s differs (%d != %d)\n",
5209 p1->value, p1->data_len,
5210 q->data_len));
5211 break;
5214 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
5215 found = True;
5216 } else {
5217 DEBUG(10, ("nt_printer_param_equal():"
5218 "data for %s differs\n", p1->value));
5221 break;
5224 q = q->next;
5227 if (!found) {
5228 DEBUG(10, ("nt_printer_param_equal(): param %s "
5229 "does not exist\n", p1->value));
5230 return False;
5233 p1 = p1->next;
5236 equal:
5238 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
5239 return True;
5242 /********************************************************************
5243 * Called by update_printer when trying to work out whether to
5244 * actually update printer info.
5245 ********************************************************************/
5247 #define PI_CHECK_INT(field) \
5248 if (pi1->field != pi2->field) { \
5249 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
5250 pi1->field, pi2->field)); \
5251 return False; \
5254 #define PI_CHECK_STR(field) \
5255 if (!strequal(pi1->field, pi2->field)) { \
5256 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
5257 pi1->field, pi2->field)); \
5258 return False; \
5261 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
5262 NT_PRINTER_INFO_LEVEL *p2)
5264 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
5266 /* Trivial conditions */
5268 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
5269 goto equal;
5272 if ((!p1 && p2) || (p1 && !p2) ||
5273 (!p1->info_2 && p2->info_2) ||
5274 (p1->info_2 && !p2->info_2)) {
5275 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
5276 "differ\n"));
5277 return False;
5280 /* Compare two nt_printer_info_level structures. Don't compare
5281 status or cjobs as they seem to have something to do with the
5282 printer queue. */
5284 pi1 = p1->info_2;
5285 pi2 = p2->info_2;
5287 /* Don't check the attributes as we stomp on the value in
5288 check_printer_ok() anyway. */
5290 #if 0
5291 PI_CHECK_INT(attributes);
5292 #endif
5294 PI_CHECK_INT(priority);
5295 PI_CHECK_INT(default_priority);
5296 PI_CHECK_INT(starttime);
5297 PI_CHECK_INT(untiltime);
5298 PI_CHECK_INT(averageppm);
5300 /* Yuck - don't check the printername or servername as the
5301 mod_a_printer() code plays games with them. You can't
5302 change the printername or the sharename through this interface
5303 in Samba. */
5305 PI_CHECK_STR(sharename);
5306 PI_CHECK_STR(portname);
5307 PI_CHECK_STR(drivername);
5308 PI_CHECK_STR(comment);
5309 PI_CHECK_STR(location);
5311 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
5312 return False;
5315 PI_CHECK_STR(sepfile);
5316 PI_CHECK_STR(printprocessor);
5317 PI_CHECK_STR(datatype);
5318 PI_CHECK_STR(parameters);
5320 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
5321 return False;
5324 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
5325 return False;
5328 PI_CHECK_INT(changeid);
5329 PI_CHECK_INT(c_setprinter);
5330 PI_CHECK_INT(setuptime);
5332 equal:
5333 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5334 return True;
5337 #endif
5339 /********************************************************************
5340 * Called by spoolss_api_setprinter
5341 * when updating a printer description.
5342 ********************************************************************/
5344 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5345 const SPOOL_PRINTER_INFO_LEVEL *info,
5346 DEVICEMODE *devmode)
5348 int snum;
5349 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5350 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5351 WERROR result;
5353 DEBUG(8,("update_printer\n"));
5355 result = WERR_OK;
5357 if (level!=2) {
5358 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5359 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5360 result = WERR_UNKNOWN_LEVEL;
5361 goto done;
5364 if (!Printer) {
5365 result = WERR_BADFID;
5366 goto done;
5369 if (!get_printer_snum(p, handle, &snum)) {
5370 result = WERR_BADFID;
5371 goto done;
5374 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5375 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5376 result = WERR_BADFID;
5377 goto done;
5380 DEBUGADD(8,("Converting info_2 struct\n"));
5383 * convert_printer_info converts the incoming
5384 * info from the client and overwrites the info
5385 * just read from the tdb in the pointer 'printer'.
5388 if (!convert_printer_info(info, printer, level)) {
5389 result = WERR_NOMEM;
5390 goto done;
5393 if (devmode) {
5394 /* we have a valid devmode
5395 convert it and link it*/
5397 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5398 if (!convert_devicemode(printer->info_2->printername, devmode,
5399 &printer->info_2->devmode)) {
5400 result = WERR_NOMEM;
5401 goto done;
5405 /* Do sanity check on the requested changes for Samba */
5407 if (!check_printer_ok(printer->info_2, snum)) {
5408 result = WERR_INVALID_PARAM;
5409 goto done;
5412 #if 0 /* JERRY */
5415 * Another one of those historical misunderstandings...
5416 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5417 * I'm leaving it here as a reminder. --jerry
5420 if (nt_printer_info_level_equal(printer, old_printer)) {
5421 DEBUG(3, ("update_printer: printer info has not changed\n"));
5422 result = WERR_OK;
5423 goto done;
5426 #endif
5428 /* Check calling user has permission to update printer description */
5430 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5431 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5432 result = WERR_ACCESS_DENIED;
5433 goto done;
5436 /* Call addprinter hook */
5438 if (*lp_addprinter_cmd()) {
5439 if ( !add_printer_hook(printer) ) {
5440 result = WERR_ACCESS_DENIED;
5441 goto done;
5446 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5447 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5448 * requires Win32 client code (see other notes elsewhere in the code).
5450 if (printer->info_2->devmode &&
5451 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5453 DEBUG(10,("update_printer: Save printer driver init data\n"));
5454 printer->info_2->devmode->displayfrequency = 0;
5456 if (update_driver_init(*printer, 2)!=0) {
5457 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5458 result = WERR_ACCESS_DENIED;
5459 goto done;
5461 } else {
5463 * When a *new* driver is bound to a printer, the drivername is used to
5464 * lookup previously saved driver initialization info, which is then
5465 * bound to the printer, simulating what happens in the Windows arch.
5467 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5468 if (!set_driver_init(printer, 2)) {
5469 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5470 printer->info_2->drivername));
5472 notify_printer_driver(snum, printer->info_2->drivername);
5476 /* Update printer info */
5477 result = mod_a_printer(*printer, 2);
5479 /* flag which changes actually occured. This is a small subset of
5480 all the possible changes */
5482 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5483 notify_printer_comment(snum, printer->info_2->comment);
5485 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5486 notify_printer_sharename(snum, printer->info_2->sharename);
5488 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5489 notify_printer_port(snum, printer->info_2->portname);
5491 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5492 notify_printer_location(snum, printer->info_2->location);
5494 done:
5495 free_a_printer(&printer, 2);
5496 free_a_printer(&old_printer, 2);
5499 return result;
5502 /****************************************************************************
5503 ****************************************************************************/
5505 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5507 POLICY_HND *handle = &q_u->handle;
5508 uint32 level = q_u->level;
5509 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5510 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5511 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5512 uint32 command = q_u->command;
5514 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5516 if (!Printer) {
5517 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5518 return WERR_BADFID;
5521 /* check the level */
5522 switch (level) {
5523 case 0:
5524 return control_printer(handle, command, p);
5525 case 2:
5526 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5527 case 3:
5528 return update_printer_sec(handle, level, info, p,
5529 secdesc_ctr);
5530 default:
5531 return WERR_UNKNOWN_LEVEL;
5535 /****************************************************************************
5536 ****************************************************************************/
5538 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5540 POLICY_HND *handle = &q_u->handle;
5542 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5544 if (!Printer) {
5545 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5546 return WERR_BADFID;
5549 if (Printer->notify.client_connected==True)
5550 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5552 Printer->notify.flags=0;
5553 Printer->notify.options=0;
5554 Printer->notify.localmachine[0]='\0';
5555 Printer->notify.printerlocal=0;
5556 if (Printer->notify.option)
5557 free_spool_notify_option(&Printer->notify.option);
5558 Printer->notify.client_connected=False;
5560 return WERR_OK;
5563 /****************************************************************************
5564 ****************************************************************************/
5566 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5568 /* that's an [in out] buffer (despite appearences to the contrary) */
5569 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5571 r_u->needed = 0;
5572 return WERR_INVALID_PARAM; /* this is what a NT server
5573 returns for AddJob. AddJob
5574 must fail on non-local
5575 printers */
5578 /****************************************************************************
5579 ****************************************************************************/
5581 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5582 int position, int snum)
5584 pstring temp_name;
5586 struct tm *t;
5588 t=gmtime(&queue->time);
5589 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5591 job_info->jobid=queue->job;
5592 init_unistr(&job_info->printername, lp_servicename(snum));
5593 init_unistr(&job_info->machinename, temp_name);
5594 init_unistr(&job_info->username, queue->fs_user);
5595 init_unistr(&job_info->document, queue->fs_file);
5596 init_unistr(&job_info->datatype, "RAW");
5597 init_unistr(&job_info->text_status, "");
5598 job_info->status=nt_printj_status(queue->status);
5599 job_info->priority=queue->priority;
5600 job_info->position=position;
5601 job_info->totalpages=queue->page_count;
5602 job_info->pagesprinted=0;
5604 make_systemtime(&job_info->submitted, t);
5607 /****************************************************************************
5608 ****************************************************************************/
5610 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5611 int position, int snum,
5612 NT_PRINTER_INFO_LEVEL *ntprinter,
5613 DEVICEMODE *devmode)
5615 pstring temp_name;
5616 pstring chaine;
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;
5624 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5626 init_unistr(&job_info->printername, chaine);
5628 init_unistr(&job_info->machinename, temp_name);
5629 init_unistr(&job_info->username, queue->fs_user);
5630 init_unistr(&job_info->document, queue->fs_file);
5631 init_unistr(&job_info->notifyname, queue->fs_user);
5632 init_unistr(&job_info->datatype, "RAW");
5633 init_unistr(&job_info->printprocessor, "winprint");
5634 init_unistr(&job_info->parameters, "");
5635 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5636 init_unistr(&job_info->text_status, "");
5638 /* and here the security descriptor */
5640 job_info->status=nt_printj_status(queue->status);
5641 job_info->priority=queue->priority;
5642 job_info->position=position;
5643 job_info->starttime=0;
5644 job_info->untiltime=0;
5645 job_info->totalpages=queue->page_count;
5646 job_info->size=queue->size;
5647 make_systemtime(&(job_info->submitted), t);
5648 job_info->timeelapsed=0;
5649 job_info->pagesprinted=0;
5651 job_info->devmode = devmode;
5653 return (True);
5656 /****************************************************************************
5657 Enumjobs at level 1.
5658 ****************************************************************************/
5660 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5661 NEW_BUFFER *buffer, uint32 offered,
5662 uint32 *needed, uint32 *returned)
5664 JOB_INFO_1 *info;
5665 int i;
5667 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5668 if (info==NULL) {
5669 SAFE_FREE(queue);
5670 *returned=0;
5671 return WERR_NOMEM;
5674 for (i=0; i<*returned; i++)
5675 fill_job_info_1(&info[i], &queue[i], i, snum);
5677 SAFE_FREE(queue);
5679 /* check the required size. */
5680 for (i=0; i<*returned; i++)
5681 (*needed) += spoolss_size_job_info_1(&info[i]);
5683 if (!alloc_buffer_size(buffer, *needed)) {
5684 SAFE_FREE(info);
5685 return WERR_INSUFFICIENT_BUFFER;
5688 /* fill the buffer with the structures */
5689 for (i=0; i<*returned; i++)
5690 smb_io_job_info_1("", buffer, &info[i], 0);
5692 /* clear memory */
5693 SAFE_FREE(info);
5695 if (*needed > offered) {
5696 *returned=0;
5697 return WERR_INSUFFICIENT_BUFFER;
5700 return WERR_OK;
5703 /****************************************************************************
5704 Enumjobs at level 2.
5705 ****************************************************************************/
5707 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5708 NEW_BUFFER *buffer, uint32 offered,
5709 uint32 *needed, uint32 *returned)
5711 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5712 JOB_INFO_2 *info = NULL;
5713 int i;
5714 WERROR result;
5715 DEVICEMODE *devmode = NULL;
5717 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5718 if (info==NULL) {
5719 *returned=0;
5720 result = WERR_NOMEM;
5721 goto done;
5724 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5725 if (!W_ERROR_IS_OK(result)) {
5726 *returned = 0;
5727 goto done;
5730 if (!(devmode = construct_dev_mode(snum))) {
5731 *returned = 0;
5732 result = WERR_NOMEM;
5733 goto done;
5736 for (i=0; i<*returned; i++)
5737 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5738 devmode);
5740 free_a_printer(&ntprinter, 2);
5741 SAFE_FREE(queue);
5743 /* check the required size. */
5744 for (i=0; i<*returned; i++)
5745 (*needed) += spoolss_size_job_info_2(&info[i]);
5747 if (*needed > offered) {
5748 *returned=0;
5749 result = WERR_INSUFFICIENT_BUFFER;
5750 goto done;
5753 if (!alloc_buffer_size(buffer, *needed)) {
5754 SAFE_FREE(info);
5755 result = WERR_INSUFFICIENT_BUFFER;
5756 goto done;
5759 /* fill the buffer with the structures */
5760 for (i=0; i<*returned; i++)
5761 smb_io_job_info_2("", buffer, &info[i], 0);
5763 result = WERR_OK;
5765 done:
5766 free_a_printer(&ntprinter, 2);
5767 free_devmode(devmode);
5768 SAFE_FREE(queue);
5769 SAFE_FREE(info);
5771 return result;
5775 /****************************************************************************
5776 Enumjobs.
5777 ****************************************************************************/
5779 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5781 POLICY_HND *handle = &q_u->handle;
5782 /* uint32 firstjob = q_u->firstjob; - notused. */
5783 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5784 uint32 level = q_u->level;
5785 NEW_BUFFER *buffer = NULL;
5786 uint32 offered = q_u->offered;
5787 uint32 *needed = &r_u->needed;
5788 uint32 *returned = &r_u->returned;
5790 int snum;
5791 print_status_struct prt_status;
5792 print_queue_struct *queue=NULL;
5794 /* that's an [in out] buffer */
5795 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5796 buffer = r_u->buffer;
5798 DEBUG(4,("_spoolss_enumjobs\n"));
5800 *needed=0;
5801 *returned=0;
5803 if (!get_printer_snum(p, handle, &snum))
5804 return WERR_BADFID;
5806 *returned = print_queue_status(snum, &queue, &prt_status);
5807 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5809 if (*returned == 0) {
5810 SAFE_FREE(queue);
5811 return WERR_OK;
5814 switch (level) {
5815 case 1:
5816 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5817 case 2:
5818 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5819 default:
5820 SAFE_FREE(queue);
5821 *returned=0;
5822 return WERR_UNKNOWN_LEVEL;
5826 /****************************************************************************
5827 ****************************************************************************/
5829 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5831 return WERR_OK;
5834 /****************************************************************************
5835 ****************************************************************************/
5837 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5839 POLICY_HND *handle = &q_u->handle;
5840 uint32 jobid = q_u->jobid;
5841 /* uint32 level = q_u->level; - notused. */
5842 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5843 uint32 command = q_u->command;
5845 struct current_user user;
5846 int snum;
5847 WERROR errcode = WERR_BADFUNC;
5849 if (!get_printer_snum(p, handle, &snum)) {
5850 return WERR_BADFID;
5853 if (!print_job_exists(jobid)) {
5854 return WERR_INVALID_PRINTER_NAME;
5857 get_current_user(&user, p);
5859 switch (command) {
5860 case JOB_CONTROL_CANCEL:
5861 case JOB_CONTROL_DELETE:
5862 if (print_job_delete(&user, jobid, &errcode)) {
5863 errcode = WERR_OK;
5865 break;
5866 case JOB_CONTROL_PAUSE:
5867 if (print_job_pause(&user, jobid, &errcode)) {
5868 errcode = WERR_OK;
5870 break;
5871 case JOB_CONTROL_RESTART:
5872 case JOB_CONTROL_RESUME:
5873 if (print_job_resume(&user, jobid, &errcode)) {
5874 errcode = WERR_OK;
5876 break;
5877 default:
5878 return WERR_UNKNOWN_LEVEL;
5881 return errcode;
5884 /****************************************************************************
5885 Enumerates all printer drivers at level 1.
5886 ****************************************************************************/
5888 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5890 int i;
5891 int ndrivers;
5892 uint32 version;
5893 fstring *list = NULL;
5895 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5896 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5898 *returned=0;
5900 #define MAX_VERSION 4
5902 for (version=0; version<MAX_VERSION; version++) {
5903 list=NULL;
5904 ndrivers=get_ntdrivers(&list, architecture, version);
5905 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5907 if(ndrivers == -1)
5908 return WERR_NOMEM;
5910 if(ndrivers != 0) {
5911 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5912 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5913 SAFE_FREE(driver_info_1);
5914 SAFE_FREE(list);
5915 return WERR_NOMEM;
5917 else driver_info_1 = tdi1;
5920 for (i=0; i<ndrivers; i++) {
5921 WERROR status;
5922 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5923 ZERO_STRUCT(driver);
5924 status = get_a_printer_driver(&driver, 3, list[i],
5925 architecture, version);
5926 if (!W_ERROR_IS_OK(status)) {
5927 SAFE_FREE(list);
5928 return status;
5930 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5931 free_a_printer_driver(driver, 3);
5934 *returned+=ndrivers;
5935 SAFE_FREE(list);
5938 /* check the required size. */
5939 for (i=0; i<*returned; i++) {
5940 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5941 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5944 if (!alloc_buffer_size(buffer, *needed)) {
5945 SAFE_FREE(driver_info_1);
5946 return WERR_INSUFFICIENT_BUFFER;
5949 /* fill the buffer with the driver structures */
5950 for (i=0; i<*returned; i++) {
5951 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5952 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5955 SAFE_FREE(driver_info_1);
5957 if (*needed > offered) {
5958 *returned=0;
5959 return WERR_INSUFFICIENT_BUFFER;
5962 return WERR_OK;
5965 /****************************************************************************
5966 Enumerates all printer drivers at level 2.
5967 ****************************************************************************/
5969 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5971 int i;
5972 int ndrivers;
5973 uint32 version;
5974 fstring *list = NULL;
5976 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5977 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5979 *returned=0;
5981 #define MAX_VERSION 4
5983 for (version=0; version<MAX_VERSION; version++) {
5984 list=NULL;
5985 ndrivers=get_ntdrivers(&list, architecture, version);
5986 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5988 if(ndrivers == -1)
5989 return WERR_NOMEM;
5991 if(ndrivers != 0) {
5992 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5993 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5994 SAFE_FREE(driver_info_2);
5995 SAFE_FREE(list);
5996 return WERR_NOMEM;
5998 else driver_info_2 = tdi2;
6001 for (i=0; i<ndrivers; i++) {
6002 WERROR status;
6004 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6005 ZERO_STRUCT(driver);
6006 status = get_a_printer_driver(&driver, 3, list[i],
6007 architecture, version);
6008 if (!W_ERROR_IS_OK(status)) {
6009 SAFE_FREE(list);
6010 return status;
6012 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6013 free_a_printer_driver(driver, 3);
6016 *returned+=ndrivers;
6017 SAFE_FREE(list);
6020 /* check the required size. */
6021 for (i=0; i<*returned; i++) {
6022 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6023 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6026 if (!alloc_buffer_size(buffer, *needed)) {
6027 SAFE_FREE(driver_info_2);
6028 return WERR_INSUFFICIENT_BUFFER;
6031 /* fill the buffer with the form structures */
6032 for (i=0; i<*returned; i++) {
6033 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6034 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6037 SAFE_FREE(driver_info_2);
6039 if (*needed > offered) {
6040 *returned=0;
6041 return WERR_INSUFFICIENT_BUFFER;
6044 return WERR_OK;
6047 /****************************************************************************
6048 Enumerates all printer drivers at level 3.
6049 ****************************************************************************/
6051 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6053 int i;
6054 int ndrivers;
6055 uint32 version;
6056 fstring *list = NULL;
6058 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6059 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6061 *returned=0;
6063 #define MAX_VERSION 4
6065 for (version=0; version<MAX_VERSION; version++) {
6066 list=NULL;
6067 ndrivers=get_ntdrivers(&list, architecture, version);
6068 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6070 if(ndrivers == -1)
6071 return WERR_NOMEM;
6073 if(ndrivers != 0) {
6074 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6075 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6076 SAFE_FREE(driver_info_3);
6077 SAFE_FREE(list);
6078 return WERR_NOMEM;
6080 else driver_info_3 = tdi3;
6083 for (i=0; i<ndrivers; i++) {
6084 WERROR status;
6086 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6087 ZERO_STRUCT(driver);
6088 status = get_a_printer_driver(&driver, 3, list[i],
6089 architecture, version);
6090 if (!W_ERROR_IS_OK(status)) {
6091 SAFE_FREE(list);
6092 return status;
6094 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6095 free_a_printer_driver(driver, 3);
6098 *returned+=ndrivers;
6099 SAFE_FREE(list);
6102 /* check the required size. */
6103 for (i=0; i<*returned; i++) {
6104 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6105 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6108 if (!alloc_buffer_size(buffer, *needed)) {
6109 SAFE_FREE(driver_info_3);
6110 return WERR_INSUFFICIENT_BUFFER;
6113 /* fill the buffer with the driver structures */
6114 for (i=0; i<*returned; i++) {
6115 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6116 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6119 for (i=0; i<*returned; i++)
6120 SAFE_FREE(driver_info_3[i].dependentfiles);
6122 SAFE_FREE(driver_info_3);
6124 if (*needed > offered) {
6125 *returned=0;
6126 return WERR_INSUFFICIENT_BUFFER;
6129 return WERR_OK;
6132 /****************************************************************************
6133 Enumerates all printer drivers.
6134 ****************************************************************************/
6136 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6138 /* UNISTR2 *name = &q_u->name; - notused. */
6139 UNISTR2 *environment = &q_u->environment;
6140 uint32 level = q_u->level;
6141 NEW_BUFFER *buffer = NULL;
6142 uint32 offered = q_u->offered;
6143 uint32 *needed = &r_u->needed;
6144 uint32 *returned = &r_u->returned;
6146 fstring *list = NULL;
6147 fstring servername;
6148 fstring architecture;
6150 /* that's an [in out] buffer */
6151 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6152 buffer = r_u->buffer;
6154 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6155 fstrcpy(servername, get_called_name());
6156 *needed=0;
6157 *returned=0;
6159 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6161 switch (level) {
6162 case 1:
6163 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6164 case 2:
6165 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6166 case 3:
6167 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6168 default:
6169 *returned=0;
6170 SAFE_FREE(list);
6171 return WERR_UNKNOWN_LEVEL;
6175 /****************************************************************************
6176 ****************************************************************************/
6178 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6180 form->flag=list->flag;
6181 init_unistr(&form->name, list->name);
6182 form->width=list->width;
6183 form->length=list->length;
6184 form->left=list->left;
6185 form->top=list->top;
6186 form->right=list->right;
6187 form->bottom=list->bottom;
6190 /****************************************************************************
6191 ****************************************************************************/
6193 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6195 /* POLICY_HND *handle = &q_u->handle; - notused. */
6196 uint32 level = q_u->level;
6197 NEW_BUFFER *buffer = NULL;
6198 uint32 offered = q_u->offered;
6199 uint32 *needed = &r_u->needed;
6200 uint32 *numofforms = &r_u->numofforms;
6201 uint32 numbuiltinforms;
6203 nt_forms_struct *list=NULL;
6204 nt_forms_struct *builtinlist=NULL;
6205 FORM_1 *forms_1;
6206 int buffer_size=0;
6207 int i;
6209 /* that's an [in out] buffer */
6210 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6211 buffer = r_u->buffer;
6213 DEBUG(4,("_spoolss_enumforms\n"));
6214 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6215 DEBUGADD(5,("Info level [%d]\n", level));
6217 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6218 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6219 *numofforms = get_ntforms(&list);
6220 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6221 *numofforms += numbuiltinforms;
6223 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6225 switch (level) {
6226 case 1:
6227 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6228 *numofforms=0;
6229 return WERR_NOMEM;
6232 /* construct the list of form structures */
6233 for (i=0; i<numbuiltinforms; i++) {
6234 DEBUGADD(6,("Filling form number [%d]\n",i));
6235 fill_form_1(&forms_1[i], &builtinlist[i]);
6238 SAFE_FREE(builtinlist);
6240 for (; i<*numofforms; i++) {
6241 DEBUGADD(6,("Filling form number [%d]\n",i));
6242 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6245 SAFE_FREE(list);
6247 /* check the required size. */
6248 for (i=0; i<numbuiltinforms; i++) {
6249 DEBUGADD(6,("adding form [%d]'s size\n",i));
6250 buffer_size += spoolss_size_form_1(&forms_1[i]);
6252 for (; i<*numofforms; i++) {
6253 DEBUGADD(6,("adding form [%d]'s size\n",i));
6254 buffer_size += spoolss_size_form_1(&forms_1[i]);
6257 *needed=buffer_size;
6259 if (!alloc_buffer_size(buffer, buffer_size)){
6260 SAFE_FREE(forms_1);
6261 return WERR_INSUFFICIENT_BUFFER;
6264 /* fill the buffer with the form structures */
6265 for (i=0; i<numbuiltinforms; i++) {
6266 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6267 smb_io_form_1("", buffer, &forms_1[i], 0);
6269 for (; i<*numofforms; i++) {
6270 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6271 smb_io_form_1("", buffer, &forms_1[i], 0);
6274 SAFE_FREE(forms_1);
6276 if (*needed > offered) {
6277 *numofforms=0;
6278 return WERR_INSUFFICIENT_BUFFER;
6280 else
6281 return WERR_OK;
6283 default:
6284 SAFE_FREE(list);
6285 SAFE_FREE(builtinlist);
6286 return WERR_UNKNOWN_LEVEL;
6291 /****************************************************************************
6292 ****************************************************************************/
6294 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6296 /* POLICY_HND *handle = &q_u->handle; - notused. */
6297 uint32 level = q_u->level;
6298 UNISTR2 *uni_formname = &q_u->formname;
6299 NEW_BUFFER *buffer = NULL;
6300 uint32 offered = q_u->offered;
6301 uint32 *needed = &r_u->needed;
6303 nt_forms_struct *list=NULL;
6304 nt_forms_struct builtin_form;
6305 BOOL foundBuiltin;
6306 FORM_1 form_1;
6307 fstring form_name;
6308 int buffer_size=0;
6309 int numofforms=0, i=0;
6311 /* that's an [in out] buffer */
6312 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6313 buffer = r_u->buffer;
6315 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6317 DEBUG(4,("_spoolss_getform\n"));
6318 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6319 DEBUGADD(5,("Info level [%d]\n", level));
6321 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6322 if (!foundBuiltin) {
6323 numofforms = get_ntforms(&list);
6324 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6326 if (numofforms == 0)
6327 return WERR_BADFID;
6330 switch (level) {
6331 case 1:
6332 if (foundBuiltin) {
6333 fill_form_1(&form_1, &builtin_form);
6334 } else {
6336 /* Check if the requested name is in the list of form structures */
6337 for (i=0; i<numofforms; i++) {
6339 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6341 if (strequal(form_name, list[i].name)) {
6342 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6343 fill_form_1(&form_1, &list[i]);
6344 break;
6348 SAFE_FREE(list);
6349 if (i == numofforms) {
6350 return WERR_BADFID;
6353 /* check the required size. */
6355 *needed=spoolss_size_form_1(&form_1);
6357 if (!alloc_buffer_size(buffer, buffer_size)){
6358 return WERR_INSUFFICIENT_BUFFER;
6361 if (*needed > offered) {
6362 return WERR_INSUFFICIENT_BUFFER;
6365 /* fill the buffer with the form structures */
6366 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6367 smb_io_form_1("", buffer, &form_1, 0);
6369 return WERR_OK;
6371 default:
6372 SAFE_FREE(list);
6373 return WERR_UNKNOWN_LEVEL;
6377 /****************************************************************************
6378 ****************************************************************************/
6380 static void fill_port_1(PORT_INFO_1 *port, char *name)
6382 init_unistr(&port->port_name, name);
6385 /****************************************************************************
6386 ****************************************************************************/
6388 static void fill_port_2(PORT_INFO_2 *port, char *name)
6390 init_unistr(&port->port_name, name);
6391 init_unistr(&port->monitor_name, "Local Monitor");
6392 init_unistr(&port->description, "Local Port");
6393 #define PORT_TYPE_WRITE 1
6394 port->port_type=PORT_TYPE_WRITE;
6395 port->reserved=0x0;
6398 /****************************************************************************
6399 enumports level 1.
6400 ****************************************************************************/
6402 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6404 PORT_INFO_1 *ports=NULL;
6405 int i=0;
6407 if (*lp_enumports_cmd()) {
6408 char *cmd = lp_enumports_cmd();
6409 char **qlines;
6410 pstring command;
6411 int numlines;
6412 int ret;
6413 int fd;
6415 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6417 DEBUG(10,("Running [%s]\n", command));
6418 ret = smbrun(command, &fd);
6419 DEBUG(10,("Returned [%d]\n", ret));
6420 if (ret != 0) {
6421 if (fd != -1)
6422 close(fd);
6423 /* Is this the best error to return here? */
6424 return WERR_ACCESS_DENIED;
6427 numlines = 0;
6428 qlines = fd_lines_load(fd, &numlines);
6429 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6430 close(fd);
6432 if(numlines) {
6433 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6434 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6435 dos_errstr(WERR_NOMEM)));
6436 file_lines_free(qlines);
6437 return WERR_NOMEM;
6440 for (i=0; i<numlines; i++) {
6441 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6442 fill_port_1(&ports[i], qlines[i]);
6445 file_lines_free(qlines);
6448 *returned = numlines;
6450 } else {
6451 *returned = 1; /* Sole Samba port returned. */
6453 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6454 return WERR_NOMEM;
6456 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6458 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6461 /* check the required size. */
6462 for (i=0; i<*returned; i++) {
6463 DEBUGADD(6,("adding port [%d]'s size\n", i));
6464 *needed += spoolss_size_port_info_1(&ports[i]);
6467 if (!alloc_buffer_size(buffer, *needed)) {
6468 SAFE_FREE(ports);
6469 return WERR_INSUFFICIENT_BUFFER;
6472 /* fill the buffer with the ports structures */
6473 for (i=0; i<*returned; i++) {
6474 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6475 smb_io_port_1("", buffer, &ports[i], 0);
6478 SAFE_FREE(ports);
6480 if (*needed > offered) {
6481 *returned=0;
6482 return WERR_INSUFFICIENT_BUFFER;
6485 return WERR_OK;
6488 /****************************************************************************
6489 enumports level 2.
6490 ****************************************************************************/
6492 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6494 PORT_INFO_2 *ports=NULL;
6495 int i=0;
6497 if (*lp_enumports_cmd()) {
6498 char *cmd = lp_enumports_cmd();
6499 char *path;
6500 char **qlines;
6501 pstring tmp_file;
6502 pstring command;
6503 int numlines;
6504 int ret;
6505 int fd;
6507 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6508 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6509 else
6510 path = lp_lockdir();
6512 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6513 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6515 unlink(tmp_file);
6516 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6517 ret = smbrun(command, &fd);
6518 DEBUGADD(10,("returned [%d]\n", ret));
6519 if (ret != 0) {
6520 if (fd != -1)
6521 close(fd);
6522 /* Is this the best error to return here? */
6523 return WERR_ACCESS_DENIED;
6526 numlines = 0;
6527 qlines = fd_lines_load(fd, &numlines);
6528 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6529 close(fd);
6531 if(numlines) {
6532 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6533 file_lines_free(qlines);
6534 return WERR_NOMEM;
6537 for (i=0; i<numlines; i++) {
6538 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6539 fill_port_2(&(ports[i]), qlines[i]);
6542 file_lines_free(qlines);
6545 *returned = numlines;
6547 } else {
6549 *returned = 1;
6551 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6552 return WERR_NOMEM;
6554 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6556 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6559 /* check the required size. */
6560 for (i=0; i<*returned; i++) {
6561 DEBUGADD(6,("adding port [%d]'s size\n", i));
6562 *needed += spoolss_size_port_info_2(&ports[i]);
6565 if (!alloc_buffer_size(buffer, *needed)) {
6566 SAFE_FREE(ports);
6567 return WERR_INSUFFICIENT_BUFFER;
6570 /* fill the buffer with the ports structures */
6571 for (i=0; i<*returned; i++) {
6572 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6573 smb_io_port_2("", buffer, &ports[i], 0);
6576 SAFE_FREE(ports);
6578 if (*needed > offered) {
6579 *returned=0;
6580 return WERR_INSUFFICIENT_BUFFER;
6583 return WERR_OK;
6586 /****************************************************************************
6587 enumports.
6588 ****************************************************************************/
6590 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6592 /* UNISTR2 *name = &q_u->name; - notused. */
6593 uint32 level = q_u->level;
6594 NEW_BUFFER *buffer = NULL;
6595 uint32 offered = q_u->offered;
6596 uint32 *needed = &r_u->needed;
6597 uint32 *returned = &r_u->returned;
6599 /* that's an [in out] buffer */
6600 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6601 buffer = r_u->buffer;
6603 DEBUG(4,("_spoolss_enumports\n"));
6605 *returned=0;
6606 *needed=0;
6608 switch (level) {
6609 case 1:
6610 return enumports_level_1(buffer, offered, needed, returned);
6611 case 2:
6612 return enumports_level_2(buffer, offered, needed, returned);
6613 default:
6614 return WERR_UNKNOWN_LEVEL;
6618 /****************************************************************************
6619 ****************************************************************************/
6621 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6622 const SPOOL_PRINTER_INFO_LEVEL *info,
6623 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6624 uint32 user_switch, const SPOOL_USER_CTR *user,
6625 POLICY_HND *handle)
6627 NT_PRINTER_INFO_LEVEL *printer = NULL;
6628 fstring name;
6629 int snum;
6630 WERROR err = WERR_OK;
6632 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6633 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6634 return WERR_NOMEM;
6637 ZERO_STRUCTP(printer);
6639 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6640 if (!convert_printer_info(info, printer, 2)) {
6641 free_a_printer(&printer, 2);
6642 return WERR_NOMEM;
6645 /* check to see if the printer already exists */
6647 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6648 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6649 printer->info_2->sharename));
6650 free_a_printer(&printer, 2);
6651 return WERR_PRINTER_ALREADY_EXISTS;
6654 if (*lp_addprinter_cmd() )
6655 if ( !add_printer_hook(printer) ) {
6656 free_a_printer(&printer,2);
6657 return WERR_ACCESS_DENIED;
6660 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6661 printer->info_2->sharename);
6663 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6664 free_a_printer(&printer,2);
6665 return WERR_ACCESS_DENIED;
6668 /* you must be a printer admin to add a new printer */
6669 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6670 free_a_printer(&printer,2);
6671 return WERR_ACCESS_DENIED;
6675 * Do sanity check on the requested changes for Samba.
6678 if (!check_printer_ok(printer->info_2, snum)) {
6679 free_a_printer(&printer,2);
6680 return WERR_INVALID_PARAM;
6684 * When a printer is created, the drivername bound to the printer is used
6685 * to lookup previously saved driver initialization info, which is then
6686 * bound to the new printer, simulating what happens in the Windows arch.
6689 if (!devmode)
6690 set_driver_init(printer, 2);
6691 else {
6692 /* A valid devmode was included, convert and link it
6694 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6696 if (!convert_devicemode(printer->info_2->printername, devmode,
6697 &printer->info_2->devmode))
6698 return WERR_NOMEM;
6701 set_driver_init(printer, 2);
6703 /* write the ASCII on disk */
6704 err = mod_a_printer(*printer, 2);
6705 if (!W_ERROR_IS_OK(err)) {
6706 free_a_printer(&printer,2);
6707 return err;
6710 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6711 /* Handle open failed - remove addition. */
6712 del_a_printer(printer->info_2->sharename);
6713 free_a_printer(&printer,2);
6714 return WERR_ACCESS_DENIED;
6717 update_c_setprinter(False);
6718 free_a_printer(&printer,2);
6720 return WERR_OK;
6723 /****************************************************************************
6724 ****************************************************************************/
6726 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6728 UNISTR2 *uni_srv_name = &q_u->server_name;
6729 uint32 level = q_u->level;
6730 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6731 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6732 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6733 uint32 user_switch = q_u->user_switch;
6734 SPOOL_USER_CTR *user = &q_u->user_ctr;
6735 POLICY_HND *handle = &r_u->handle;
6737 switch (level) {
6738 case 1:
6739 /* we don't handle yet */
6740 /* but I know what to do ... */
6741 return WERR_UNKNOWN_LEVEL;
6742 case 2:
6743 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6744 devmode, sdb,
6745 user_switch, user, handle);
6746 default:
6747 return WERR_UNKNOWN_LEVEL;
6751 /****************************************************************************
6752 ****************************************************************************/
6754 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6756 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6757 uint32 level = q_u->level;
6758 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6759 WERROR err = WERR_OK;
6760 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6761 struct current_user user;
6762 fstring driver_name;
6763 uint32 version;
6765 ZERO_STRUCT(driver);
6767 get_current_user(&user, p);
6769 if (!convert_printer_driver_info(info, &driver, level)) {
6770 err = WERR_NOMEM;
6771 goto done;
6774 DEBUG(5,("Cleaning driver's information\n"));
6775 err = clean_up_driver_struct(driver, level, &user);
6776 if (!W_ERROR_IS_OK(err))
6777 goto done;
6779 DEBUG(5,("Moving driver to final destination\n"));
6780 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6781 if (W_ERROR_IS_OK(err))
6782 err = WERR_ACCESS_DENIED;
6783 goto done;
6786 if (add_a_printer_driver(driver, level)!=0) {
6787 err = WERR_ACCESS_DENIED;
6788 goto done;
6791 /* BEGIN_ADMIN_LOG */
6792 switch(level) {
6793 case 3:
6794 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6795 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6796 fstrcpy(driver_name, driver.info_3->name);
6797 break;
6798 case 6:
6799 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6800 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6801 fstrcpy(driver_name, driver.info_6->name);
6802 break;
6804 /* END_ADMIN_LOG */
6807 * I think this is where he DrvUpgradePrinter() hook would be
6808 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6809 * server. Right now, we just need to send ourselves a message
6810 * to update each printer bound to this driver. --jerry
6813 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6814 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6815 driver_name));
6819 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6820 * decide if the driver init data should be deleted. The rules are:
6821 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6822 * 2) delete init data only if there is no 2k/Xp driver
6823 * 3) always delete init data
6824 * The generalized rule is always use init data from the highest order driver.
6825 * It is necessary to follow the driver install by an initialization step to
6826 * finish off this process.
6828 if (level == 3)
6829 version = driver.info_3->cversion;
6830 else if (level == 6)
6831 version = driver.info_6->version;
6832 else
6833 version = -1;
6834 switch (version) {
6836 * 9x printer driver - never delete init data
6838 case 0:
6839 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6840 driver_name));
6841 break;
6844 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6845 * there is no 2k/Xp driver init data for this driver name.
6847 case 2:
6849 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
6851 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
6853 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6855 if (!del_driver_init(driver_name))
6856 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
6857 } else {
6859 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6861 free_a_printer_driver(driver1,3);
6862 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6863 driver_name));
6866 break;
6869 * 2k or Xp printer driver - always delete init data
6871 case 3:
6872 if (!del_driver_init(driver_name))
6873 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
6874 break;
6876 default:
6877 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
6878 break;
6882 done:
6883 free_a_printer_driver(driver, level);
6884 return err;
6887 /****************************************************************************
6888 ****************************************************************************/
6890 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6892 init_unistr(&info->name, name);
6895 /****************************************************************************
6896 ****************************************************************************/
6898 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6900 pstring path;
6901 pstring long_archi;
6902 pstring short_archi;
6903 DRIVER_DIRECTORY_1 *info=NULL;
6905 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6907 if (get_short_archi(short_archi, long_archi)==False)
6908 return WERR_INVALID_ENVIRONMENT;
6910 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6911 return WERR_NOMEM;
6913 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6915 DEBUG(4,("printer driver directory: [%s]\n", path));
6917 fill_driverdir_1(info, path);
6919 *needed += spoolss_size_driverdir_info_1(info);
6921 if (!alloc_buffer_size(buffer, *needed)) {
6922 SAFE_FREE(info);
6923 return WERR_INSUFFICIENT_BUFFER;
6926 smb_io_driverdir_1("", buffer, info, 0);
6928 SAFE_FREE(info);
6930 if (*needed > offered)
6931 return WERR_INSUFFICIENT_BUFFER;
6933 return WERR_OK;
6936 /****************************************************************************
6937 ****************************************************************************/
6939 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6941 UNISTR2 *name = &q_u->name;
6942 UNISTR2 *uni_environment = &q_u->environment;
6943 uint32 level = q_u->level;
6944 NEW_BUFFER *buffer = NULL;
6945 uint32 offered = q_u->offered;
6946 uint32 *needed = &r_u->needed;
6948 /* that's an [in out] buffer */
6949 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6950 buffer = r_u->buffer;
6952 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6954 *needed=0;
6956 switch(level) {
6957 case 1:
6958 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6959 default:
6960 return WERR_UNKNOWN_LEVEL;
6964 /****************************************************************************
6965 ****************************************************************************/
6967 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6969 POLICY_HND *handle = &q_u->handle;
6970 uint32 idx = q_u->index;
6971 uint32 in_value_len = q_u->valuesize;
6972 uint32 in_data_len = q_u->datasize;
6973 uint32 *out_max_value_len = &r_u->valuesize;
6974 uint16 **out_value = &r_u->value;
6975 uint32 *out_value_len = &r_u->realvaluesize;
6976 uint32 *out_type = &r_u->type;
6977 uint32 *out_max_data_len = &r_u->datasize;
6978 uint8 **data_out = &r_u->data;
6979 uint32 *out_data_len = &r_u->realdatasize;
6981 NT_PRINTER_INFO_LEVEL *printer = NULL;
6983 fstring value;
6985 uint32 param_index;
6986 uint32 biggest_valuesize;
6987 uint32 biggest_datasize;
6988 uint32 data_len;
6989 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6990 int snum;
6991 uint8 *data=NULL;
6992 uint32 type;
6993 WERROR result;
6995 ZERO_STRUCT(printer);
6997 *out_type=0;
6999 *out_max_data_len=0;
7000 *data_out=NULL;
7001 *out_data_len=0;
7003 DEBUG(5,("spoolss_enumprinterdata\n"));
7005 if (!Printer) {
7006 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7007 return WERR_BADFID;
7010 if (!get_printer_snum(p,handle, &snum))
7011 return WERR_BADFID;
7013 result = get_a_printer(&printer, 2, lp_servicename(snum));
7014 if (!W_ERROR_IS_OK(result))
7015 return result;
7018 * The NT machine wants to know the biggest size of value and data
7020 * cf: MSDN EnumPrinterData remark section
7022 if ( (in_value_len==0) && (in_data_len==0) ) {
7023 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7025 SAFE_FREE(data);
7027 param_index=0;
7028 biggest_valuesize=0;
7029 biggest_datasize=0;
7031 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
7032 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
7033 if (data_len > biggest_datasize) biggest_datasize=data_len;
7035 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
7037 SAFE_FREE(data);
7038 param_index++;
7041 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
7042 *out_value_len=2*(1+biggest_valuesize);
7043 *out_data_len=biggest_datasize;
7045 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7047 free_a_printer(&printer, 2);
7048 return WERR_OK;
7052 * the value len is wrong in NT sp3
7053 * that's the number of bytes not the number of unicode chars
7056 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
7058 SAFE_FREE(data);
7059 free_a_printer(&printer, 2);
7061 /* out_value should default to "" or else NT4 has
7062 problems unmarshalling the response */
7064 *out_max_value_len=(in_value_len/sizeof(uint16));
7065 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7066 return WERR_NOMEM;
7068 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7070 /* the data is counted in bytes */
7071 *out_max_data_len = in_data_len;
7072 *out_data_len = in_data_len;
7073 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7074 return WERR_NOMEM;
7076 return WERR_NO_MORE_ITEMS;
7079 free_a_printer(&printer, 2);
7082 * the value is:
7083 * - counted in bytes in the request
7084 * - counted in UNICODE chars in the max reply
7085 * - counted in bytes in the real size
7087 * take a pause *before* coding not *during* coding
7090 *out_max_value_len=(in_value_len/sizeof(uint16));
7091 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
7092 SAFE_FREE(data);
7093 return WERR_NOMEM;
7096 *out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0);
7098 *out_type=type;
7100 /* the data is counted in bytes */
7101 *out_max_data_len=in_data_len;
7102 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
7103 SAFE_FREE(data);
7104 return WERR_NOMEM;
7107 memcpy(*data_out, data, (size_t)data_len);
7108 *out_data_len=data_len;
7110 SAFE_FREE(data);
7112 return WERR_OK;
7115 /****************************************************************************
7116 ****************************************************************************/
7118 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7120 POLICY_HND *handle = &q_u->handle;
7121 UNISTR2 *value = &q_u->value;
7122 uint32 type = q_u->type;
7123 /* uint32 max_len = q_u->max_len; - notused. */
7124 uint8 *data = q_u->data;
7125 uint32 real_len = q_u->real_len;
7126 /* uint32 numeric_data = q_u->numeric_data; - notused. */
7128 NT_PRINTER_INFO_LEVEL *printer = NULL;
7129 NT_PRINTER_PARAM *param = NULL, old_param;
7130 int snum=0;
7131 WERROR status = WERR_OK;
7132 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7134 DEBUG(5,("spoolss_setprinterdata\n"));
7136 if (!Printer) {
7137 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7138 return WERR_BADFID;
7141 if (!get_printer_snum(p,handle, &snum))
7142 return WERR_BADFID;
7144 ZERO_STRUCT(old_param);
7147 * Access check : NT returns "access denied" if you make a
7148 * SetPrinterData call without the necessary privildge.
7149 * we were originally returning OK if nothing changed
7150 * which made Win2k issue **a lot** of SetPrinterData
7151 * when connecting to a printer --jerry
7154 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7155 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7156 status = WERR_ACCESS_DENIED;
7157 goto done;
7160 /* Check if we are making any changes or not. Return true if
7161 nothing is actually changing. This is not needed anymore but
7162 has been left in as an optimization to keep from from
7163 writing to disk as often --jerry */
7165 status = get_a_printer(&printer, 2, lp_servicename(snum));
7166 if (!W_ERROR_IS_OK(status))
7167 return status;
7169 convert_specific_param(&param, value , type, data, real_len);
7171 unlink_specific_param_if_exist(printer->info_2, param);
7174 * When client side code sets a magic printer data key, detect it and save
7175 * the current printer data and the magic key's data (its the DEVMODE) for
7176 * future printer/driver initializations.
7178 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
7180 * Set devmode and printer initialization info
7182 status = save_driver_init(printer, 2, param);
7184 else {
7185 add_a_specific_param(printer->info_2, &param);
7186 status = mod_a_printer(*printer, 2);
7189 done:
7190 free_a_printer(&printer, 2);
7191 if (param)
7192 free_nt_printer_param(&param);
7193 SAFE_FREE(old_param.data);
7195 return status;
7198 /****************************************************************************
7199 ****************************************************************************/
7201 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7203 POLICY_HND *handle = &q_u->handle;
7204 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7205 int snum;
7207 DEBUG(5,("_spoolss_resetprinter\n"));
7210 * All we do is to check to see if the handle and queue is valid.
7211 * This call really doesn't mean anything to us because we only
7212 * support RAW printing. --jerry
7215 if (!Printer) {
7216 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7217 return WERR_BADFID;
7220 if (!get_printer_snum(p,handle, &snum))
7221 return WERR_BADFID;
7224 /* blindly return success */
7225 return WERR_OK;
7229 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7231 POLICY_HND *handle = &q_u->handle;
7232 UNISTR2 *value = &q_u->valuename;
7234 NT_PRINTER_INFO_LEVEL *printer = NULL;
7235 NT_PRINTER_PARAM param;
7236 int snum=0;
7237 WERROR status = WERR_OK;
7238 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7240 DEBUG(5,("spoolss_deleteprinterdata\n"));
7242 if (!Printer) {
7243 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7244 return WERR_BADFID;
7247 if (!get_printer_snum(p, handle, &snum))
7248 return WERR_BADFID;
7250 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7251 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7252 return WERR_ACCESS_DENIED;
7255 status = get_a_printer(&printer, 2, lp_servicename(snum));
7256 if (!W_ERROR_IS_OK(status))
7257 return status;
7259 ZERO_STRUCTP(&param);
7260 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
7262 if(!unlink_specific_param_if_exist(printer->info_2, &param))
7263 status = WERR_INVALID_PARAM;
7264 else
7265 status = mod_a_printer(*printer, 2);
7267 free_a_printer(&printer, 2);
7268 return status;
7271 /****************************************************************************
7272 ****************************************************************************/
7274 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7276 POLICY_HND *handle = &q_u->handle;
7277 /* uint32 level = q_u->level; - notused. */
7278 FORM *form = &q_u->form;
7279 nt_forms_struct tmpForm;
7280 int snum;
7281 WERROR status = WERR_OK;
7282 NT_PRINTER_INFO_LEVEL *printer = NULL;
7284 int count=0;
7285 nt_forms_struct *list=NULL;
7286 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7288 DEBUG(5,("spoolss_addform\n"));
7290 if (!Printer) {
7291 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7292 return WERR_BADFID;
7295 if (!get_printer_snum(p,handle, &snum))
7296 return WERR_BADFID;
7298 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7299 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7300 status = WERR_ACCESS_DENIED;
7301 goto done;
7304 /* can't add if builtin */
7305 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7306 return WERR_ALREADY_EXISTS;
7309 count=get_ntforms(&list);
7310 if(!add_a_form(&list, form, &count))
7311 return WERR_NOMEM;
7312 write_ntforms(&list, count);
7315 * ChangeID must always be set
7318 status = get_a_printer(&printer, 2, lp_servicename(snum));
7319 if (!W_ERROR_IS_OK(status))
7320 goto done;
7322 status = mod_a_printer(*printer, 2);
7323 if (!W_ERROR_IS_OK(status))
7324 goto done;
7326 done:
7327 free_a_printer(&printer, 2);
7328 SAFE_FREE(list);
7330 return status;
7333 /****************************************************************************
7334 ****************************************************************************/
7336 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7338 POLICY_HND *handle = &q_u->handle;
7339 UNISTR2 *form_name = &q_u->name;
7340 nt_forms_struct tmpForm;
7341 int count=0;
7342 WERROR ret = WERR_OK;
7343 nt_forms_struct *list=NULL;
7344 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7345 int snum;
7346 WERROR status = WERR_OK;
7347 NT_PRINTER_INFO_LEVEL *printer = NULL;
7349 DEBUG(5,("spoolss_deleteform\n"));
7351 if (!Printer) {
7352 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7353 return WERR_BADFID;
7356 if (!get_printer_snum(p, handle, &snum))
7357 return WERR_BADFID;
7359 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7360 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7361 return WERR_ACCESS_DENIED;
7364 /* can't delete if builtin */
7365 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7366 return WERR_INVALID_PARAM;
7369 count = get_ntforms(&list);
7370 if(!delete_a_form(&list, form_name, &count, &ret))
7371 return WERR_INVALID_PARAM;
7374 * ChangeID must always be set
7377 status = get_a_printer(&printer, 2, lp_servicename(snum));
7378 if (!W_ERROR_IS_OK(status))
7379 goto done;
7381 status = mod_a_printer(*printer, 2);
7382 if (!W_ERROR_IS_OK(status))
7383 goto done;
7385 done:
7386 free_a_printer(&printer, 2);
7387 SAFE_FREE(list);
7389 return ret;
7392 /****************************************************************************
7393 ****************************************************************************/
7395 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7397 POLICY_HND *handle = &q_u->handle;
7398 /* UNISTR2 *uni_name = &q_u->name; - notused. */
7399 /* uint32 level = q_u->level; - notused. */
7400 FORM *form = &q_u->form;
7401 nt_forms_struct tmpForm;
7402 int snum;
7403 WERROR status = WERR_OK;
7404 NT_PRINTER_INFO_LEVEL *printer = NULL;
7406 int count=0;
7407 nt_forms_struct *list=NULL;
7408 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7410 DEBUG(5,("spoolss_setform\n"));
7412 if (!Printer) {
7413 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7414 return WERR_BADFID;
7417 if (!get_printer_snum(p, handle, &snum))
7418 return WERR_BADFID;
7420 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7421 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7422 return WERR_ACCESS_DENIED;
7425 /* can't set if builtin */
7426 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7427 return WERR_INVALID_PARAM;
7430 count=get_ntforms(&list);
7431 update_a_form(&list, form, count);
7432 write_ntforms(&list, count);
7435 * ChangeID must always be set
7438 status = get_a_printer(&printer, 2, lp_servicename(snum));
7439 if (!W_ERROR_IS_OK(status))
7440 goto done;
7442 status = mod_a_printer(*printer, 2);
7443 if (!W_ERROR_IS_OK(status))
7444 goto done;
7446 done:
7447 free_a_printer(&printer, 2);
7448 SAFE_FREE(list);
7450 return WERR_OK;
7453 /****************************************************************************
7454 enumprintprocessors level 1.
7455 ****************************************************************************/
7457 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7459 PRINTPROCESSOR_1 *info_1=NULL;
7461 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7462 return WERR_NOMEM;
7464 (*returned) = 0x1;
7466 init_unistr(&info_1->name, "winprint");
7468 *needed += spoolss_size_printprocessor_info_1(info_1);
7470 if (!alloc_buffer_size(buffer, *needed))
7471 return WERR_INSUFFICIENT_BUFFER;
7473 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7475 SAFE_FREE(info_1);
7477 if (*needed > offered) {
7478 *returned=0;
7479 return WERR_INSUFFICIENT_BUFFER;
7482 return WERR_OK;
7485 /****************************************************************************
7486 ****************************************************************************/
7488 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7490 /* UNISTR2 *name = &q_u->name; - notused. */
7491 /* UNISTR2 *environment = &q_u->environment; - notused. */
7492 uint32 level = q_u->level;
7493 NEW_BUFFER *buffer = NULL;
7494 uint32 offered = q_u->offered;
7495 uint32 *needed = &r_u->needed;
7496 uint32 *returned = &r_u->returned;
7498 /* that's an [in out] buffer */
7499 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7500 buffer = r_u->buffer;
7502 DEBUG(5,("spoolss_enumprintprocessors\n"));
7505 * Enumerate the print processors ...
7507 * Just reply with "winprint", to keep NT happy
7508 * and I can use my nice printer checker.
7511 *returned=0;
7512 *needed=0;
7514 switch (level) {
7515 case 1:
7516 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7517 default:
7518 return WERR_UNKNOWN_LEVEL;
7522 /****************************************************************************
7523 enumprintprocdatatypes level 1.
7524 ****************************************************************************/
7526 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7528 PRINTPROCDATATYPE_1 *info_1=NULL;
7530 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7531 return WERR_NOMEM;
7533 (*returned) = 0x1;
7535 init_unistr(&info_1->name, "RAW");
7537 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7539 if (!alloc_buffer_size(buffer, *needed))
7540 return WERR_INSUFFICIENT_BUFFER;
7542 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7544 SAFE_FREE(info_1);
7546 if (*needed > offered) {
7547 *returned=0;
7548 return WERR_INSUFFICIENT_BUFFER;
7551 return WERR_OK;
7554 /****************************************************************************
7555 ****************************************************************************/
7557 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7559 /* UNISTR2 *name = &q_u->name; - notused. */
7560 /* UNISTR2 *processor = &q_u->processor; - notused. */
7561 uint32 level = q_u->level;
7562 NEW_BUFFER *buffer = NULL;
7563 uint32 offered = q_u->offered;
7564 uint32 *needed = &r_u->needed;
7565 uint32 *returned = &r_u->returned;
7567 /* that's an [in out] buffer */
7568 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7569 buffer = r_u->buffer;
7571 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7573 *returned=0;
7574 *needed=0;
7576 switch (level) {
7577 case 1:
7578 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7579 default:
7580 return WERR_UNKNOWN_LEVEL;
7584 /****************************************************************************
7585 enumprintmonitors level 1.
7586 ****************************************************************************/
7588 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7590 PRINTMONITOR_1 *info_1=NULL;
7592 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7593 return WERR_NOMEM;
7595 (*returned) = 0x1;
7597 init_unistr(&info_1->name, "Local Port");
7599 *needed += spoolss_size_printmonitor_info_1(info_1);
7601 if (!alloc_buffer_size(buffer, *needed))
7602 return WERR_INSUFFICIENT_BUFFER;
7604 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7606 SAFE_FREE(info_1);
7608 if (*needed > offered) {
7609 *returned=0;
7610 return WERR_INSUFFICIENT_BUFFER;
7613 return WERR_OK;
7616 /****************************************************************************
7617 enumprintmonitors level 2.
7618 ****************************************************************************/
7620 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7622 PRINTMONITOR_2 *info_2=NULL;
7624 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7625 return WERR_NOMEM;
7627 (*returned) = 0x1;
7629 init_unistr(&info_2->name, "Local Port");
7630 init_unistr(&info_2->environment, "Windows NT X86");
7631 init_unistr(&info_2->dll_name, "localmon.dll");
7633 *needed += spoolss_size_printmonitor_info_2(info_2);
7635 if (!alloc_buffer_size(buffer, *needed))
7636 return WERR_INSUFFICIENT_BUFFER;
7638 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7640 SAFE_FREE(info_2);
7642 if (*needed > offered) {
7643 *returned=0;
7644 return WERR_INSUFFICIENT_BUFFER;
7647 return WERR_OK;
7650 /****************************************************************************
7651 ****************************************************************************/
7653 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7655 /* UNISTR2 *name = &q_u->name; - notused. */
7656 uint32 level = q_u->level;
7657 NEW_BUFFER *buffer = NULL;
7658 uint32 offered = q_u->offered;
7659 uint32 *needed = &r_u->needed;
7660 uint32 *returned = &r_u->returned;
7662 /* that's an [in out] buffer */
7663 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7664 buffer = r_u->buffer;
7666 DEBUG(5,("spoolss_enumprintmonitors\n"));
7669 * Enumerate the print monitors ...
7671 * Just reply with "Local Port", to keep NT happy
7672 * and I can use my nice printer checker.
7675 *returned=0;
7676 *needed=0;
7678 switch (level) {
7679 case 1:
7680 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7681 case 2:
7682 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7683 default:
7684 return WERR_UNKNOWN_LEVEL;
7688 /****************************************************************************
7689 ****************************************************************************/
7691 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7693 int i=0;
7694 BOOL found=False;
7695 JOB_INFO_1 *info_1=NULL;
7697 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7699 if (info_1 == NULL) {
7700 SAFE_FREE(queue);
7701 return WERR_NOMEM;
7704 for (i=0; i<count && found==False; i++) {
7705 if (queue[i].job==(int)jobid)
7706 found=True;
7709 if (found==False) {
7710 SAFE_FREE(queue);
7711 SAFE_FREE(info_1);
7712 /* NT treats not found as bad param... yet another bad choice */
7713 return WERR_INVALID_PARAM;
7716 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7718 SAFE_FREE(queue);
7720 *needed += spoolss_size_job_info_1(info_1);
7722 if (!alloc_buffer_size(buffer, *needed)) {
7723 SAFE_FREE(info_1);
7724 return WERR_INSUFFICIENT_BUFFER;
7727 smb_io_job_info_1("", buffer, info_1, 0);
7729 SAFE_FREE(info_1);
7731 if (*needed > offered)
7732 return WERR_INSUFFICIENT_BUFFER;
7734 return WERR_OK;
7737 /****************************************************************************
7738 ****************************************************************************/
7740 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7742 int i=0;
7743 BOOL found=False;
7744 JOB_INFO_2 *info_2;
7745 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7746 WERROR ret;
7747 DEVICEMODE *devmode = NULL;
7749 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7751 ZERO_STRUCTP(info_2);
7753 if (info_2 == NULL) {
7754 ret = WERR_NOMEM;
7755 goto done;
7758 for (i=0; i<count && found==False; i++) {
7759 if (queue[i].job==(int)jobid)
7760 found=True;
7763 if (found==False) {
7764 /* NT treats not found as bad param... yet another bad
7765 choice */
7766 ret = WERR_INVALID_PARAM;
7767 goto done;
7770 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7771 if (!W_ERROR_IS_OK(ret))
7772 goto done;
7773 if (construct_dev_mode(snum) == NULL) {
7774 ret = WERR_NOMEM;
7775 goto done;
7778 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7780 *needed += spoolss_size_job_info_2(info_2);
7782 if (!alloc_buffer_size(buffer, *needed)) {
7783 ret = WERR_INSUFFICIENT_BUFFER;
7784 goto done;
7787 smb_io_job_info_2("", buffer, info_2, 0);
7789 if (*needed > offered) {
7790 ret = WERR_INSUFFICIENT_BUFFER;
7791 goto done;
7794 ret = WERR_OK;
7796 done:
7797 /* Cleanup allocated memory */
7799 SAFE_FREE(queue);
7800 free_job_info_2(info_2); /* Also frees devmode */
7801 SAFE_FREE(info_2);
7802 free_a_printer(&ntprinter, 2);
7804 return ret;
7807 /****************************************************************************
7808 ****************************************************************************/
7810 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7812 POLICY_HND *handle = &q_u->handle;
7813 uint32 jobid = q_u->jobid;
7814 uint32 level = q_u->level;
7815 NEW_BUFFER *buffer = NULL;
7816 uint32 offered = q_u->offered;
7817 uint32 *needed = &r_u->needed;
7819 int snum;
7820 int count;
7821 print_queue_struct *queue=NULL;
7822 print_status_struct prt_status;
7824 /* that's an [in out] buffer */
7825 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7826 buffer = r_u->buffer;
7828 DEBUG(5,("spoolss_getjob\n"));
7830 *needed=0;
7832 if (!get_printer_snum(p, handle, &snum))
7833 return WERR_BADFID;
7835 count = print_queue_status(snum, &queue, &prt_status);
7837 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7838 count, prt_status.status, prt_status.message));
7840 switch (level) {
7841 case 1:
7842 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7843 case 2:
7844 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7845 default:
7846 SAFE_FREE(queue);
7847 return WERR_UNKNOWN_LEVEL;
7851 /********************************************************************
7852 * spoolss_getprinterdataex
7853 ********************************************************************/
7855 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7857 POLICY_HND *handle = &q_u->handle;
7858 uint32 in_size = q_u->size;
7859 uint32 *type = &r_u->type;
7860 uint32 *out_size = &r_u->size;
7861 uint8 **data = &r_u->data;
7862 uint32 *needed = &r_u->needed;
7864 fstring key, value;
7865 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7866 BOOL found = False;
7868 DEBUG(4,("_spoolss_getprinterdataex\n"));
7870 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7871 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7873 /* in case of problem, return some default values */
7874 *needed=0;
7875 *type=0;
7876 *out_size=0;
7879 if (!Printer) {
7880 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7881 return WERR_NOMEM;
7882 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7883 return WERR_BADFID;
7887 /* Is the handle to a printer or to the server? */
7889 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7891 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7892 return WERR_INVALID_PARAM;
7894 else
7897 * From MSDN documentation of GetPrinterDataEx: pass request
7898 * to GetPrinterData if key is "PrinterDriverData". This is
7899 * the only key we really support. Other keys to implement:
7900 * (a) DsDriver
7901 * (b) DsSpooler
7902 * (c) PnPData
7905 if (strcmp(key, "PrinterDriverData") != 0)
7906 return WERR_BADFILE;
7908 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7909 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7910 type, data, needed, in_size);
7914 if (!found) {
7915 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7917 /* reply this param doesn't exist */
7918 if (*out_size) {
7919 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7920 return WERR_NOMEM;
7921 } else {
7922 *data = NULL;
7925 return WERR_INVALID_PARAM;
7928 if (*needed > *out_size)
7929 return WERR_MORE_DATA;
7930 else
7931 return WERR_OK;
7934 /********************************************************************
7935 * spoolss_setprinterdata
7936 ********************************************************************/
7938 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7940 SPOOL_Q_SETPRINTERDATA q_u_local;
7941 SPOOL_R_SETPRINTERDATA r_u_local;
7942 fstring key;
7944 DEBUG(4,("_spoolss_setprinterdataex\n"));
7946 /* From MSDN documentation of SetPrinterDataEx: pass request to
7947 SetPrinterData if key is "PrinterDriverData" */
7949 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7951 if (strcmp(key, "PrinterDriverData") != 0)
7952 return WERR_INVALID_PARAM;
7954 ZERO_STRUCT(q_u_local);
7955 ZERO_STRUCT(r_u_local);
7957 /* make a copy to call _spoolss_setprinterdata() */
7959 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7960 copy_unistr2(&q_u_local.value, &q_u->value);
7961 q_u_local.type = q_u->type;
7962 q_u_local.max_len = q_u->max_len;
7963 q_u_local.data = q_u->data;
7964 q_u_local.real_len = q_u->real_len;
7965 q_u_local.numeric_data = q_u->numeric_data;
7967 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7971 /********************************************************************
7972 * spoolss_deleteprinterdataex
7973 ********************************************************************/
7975 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
7977 SPOOL_Q_DELETEPRINTERDATA q_u_local;
7978 SPOOL_R_DELETEPRINTERDATA r_u_local;
7979 fstring key;
7981 /* From MSDN documentation of SetPrinterDataEx: pass request to
7982 SetPrinterData if key is "PrinterDriverData" */
7984 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7986 if (strcmp(key, "PrinterDriverData") != 0)
7987 return WERR_INVALID_PARAM;
7989 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7990 copy_unistr2(&q_u_local.valuename, &q_u->valuename);
7992 return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
7998 /********************************************************************
7999 * spoolss_enumprinterkey
8000 ********************************************************************/
8002 /* constants for EnumPrinterKey() */
8003 #define ENUMERATED_KEY_SIZE 19
8005 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8007 fstring key;
8008 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
8009 char* ptr = NULL;
8010 int i;
8011 char *PrinterKey = "PrinterDriverData";
8013 DEBUG(4,("_spoolss_enumprinterkey\n"));
8015 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8018 * we only support enumating all keys (key == "")
8019 * Of course, the only key we support is the "PrinterDriverData"
8020 * key
8022 if (strlen(key) == 0)
8024 r_u->needed = ENUMERATED_KEY_SIZE *2;
8025 if (q_u->size < r_u->needed)
8026 return WERR_MORE_DATA;
8028 ptr = PrinterKey;
8029 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
8031 enumkeys[i] = (uint16)(*ptr);
8032 ptr++;
8035 /* tag of with 2 '\0's */
8036 enumkeys[i++] = '\0';
8037 enumkeys[i] = '\0';
8039 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
8040 return WERR_BADFILE;
8042 return WERR_OK;
8045 /* The "PrinterDriverData" key should have no subkeys */
8046 if (strcmp(key, PrinterKey) == 0)
8048 r_u-> needed = 2;
8049 if (q_u->size < r_u->needed)
8050 return WERR_MORE_DATA;
8051 enumkeys[0] = 0x0;
8052 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
8053 return WERR_BADFILE;
8055 return WERR_OK;
8059 /* The return value for an unknown key is documented in MSDN
8060 EnumPrinterKey description */
8061 return WERR_BADFILE;
8064 /********************************************************************
8065 * spoolss_enumprinterdataex
8066 ********************************************************************/
8068 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8070 POLICY_HND *handle = &q_u->handle;
8071 uint32 in_size = q_u->size;
8072 uint32 num_entries,
8073 needed;
8074 NT_PRINTER_INFO_LEVEL *printer = NULL;
8075 PRINTER_ENUM_VALUES *enum_values = NULL;
8076 fstring key, value;
8077 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8078 int snum;
8079 uint32 param_index,
8080 data_len,
8081 type;
8082 WERROR result;
8083 uint8 *data=NULL;
8086 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8088 if (!Printer) {
8089 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8090 return WERR_BADFID;
8095 * The only key we support is "PrinterDriverData". This should return
8096 > an array of all the key/value pairs returned by EnumPrinterDataSee
8097 * _spoolss_getprinterdataex() for details --jerry
8100 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8101 if (strcmp(key, "PrinterDriverData") != 0)
8103 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8104 return WERR_INVALID_PARAM;
8108 if (!get_printer_snum(p,handle, &snum))
8109 return WERR_BADFID;
8111 ZERO_STRUCT(printer);
8112 result = get_a_printer(&printer, 2, lp_servicename(snum));
8113 if (!W_ERROR_IS_OK(result))
8114 return result;
8118 * loop through all params and build the array to pass
8119 * back to the client
8121 result = WERR_OK;
8122 param_index = 0;
8123 needed = 0;
8124 num_entries = 0;
8126 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
8128 PRINTER_ENUM_VALUES *ptr;
8129 uint32 add_len = 0;
8131 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
8133 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
8135 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
8136 result = WERR_NOMEM;
8137 goto done;
8139 enum_values = ptr;
8141 /* copy the data */
8142 init_unistr(&enum_values[num_entries].valuename, value);
8143 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
8144 enum_values[num_entries].type = type;
8146 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
8147 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
8148 result = WERR_NOMEM;
8149 goto done;
8151 memcpy(enum_values[num_entries].data, data, data_len);
8152 enum_values[num_entries].data_len = data_len + add_len;
8154 /* keep track of the size of the array in bytes */
8156 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
8158 num_entries++;
8159 param_index++;
8162 r_u->needed = needed;
8163 r_u->returned = num_entries;
8165 if (needed > in_size) {
8166 result = WERR_MORE_DATA;
8167 goto done;
8170 /* copy data into the reply */
8172 r_u->ctr.size = r_u->needed;
8173 r_u->ctr.size_of_array = r_u->returned;
8174 r_u->ctr.values = enum_values;
8178 done:
8179 free_a_printer(&printer, 2);
8181 return result;
8184 /****************************************************************************
8185 ****************************************************************************/
8187 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8189 init_unistr(&info->name, name);
8192 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8193 UNISTR2 *environment,
8194 NEW_BUFFER *buffer,
8195 uint32 offered,
8196 uint32 *needed)
8198 pstring path;
8199 pstring long_archi;
8200 pstring short_archi;
8201 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8203 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8205 if (get_short_archi(short_archi, long_archi)==False)
8206 return WERR_INVALID_ENVIRONMENT;
8208 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8209 return WERR_NOMEM;
8211 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8213 fill_printprocessordirectory_1(info, path);
8215 *needed += spoolss_size_printprocessordirectory_info_1(info);
8217 if (!alloc_buffer_size(buffer, *needed)) {
8218 safe_free(info);
8219 return WERR_INSUFFICIENT_BUFFER;
8222 smb_io_printprocessordirectory_1("", buffer, info, 0);
8224 safe_free(info);
8226 if (*needed > offered)
8227 return WERR_INSUFFICIENT_BUFFER;
8228 else
8229 return WERR_OK;
8232 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8234 uint32 level = q_u->level;
8235 NEW_BUFFER *buffer = NULL;
8236 uint32 offered = q_u->offered;
8237 uint32 *needed = &r_u->needed;
8238 WERROR result;
8240 /* that's an [in out] buffer */
8241 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8242 buffer = r_u->buffer;
8244 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8246 *needed=0;
8248 switch(level) {
8249 case 1:
8250 result = getprintprocessordirectory_level_1
8251 (&q_u->name, &q_u->environment, buffer, offered, needed);
8252 default:
8253 result = WERR_UNKNOWN_LEVEL;
8256 return result;
8259 /********************************************************************
8260 * spoolss_addprinterdriverex
8261 ********************************************************************/
8263 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
8265 return WERR_OK;
8268 /********************************************************************
8269 * spoolss_deleteprinterdriverex
8270 ********************************************************************/
8272 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
8274 return WERR_OK;
8277 /********************************************************************
8278 * spoolss_deleteprinterkey
8279 ********************************************************************/
8281 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8283 fstring key;
8285 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8287 if (strcmp(key, "PrinterDriverData") != 0)
8288 return WERR_INVALID_PARAM;
8291 * this is what 2k returns when you try to delete the "PrinterDriverData"
8292 * key
8295 return WERR_ACCESS_DENIED;