* fix to display correct form information in REG_BINARY information
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobbc58655f71195468c08a6e025c0c5a0d0c4235b8
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001,
8 * Copyright (C) Gerald Carter 2000-2002,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
33 /* #define EMULATE_WIN2K_HACK 1 */
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41 #define PRINTER_HANDLE_IS_PRINTER 0
42 #define PRINTER_HANDLE_IS_PRINTSERVER 1
44 /* Table to map the driver version */
45 /* to OS */
46 char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
48 "", /* unused ? */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 struct table_node {
54 char *long_archi;
55 char *short_archi;
56 int version;
60 /* structure to store the printer handles */
61 /* and a reference to what it's pointing to */
62 /* and the notify info asked about */
63 /* that's the central struct */
64 typedef struct _Printer{
65 struct _Printer *prev, *next;
66 BOOL document_started;
67 BOOL page_started;
68 uint32 jobid; /* jobid in printing backend */
69 BOOL printer_type;
70 union {
71 fstring handlename;
72 fstring printerservername;
73 } dev;
74 uint32 type;
75 uint32 access_granted;
76 struct {
77 uint32 flags;
78 uint32 options;
79 fstring localmachine;
80 uint32 printerlocal;
81 SPOOL_NOTIFY_OPTION *option;
82 POLICY_HND client_hnd;
83 uint32 client_connected;
84 uint32 change;
85 } notify;
86 struct {
87 fstring machine;
88 fstring user;
89 } client;
90 } Printer_entry;
92 static Printer_entry *printers_list;
94 typedef struct _counter_printer_0 {
95 ubi_dlNode Next;
96 ubi_dlNode Prev;
98 int snum;
99 uint32 counter;
100 } counter_printer_0;
102 static ubi_dlList counter_list;
104 static struct cli_state notify_cli; /* print notify back-channel */
105 static uint32 smb_connections=0;
108 /* in printing/nt_printing.c */
110 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
112 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
113 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
115 /* translate between internal status numbers and NT status numbers */
116 static int nt_printj_status(int v)
118 switch (v) {
119 case LPQ_QUEUED:
120 return 0;
121 case LPQ_PAUSED:
122 return JOB_STATUS_PAUSED;
123 case LPQ_SPOOLING:
124 return JOB_STATUS_SPOOLING;
125 case LPQ_PRINTING:
126 return JOB_STATUS_PRINTING;
127 case LPQ_ERROR:
128 return JOB_STATUS_ERROR;
129 case LPQ_DELETING:
130 return JOB_STATUS_DELETING;
131 case LPQ_OFFLINE:
132 return JOB_STATUS_OFFLINE;
133 case LPQ_PAPEROUT:
134 return JOB_STATUS_PAPEROUT;
135 case LPQ_PRINTED:
136 return JOB_STATUS_PRINTED;
137 case LPQ_DELETED:
138 return JOB_STATUS_DELETED;
139 case LPQ_BLOCKED:
140 return JOB_STATUS_BLOCKED;
141 case LPQ_USER_INTERVENTION:
142 return JOB_STATUS_USER_INTERVENTION;
144 return 0;
147 static int nt_printq_status(int v)
149 switch (v) {
150 case LPQ_PAUSED:
151 return PRINTER_STATUS_PAUSED;
152 case LPQ_QUEUED:
153 case LPQ_SPOOLING:
154 case LPQ_PRINTING:
155 return 0;
157 return 0;
160 /****************************************************************************
161 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
162 ****************************************************************************/
164 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
166 if (*pp == NULL)
167 return;
169 SAFE_FREE((*pp)->ctr.type);
170 SAFE_FREE(*pp);
173 /***************************************************************************
174 Disconnect from the client
175 ****************************************************************************/
177 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
179 WERROR result;
181 /* weird if the test succeds !!! */
182 if (smb_connections==0) {
183 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
184 return;
187 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
189 if (!W_ERROR_IS_OK(result))
190 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
191 dos_errstr(result)));
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
195 cli_nt_session_close(&notify_cli);
196 cli_ulogoff(&notify_cli);
197 cli_shutdown(&notify_cli);
198 message_deregister(MSG_PRINTER_NOTIFY2);
201 smb_connections--;
204 /****************************************************************************
205 Functions to free a printer entry datastruct.
206 ****************************************************************************/
208 static void free_printer_entry(void *ptr)
210 Printer_entry *Printer = (Printer_entry *)ptr;
212 if (Printer->notify.client_connected==True)
213 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
215 Printer->notify.flags=0;
216 Printer->notify.options=0;
217 Printer->notify.localmachine[0]='\0';
218 Printer->notify.printerlocal=0;
219 free_spool_notify_option(&Printer->notify.option);
220 Printer->notify.option=NULL;
221 Printer->notify.client_connected=False;
223 /* Remove from the internal list. */
224 DLIST_REMOVE(printers_list, Printer);
226 SAFE_FREE(Printer);
229 /****************************************************************************
230 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
231 ****************************************************************************/
233 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
235 SPOOL_NOTIFY_OPTION *new_sp = NULL;
237 if (!sp)
238 return NULL;
240 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
241 if (!new_sp)
242 return NULL;
244 *new_sp = *sp;
246 if (sp->ctr.count) {
247 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
249 if (!new_sp->ctr.type) {
250 SAFE_FREE(new_sp);
251 return NULL;
255 return new_sp;
258 /****************************************************************************
259 find printer index by handle
260 ****************************************************************************/
262 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
264 Printer_entry *find_printer = NULL;
266 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
267 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
268 return NULL;
271 return find_printer;
274 /****************************************************************************
275 Close printer index by handle.
276 ****************************************************************************/
278 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
280 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
282 if (!Printer) {
283 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
284 return False;
287 close_policy_hnd(p, hnd);
289 return True;
292 /****************************************************************************
293 Delete a printer given a handle.
294 ****************************************************************************/
296 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
298 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
300 if (!Printer) {
301 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
302 return WERR_BADFID;
305 if (del_a_printer(Printer->dev.handlename) != 0) {
306 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
307 return WERR_BADFID;
310 /* Check calling user has permission to delete printer. Note that
311 since we set the snum parameter to -1 only administrators can
312 delete the printer. This stops people with the Full Control
313 permission from deleting the printer. */
315 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
316 DEBUG(3, ("printer delete denied by security descriptor\n"));
317 return WERR_ACCESS_DENIED;
320 if (*lp_deleteprinter_cmd()) {
322 char *cmd = lp_deleteprinter_cmd();
323 pstring command;
324 int ret;
325 int i;
327 /* Printer->dev.handlename equals portname equals sharename */
328 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
329 Printer->dev.handlename);
331 DEBUG(10,("Running [%s]\n", command));
332 ret = smbrun(command, NULL);
333 if (ret != 0) {
334 return WERR_BADFID; /* What to return here? */
336 DEBUGADD(10,("returned [%d]\n", ret));
338 /* Send SIGHUP to process group... is there a better way? */
339 kill(0, SIGHUP);
341 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
342 lp_killservice( i );
343 return WERR_OK;
344 } else
345 return WERR_ACCESS_DENIED;
348 return WERR_OK;
351 /****************************************************************************
352 Return the snum of a printer corresponding to an handle.
353 ****************************************************************************/
355 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
357 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
359 if (!Printer) {
360 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
361 return False;
364 switch (Printer->printer_type) {
365 case PRINTER_HANDLE_IS_PRINTER:
366 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
367 *number = print_queue_snum(Printer->dev.handlename);
368 return (*number != -1);
369 case PRINTER_HANDLE_IS_PRINTSERVER:
370 return False;
371 default:
372 return False;
376 /****************************************************************************
377 Set printer handle type.
378 Check if it's \\server or \\server\printer
379 ****************************************************************************/
381 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
383 DEBUG(3,("Setting printer type=%s\n", handlename));
385 if ( strlen(handlename) < 3 ) {
386 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
387 return False;
390 /* it's a print server */
391 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
392 DEBUGADD(4,("Printer is a print server\n"));
393 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
395 /* it's a printer */
396 else {
397 DEBUGADD(4,("Printer is a printer\n"));
398 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
401 return True;
404 /****************************************************************************
405 Set printer handle name.
406 ****************************************************************************/
408 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
410 int snum;
411 int n_services=lp_numservices();
412 char *aprinter;
413 fstring sname;
414 BOOL found=False;
416 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
418 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
419 ZERO_STRUCT(Printer->dev.printerservername);
420 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
421 return True;
424 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
425 return False;
427 if (*handlename=='\\') {
428 aprinter=strchr_m(handlename+2, '\\');
429 aprinter++;
431 else {
432 aprinter=handlename;
435 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
438 * The original code allowed smbd to store a printer name that
439 * was different from the share name. This is not possible
440 * anymore, so I've simplified this loop greatly. Here
441 * we are just verifying that the printer name is a valid
442 * printer service defined in smb.conf
443 * --jerry [Fri Feb 15 11:17:46 CST 2002]
446 for (snum=0; snum<n_services; snum++) {
448 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
449 continue;
451 fstrcpy(sname, lp_servicename(snum));
453 DEBUGADD(5,("share:%s\n",sname));
455 if (! StrCaseCmp(sname, aprinter)) {
456 found = True;
457 break;
463 if (!found) {
464 DEBUGADD(4,("Printer not found\n"));
465 return False;
468 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
470 ZERO_STRUCT(Printer->dev.handlename);
471 fstrcpy(Printer->dev.handlename, sname);
473 return True;
476 /****************************************************************************
477 Find first available printer slot. creates a printer handle for you.
478 ****************************************************************************/
480 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
482 Printer_entry *new_printer;
484 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
486 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
487 return False;
489 ZERO_STRUCTP(new_printer);
491 new_printer->notify.option=NULL;
493 /* Add to the internal list. */
494 DLIST_ADD(printers_list, new_printer);
496 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
497 SAFE_FREE(new_printer);
498 return False;
501 if (!set_printer_hnd_printertype(new_printer, name)) {
502 close_printer_handle(p, hnd);
503 return False;
506 if (!set_printer_hnd_name(new_printer, name)) {
507 close_printer_handle(p, hnd);
508 return False;
511 new_printer->access_granted = access_granted;
513 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
515 return True;
518 /****************************************************************************
519 Allocate more memory for a BUFFER.
520 ****************************************************************************/
522 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
524 prs_struct *ps;
525 uint32 extra_space;
526 uint32 old_offset;
528 ps= &buffer->prs;
530 /* damn, I'm doing the reverse operation of prs_grow() :) */
531 if (buffer_size < prs_data_size(ps))
532 extra_space=0;
533 else
534 extra_space = buffer_size - prs_data_size(ps);
537 * save the offset and move to the end of the buffer
538 * prs_grow() checks the extra_space against the offset
540 old_offset=prs_offset(ps);
541 prs_set_offset(ps, prs_data_size(ps));
543 if (!prs_grow(ps, extra_space))
544 return False;
546 prs_set_offset(ps, old_offset);
548 buffer->string_at_end=prs_data_size(ps);
550 return True;
553 /***************************************************************************
554 check to see if the client motify handle is monitoring the notification
555 given by (notify_type, notify_field).
556 **************************************************************************/
558 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
559 uint16 notify_field)
561 return True;
564 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
565 uint16 notify_field)
567 SPOOL_NOTIFY_OPTION *option = p->notify.option;
568 uint32 i, j;
570 if (p->notify.flags)
571 return is_monitoring_event_flags(
572 p->notify.flags, notify_type, notify_field);
574 for (i = 0; i < option->count; i++) {
576 /* Check match for notify_type */
578 if (option->ctr.type[i].type != notify_type)
579 continue;
581 /* Check match for field */
583 for (j = 0; j < option->ctr.type[i].count; j++) {
584 if (option->ctr.type[i].fields[j] == notify_field) {
585 return True;
590 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
591 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
592 p->dev.handlename : p->dev.printerservername,
593 notify_type, notify_field));
595 return False;
598 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
600 static void notify_one_value(struct spoolss_notify_msg *msg,
601 SPOOL_NOTIFY_INFO_DATA *data,
602 TALLOC_CTX *mem_ctx)
604 data->notify_data.value[0] = msg->notify.value[0];
605 data->notify_data.value[1] = 0;
608 static void notify_string(struct spoolss_notify_msg *msg,
609 SPOOL_NOTIFY_INFO_DATA *data,
610 TALLOC_CTX *mem_ctx)
612 UNISTR2 unistr;
614 /* The length of the message includes the trailing \0 */
616 init_unistr2(&unistr, msg->notify.data, msg->len);
618 data->notify_data.data.length = msg->len * 2;
619 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
621 if (!data->notify_data.data.string) {
622 data->notify_data.data.length = 0;
623 return;
626 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
629 static void notify_system_time(struct spoolss_notify_msg *msg,
630 SPOOL_NOTIFY_INFO_DATA *data,
631 TALLOC_CTX *mem_ctx)
633 SYSTEMTIME systime;
634 prs_struct ps;
636 if (msg->len != sizeof(time_t)) {
637 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
638 msg->len));
639 return;
642 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
643 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
644 return;
647 if (!make_systemtime(&systime, localtime((time_t *)msg->notify.data))) {
648 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
649 return;
652 if (!spoolss_io_system_time("", &ps, 0, &systime))
653 return;
655 data->notify_data.data.length = prs_offset(&ps);
656 data->notify_data.data.string =
657 talloc(mem_ctx, prs_offset(&ps));
659 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
661 prs_mem_free(&ps);
664 struct notify2_message_table {
665 char *name;
666 void (*fn)(struct spoolss_notify_msg *msg,
667 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
670 static struct notify2_message_table printer_notify_table[] = {
671 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", 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 &notify_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 &notify_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);
1446 int snum;
1448 if (!Printer) {
1449 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1450 return WERR_BADFID;
1453 if (!get_printer_snum(p, handle, &snum))
1454 return WERR_BADFID;
1456 Printer->document_started=False;
1457 print_job_end(snum, Printer->jobid,True);
1458 /* error codes unhandled so far ... */
1460 return WERR_OK;
1463 /********************************************************************
1464 * api_spoolss_closeprinter
1465 ********************************************************************/
1467 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1469 POLICY_HND *handle = &q_u->handle;
1471 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1473 if (Printer && Printer->document_started)
1474 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1476 if (!close_printer_handle(p, handle))
1477 return WERR_BADFID;
1479 /* clear the returned printer handle. Observed behavior
1480 from Win2k server. Don't think this really matters.
1481 Previous code just copied the value of the closed
1482 handle. --jerry */
1484 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1486 return WERR_OK;
1489 /********************************************************************
1490 * api_spoolss_deleteprinter
1492 ********************************************************************/
1494 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1496 POLICY_HND *handle = &q_u->handle;
1497 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1498 WERROR result;
1500 if (Printer && Printer->document_started)
1501 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1503 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1505 result = delete_printer_handle(p, handle);
1507 update_c_setprinter(False);
1509 return result;
1512 /*******************************************************************
1513 * static function to lookup the version id corresponding to an
1514 * long architecture string
1515 ******************************************************************/
1517 static int get_version_id (char * arch)
1519 int i;
1520 struct table_node archi_table[]= {
1522 {"Windows 4.0", "WIN40", 0 },
1523 {"Windows NT x86", "W32X86", 2 },
1524 {"Windows NT R4000", "W32MIPS", 2 },
1525 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1526 {"Windows NT PowerPC", "W32PPC", 2 },
1527 {NULL, "", -1 }
1530 for (i=0; archi_table[i].long_archi != NULL; i++)
1532 if (strcmp(arch, archi_table[i].long_archi) == 0)
1533 return (archi_table[i].version);
1536 return -1;
1539 /********************************************************************
1540 * _spoolss_deleteprinterdriver
1541 ********************************************************************/
1543 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1545 fstring driver;
1546 fstring arch;
1547 NT_PRINTER_DRIVER_INFO_LEVEL info;
1548 int version;
1549 struct current_user user;
1551 get_current_user(&user, p);
1553 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1554 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1556 /* check that we have a valid driver name first */
1557 if ((version=get_version_id(arch)) == -1) {
1558 /* this is what NT returns */
1559 return WERR_INVALID_ENVIRONMENT;
1562 /* if they said "Windows NT x86", then try for version 2 & 3 */
1564 if ( version == 2 )
1565 version = DRIVER_ANY_VERSION;
1567 ZERO_STRUCT(info);
1569 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1570 return WERR_UNKNOWN_PRINTER_DRIVER;
1572 if (printer_driver_in_use(info.info_3))
1573 return WERR_PRINTER_DRIVER_IN_USE;
1575 return delete_printer_driver(info.info_3, &user, DRIVER_ANY_VERSION, False);
1578 /********************************************************************
1579 * spoolss_deleteprinterdriverex
1580 ********************************************************************/
1582 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1584 fstring driver;
1585 fstring arch;
1586 NT_PRINTER_DRIVER_INFO_LEVEL info;
1587 int version;
1588 uint32 flags = q_u->delete_flags;
1589 BOOL delete_files;
1590 struct current_user user;
1592 get_current_user(&user, p);
1594 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1595 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1597 /* check that we have a valid driver name first */
1598 if ((version=get_version_id(arch)) == -1) {
1599 /* this is what NT returns */
1600 return WERR_INVALID_ENVIRONMENT;
1603 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1604 version = q_u->version;
1605 else if ( version == 2 )
1606 /* if they said "Windows NT x86", then try for version 2 & 3 */
1607 version = DRIVER_ANY_VERSION;
1609 ZERO_STRUCT(info);
1611 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1612 return WERR_UNKNOWN_PRINTER_DRIVER;
1614 if ( printer_driver_in_use(info.info_3) )
1615 return WERR_PRINTER_DRIVER_IN_USE;
1618 * we have a couple of cases to consider.
1619 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1620 * then the delete should fail if **any** files overlap with
1621 * other drivers
1622 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1623 * non-overlapping files
1624 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1625 * is set, the do not delete any files
1626 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1629 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1631 if ( delete_files )
1633 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1635 if ( printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) )
1636 /* no idea of the correct error here */
1637 return WERR_ACCESS_DENIED;
1640 return delete_printer_driver(info.info_3, &user, version, delete_files);
1644 /********************************************************************
1645 GetPrinterData on a printer server Handle.
1646 ********************************************************************/
1648 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1650 int i;
1652 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1654 if (!strcmp(value, "W3SvcInstalled")) {
1655 *type = 0x4;
1656 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1657 return False;
1658 *needed = 0x4;
1659 return True;
1662 if (!strcmp(value, "BeepEnabled")) {
1663 *type = 0x4;
1664 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1665 return False;
1666 SIVAL(*data, 0, 0x00);
1667 *needed = 0x4;
1668 return True;
1671 if (!strcmp(value, "EventLog")) {
1672 *type = 0x4;
1673 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1674 return False;
1675 /* formally was 0x1b */
1676 SIVAL(*data, 0, 0x0);
1677 *needed = 0x4;
1678 return True;
1681 if (!strcmp(value, "NetPopup")) {
1682 *type = 0x4;
1683 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1684 return False;
1685 SIVAL(*data, 0, 0x00);
1686 *needed = 0x4;
1687 return True;
1690 if (!strcmp(value, "MajorVersion")) {
1691 *type = 0x4;
1692 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1693 return False;
1694 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1695 SIVAL(*data, 0, 2);
1696 #else
1697 SIVAL(*data, 0, 3);
1698 #endif
1699 *needed = 0x4;
1700 return True;
1703 if (!strcmp(value, "DefaultSpoolDirectory")) {
1704 fstring string;
1706 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1707 *type = 0x1;
1708 *needed = 2*(strlen(string)+1);
1709 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1710 return False;
1711 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1713 /* it's done by hand ready to go on the wire */
1714 for (i=0; i<strlen(string); i++) {
1715 (*data)[2*i]=string[i];
1716 (*data)[2*i+1]='\0';
1718 return True;
1721 if (!strcmp(value, "Architecture")) {
1722 pstring string="Windows NT x86";
1723 *type = 0x1;
1724 *needed = 2*(strlen(string)+1);
1725 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1726 return False;
1727 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1728 for (i=0; i<strlen(string); i++) {
1729 (*data)[2*i]=string[i];
1730 (*data)[2*i+1]='\0';
1732 return True;
1735 return False;
1738 /********************************************************************
1739 GetPrinterData on a printer Handle.
1740 ********************************************************************/
1742 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1743 fstring value, uint32 *type,
1744 uint8 **data, uint32 *needed, uint32 in_size )
1746 NT_PRINTER_INFO_LEVEL *printer = NULL;
1747 int snum=0;
1748 uint8 *idata=NULL;
1749 uint32 len;
1750 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1752 DEBUG(5,("getprinterdata_printer\n"));
1754 if (!Printer) {
1755 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1756 return False;
1759 if(!get_printer_snum(p, handle, &snum))
1760 return False;
1762 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1763 return False;
1765 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1766 free_a_printer(&printer, 2);
1767 return False;
1770 free_a_printer(&printer, 2);
1772 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1774 if (in_size) {
1775 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1776 return False;
1779 memset(*data, 0, in_size *sizeof(uint8));
1780 /* copy the min(in_size, len) */
1781 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1782 } else {
1783 *data = NULL;
1786 *needed = len;
1788 DEBUG(5,("getprinterdata_printer:copy done\n"));
1790 SAFE_FREE(idata);
1792 return True;
1795 /********************************************************************
1796 * spoolss_getprinterdata
1797 ********************************************************************/
1799 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1801 POLICY_HND *handle = &q_u->handle;
1802 UNISTR2 *valuename = &q_u->valuename;
1803 uint32 in_size = q_u->size;
1804 uint32 *type = &r_u->type;
1805 uint32 *out_size = &r_u->size;
1806 uint8 **data = &r_u->data;
1807 uint32 *needed = &r_u->needed;
1809 fstring value;
1810 BOOL found=False;
1811 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1814 * Reminder: when it's a string, the length is in BYTES
1815 * even if UNICODE is negociated.
1817 * JFM, 4/19/1999
1820 *out_size=in_size;
1822 /* in case of problem, return some default values */
1823 *needed=0;
1824 *type=0;
1826 DEBUG(4,("_spoolss_getprinterdata\n"));
1828 if (!Printer) {
1829 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1830 return WERR_NOMEM;
1831 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1832 return WERR_BADFID;
1835 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1837 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1838 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1839 else
1840 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1842 if (found==False) {
1843 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1844 /* reply this param doesn't exist */
1845 if (*out_size) {
1846 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1847 return WERR_NOMEM;
1848 } else {
1849 *data = NULL;
1852 /* error depends on handle type */
1854 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1855 return WERR_INVALID_PARAM;
1856 else
1857 return WERR_BADFILE;
1860 if (*needed > *out_size)
1861 return WERR_MORE_DATA;
1862 else
1863 return WERR_OK;
1866 /*********************************************************
1867 Connect to the client machine.
1868 **********************************************************/
1870 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
1872 extern pstring global_myname;
1874 ZERO_STRUCTP(the_cli);
1875 if(cli_initialise(the_cli) == NULL) {
1876 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
1877 return False;
1880 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
1881 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
1882 cli_shutdown(the_cli);
1883 return False;
1886 if (ismyip(the_cli->dest_ip)) {
1887 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
1888 cli_shutdown(the_cli);
1889 return False;
1892 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
1893 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1894 cli_shutdown(the_cli);
1895 return False;
1898 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
1899 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
1900 remote_machine));
1901 return False;
1904 the_cli->protocol = PROTOCOL_NT1;
1906 if (!cli_negprot(the_cli)) {
1907 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1908 cli_shutdown(the_cli);
1909 return False;
1912 if (the_cli->protocol != PROTOCOL_NT1) {
1913 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
1914 cli_shutdown(the_cli);
1915 return False;
1919 * Do an anonymous session setup.
1922 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
1923 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1924 cli_shutdown(the_cli);
1925 return False;
1928 if (!(the_cli->sec_mode & 1)) {
1929 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
1930 cli_shutdown(the_cli);
1931 return False;
1934 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
1935 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
1936 cli_shutdown(the_cli);
1937 return False;
1941 * Ok - we have an anonymous connection to the IPC$ share.
1942 * Now start the NT Domain stuff :-).
1945 if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
1946 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)));
1947 cli_nt_session_close(the_cli);
1948 cli_ulogoff(the_cli);
1949 cli_shutdown(the_cli);
1950 return False;
1953 return True;
1956 /***************************************************************************
1957 Connect to the client.
1958 ****************************************************************************/
1960 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1962 WERROR result;
1965 * If it's the first connection, contact the client
1966 * and connect to the IPC$ share anonumously
1968 if (smb_connections==0) {
1969 fstring unix_printer;
1971 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1973 if(!spoolss_connect_to_client(&notify_cli, unix_printer))
1974 return False;
1976 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
1979 smb_connections++;
1981 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
1982 type, handle);
1984 if (!W_ERROR_IS_OK(result))
1985 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1986 dos_errstr(result)));
1988 return (W_ERROR_IS_OK(result));
1991 /********************************************************************
1992 * _spoolss_rffpcnex
1993 * ReplyFindFirstPrinterChangeNotifyEx
1995 * before replying OK: status=0 a rpc call is made to the workstation
1996 * asking ReplyOpenPrinter
1998 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1999 * called from api_spoolss_rffpcnex
2000 ********************************************************************/
2002 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2004 POLICY_HND *handle = &q_u->handle;
2005 uint32 flags = q_u->flags;
2006 uint32 options = q_u->options;
2007 UNISTR2 *localmachine = &q_u->localmachine;
2008 uint32 printerlocal = q_u->printerlocal;
2009 SPOOL_NOTIFY_OPTION *option = q_u->option;
2011 /* store the notify value in the printer struct */
2013 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2015 if (!Printer) {
2016 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2017 return WERR_BADFID;
2020 Printer->notify.flags=flags;
2021 Printer->notify.options=options;
2022 Printer->notify.printerlocal=printerlocal;
2024 if (Printer->notify.option)
2025 free_spool_notify_option(&Printer->notify.option);
2027 Printer->notify.option=dup_spool_notify_option(option);
2029 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2030 sizeof(Printer->notify.localmachine)-1);
2032 /* Connect to the client machine and send a ReplyOpenPrinter */
2034 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
2035 Printer->notify.printerlocal, 1,
2036 &Printer->notify.client_hnd))
2037 return WERR_SERVER_UNAVAILABLE;
2039 Printer->notify.client_connected=True;
2041 return WERR_OK;
2044 /*******************************************************************
2045 * fill a notify_info_data with the servername
2046 ********************************************************************/
2048 void spoolss_notify_server_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_name, temp;
2055 uint32 len;
2057 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2059 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2061 data->notify_data.data.length = len;
2062 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2064 if (!data->notify_data.data.string) {
2065 data->notify_data.data.length = 0;
2066 return;
2069 memcpy(data->notify_data.data.string, temp, len);
2072 /*******************************************************************
2073 * fill a notify_info_data with the printername (not including the servername).
2074 ********************************************************************/
2076 void spoolss_notify_printer_name(int snum,
2077 SPOOL_NOTIFY_INFO_DATA *data,
2078 print_queue_struct *queue,
2079 NT_PRINTER_INFO_LEVEL *printer,
2080 TALLOC_CTX *mem_ctx)
2082 pstring temp;
2083 uint32 len;
2085 /* the notify name should not contain the \\server\ part */
2086 char *p = strrchr(printer->info_2->printername, '\\');
2088 if (!p) {
2089 p = printer->info_2->printername;
2090 } else {
2091 p++;
2094 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2096 data->notify_data.data.length = len;
2097 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2099 if (!data->notify_data.data.string) {
2100 data->notify_data.data.length = 0;
2101 return;
2104 memcpy(data->notify_data.data.string, temp, len);
2107 /*******************************************************************
2108 * fill a notify_info_data with the servicename
2109 ********************************************************************/
2111 void spoolss_notify_share_name(int snum,
2112 SPOOL_NOTIFY_INFO_DATA *data,
2113 print_queue_struct *queue,
2114 NT_PRINTER_INFO_LEVEL *printer,
2115 TALLOC_CTX *mem_ctx)
2117 pstring temp;
2118 uint32 len;
2120 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2122 data->notify_data.data.length = len;
2123 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2125 if (!data->notify_data.data.string) {
2126 data->notify_data.data.length = 0;
2127 return;
2130 memcpy(data->notify_data.data.string, temp, len);
2133 /*******************************************************************
2134 * fill a notify_info_data with the port name
2135 ********************************************************************/
2137 void spoolss_notify_port_name(int snum,
2138 SPOOL_NOTIFY_INFO_DATA *data,
2139 print_queue_struct *queue,
2140 NT_PRINTER_INFO_LEVEL *printer,
2141 TALLOC_CTX *mem_ctx)
2143 pstring temp;
2144 uint32 len;
2146 /* even if it's strange, that's consistant in all the code */
2148 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2150 data->notify_data.data.length = len;
2151 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2153 if (!data->notify_data.data.string) {
2154 data->notify_data.data.length = 0;
2155 return;
2158 memcpy(data->notify_data.data.string, temp, len);
2161 /*******************************************************************
2162 * fill a notify_info_data with the printername
2163 * but it doesn't exist, have to see what to do
2164 ********************************************************************/
2166 void spoolss_notify_driver_name(int snum,
2167 SPOOL_NOTIFY_INFO_DATA *data,
2168 print_queue_struct *queue,
2169 NT_PRINTER_INFO_LEVEL *printer,
2170 TALLOC_CTX *mem_ctx)
2172 pstring temp;
2173 uint32 len;
2175 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2177 data->notify_data.data.length = len;
2178 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2180 if (!data->notify_data.data.string) {
2181 data->notify_data.data.length = 0;
2182 return;
2185 memcpy(data->notify_data.data.string, temp, len);
2188 /*******************************************************************
2189 * fill a notify_info_data with the comment
2190 ********************************************************************/
2192 void spoolss_notify_comment(int snum,
2193 SPOOL_NOTIFY_INFO_DATA *data,
2194 print_queue_struct *queue,
2195 NT_PRINTER_INFO_LEVEL *printer,
2196 TALLOC_CTX *mem_ctx)
2198 pstring temp;
2199 uint32 len;
2201 if (*printer->info_2->comment == '\0')
2202 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2203 else
2204 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2206 data->notify_data.data.length = len;
2207 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2209 if (!data->notify_data.data.string) {
2210 data->notify_data.data.length = 0;
2211 return;
2214 memcpy(data->notify_data.data.string, temp, len);
2217 /*******************************************************************
2218 * fill a notify_info_data with the comment
2219 * location = "Room 1, floor 2, building 3"
2220 ********************************************************************/
2222 void spoolss_notify_location(int snum,
2223 SPOOL_NOTIFY_INFO_DATA *data,
2224 print_queue_struct *queue,
2225 NT_PRINTER_INFO_LEVEL *printer,
2226 TALLOC_CTX *mem_ctx)
2228 pstring temp;
2229 uint32 len;
2231 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2233 data->notify_data.data.length = len;
2234 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2236 if (!data->notify_data.data.string) {
2237 data->notify_data.data.length = 0;
2238 return;
2241 memcpy(data->notify_data.data.string, temp, len);
2244 /*******************************************************************
2245 * fill a notify_info_data with the device mode
2246 * jfm:xxxx don't to it for know but that's a real problem !!!
2247 ********************************************************************/
2249 static void spoolss_notify_devmode(int snum,
2250 SPOOL_NOTIFY_INFO_DATA *data,
2251 print_queue_struct *queue,
2252 NT_PRINTER_INFO_LEVEL *printer,
2253 TALLOC_CTX *mem_ctx)
2257 /*******************************************************************
2258 * fill a notify_info_data with the separator file name
2259 ********************************************************************/
2261 void spoolss_notify_sepfile(int snum,
2262 SPOOL_NOTIFY_INFO_DATA *data,
2263 print_queue_struct *queue,
2264 NT_PRINTER_INFO_LEVEL *printer,
2265 TALLOC_CTX *mem_ctx)
2267 pstring temp;
2268 uint32 len;
2270 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2272 data->notify_data.data.length = len;
2273 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2275 if (!data->notify_data.data.string) {
2276 data->notify_data.data.length = 0;
2277 return;
2280 memcpy(data->notify_data.data.string, temp, len);
2283 /*******************************************************************
2284 * fill a notify_info_data with the print processor
2285 * jfm:xxxx return always winprint to indicate we don't do anything to it
2286 ********************************************************************/
2288 void spoolss_notify_print_processor(int snum,
2289 SPOOL_NOTIFY_INFO_DATA *data,
2290 print_queue_struct *queue,
2291 NT_PRINTER_INFO_LEVEL *printer,
2292 TALLOC_CTX *mem_ctx)
2294 pstring temp;
2295 uint32 len;
2297 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2299 data->notify_data.data.length = len;
2300 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2302 if (!data->notify_data.data.string) {
2303 data->notify_data.data.length = 0;
2304 return;
2307 memcpy(data->notify_data.data.string, temp, len);
2310 /*******************************************************************
2311 * fill a notify_info_data with the print processor options
2312 * jfm:xxxx send an empty string
2313 ********************************************************************/
2315 void spoolss_notify_parameters(int snum,
2316 SPOOL_NOTIFY_INFO_DATA *data,
2317 print_queue_struct *queue,
2318 NT_PRINTER_INFO_LEVEL *printer,
2319 TALLOC_CTX *mem_ctx)
2321 pstring temp;
2322 uint32 len;
2324 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2326 data->notify_data.data.length = len;
2327 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2329 if (!data->notify_data.data.string) {
2330 data->notify_data.data.length = 0;
2331 return;
2334 memcpy(data->notify_data.data.string, temp, len);
2337 /*******************************************************************
2338 * fill a notify_info_data with the data type
2339 * jfm:xxxx always send RAW as data type
2340 ********************************************************************/
2342 void spoolss_notify_datatype(int snum,
2343 SPOOL_NOTIFY_INFO_DATA *data,
2344 print_queue_struct *queue,
2345 NT_PRINTER_INFO_LEVEL *printer,
2346 TALLOC_CTX *mem_ctx)
2348 pstring temp;
2349 uint32 len;
2351 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2353 data->notify_data.data.length = len;
2354 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2356 if (!data->notify_data.data.string) {
2357 data->notify_data.data.length = 0;
2358 return;
2361 memcpy(data->notify_data.data.string, temp, len);
2364 /*******************************************************************
2365 * fill a notify_info_data with the security descriptor
2366 * jfm:xxxx send an null pointer to say no security desc
2367 * have to implement security before !
2368 ********************************************************************/
2370 static void spoolss_notify_security_desc(int snum,
2371 SPOOL_NOTIFY_INFO_DATA *data,
2372 print_queue_struct *queue,
2373 NT_PRINTER_INFO_LEVEL *printer,
2374 TALLOC_CTX *mem_ctx)
2376 data->notify_data.data.length=0;
2377 data->notify_data.data.string = NULL;
2380 /*******************************************************************
2381 * fill a notify_info_data with the attributes
2382 * jfm:xxxx a samba printer is always shared
2383 ********************************************************************/
2385 void spoolss_notify_attributes(int snum,
2386 SPOOL_NOTIFY_INFO_DATA *data,
2387 print_queue_struct *queue,
2388 NT_PRINTER_INFO_LEVEL *printer,
2389 TALLOC_CTX *mem_ctx)
2391 data->notify_data.value[0] = printer->info_2->attributes;
2392 data->notify_data.value[1] = 0;
2395 /*******************************************************************
2396 * fill a notify_info_data with the priority
2397 ********************************************************************/
2399 static void spoolss_notify_priority(int snum,
2400 SPOOL_NOTIFY_INFO_DATA *data,
2401 print_queue_struct *queue,
2402 NT_PRINTER_INFO_LEVEL *printer,
2403 TALLOC_CTX *mem_ctx)
2405 data->notify_data.value[0] = printer->info_2->priority;
2406 data->notify_data.value[1] = 0;
2409 /*******************************************************************
2410 * fill a notify_info_data with the default priority
2411 ********************************************************************/
2413 static void spoolss_notify_default_priority(int snum,
2414 SPOOL_NOTIFY_INFO_DATA *data,
2415 print_queue_struct *queue,
2416 NT_PRINTER_INFO_LEVEL *printer,
2417 TALLOC_CTX *mem_ctx)
2419 data->notify_data.value[0] = printer->info_2->default_priority;
2420 data->notify_data.value[1] = 0;
2423 /*******************************************************************
2424 * fill a notify_info_data with the start time
2425 ********************************************************************/
2427 static void spoolss_notify_start_time(int snum,
2428 SPOOL_NOTIFY_INFO_DATA *data,
2429 print_queue_struct *queue,
2430 NT_PRINTER_INFO_LEVEL *printer,
2431 TALLOC_CTX *mem_ctx)
2433 data->notify_data.value[0] = printer->info_2->starttime;
2434 data->notify_data.value[1] = 0;
2437 /*******************************************************************
2438 * fill a notify_info_data with the until time
2439 ********************************************************************/
2441 static void spoolss_notify_until_time(int snum,
2442 SPOOL_NOTIFY_INFO_DATA *data,
2443 print_queue_struct *queue,
2444 NT_PRINTER_INFO_LEVEL *printer,
2445 TALLOC_CTX *mem_ctx)
2447 data->notify_data.value[0] = printer->info_2->untiltime;
2448 data->notify_data.value[1] = 0;
2451 /*******************************************************************
2452 * fill a notify_info_data with the status
2453 ********************************************************************/
2455 static void spoolss_notify_status(int snum,
2456 SPOOL_NOTIFY_INFO_DATA *data,
2457 print_queue_struct *queue,
2458 NT_PRINTER_INFO_LEVEL *printer,
2459 TALLOC_CTX *mem_ctx)
2461 print_status_struct status;
2463 print_queue_length(snum, &status);
2464 data->notify_data.value[0]=(uint32) status.status;
2465 data->notify_data.value[1] = 0;
2468 /*******************************************************************
2469 * fill a notify_info_data with the number of jobs queued
2470 ********************************************************************/
2472 void spoolss_notify_cjobs(int snum,
2473 SPOOL_NOTIFY_INFO_DATA *data,
2474 print_queue_struct *queue,
2475 NT_PRINTER_INFO_LEVEL *printer,
2476 TALLOC_CTX *mem_ctx)
2478 data->notify_data.value[0] = print_queue_length(snum, NULL);
2479 data->notify_data.value[1] = 0;
2482 /*******************************************************************
2483 * fill a notify_info_data with the average ppm
2484 ********************************************************************/
2486 static void spoolss_notify_average_ppm(int snum,
2487 SPOOL_NOTIFY_INFO_DATA *data,
2488 print_queue_struct *queue,
2489 NT_PRINTER_INFO_LEVEL *printer,
2490 TALLOC_CTX *mem_ctx)
2492 /* always respond 8 pages per minutes */
2493 /* a little hard ! */
2494 data->notify_data.value[0] = printer->info_2->averageppm;
2495 data->notify_data.value[1] = 0;
2498 /*******************************************************************
2499 * fill a notify_info_data with username
2500 ********************************************************************/
2502 static void spoolss_notify_username(int snum,
2503 SPOOL_NOTIFY_INFO_DATA *data,
2504 print_queue_struct *queue,
2505 NT_PRINTER_INFO_LEVEL *printer,
2506 TALLOC_CTX *mem_ctx)
2508 pstring temp;
2509 uint32 len;
2511 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2513 data->notify_data.data.length = len;
2514 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2516 if (!data->notify_data.data.string) {
2517 data->notify_data.data.length = 0;
2518 return;
2521 memcpy(data->notify_data.data.string, temp, len);
2524 /*******************************************************************
2525 * fill a notify_info_data with job status
2526 ********************************************************************/
2528 static void spoolss_notify_job_status(int snum,
2529 SPOOL_NOTIFY_INFO_DATA *data,
2530 print_queue_struct *queue,
2531 NT_PRINTER_INFO_LEVEL *printer,
2532 TALLOC_CTX *mem_ctx)
2534 data->notify_data.value[0]=nt_printj_status(queue->status);
2535 data->notify_data.value[1] = 0;
2538 /*******************************************************************
2539 * fill a notify_info_data with job name
2540 ********************************************************************/
2542 static void spoolss_notify_job_name(int snum,
2543 SPOOL_NOTIFY_INFO_DATA *data,
2544 print_queue_struct *queue,
2545 NT_PRINTER_INFO_LEVEL *printer,
2546 TALLOC_CTX *mem_ctx)
2548 pstring temp;
2549 uint32 len;
2551 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2553 data->notify_data.data.length = len;
2554 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2556 if (!data->notify_data.data.string) {
2557 data->notify_data.data.length = 0;
2558 return;
2561 memcpy(data->notify_data.data.string, temp, len);
2564 /*******************************************************************
2565 * fill a notify_info_data with job status
2566 ********************************************************************/
2568 static void spoolss_notify_job_status_string(int snum,
2569 SPOOL_NOTIFY_INFO_DATA *data,
2570 print_queue_struct *queue,
2571 NT_PRINTER_INFO_LEVEL *printer,
2572 TALLOC_CTX *mem_ctx)
2575 * Now we're returning job status codes we just return a "" here. JRA.
2578 char *p = "";
2579 pstring temp;
2580 uint32 len;
2582 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2583 p = "unknown";
2585 switch (queue->status) {
2586 case LPQ_QUEUED:
2587 p = "Queued";
2588 break;
2589 case LPQ_PAUSED:
2590 p = ""; /* NT provides the paused string */
2591 break;
2592 case LPQ_SPOOLING:
2593 p = "Spooling";
2594 break;
2595 case LPQ_PRINTING:
2596 p = "Printing";
2597 break;
2599 #endif /* NO LONGER NEEDED. */
2601 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2603 data->notify_data.data.length = len;
2604 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2606 if (!data->notify_data.data.string) {
2607 data->notify_data.data.length = 0;
2608 return;
2611 memcpy(data->notify_data.data.string, temp, len);
2614 /*******************************************************************
2615 * fill a notify_info_data with job time
2616 ********************************************************************/
2618 static void spoolss_notify_job_time(int snum,
2619 SPOOL_NOTIFY_INFO_DATA *data,
2620 print_queue_struct *queue,
2621 NT_PRINTER_INFO_LEVEL *printer,
2622 TALLOC_CTX *mem_ctx)
2624 data->notify_data.value[0]=0x0;
2625 data->notify_data.value[1]=0;
2628 /*******************************************************************
2629 * fill a notify_info_data with job size
2630 ********************************************************************/
2632 static void spoolss_notify_job_size(int snum,
2633 SPOOL_NOTIFY_INFO_DATA *data,
2634 print_queue_struct *queue,
2635 NT_PRINTER_INFO_LEVEL *printer,
2636 TALLOC_CTX *mem_ctx)
2638 data->notify_data.value[0]=queue->size;
2639 data->notify_data.value[1]=0;
2642 /*******************************************************************
2643 * fill a notify_info_data with page info
2644 ********************************************************************/
2645 static void spoolss_notify_total_pages(int snum,
2646 SPOOL_NOTIFY_INFO_DATA *data,
2647 print_queue_struct *queue,
2648 NT_PRINTER_INFO_LEVEL *printer,
2649 TALLOC_CTX *mem_ctx)
2651 data->notify_data.value[0]=queue->page_count;
2652 data->notify_data.value[1]=0;
2655 /*******************************************************************
2656 * fill a notify_info_data with pages printed info.
2657 ********************************************************************/
2658 static void spoolss_notify_pages_printed(int snum,
2659 SPOOL_NOTIFY_INFO_DATA *data,
2660 print_queue_struct *queue,
2661 NT_PRINTER_INFO_LEVEL *printer,
2662 TALLOC_CTX *mem_ctx)
2664 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2665 data->notify_data.value[1]=0;
2668 /*******************************************************************
2669 Fill a notify_info_data with job position.
2670 ********************************************************************/
2672 static void spoolss_notify_job_position(int snum,
2673 SPOOL_NOTIFY_INFO_DATA *data,
2674 print_queue_struct *queue,
2675 NT_PRINTER_INFO_LEVEL *printer,
2676 TALLOC_CTX *mem_ctx)
2678 data->notify_data.value[0]=queue->job;
2679 data->notify_data.value[1]=0;
2682 /*******************************************************************
2683 Fill a notify_info_data with submitted time.
2684 ********************************************************************/
2686 static void spoolss_notify_submitted_time(int snum,
2687 SPOOL_NOTIFY_INFO_DATA *data,
2688 print_queue_struct *queue,
2689 NT_PRINTER_INFO_LEVEL *printer,
2690 TALLOC_CTX *mem_ctx)
2692 struct tm *t;
2693 uint32 len;
2694 SYSTEMTIME st;
2695 char *p;
2697 t=gmtime(&queue->time);
2699 len = sizeof(SYSTEMTIME);
2701 data->notify_data.data.length = len;
2702 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2704 if (!data->notify_data.data.string) {
2705 data->notify_data.data.length = 0;
2706 return;
2709 make_systemtime(&st, t);
2712 * Systemtime must be linearized as a set of UINT16's.
2713 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2716 p = (char *)data->notify_data.data.string;
2717 SSVAL(p, 0, st.year);
2718 SSVAL(p, 2, st.month);
2719 SSVAL(p, 4, st.dayofweek);
2720 SSVAL(p, 6, st.day);
2721 SSVAL(p, 8, st.hour);
2722 SSVAL(p, 10, st.minute);
2723 SSVAL(p, 12, st.second);
2724 SSVAL(p, 14, st.milliseconds);
2727 struct s_notify_info_data_table
2729 uint16 type;
2730 uint16 field;
2731 char *name;
2732 uint32 size;
2733 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2734 print_queue_struct *queue,
2735 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2738 /* A table describing the various print notification constants and
2739 whether the notification data is a pointer to a variable sized
2740 buffer, a one value uint32 or a two value uint32. */
2742 struct s_notify_info_data_table notify_info_data_table[] =
2744 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2745 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2746 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
2747 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2748 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2749 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
2750 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
2751 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2752 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
2753 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2754 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2755 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2756 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, spoolss_notify_security_desc },
2757 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
2758 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2759 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
2760 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2761 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2762 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
2763 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
2764 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
2765 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
2766 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
2767 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
2768 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
2769 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
2770 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
2771 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
2772 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
2773 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
2774 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
2775 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
2776 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
2777 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
2778 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
2779 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
2780 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
2781 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
2782 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
2783 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
2784 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
2785 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
2786 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
2787 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
2788 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
2789 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
2790 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
2791 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
2792 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
2795 /*******************************************************************
2796 Return the size of info_data structure.
2797 ********************************************************************/
2799 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2801 int i=0;
2803 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2804 if (notify_info_data_table[i].type == type &&
2805 notify_info_data_table[i].field == field) {
2806 switch(notify_info_data_table[i].size) {
2807 case NOTIFY_ONE_VALUE:
2808 case NOTIFY_TWO_VALUE:
2809 return 1;
2810 case NOTIFY_STRING:
2811 return 2;
2813 /* The only pointer notify data I have seen on
2814 the wire is the submitted time and this has
2815 the notify size set to 4. -tpot */
2817 case NOTIFY_POINTER:
2818 return 4;
2823 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2825 return 0;
2828 /*******************************************************************
2829 Return the type of notify_info_data.
2830 ********************************************************************/
2832 static int type_of_notify_info_data(uint16 type, uint16 field)
2834 int i=0;
2836 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2837 if (notify_info_data_table[i].type == type &&
2838 notify_info_data_table[i].field == field)
2839 return notify_info_data_table[i].size;
2842 return False;
2845 /****************************************************************************
2846 ****************************************************************************/
2848 static int search_notify(uint16 type, uint16 field, int *value)
2850 int i;
2852 for (i = 0; i < sizeof(notify_info_data_table); i++) {
2853 if (notify_info_data_table[i].type == type &&
2854 notify_info_data_table[i].field == field &&
2855 notify_info_data_table[i].fn != NULL) {
2856 *value = i;
2857 return True;
2861 return False;
2864 /****************************************************************************
2865 ****************************************************************************/
2867 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2869 info_data->type = type;
2870 info_data->field = field;
2871 info_data->reserved = 0;
2873 if (type == JOB_NOTIFY_TYPE)
2874 info_data->id = id;
2875 else
2876 info_data->id = 0;
2878 info_data->size = size_of_notify_info_data(type, field);
2879 info_data->enc_type = type_of_notify_info_data(type, field);
2883 /*******************************************************************
2885 * fill a notify_info struct with info asked
2887 ********************************************************************/
2889 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2890 snum, SPOOL_NOTIFY_OPTION_TYPE
2891 *option_type, uint32 id,
2892 TALLOC_CTX *mem_ctx)
2894 int field_num,j;
2895 uint16 type;
2896 uint16 field;
2898 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2899 NT_PRINTER_INFO_LEVEL *printer = NULL;
2900 print_queue_struct *queue=NULL;
2902 type=option_type->type;
2904 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2905 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2906 option_type->count, lp_servicename(snum)));
2908 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2909 return False;
2911 for(field_num=0; field_num<option_type->count; field_num++) {
2912 field = option_type->fields[field_num];
2913 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2915 if (!search_notify(type, field, &j) )
2916 continue;
2918 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2919 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2920 return False;
2922 else info->data = tid;
2924 current_data=&info->data[info->count];
2926 construct_info_data(current_data, type, field, id);
2928 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2929 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2931 notify_info_data_table[j].fn(snum, current_data, queue,
2932 printer, mem_ctx);
2934 info->count++;
2937 free_a_printer(&printer, 2);
2938 return True;
2941 /*******************************************************************
2943 * fill a notify_info struct with info asked
2945 ********************************************************************/
2947 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2948 SPOOL_NOTIFY_INFO *info,
2949 NT_PRINTER_INFO_LEVEL *printer,
2950 int snum, SPOOL_NOTIFY_OPTION_TYPE
2951 *option_type, uint32 id,
2952 TALLOC_CTX *mem_ctx)
2954 int field_num,j;
2955 uint16 type;
2956 uint16 field;
2958 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2960 DEBUG(4,("construct_notify_jobs_info\n"));
2962 type = option_type->type;
2964 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2965 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2966 option_type->count));
2968 for(field_num=0; field_num<option_type->count; field_num++) {
2969 field = option_type->fields[field_num];
2971 if (!search_notify(type, field, &j) )
2972 continue;
2974 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2975 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2976 return False;
2978 else info->data = tid;
2980 current_data=&(info->data[info->count]);
2982 construct_info_data(current_data, type, field, id);
2983 notify_info_data_table[j].fn(snum, current_data, queue,
2984 printer, mem_ctx);
2985 info->count++;
2988 return True;
2992 * JFM: The enumeration is not that simple, it's even non obvious.
2994 * let's take an example: I want to monitor the PRINTER SERVER for
2995 * the printer's name and the number of jobs currently queued.
2996 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2997 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2999 * I have 3 printers on the back of my server.
3001 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3002 * structures.
3003 * Number Data Id
3004 * 1 printer 1 name 1
3005 * 2 printer 1 cjob 1
3006 * 3 printer 2 name 2
3007 * 4 printer 2 cjob 2
3008 * 5 printer 3 name 3
3009 * 6 printer 3 name 3
3011 * that's the print server case, the printer case is even worse.
3014 /*******************************************************************
3016 * enumerate all printers on the printserver
3017 * fill a notify_info struct with info asked
3019 ********************************************************************/
3021 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3022 SPOOL_NOTIFY_INFO *info,
3023 TALLOC_CTX *mem_ctx)
3025 int snum;
3026 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3027 int n_services=lp_numservices();
3028 int i;
3029 uint32 id;
3030 SPOOL_NOTIFY_OPTION *option;
3031 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3033 DEBUG(4,("printserver_notify_info\n"));
3035 if (!Printer)
3036 return WERR_BADFID;
3038 option=Printer->notify.option;
3039 id=1;
3040 info->version=2;
3041 info->data=NULL;
3042 info->count=0;
3044 for (i=0; i<option->count; i++) {
3045 option_type=&(option->ctr.type[i]);
3047 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3048 continue;
3050 for (snum=0; snum<n_services; snum++)
3051 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3052 if (construct_notify_printer_info
3053 (info, snum, option_type, id, mem_ctx))
3054 id++;
3058 * Debugging information, don't delete.
3061 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3062 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3063 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3065 for (i=0; i<info->count; i++) {
3066 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3067 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3068 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3072 return WERR_OK;
3075 /*******************************************************************
3077 * fill a notify_info struct with info asked
3079 ********************************************************************/
3081 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3082 TALLOC_CTX *mem_ctx)
3084 int snum;
3085 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3086 int i;
3087 uint32 id;
3088 SPOOL_NOTIFY_OPTION *option;
3089 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3090 int count,j;
3091 print_queue_struct *queue=NULL;
3092 print_status_struct status;
3094 DEBUG(4,("printer_notify_info\n"));
3096 if (!Printer)
3097 return WERR_BADFID;
3099 option=Printer->notify.option;
3100 id = 0x0;
3101 info->version=2;
3102 info->data=NULL;
3103 info->count=0;
3105 get_printer_snum(p, hnd, &snum);
3107 for (i=0; i<option->count; i++) {
3108 option_type=&option->ctr.type[i];
3110 switch ( option_type->type ) {
3111 case PRINTER_NOTIFY_TYPE:
3112 if(construct_notify_printer_info(info, snum,
3113 option_type, id,
3114 mem_ctx))
3115 id--;
3116 break;
3118 case JOB_NOTIFY_TYPE: {
3119 NT_PRINTER_INFO_LEVEL *printer = NULL;
3121 count = print_queue_status(snum, &queue, &status);
3123 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3124 lp_servicename(snum))))
3125 goto done;
3127 for (j=0; j<count; j++) {
3128 construct_notify_jobs_info(&queue[j], info,
3129 printer, snum,
3130 option_type,
3131 queue[j].job,
3132 mem_ctx);
3135 free_a_printer(&printer, 2);
3137 done:
3138 SAFE_FREE(queue);
3139 break;
3145 * Debugging information, don't delete.
3148 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3149 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3150 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3152 for (i=0; i<info->count; i++) {
3153 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3154 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3155 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3158 return WERR_OK;
3161 /********************************************************************
3162 * spoolss_rfnpcnex
3163 ********************************************************************/
3165 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3167 POLICY_HND *handle = &q_u->handle;
3168 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
3169 SPOOL_NOTIFY_INFO *info = &r_u->info;
3171 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3172 WERROR result = WERR_BADFID;
3174 /* we always have a NOTIFY_INFO struct */
3175 r_u->info_ptr=0x1;
3177 if (!Printer) {
3178 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3179 OUR_HANDLE(handle)));
3180 goto done;
3183 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3186 * We are now using the change value, and
3187 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3188 * I don't have a global notification system, I'm sending back all the
3189 * informations even when _NOTHING_ has changed.
3192 /* We need to keep track of the change value to send back in
3193 RRPCN replies otherwise our updates are ignored. */
3195 if (Printer->notify.client_connected)
3196 Printer->notify.change = q_u->change;
3198 /* just ignore the SPOOL_NOTIFY_OPTION */
3200 switch (Printer->printer_type) {
3201 case PRINTER_HANDLE_IS_PRINTSERVER:
3202 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3203 break;
3205 case PRINTER_HANDLE_IS_PRINTER:
3206 result = printer_notify_info(p, handle, info, p->mem_ctx);
3207 break;
3210 done:
3211 return result;
3214 /********************************************************************
3215 * construct_printer_info_0
3216 * fill a printer_info_0 struct
3217 ********************************************************************/
3219 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3221 pstring chaine;
3222 int count;
3223 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3224 counter_printer_0 *session_counter;
3225 uint32 global_counter;
3226 struct tm *t;
3227 time_t setuptime;
3228 print_status_struct status;
3230 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3231 return False;
3233 count = print_queue_length(snum, &status);
3235 /* check if we already have a counter for this printer */
3236 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3238 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3239 if (session_counter->snum == snum)
3240 break;
3243 /* it's the first time, add it to the list */
3244 if (session_counter==NULL) {
3245 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3246 free_a_printer(&ntprinter, 2);
3247 return False;
3249 ZERO_STRUCTP(session_counter);
3250 session_counter->snum=snum;
3251 session_counter->counter=0;
3252 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3255 /* increment it */
3256 session_counter->counter++;
3258 /* JFM:
3259 * the global_counter should be stored in a TDB as it's common to all the clients
3260 * and should be zeroed on samba startup
3262 global_counter=session_counter->counter;
3264 pstrcpy(chaine,ntprinter->info_2->printername);
3266 init_unistr(&printer->printername, chaine);
3268 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3269 init_unistr(&printer->servername, chaine);
3271 printer->cjobs = count;
3272 printer->total_jobs = 0;
3273 printer->total_bytes = 0;
3275 setuptime = (time_t)ntprinter->info_2->setuptime;
3276 t=gmtime(&setuptime);
3278 printer->year = t->tm_year+1900;
3279 printer->month = t->tm_mon+1;
3280 printer->dayofweek = t->tm_wday;
3281 printer->day = t->tm_mday;
3282 printer->hour = t->tm_hour;
3283 printer->minute = t->tm_min;
3284 printer->second = t->tm_sec;
3285 printer->milliseconds = 0;
3287 printer->global_counter = global_counter;
3288 printer->total_pages = 0;
3289 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3290 printer->major_version = 0x0004; /* NT 4 */
3291 printer->build_version = 0x0565; /* build 1381 */
3292 #else
3293 printer->major_version = 0x0005; /* NT 5 */
3294 printer->build_version = 0x0893; /* build 2195 */
3295 #endif
3296 printer->unknown7 = 0x1;
3297 printer->unknown8 = 0x0;
3298 printer->unknown9 = 0x0;
3299 printer->session_counter = session_counter->counter;
3300 printer->unknown11 = 0x0;
3301 printer->printer_errors = 0x0; /* number of print failure */
3302 printer->unknown13 = 0x0;
3303 printer->unknown14 = 0x1;
3304 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3305 printer->unknown16 = 0x0;
3306 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3307 printer->unknown18 = 0x0;
3308 printer->status = nt_printq_status(status.status);
3309 printer->unknown20 = 0x0;
3310 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3311 printer->unknown22 = 0x0;
3312 printer->unknown23 = 0x6; /* 6 ???*/
3313 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3314 printer->unknown25 = 0;
3315 printer->unknown26 = 0;
3316 printer->unknown27 = 0;
3317 printer->unknown28 = 0;
3318 printer->unknown29 = 0;
3320 free_a_printer(&ntprinter,2);
3321 return (True);
3324 /********************************************************************
3325 * construct_printer_info_1
3326 * fill a printer_info_1 struct
3327 ********************************************************************/
3328 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3330 pstring chaine;
3331 pstring chaine2;
3332 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3334 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3335 return False;
3337 printer->flags=flags;
3339 if (*ntprinter->info_2->comment == '\0') {
3340 init_unistr(&printer->comment, lp_comment(snum));
3341 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3342 ntprinter->info_2->drivername, lp_comment(snum));
3344 else {
3345 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3346 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3347 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3350 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3352 init_unistr(&printer->description, chaine);
3353 init_unistr(&printer->name, chaine2);
3355 free_a_printer(&ntprinter,2);
3357 return True;
3360 /****************************************************************************
3361 Free a DEVMODE struct.
3362 ****************************************************************************/
3364 static void free_dev_mode(DEVICEMODE *dev)
3366 if (dev == NULL)
3367 return;
3369 SAFE_FREE(dev->private);
3370 SAFE_FREE(dev);
3373 /****************************************************************************
3374 Create a DEVMODE struct. Returns malloced memory.
3375 ****************************************************************************/
3377 static DEVICEMODE *construct_dev_mode(int snum)
3379 char adevice[32];
3380 char aform[32];
3381 NT_PRINTER_INFO_LEVEL *printer = NULL;
3382 NT_DEVICEMODE *ntdevmode = NULL;
3383 DEVICEMODE *devmode = NULL;
3385 DEBUG(7,("construct_dev_mode\n"));
3387 DEBUGADD(8,("getting printer characteristics\n"));
3389 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3390 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3391 return NULL;
3394 ZERO_STRUCTP(devmode);
3396 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3397 goto fail;
3399 if (printer->info_2->devmode)
3400 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3402 if (ntdevmode == NULL) {
3403 DEBUG(5, ("BONG! There was no device mode!\n"));
3404 goto fail;
3407 DEBUGADD(8,("loading DEVICEMODE\n"));
3409 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3410 init_unistr(&devmode->devicename, adevice);
3412 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3413 init_unistr(&devmode->formname, aform);
3415 devmode->specversion = ntdevmode->specversion;
3416 devmode->driverversion = ntdevmode->driverversion;
3417 devmode->size = ntdevmode->size;
3418 devmode->driverextra = ntdevmode->driverextra;
3419 devmode->fields = ntdevmode->fields;
3421 devmode->orientation = ntdevmode->orientation;
3422 devmode->papersize = ntdevmode->papersize;
3423 devmode->paperlength = ntdevmode->paperlength;
3424 devmode->paperwidth = ntdevmode->paperwidth;
3425 devmode->scale = ntdevmode->scale;
3426 devmode->copies = ntdevmode->copies;
3427 devmode->defaultsource = ntdevmode->defaultsource;
3428 devmode->printquality = ntdevmode->printquality;
3429 devmode->color = ntdevmode->color;
3430 devmode->duplex = ntdevmode->duplex;
3431 devmode->yresolution = ntdevmode->yresolution;
3432 devmode->ttoption = ntdevmode->ttoption;
3433 devmode->collate = ntdevmode->collate;
3434 devmode->icmmethod = ntdevmode->icmmethod;
3435 devmode->icmintent = ntdevmode->icmintent;
3436 devmode->mediatype = ntdevmode->mediatype;
3437 devmode->dithertype = ntdevmode->dithertype;
3439 if (ntdevmode->private != NULL) {
3440 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3441 goto fail;
3444 free_nt_devicemode(&ntdevmode);
3445 free_a_printer(&printer,2);
3447 return devmode;
3449 fail:
3451 if (ntdevmode)
3452 free_nt_devicemode(&ntdevmode);
3453 if (printer)
3454 free_a_printer(&printer,2);
3455 free_dev_mode(devmode);
3457 return NULL;
3460 /********************************************************************
3461 * construct_printer_info_2
3462 * fill a printer_info_2 struct
3463 ********************************************************************/
3465 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3467 int count;
3468 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3470 print_status_struct status;
3472 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3473 return False;
3475 count = print_queue_length(snum, &status);
3477 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3478 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3479 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3480 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3481 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3483 if (*ntprinter->info_2->comment == '\0')
3484 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3485 else
3486 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3488 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3489 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3490 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3491 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3492 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3494 printer->attributes = ntprinter->info_2->attributes;
3496 printer->priority = ntprinter->info_2->priority; /* priority */
3497 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3498 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3499 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3500 printer->status = nt_printq_status(status.status); /* status */
3501 printer->cjobs = count; /* jobs */
3502 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3504 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3505 DEBUG(8, ("Returning NULL Devicemode!\n"));
3508 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3509 /* steal the printer info sec_desc structure. [badly done]. */
3510 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3511 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3512 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3513 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3515 else {
3516 printer->secdesc = NULL;
3519 free_a_printer(&ntprinter, 2);
3520 return True;
3523 /********************************************************************
3524 * construct_printer_info_3
3525 * fill a printer_info_3 struct
3526 ********************************************************************/
3528 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3530 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3531 PRINTER_INFO_3 *printer = NULL;
3533 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3534 return False;
3536 *pp_printer = NULL;
3537 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3538 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3539 return False;
3542 ZERO_STRUCTP(printer);
3544 printer->flags = 4; /* These are the components of the SD we are returning. */
3545 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3546 /* steal the printer info sec_desc structure. [badly done]. */
3547 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3549 #if 0
3551 * Set the flags for the components we are returning.
3554 if (printer->secdesc->owner_sid)
3555 printer->flags |= OWNER_SECURITY_INFORMATION;
3557 if (printer->secdesc->grp_sid)
3558 printer->flags |= GROUP_SECURITY_INFORMATION;
3560 if (printer->secdesc->dacl)
3561 printer->flags |= DACL_SECURITY_INFORMATION;
3563 if (printer->secdesc->sacl)
3564 printer->flags |= SACL_SECURITY_INFORMATION;
3565 #endif
3567 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3568 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3569 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3572 free_a_printer(&ntprinter, 2);
3574 *pp_printer = printer;
3575 return True;
3578 /********************************************************************
3579 * construct_printer_info_4
3580 * fill a printer_info_4 struct
3581 ********************************************************************/
3583 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3585 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3587 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3588 return False;
3590 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3591 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3592 printer->attributes = ntprinter->info_2->attributes;
3594 free_a_printer(&ntprinter, 2);
3595 return True;
3598 /********************************************************************
3599 * construct_printer_info_5
3600 * fill a printer_info_5 struct
3601 ********************************************************************/
3603 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3605 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3607 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3608 return False;
3610 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3611 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3612 printer->attributes = ntprinter->info_2->attributes;
3613 printer->device_not_selected_timeout = 0x3a98;
3614 printer->transmission_retry_timeout = 0xafc8;
3616 free_a_printer(&ntprinter, 2);
3617 return True;
3620 /********************************************************************
3621 Spoolss_enumprinters.
3622 ********************************************************************/
3624 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3626 int snum;
3627 int i;
3628 int n_services=lp_numservices();
3629 PRINTER_INFO_1 *tp, *printers=NULL;
3630 PRINTER_INFO_1 current_prt;
3632 DEBUG(4,("enum_all_printers_info_1\n"));
3634 for (snum=0; snum<n_services; snum++) {
3635 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3636 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3638 if (construct_printer_info_1(flags, &current_prt, snum)) {
3639 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3640 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3641 SAFE_FREE(printers);
3642 *returned=0;
3643 return WERR_NOMEM;
3645 else printers = tp;
3646 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3648 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
3649 (*returned)++;
3654 /* check the required size. */
3655 for (i=0; i<*returned; i++)
3656 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3658 if (!alloc_buffer_size(buffer, *needed))
3659 return WERR_INSUFFICIENT_BUFFER;
3661 /* fill the buffer with the structures */
3662 for (i=0; i<*returned; i++)
3663 smb_io_printer_info_1("", buffer, &printers[i], 0);
3665 /* clear memory */
3666 SAFE_FREE(printers);
3668 if (*needed > offered) {
3669 *returned=0;
3670 return WERR_INSUFFICIENT_BUFFER;
3672 else
3673 return WERR_OK;
3676 /********************************************************************
3677 enum_all_printers_info_1_local.
3678 *********************************************************************/
3680 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3682 DEBUG(4,("enum_all_printers_info_1_local\n"));
3684 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3687 /********************************************************************
3688 enum_all_printers_info_1_name.
3689 *********************************************************************/
3691 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3693 char *s = name;
3695 DEBUG(4,("enum_all_printers_info_1_name\n"));
3697 if ((name[0] == '\\') && (name[1] == '\\'))
3698 s = name + 2;
3700 if (is_myname_or_ipaddr(s)) {
3701 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3703 else
3704 return WERR_INVALID_NAME;
3707 /********************************************************************
3708 enum_all_printers_info_1_remote.
3709 *********************************************************************/
3711 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3713 PRINTER_INFO_1 *printer;
3714 fstring printername;
3715 fstring desc;
3716 fstring comment;
3717 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3719 /* JFM: currently it's more a place holder than anything else.
3720 * In the spooler world there is a notion of server registration.
3721 * the print servers are registring (sp ?) on the PDC (in the same domain)
3723 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3726 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3727 return WERR_NOMEM;
3729 *returned=1;
3731 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3732 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3733 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3735 init_unistr(&printer->description, desc);
3736 init_unistr(&printer->name, printername);
3737 init_unistr(&printer->comment, comment);
3738 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3740 /* check the required size. */
3741 *needed += spoolss_size_printer_info_1(printer);
3743 if (!alloc_buffer_size(buffer, *needed)) {
3744 SAFE_FREE(printer);
3745 return WERR_INSUFFICIENT_BUFFER;
3748 /* fill the buffer with the structures */
3749 smb_io_printer_info_1("", buffer, printer, 0);
3751 /* clear memory */
3752 SAFE_FREE(printer);
3754 if (*needed > offered) {
3755 *returned=0;
3756 return WERR_INSUFFICIENT_BUFFER;
3758 else
3759 return WERR_OK;
3762 /********************************************************************
3763 enum_all_printers_info_1_network.
3764 *********************************************************************/
3766 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3768 char *s = name;
3770 DEBUG(4,("enum_all_printers_info_1_network\n"));
3772 /* If we respond to a enum_printers level 1 on our name with flags
3773 set to PRINTER_ENUM_REMOTE with a list of printers then these
3774 printers incorrectly appear in the APW browse list.
3775 Specifically the printers for the server appear at the workgroup
3776 level where all the other servers in the domain are
3777 listed. Windows responds to this call with a
3778 WERR_CAN_NOT_COMPLETE so we should do the same. */
3780 if (name[0] == '\\' && name[1] == '\\')
3781 s = name + 2;
3783 if (is_myname_or_ipaddr(s))
3784 return WERR_CAN_NOT_COMPLETE;
3786 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3789 /********************************************************************
3790 * api_spoolss_enumprinters
3792 * called from api_spoolss_enumprinters (see this to understand)
3793 ********************************************************************/
3795 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3797 int snum;
3798 int i;
3799 int n_services=lp_numservices();
3800 PRINTER_INFO_2 *tp, *printers=NULL;
3801 PRINTER_INFO_2 current_prt;
3803 for (snum=0; snum<n_services; snum++) {
3804 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3805 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3807 if (construct_printer_info_2(&current_prt, snum)) {
3808 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3809 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3810 SAFE_FREE(printers);
3811 *returned = 0;
3812 return WERR_NOMEM;
3814 else printers = tp;
3815 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3816 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3817 (*returned)++;
3822 /* check the required size. */
3823 for (i=0; i<*returned; i++)
3824 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3826 if (!alloc_buffer_size(buffer, *needed)) {
3827 for (i=0; i<*returned; i++) {
3828 free_devmode(printers[i].devmode);
3830 SAFE_FREE(printers);
3831 return WERR_INSUFFICIENT_BUFFER;
3834 /* fill the buffer with the structures */
3835 for (i=0; i<*returned; i++)
3836 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3838 /* clear memory */
3839 for (i=0; i<*returned; i++) {
3840 free_devmode(printers[i].devmode);
3842 SAFE_FREE(printers);
3844 if (*needed > offered) {
3845 *returned=0;
3846 return WERR_INSUFFICIENT_BUFFER;
3848 else
3849 return WERR_OK;
3852 /********************************************************************
3853 * handle enumeration of printers at level 1
3854 ********************************************************************/
3856 static WERROR enumprinters_level1( uint32 flags, fstring name,
3857 NEW_BUFFER *buffer, uint32 offered,
3858 uint32 *needed, uint32 *returned)
3860 /* Not all the flags are equals */
3862 if (flags & PRINTER_ENUM_LOCAL)
3863 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3865 if (flags & PRINTER_ENUM_NAME)
3866 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3868 if (flags & PRINTER_ENUM_REMOTE)
3869 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3871 if (flags & PRINTER_ENUM_NETWORK)
3872 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
3874 return WERR_OK; /* NT4sp5 does that */
3877 /********************************************************************
3878 * handle enumeration of printers at level 2
3879 ********************************************************************/
3881 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3882 NEW_BUFFER *buffer, uint32 offered,
3883 uint32 *needed, uint32 *returned)
3885 char *s = servername;
3887 if (flags & PRINTER_ENUM_LOCAL) {
3888 return enum_all_printers_info_2(buffer, offered, needed, returned);
3891 if (flags & PRINTER_ENUM_NAME) {
3892 if ((servername[0] == '\\') && (servername[1] == '\\'))
3893 s = servername + 2;
3894 if (is_myname_or_ipaddr(s))
3895 return enum_all_printers_info_2(buffer, offered, needed, returned);
3896 else
3897 return WERR_INVALID_NAME;
3900 if (flags & PRINTER_ENUM_REMOTE)
3901 return WERR_UNKNOWN_LEVEL;
3903 return WERR_OK;
3906 /********************************************************************
3907 * handle enumeration of printers at level 5
3908 ********************************************************************/
3910 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3911 NEW_BUFFER *buffer, uint32 offered,
3912 uint32 *needed, uint32 *returned)
3914 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3915 return WERR_OK;
3918 /********************************************************************
3919 * api_spoolss_enumprinters
3921 * called from api_spoolss_enumprinters (see this to understand)
3922 ********************************************************************/
3924 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3926 uint32 flags = q_u->flags;
3927 UNISTR2 *servername = &q_u->servername;
3928 uint32 level = q_u->level;
3929 NEW_BUFFER *buffer = NULL;
3930 uint32 offered = q_u->offered;
3931 uint32 *needed = &r_u->needed;
3932 uint32 *returned = &r_u->returned;
3934 fstring name;
3936 /* that's an [in out] buffer */
3937 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3938 buffer = r_u->buffer;
3940 DEBUG(4,("_spoolss_enumprinters\n"));
3942 *needed=0;
3943 *returned=0;
3946 * Level 1:
3947 * flags==PRINTER_ENUM_NAME
3948 * if name=="" then enumerates all printers
3949 * if name!="" then enumerate the printer
3950 * flags==PRINTER_ENUM_REMOTE
3951 * name is NULL, enumerate printers
3952 * Level 2: name!="" enumerates printers, name can't be NULL
3953 * Level 3: doesn't exist
3954 * Level 4: does a local registry lookup
3955 * Level 5: same as Level 2
3958 unistr2_to_ascii(name, servername, sizeof(name)-1);
3959 strupper(name);
3961 switch (level) {
3962 case 1:
3963 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3964 case 2:
3965 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3966 case 5:
3967 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3968 case 3:
3969 case 4:
3970 break;
3972 return WERR_UNKNOWN_LEVEL;
3975 /****************************************************************************
3976 ****************************************************************************/
3978 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3980 PRINTER_INFO_0 *printer=NULL;
3982 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3983 return WERR_NOMEM;
3985 construct_printer_info_0(printer, snum);
3987 /* check the required size. */
3988 *needed += spoolss_size_printer_info_0(printer);
3990 if (!alloc_buffer_size(buffer, *needed)) {
3991 SAFE_FREE(printer);
3992 return WERR_INSUFFICIENT_BUFFER;
3995 /* fill the buffer with the structures */
3996 smb_io_printer_info_0("", buffer, printer, 0);
3998 /* clear memory */
3999 SAFE_FREE(printer);
4001 if (*needed > offered) {
4002 return WERR_INSUFFICIENT_BUFFER;
4005 return WERR_OK;
4008 /****************************************************************************
4009 ****************************************************************************/
4011 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4013 PRINTER_INFO_1 *printer=NULL;
4015 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4016 return WERR_NOMEM;
4018 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4020 /* check the required size. */
4021 *needed += spoolss_size_printer_info_1(printer);
4023 if (!alloc_buffer_size(buffer, *needed)) {
4024 SAFE_FREE(printer);
4025 return WERR_INSUFFICIENT_BUFFER;
4028 /* fill the buffer with the structures */
4029 smb_io_printer_info_1("", buffer, printer, 0);
4031 /* clear memory */
4032 SAFE_FREE(printer);
4034 if (*needed > offered) {
4035 return WERR_INSUFFICIENT_BUFFER;
4038 return WERR_OK;
4041 /****************************************************************************
4042 ****************************************************************************/
4044 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4046 PRINTER_INFO_2 *printer=NULL;
4048 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4049 return WERR_NOMEM;
4051 construct_printer_info_2(printer, snum);
4053 /* check the required size. */
4054 *needed += spoolss_size_printer_info_2(printer);
4056 if (!alloc_buffer_size(buffer, *needed)) {
4057 free_printer_info_2(printer);
4058 return WERR_INSUFFICIENT_BUFFER;
4061 /* fill the buffer with the structures */
4062 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4063 free_printer_info_2(printer);
4064 return WERR_NOMEM;
4067 /* clear memory */
4068 free_printer_info_2(printer);
4070 if (*needed > offered) {
4071 return WERR_INSUFFICIENT_BUFFER;
4074 return WERR_OK;
4077 /****************************************************************************
4078 ****************************************************************************/
4080 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4082 PRINTER_INFO_3 *printer=NULL;
4084 if (!construct_printer_info_3(&printer, snum))
4085 return WERR_NOMEM;
4087 /* check the required size. */
4088 *needed += spoolss_size_printer_info_3(printer);
4090 if (!alloc_buffer_size(buffer, *needed)) {
4091 free_printer_info_3(printer);
4092 return WERR_INSUFFICIENT_BUFFER;
4095 /* fill the buffer with the structures */
4096 smb_io_printer_info_3("", buffer, printer, 0);
4098 /* clear memory */
4099 free_printer_info_3(printer);
4101 if (*needed > offered) {
4102 return WERR_INSUFFICIENT_BUFFER;
4105 return WERR_OK;
4108 /****************************************************************************
4109 ****************************************************************************/
4111 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4113 PRINTER_INFO_4 *printer=NULL;
4115 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4116 return WERR_NOMEM;
4118 if (!construct_printer_info_4(printer, snum))
4119 return WERR_NOMEM;
4121 /* check the required size. */
4122 *needed += spoolss_size_printer_info_4(printer);
4124 if (!alloc_buffer_size(buffer, *needed)) {
4125 free_printer_info_4(printer);
4126 return WERR_INSUFFICIENT_BUFFER;
4129 /* fill the buffer with the structures */
4130 smb_io_printer_info_4("", buffer, printer, 0);
4132 /* clear memory */
4133 free_printer_info_4(printer);
4135 if (*needed > offered) {
4136 return WERR_INSUFFICIENT_BUFFER;
4139 return WERR_OK;
4142 /****************************************************************************
4143 ****************************************************************************/
4145 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4147 PRINTER_INFO_5 *printer=NULL;
4149 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4150 return WERR_NOMEM;
4152 if (!construct_printer_info_5(printer, snum))
4153 return WERR_NOMEM;
4155 /* check the required size. */
4156 *needed += spoolss_size_printer_info_5(printer);
4158 if (!alloc_buffer_size(buffer, *needed)) {
4159 free_printer_info_5(printer);
4160 return WERR_INSUFFICIENT_BUFFER;
4163 /* fill the buffer with the structures */
4164 smb_io_printer_info_5("", buffer, printer, 0);
4166 /* clear memory */
4167 free_printer_info_5(printer);
4169 if (*needed > offered) {
4170 return WERR_INSUFFICIENT_BUFFER;
4173 return WERR_OK;
4176 /****************************************************************************
4177 ****************************************************************************/
4179 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4181 POLICY_HND *handle = &q_u->handle;
4182 uint32 level = q_u->level;
4183 NEW_BUFFER *buffer = NULL;
4184 uint32 offered = q_u->offered;
4185 uint32 *needed = &r_u->needed;
4187 int snum;
4189 /* that's an [in out] buffer */
4190 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4191 buffer = r_u->buffer;
4193 *needed=0;
4195 if (!get_printer_snum(p, handle, &snum))
4196 return WERR_BADFID;
4198 switch (level) {
4199 case 0:
4200 return getprinter_level_0(snum, buffer, offered, needed);
4201 case 1:
4202 return getprinter_level_1(snum, buffer, offered, needed);
4203 case 2:
4204 return getprinter_level_2(snum, buffer, offered, needed);
4205 case 3:
4206 return getprinter_level_3(snum, buffer, offered, needed);
4207 case 4:
4208 return getprinter_level_4(snum, buffer, offered, needed);
4209 case 5:
4210 return getprinter_level_5(snum, buffer, offered, needed);
4212 return WERR_UNKNOWN_LEVEL;
4215 /********************************************************************
4216 * fill a DRIVER_INFO_1 struct
4217 ********************************************************************/
4219 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4221 init_unistr( &info->name, driver.info_3->name);
4224 /********************************************************************
4225 * construct_printer_driver_info_1
4226 ********************************************************************/
4228 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4230 NT_PRINTER_INFO_LEVEL *printer = NULL;
4231 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4233 ZERO_STRUCT(driver);
4235 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4236 return WERR_INVALID_PRINTER_NAME;
4238 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4239 return WERR_UNKNOWN_PRINTER_DRIVER;
4241 fill_printer_driver_info_1(info, driver, servername, architecture);
4243 free_a_printer(&printer,2);
4245 return WERR_OK;
4248 /********************************************************************
4249 * construct_printer_driver_info_2
4250 * fill a printer_info_2 struct
4251 ********************************************************************/
4253 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4255 pstring temp;
4257 info->version=driver.info_3->cversion;
4259 init_unistr( &info->name, driver.info_3->name );
4260 init_unistr( &info->architecture, driver.info_3->environment );
4263 if (strlen(driver.info_3->driverpath)) {
4264 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4265 init_unistr( &info->driverpath, temp );
4266 } else
4267 init_unistr( &info->driverpath, "" );
4269 if (strlen(driver.info_3->datafile)) {
4270 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4271 init_unistr( &info->datafile, temp );
4272 } else
4273 init_unistr( &info->datafile, "" );
4275 if (strlen(driver.info_3->configfile)) {
4276 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4277 init_unistr( &info->configfile, temp );
4278 } else
4279 init_unistr( &info->configfile, "" );
4282 /********************************************************************
4283 * construct_printer_driver_info_2
4284 * fill a printer_info_2 struct
4285 ********************************************************************/
4287 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4289 NT_PRINTER_INFO_LEVEL *printer = NULL;
4290 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4292 ZERO_STRUCT(printer);
4293 ZERO_STRUCT(driver);
4295 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4296 return WERR_INVALID_PRINTER_NAME;
4298 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4299 return WERR_UNKNOWN_PRINTER_DRIVER;
4301 fill_printer_driver_info_2(info, driver, servername);
4303 free_a_printer(&printer,2);
4305 return WERR_OK;
4308 /********************************************************************
4309 * copy a strings array and convert to UNICODE
4311 * convert an array of ascii string to a UNICODE string
4312 ********************************************************************/
4314 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4316 int i=0;
4317 int j=0;
4318 char *v;
4319 pstring line;
4320 uint16 *tuary;
4322 DEBUG(6,("init_unistr_array\n"));
4323 *uni_array=NULL;
4325 while (1) {
4326 if (char_array == NULL)
4327 v = "";
4328 else {
4329 v = char_array[i];
4330 if (!v) v = ""; /* hack to handle null lists */
4332 if (strlen(v) == 0) break;
4333 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
4334 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4335 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
4336 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4337 return;
4338 } else
4339 *uni_array = tuary;
4340 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
4341 i++;
4344 if (*uni_array) {
4345 (*uni_array)[j]=0x0000;
4348 DEBUGADD(6,("last one:done\n"));
4351 /********************************************************************
4352 * construct_printer_info_3
4353 * fill a printer_info_3 struct
4354 ********************************************************************/
4356 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4358 pstring temp;
4360 ZERO_STRUCTP(info);
4362 info->version=driver.info_3->cversion;
4364 init_unistr( &info->name, driver.info_3->name );
4365 init_unistr( &info->architecture, driver.info_3->environment );
4367 if (strlen(driver.info_3->driverpath)) {
4368 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4369 init_unistr( &info->driverpath, temp );
4370 } else
4371 init_unistr( &info->driverpath, "" );
4373 if (strlen(driver.info_3->datafile)) {
4374 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4375 init_unistr( &info->datafile, temp );
4376 } else
4377 init_unistr( &info->datafile, "" );
4379 if (strlen(driver.info_3->configfile)) {
4380 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4381 init_unistr( &info->configfile, temp );
4382 } else
4383 init_unistr( &info->configfile, "" );
4385 if (strlen(driver.info_3->helpfile)) {
4386 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4387 init_unistr( &info->helpfile, temp );
4388 } else
4389 init_unistr( &info->helpfile, "" );
4391 init_unistr( &info->monitorname, driver.info_3->monitorname );
4392 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4394 info->dependentfiles=NULL;
4395 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4398 /********************************************************************
4399 * construct_printer_info_3
4400 * fill a printer_info_3 struct
4401 ********************************************************************/
4403 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4405 NT_PRINTER_INFO_LEVEL *printer = NULL;
4406 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4407 WERROR status;
4408 ZERO_STRUCT(driver);
4410 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4411 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4412 if (!W_ERROR_IS_OK(status))
4413 return WERR_INVALID_PRINTER_NAME;
4415 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4416 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4418 #if 0 /* JERRY */
4421 * I put this code in during testing. Helpful when commenting out the
4422 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4423 * as win2k always queries the driver using an infor level of 6.
4424 * I've left it in (but ifdef'd out) because I'll probably
4425 * use it in experimentation again in the future. --jerry 22/01/2002
4428 if (!W_ERROR_IS_OK(status)) {
4430 * Is this a W2k client ?
4432 if (version == 3) {
4433 /* Yes - try again with a WinNT driver. */
4434 version = 2;
4435 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4436 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4438 #endif
4440 if (!W_ERROR_IS_OK(status)) {
4441 free_a_printer(&printer,2);
4442 return WERR_UNKNOWN_PRINTER_DRIVER;
4445 #if 0 /* JERRY */
4447 #endif
4450 fill_printer_driver_info_3(info, driver, servername);
4452 free_a_printer(&printer,2);
4454 return WERR_OK;
4457 /********************************************************************
4458 * construct_printer_info_6
4459 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4460 ********************************************************************/
4462 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4464 pstring temp;
4465 fstring nullstr;
4467 ZERO_STRUCTP(info);
4468 memset(&nullstr, '\0', sizeof(fstring));
4470 info->version=driver.info_3->cversion;
4472 init_unistr( &info->name, driver.info_3->name );
4473 init_unistr( &info->architecture, driver.info_3->environment );
4475 if (strlen(driver.info_3->driverpath)) {
4476 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4477 init_unistr( &info->driverpath, temp );
4478 } else
4479 init_unistr( &info->driverpath, "" );
4481 if (strlen(driver.info_3->datafile)) {
4482 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4483 init_unistr( &info->datafile, temp );
4484 } else
4485 init_unistr( &info->datafile, "" );
4487 if (strlen(driver.info_3->configfile)) {
4488 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4489 init_unistr( &info->configfile, temp );
4490 } else
4491 init_unistr( &info->configfile, "" );
4493 if (strlen(driver.info_3->helpfile)) {
4494 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4495 init_unistr( &info->helpfile, temp );
4496 } else
4497 init_unistr( &info->helpfile, "" );
4499 init_unistr( &info->monitorname, driver.info_3->monitorname );
4500 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4502 info->dependentfiles=NULL;
4503 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4505 info->previousdrivernames=NULL;
4506 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4508 info->driver_date.low=0;
4509 info->driver_date.high=0;
4511 info->padding=0;
4512 info->driver_version_low=0;
4513 info->driver_version_high=0;
4515 init_unistr( &info->mfgname, "");
4516 init_unistr( &info->oem_url, "");
4517 init_unistr( &info->hardware_id, "");
4518 init_unistr( &info->provider, "");
4521 /********************************************************************
4522 * construct_printer_info_6
4523 * fill a printer_info_6 struct
4524 ********************************************************************/
4526 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4528 NT_PRINTER_INFO_LEVEL *printer = NULL;
4529 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4530 WERROR status;
4531 ZERO_STRUCT(driver);
4533 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4534 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4535 if (!W_ERROR_IS_OK(status))
4536 return WERR_INVALID_PRINTER_NAME;
4538 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4539 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4540 if (!W_ERROR_IS_OK(status)) {
4542 * Is this a W2k client ?
4545 if (version < 3) {
4546 free_a_printer(&printer,2);
4547 return WERR_UNKNOWN_PRINTER_DRIVER;
4550 /* Yes - try again with a WinNT driver. */
4551 version = 2;
4552 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4553 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4554 if (!W_ERROR_IS_OK(status)) {
4555 free_a_printer(&printer,2);
4556 return WERR_UNKNOWN_PRINTER_DRIVER;
4560 fill_printer_driver_info_6(info, driver, servername);
4562 free_a_printer(&printer,2);
4564 return WERR_OK;
4567 /****************************************************************************
4568 ****************************************************************************/
4570 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4572 SAFE_FREE(info->dependentfiles);
4575 /****************************************************************************
4576 ****************************************************************************/
4578 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4580 SAFE_FREE(info->dependentfiles);
4584 /****************************************************************************
4585 ****************************************************************************/
4587 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4589 DRIVER_INFO_1 *info=NULL;
4590 WERROR status;
4592 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4593 return WERR_NOMEM;
4595 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4596 if (!W_ERROR_IS_OK(status)) {
4597 SAFE_FREE(info);
4598 return status;
4601 /* check the required size. */
4602 *needed += spoolss_size_printer_driver_info_1(info);
4604 if (!alloc_buffer_size(buffer, *needed)) {
4605 SAFE_FREE(info);
4606 return WERR_INSUFFICIENT_BUFFER;
4609 /* fill the buffer with the structures */
4610 smb_io_printer_driver_info_1("", buffer, info, 0);
4612 /* clear memory */
4613 SAFE_FREE(info);
4615 if (*needed > offered)
4616 return WERR_INSUFFICIENT_BUFFER;
4618 return WERR_OK;
4621 /****************************************************************************
4622 ****************************************************************************/
4624 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4626 DRIVER_INFO_2 *info=NULL;
4627 WERROR status;
4629 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4630 return WERR_NOMEM;
4632 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4633 if (!W_ERROR_IS_OK(status)) {
4634 SAFE_FREE(info);
4635 return status;
4638 /* check the required size. */
4639 *needed += spoolss_size_printer_driver_info_2(info);
4641 if (!alloc_buffer_size(buffer, *needed)) {
4642 SAFE_FREE(info);
4643 return WERR_INSUFFICIENT_BUFFER;
4646 /* fill the buffer with the structures */
4647 smb_io_printer_driver_info_2("", buffer, info, 0);
4649 /* clear memory */
4650 SAFE_FREE(info);
4652 if (*needed > offered)
4653 return WERR_INSUFFICIENT_BUFFER;
4655 return WERR_OK;
4658 /****************************************************************************
4659 ****************************************************************************/
4661 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4663 DRIVER_INFO_3 info;
4664 WERROR status;
4666 ZERO_STRUCT(info);
4668 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4669 if (!W_ERROR_IS_OK(status)) {
4670 return status;
4673 /* check the required size. */
4674 *needed += spoolss_size_printer_driver_info_3(&info);
4676 if (!alloc_buffer_size(buffer, *needed)) {
4677 free_printer_driver_info_3(&info);
4678 return WERR_INSUFFICIENT_BUFFER;
4681 /* fill the buffer with the structures */
4682 smb_io_printer_driver_info_3("", buffer, &info, 0);
4684 free_printer_driver_info_3(&info);
4686 if (*needed > offered)
4687 return WERR_INSUFFICIENT_BUFFER;
4689 return WERR_OK;
4692 /****************************************************************************
4693 ****************************************************************************/
4695 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4697 DRIVER_INFO_6 info;
4698 WERROR status;
4700 ZERO_STRUCT(info);
4702 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4703 if (!W_ERROR_IS_OK(status)) {
4704 return status;
4707 /* check the required size. */
4708 *needed += spoolss_size_printer_driver_info_6(&info);
4710 if (!alloc_buffer_size(buffer, *needed)) {
4711 free_printer_driver_info_6(&info);
4712 return WERR_INSUFFICIENT_BUFFER;
4715 /* fill the buffer with the structures */
4716 smb_io_printer_driver_info_6("", buffer, &info, 0);
4718 free_printer_driver_info_6(&info);
4720 if (*needed > offered)
4721 return WERR_INSUFFICIENT_BUFFER;
4723 return WERR_OK;
4726 /****************************************************************************
4727 ****************************************************************************/
4729 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4731 POLICY_HND *handle = &q_u->handle;
4732 UNISTR2 *uni_arch = &q_u->architecture;
4733 uint32 level = q_u->level;
4734 uint32 clientmajorversion = q_u->clientmajorversion;
4735 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4736 NEW_BUFFER *buffer = NULL;
4737 uint32 offered = q_u->offered;
4738 uint32 *needed = &r_u->needed;
4739 uint32 *servermajorversion = &r_u->servermajorversion;
4740 uint32 *serverminorversion = &r_u->serverminorversion;
4742 fstring servername;
4743 fstring architecture;
4744 int snum;
4746 /* that's an [in out] buffer */
4747 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4748 buffer = r_u->buffer;
4750 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4752 *needed=0;
4753 *servermajorversion=0;
4754 *serverminorversion=0;
4756 pstrcpy(servername, get_called_name());
4757 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4759 if (!get_printer_snum(p, handle, &snum))
4760 return WERR_BADFID;
4762 switch (level) {
4763 case 1:
4764 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4765 case 2:
4766 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4767 case 3:
4768 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4769 case 6:
4770 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4773 return WERR_UNKNOWN_LEVEL;
4776 /****************************************************************************
4777 ****************************************************************************/
4779 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4781 POLICY_HND *handle = &q_u->handle;
4783 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4785 if (!Printer) {
4786 DEBUG(3,("Error in startpageprinter printer handle\n"));
4787 return WERR_BADFID;
4790 Printer->page_started=True;
4791 return WERR_OK;
4794 /****************************************************************************
4795 ****************************************************************************/
4797 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4799 POLICY_HND *handle = &q_u->handle;
4800 int snum;
4802 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4804 if (!Printer) {
4805 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4806 return WERR_BADFID;
4809 if (!get_printer_snum(p, handle, &snum))
4810 return WERR_BADFID;
4812 Printer->page_started=False;
4813 print_job_endpage(snum, Printer->jobid);
4815 return WERR_OK;
4818 /********************************************************************
4819 * api_spoolss_getprinter
4820 * called from the spoolss dispatcher
4822 ********************************************************************/
4824 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4826 POLICY_HND *handle = &q_u->handle;
4827 /* uint32 level = q_u->doc_info_container.level; - notused. */
4828 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4829 uint32 *jobid = &r_u->jobid;
4830 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4831 int snum;
4832 pstring jobname;
4833 fstring datatype;
4834 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4835 struct current_user user;
4837 if (!Printer) {
4838 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4839 return WERR_BADFID;
4842 get_current_user(&user, p);
4845 * a nice thing with NT is it doesn't listen to what you tell it.
4846 * when asked to send _only_ RAW datas, it tries to send datas
4847 * in EMF format.
4849 * So I add checks like in NT Server ...
4851 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4852 * there's a bug in NT client-side code, so we'll fix it in the
4853 * server-side code. *nnnnnggggh!*
4856 if (info_1->p_datatype != 0) {
4857 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4858 if (strcmp(datatype, "RAW") != 0) {
4859 (*jobid)=0;
4860 return WERR_INVALID_DATATYPE;
4864 /* get the share number of the printer */
4865 if (!get_printer_snum(p, handle, &snum)) {
4866 return WERR_BADFID;
4869 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4871 Printer->jobid = print_job_start(&user, snum, jobname);
4873 /* An error occured in print_job_start() so return an appropriate
4874 NT error code. */
4876 if (Printer->jobid == -1) {
4877 return map_werror_from_unix(errno);
4880 Printer->document_started=True;
4881 (*jobid) = Printer->jobid;
4883 return WERR_OK;
4886 /********************************************************************
4887 * api_spoolss_getprinter
4888 * called from the spoolss dispatcher
4890 ********************************************************************/
4892 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4894 POLICY_HND *handle = &q_u->handle;
4896 return _spoolss_enddocprinter_internal(p, handle);
4899 /****************************************************************************
4900 ****************************************************************************/
4902 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4904 POLICY_HND *handle = &q_u->handle;
4905 uint32 buffer_size = q_u->buffer_size;
4906 uint8 *buffer = q_u->buffer;
4907 uint32 *buffer_written = &q_u->buffer_size2;
4908 int snum;
4909 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4911 if (!Printer) {
4912 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4913 r_u->buffer_written = q_u->buffer_size2;
4914 return WERR_BADFID;
4917 if (!get_printer_snum(p, handle, &snum))
4918 return WERR_BADFID;
4920 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
4922 r_u->buffer_written = q_u->buffer_size2;
4924 return WERR_OK;
4927 /********************************************************************
4928 * api_spoolss_getprinter
4929 * called from the spoolss dispatcher
4931 ********************************************************************/
4933 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4934 pipes_struct *p)
4936 struct current_user user;
4937 int snum;
4938 WERROR errcode = WERR_BADFUNC;
4939 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4941 get_current_user(&user, p);
4943 if (!Printer) {
4944 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4945 return WERR_BADFID;
4948 if (!get_printer_snum(p, handle, &snum))
4949 return WERR_BADFID;
4951 switch (command) {
4952 case PRINTER_CONTROL_PAUSE:
4953 if (print_queue_pause(&user, snum, &errcode)) {
4954 errcode = WERR_OK;
4956 break;
4957 case PRINTER_CONTROL_RESUME:
4958 case PRINTER_CONTROL_UNPAUSE:
4959 if (print_queue_resume(&user, snum, &errcode)) {
4960 errcode = WERR_OK;
4962 break;
4963 case PRINTER_CONTROL_PURGE:
4964 if (print_queue_purge(&user, snum, &errcode)) {
4965 errcode = WERR_OK;
4967 break;
4968 default:
4969 return WERR_UNKNOWN_LEVEL;
4972 return errcode;
4975 /********************************************************************
4976 * api_spoolss_abortprinter
4977 ********************************************************************/
4979 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4981 POLICY_HND *handle = &q_u->handle;
4983 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4986 /********************************************************************
4987 * called by spoolss_api_setprinter
4988 * when updating a printer description
4989 ********************************************************************/
4991 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4992 const SPOOL_PRINTER_INFO_LEVEL *info,
4993 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4995 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4996 struct current_user user;
4997 WERROR result;
4998 int snum;
5000 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5002 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5003 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5004 OUR_HANDLE(handle)));
5006 result = WERR_BADFID;
5007 goto done;
5010 /* NT seems to like setting the security descriptor even though
5011 nothing may have actually changed. This causes annoying
5012 dialog boxes when the user doesn't have permission to change
5013 the security descriptor. */
5015 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5017 if (DEBUGLEVEL >= 10) {
5018 SEC_ACL *the_acl;
5019 int i;
5021 the_acl = old_secdesc_ctr->sec->dacl;
5022 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5023 PRINTERNAME(snum), the_acl->num_aces));
5025 for (i = 0; i < the_acl->num_aces; i++) {
5026 fstring sid_str;
5028 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5030 DEBUG(10, ("%s 0x%08x\n", sid_str,
5031 the_acl->ace[i].info.mask));
5034 the_acl = secdesc_ctr->sec->dacl;
5036 if (the_acl) {
5037 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5038 PRINTERNAME(snum), the_acl->num_aces));
5040 for (i = 0; i < the_acl->num_aces; i++) {
5041 fstring sid_str;
5043 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5045 DEBUG(10, ("%s 0x%08x\n", sid_str,
5046 the_acl->ace[i].info.mask));
5048 } else {
5049 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5053 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5055 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5056 result = WERR_OK;
5057 goto done;
5060 /* Work out which user is performing the operation */
5062 get_current_user(&user, p);
5064 /* Check the user has permissions to change the security
5065 descriptor. By experimentation with two NT machines, the user
5066 requires Full Access to the printer to change security
5067 information. */
5069 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5070 result = WERR_ACCESS_DENIED;
5071 goto done;
5074 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5076 done:
5078 return result;
5081 /********************************************************************
5082 Do Samba sanity checks on a printer info struct.
5083 this has changed purpose: it now "canonicalises" printer
5084 info from a client rather than just checking it is correct
5085 ********************************************************************/
5087 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5089 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5090 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5092 /* we force some elements to "correct" values */
5093 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5094 fstrcpy(info->sharename, lp_servicename(snum));
5095 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5096 get_called_name(), info->sharename);
5097 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5099 return True;
5102 /****************************************************************************
5103 ****************************************************************************/
5105 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5107 extern userdom_struct current_user_info;
5108 char *cmd = lp_addprinter_cmd();
5109 char **qlines;
5110 pstring command;
5111 pstring driverlocation;
5112 int numlines;
5113 int ret;
5114 int fd;
5115 fstring remote_machine = "%m";
5117 /* build driver path... only 9X architecture is needed for legacy reasons */
5118 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5119 get_called_name());
5120 /* change \ to \\ for the shell */
5121 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5122 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5124 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5125 cmd, printer->info_2->printername, printer->info_2->sharename,
5126 printer->info_2->portname, printer->info_2->drivername,
5127 printer->info_2->location, driverlocation, remote_machine);
5129 DEBUG(10,("Running [%s]\n", command));
5130 ret = smbrun(command, &fd);
5131 DEBUGADD(10,("returned [%d]\n", ret));
5133 if ( ret != 0 ) {
5134 if (fd != -1)
5135 close(fd);
5136 return False;
5139 numlines = 0;
5140 /* Get lines and convert them back to dos-codepage */
5141 qlines = fd_lines_load(fd, &numlines);
5142 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5143 close(fd);
5145 if(numlines) {
5146 /* Set the portname to what the script says the portname should be. */
5147 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5148 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5150 /* Send SIGHUP to process group... is there a better way? */
5151 kill(0, SIGHUP);
5152 add_all_printers();
5155 file_lines_free(qlines);
5156 return True;
5159 #if 0 /* JERRY */
5161 /* Return true if two devicemodes are equal */
5163 #define DEVMODE_CHECK_INT(field) \
5164 if (d1->field != d2->field) { \
5165 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
5166 d1->field, d2->field)); \
5167 return False; \
5170 /************************************************************************
5171 Handy, but currently unused functions
5172 ***********************************************************************/
5174 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
5176 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
5178 if (!d1 ^ !d2) {
5179 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
5180 return False; /* if either is exclusively NULL are not equal */
5183 if (!strequal(d1->devicename, d2->devicename)) {
5184 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
5185 return False;
5188 if (!strequal(d1->formname, d2->formname)) {
5189 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
5190 return False;
5193 DEVMODE_CHECK_INT(specversion);
5194 DEVMODE_CHECK_INT(driverversion);
5195 DEVMODE_CHECK_INT(driverextra);
5196 DEVMODE_CHECK_INT(orientation);
5197 DEVMODE_CHECK_INT(papersize);
5198 DEVMODE_CHECK_INT(paperlength);
5199 DEVMODE_CHECK_INT(paperwidth);
5200 DEVMODE_CHECK_INT(scale);
5201 DEVMODE_CHECK_INT(copies);
5202 DEVMODE_CHECK_INT(defaultsource);
5203 DEVMODE_CHECK_INT(printquality);
5204 DEVMODE_CHECK_INT(color);
5205 DEVMODE_CHECK_INT(duplex);
5206 DEVMODE_CHECK_INT(yresolution);
5207 DEVMODE_CHECK_INT(ttoption);
5208 DEVMODE_CHECK_INT(collate);
5209 DEVMODE_CHECK_INT(logpixels);
5211 DEVMODE_CHECK_INT(fields);
5212 DEVMODE_CHECK_INT(bitsperpel);
5213 DEVMODE_CHECK_INT(pelswidth);
5214 DEVMODE_CHECK_INT(pelsheight);
5215 DEVMODE_CHECK_INT(displayflags);
5216 DEVMODE_CHECK_INT(displayfrequency);
5217 DEVMODE_CHECK_INT(icmmethod);
5218 DEVMODE_CHECK_INT(icmintent);
5219 DEVMODE_CHECK_INT(mediatype);
5220 DEVMODE_CHECK_INT(dithertype);
5221 DEVMODE_CHECK_INT(reserved1);
5222 DEVMODE_CHECK_INT(reserved2);
5223 DEVMODE_CHECK_INT(panningwidth);
5224 DEVMODE_CHECK_INT(panningheight);
5226 /* compare the private data if it exists */
5227 if (!d1->driverextra && !d2->driverextra) goto equal;
5230 DEVMODE_CHECK_INT(driverextra);
5232 if (memcmp(d1->private, d2->private, d1->driverextra)) {
5233 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
5234 return False;
5237 equal:
5238 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
5239 return True;
5242 /* Return true if two NT_PRINTER_PARAM structures are equal */
5244 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
5245 NT_PRINTER_PARAM *p2)
5247 if (!p1 && !p2) goto equal;
5249 if ((!p1 && p2) || (p1 && !p2)) {
5250 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
5251 return False;
5254 /* Compare lists of printer parameters */
5256 while (p1) {
5257 BOOL found = False;
5258 NT_PRINTER_PARAM *q = p1;
5260 /* Find the parameter in the second structure */
5262 while(q) {
5264 if (strequal(p1->value, q->value)) {
5266 if (p1->type != q->type) {
5267 DEBUG(10, ("nt_printer_param_equal():"
5268 "types for %s differ (%d != %d)\n",
5269 p1->value, p1->type,
5270 q->type));
5271 break;
5274 if (p1->data_len != q->data_len) {
5275 DEBUG(10, ("nt_printer_param_equal():"
5276 "len for %s differs (%d != %d)\n",
5277 p1->value, p1->data_len,
5278 q->data_len));
5279 break;
5282 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
5283 found = True;
5284 } else {
5285 DEBUG(10, ("nt_printer_param_equal():"
5286 "data for %s differs\n", p1->value));
5289 break;
5292 q = q->next;
5295 if (!found) {
5296 DEBUG(10, ("nt_printer_param_equal(): param %s "
5297 "does not exist\n", p1->value));
5298 return False;
5301 p1 = p1->next;
5304 equal:
5306 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
5307 return True;
5310 /********************************************************************
5311 * Called by update_printer when trying to work out whether to
5312 * actually update printer info.
5313 ********************************************************************/
5315 #define PI_CHECK_INT(field) \
5316 if (pi1->field != pi2->field) { \
5317 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
5318 pi1->field, pi2->field)); \
5319 return False; \
5322 #define PI_CHECK_STR(field) \
5323 if (!strequal(pi1->field, pi2->field)) { \
5324 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
5325 pi1->field, pi2->field)); \
5326 return False; \
5329 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
5330 NT_PRINTER_INFO_LEVEL *p2)
5332 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
5334 /* Trivial conditions */
5336 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
5337 goto equal;
5340 if ((!p1 && p2) || (p1 && !p2) ||
5341 (!p1->info_2 && p2->info_2) ||
5342 (p1->info_2 && !p2->info_2)) {
5343 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
5344 "differ\n"));
5345 return False;
5348 /* Compare two nt_printer_info_level structures. Don't compare
5349 status or cjobs as they seem to have something to do with the
5350 printer queue. */
5352 pi1 = p1->info_2;
5353 pi2 = p2->info_2;
5355 /* Don't check the attributes as we stomp on the value in
5356 check_printer_ok() anyway. */
5358 #if 0
5359 PI_CHECK_INT(attributes);
5360 #endif
5362 PI_CHECK_INT(priority);
5363 PI_CHECK_INT(default_priority);
5364 PI_CHECK_INT(starttime);
5365 PI_CHECK_INT(untiltime);
5366 PI_CHECK_INT(averageppm);
5368 /* Yuck - don't check the printername or servername as the
5369 mod_a_printer() code plays games with them. You can't
5370 change the printername or the sharename through this interface
5371 in Samba. */
5373 PI_CHECK_STR(sharename);
5374 PI_CHECK_STR(portname);
5375 PI_CHECK_STR(drivername);
5376 PI_CHECK_STR(comment);
5377 PI_CHECK_STR(location);
5379 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
5380 return False;
5383 PI_CHECK_STR(sepfile);
5384 PI_CHECK_STR(printprocessor);
5385 PI_CHECK_STR(datatype);
5386 PI_CHECK_STR(parameters);
5388 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
5389 return False;
5392 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
5393 return False;
5396 PI_CHECK_INT(changeid);
5397 PI_CHECK_INT(c_setprinter);
5398 PI_CHECK_INT(setuptime);
5400 equal:
5401 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5402 return True;
5405 #endif
5407 /********************************************************************
5408 * Called by spoolss_api_setprinter
5409 * when updating a printer description.
5410 ********************************************************************/
5412 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5413 const SPOOL_PRINTER_INFO_LEVEL *info,
5414 DEVICEMODE *devmode)
5416 int snum;
5417 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5418 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5419 WERROR result;
5421 DEBUG(8,("update_printer\n"));
5423 result = WERR_OK;
5425 if (level!=2) {
5426 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5427 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5428 result = WERR_UNKNOWN_LEVEL;
5429 goto done;
5432 if (!Printer) {
5433 result = WERR_BADFID;
5434 goto done;
5437 if (!get_printer_snum(p, handle, &snum)) {
5438 result = WERR_BADFID;
5439 goto done;
5442 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5443 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5444 result = WERR_BADFID;
5445 goto done;
5448 DEBUGADD(8,("Converting info_2 struct\n"));
5451 * convert_printer_info converts the incoming
5452 * info from the client and overwrites the info
5453 * just read from the tdb in the pointer 'printer'.
5456 if (!convert_printer_info(info, printer, level)) {
5457 result = WERR_NOMEM;
5458 goto done;
5461 if (devmode) {
5462 /* we have a valid devmode
5463 convert it and link it*/
5465 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5466 if (!convert_devicemode(printer->info_2->printername, devmode,
5467 &printer->info_2->devmode)) {
5468 result = WERR_NOMEM;
5469 goto done;
5473 /* Do sanity check on the requested changes for Samba */
5475 if (!check_printer_ok(printer->info_2, snum)) {
5476 result = WERR_INVALID_PARAM;
5477 goto done;
5480 #if 0 /* JERRY */
5483 * Another one of those historical misunderstandings...
5484 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5485 * I'm leaving it here as a reminder. --jerry
5488 if (nt_printer_info_level_equal(printer, old_printer)) {
5489 DEBUG(3, ("update_printer: printer info has not changed\n"));
5490 result = WERR_OK;
5491 goto done;
5494 #endif
5496 /* Check calling user has permission to update printer description */
5498 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5499 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5500 result = WERR_ACCESS_DENIED;
5501 goto done;
5504 /* Call addprinter hook */
5506 if (*lp_addprinter_cmd()) {
5507 if ( !add_printer_hook(printer) ) {
5508 result = WERR_ACCESS_DENIED;
5509 goto done;
5514 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5515 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5516 * requires Win32 client code (see other notes elsewhere in the code).
5518 if (printer->info_2->devmode &&
5519 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5521 DEBUG(10,("update_printer: Save printer driver init data\n"));
5522 printer->info_2->devmode->displayfrequency = 0;
5524 if (update_driver_init(*printer, 2)!=0) {
5525 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5526 result = WERR_ACCESS_DENIED;
5527 goto done;
5529 } else {
5531 * When a *new* driver is bound to a printer, the drivername is used to
5532 * lookup previously saved driver initialization info, which is then
5533 * bound to the printer, simulating what happens in the Windows arch.
5535 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5536 if (!set_driver_init(printer, 2)) {
5537 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5538 printer->info_2->drivername));
5540 notify_printer_driver(snum, printer->info_2->drivername);
5544 /* Update printer info */
5545 result = mod_a_printer(*printer, 2);
5547 /* flag which changes actually occured. This is a small subset of
5548 all the possible changes */
5550 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5551 notify_printer_comment(snum, printer->info_2->comment);
5553 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5554 notify_printer_sharename(snum, printer->info_2->sharename);
5556 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5557 notify_printer_port(snum, printer->info_2->portname);
5559 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5560 notify_printer_location(snum, printer->info_2->location);
5562 done:
5563 free_a_printer(&printer, 2);
5564 free_a_printer(&old_printer, 2);
5567 return result;
5570 /****************************************************************************
5571 ****************************************************************************/
5573 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5575 POLICY_HND *handle = &q_u->handle;
5576 uint32 level = q_u->level;
5577 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5578 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5579 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5580 uint32 command = q_u->command;
5582 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5584 if (!Printer) {
5585 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5586 return WERR_BADFID;
5589 /* check the level */
5590 switch (level) {
5591 case 0:
5592 return control_printer(handle, command, p);
5593 case 2:
5594 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5595 case 3:
5596 return update_printer_sec(handle, level, info, p,
5597 secdesc_ctr);
5598 default:
5599 return WERR_UNKNOWN_LEVEL;
5603 /****************************************************************************
5604 ****************************************************************************/
5606 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5608 POLICY_HND *handle = &q_u->handle;
5610 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5612 if (!Printer) {
5613 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5614 return WERR_BADFID;
5617 if (Printer->notify.client_connected==True)
5618 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5620 Printer->notify.flags=0;
5621 Printer->notify.options=0;
5622 Printer->notify.localmachine[0]='\0';
5623 Printer->notify.printerlocal=0;
5624 if (Printer->notify.option)
5625 free_spool_notify_option(&Printer->notify.option);
5626 Printer->notify.client_connected=False;
5628 return WERR_OK;
5631 /****************************************************************************
5632 ****************************************************************************/
5634 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5636 /* that's an [in out] buffer (despite appearences to the contrary) */
5637 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5639 r_u->needed = 0;
5640 return WERR_INVALID_PARAM; /* this is what a NT server
5641 returns for AddJob. AddJob
5642 must fail on non-local
5643 printers */
5646 /****************************************************************************
5647 ****************************************************************************/
5649 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5650 int position, int snum)
5652 pstring temp_name;
5654 struct tm *t;
5656 t=gmtime(&queue->time);
5657 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5659 job_info->jobid=queue->job;
5660 init_unistr(&job_info->printername, lp_servicename(snum));
5661 init_unistr(&job_info->machinename, temp_name);
5662 init_unistr(&job_info->username, queue->fs_user);
5663 init_unistr(&job_info->document, queue->fs_file);
5664 init_unistr(&job_info->datatype, "RAW");
5665 init_unistr(&job_info->text_status, "");
5666 job_info->status=nt_printj_status(queue->status);
5667 job_info->priority=queue->priority;
5668 job_info->position=position;
5669 job_info->totalpages=queue->page_count;
5670 job_info->pagesprinted=0;
5672 make_systemtime(&job_info->submitted, t);
5675 /****************************************************************************
5676 ****************************************************************************/
5678 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5679 int position, int snum,
5680 NT_PRINTER_INFO_LEVEL *ntprinter,
5681 DEVICEMODE *devmode)
5683 pstring temp_name;
5684 pstring chaine;
5685 struct tm *t;
5687 t=gmtime(&queue->time);
5688 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5690 job_info->jobid=queue->job;
5692 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5694 init_unistr(&job_info->printername, chaine);
5696 init_unistr(&job_info->machinename, temp_name);
5697 init_unistr(&job_info->username, queue->fs_user);
5698 init_unistr(&job_info->document, queue->fs_file);
5699 init_unistr(&job_info->notifyname, queue->fs_user);
5700 init_unistr(&job_info->datatype, "RAW");
5701 init_unistr(&job_info->printprocessor, "winprint");
5702 init_unistr(&job_info->parameters, "");
5703 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5704 init_unistr(&job_info->text_status, "");
5706 /* and here the security descriptor */
5708 job_info->status=nt_printj_status(queue->status);
5709 job_info->priority=queue->priority;
5710 job_info->position=position;
5711 job_info->starttime=0;
5712 job_info->untiltime=0;
5713 job_info->totalpages=queue->page_count;
5714 job_info->size=queue->size;
5715 make_systemtime(&(job_info->submitted), t);
5716 job_info->timeelapsed=0;
5717 job_info->pagesprinted=0;
5719 job_info->devmode = devmode;
5721 return (True);
5724 /****************************************************************************
5725 Enumjobs at level 1.
5726 ****************************************************************************/
5728 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5729 NEW_BUFFER *buffer, uint32 offered,
5730 uint32 *needed, uint32 *returned)
5732 JOB_INFO_1 *info;
5733 int i;
5735 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5736 if (info==NULL) {
5737 SAFE_FREE(queue);
5738 *returned=0;
5739 return WERR_NOMEM;
5742 for (i=0; i<*returned; i++)
5743 fill_job_info_1(&info[i], &queue[i], i, snum);
5745 SAFE_FREE(queue);
5747 /* check the required size. */
5748 for (i=0; i<*returned; i++)
5749 (*needed) += spoolss_size_job_info_1(&info[i]);
5751 if (!alloc_buffer_size(buffer, *needed)) {
5752 SAFE_FREE(info);
5753 return WERR_INSUFFICIENT_BUFFER;
5756 /* fill the buffer with the structures */
5757 for (i=0; i<*returned; i++)
5758 smb_io_job_info_1("", buffer, &info[i], 0);
5760 /* clear memory */
5761 SAFE_FREE(info);
5763 if (*needed > offered) {
5764 *returned=0;
5765 return WERR_INSUFFICIENT_BUFFER;
5768 return WERR_OK;
5771 /****************************************************************************
5772 Enumjobs at level 2.
5773 ****************************************************************************/
5775 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5776 NEW_BUFFER *buffer, uint32 offered,
5777 uint32 *needed, uint32 *returned)
5779 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5780 JOB_INFO_2 *info = NULL;
5781 int i;
5782 WERROR result;
5783 DEVICEMODE *devmode = NULL;
5785 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5786 if (info==NULL) {
5787 *returned=0;
5788 result = WERR_NOMEM;
5789 goto done;
5792 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5793 if (!W_ERROR_IS_OK(result)) {
5794 *returned = 0;
5795 goto done;
5798 if (!(devmode = construct_dev_mode(snum))) {
5799 *returned = 0;
5800 result = WERR_NOMEM;
5801 goto done;
5804 for (i=0; i<*returned; i++)
5805 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5806 devmode);
5808 free_a_printer(&ntprinter, 2);
5809 SAFE_FREE(queue);
5811 /* check the required size. */
5812 for (i=0; i<*returned; i++)
5813 (*needed) += spoolss_size_job_info_2(&info[i]);
5815 if (*needed > offered) {
5816 *returned=0;
5817 result = WERR_INSUFFICIENT_BUFFER;
5818 goto done;
5821 if (!alloc_buffer_size(buffer, *needed)) {
5822 SAFE_FREE(info);
5823 result = WERR_INSUFFICIENT_BUFFER;
5824 goto done;
5827 /* fill the buffer with the structures */
5828 for (i=0; i<*returned; i++)
5829 smb_io_job_info_2("", buffer, &info[i], 0);
5831 result = WERR_OK;
5833 done:
5834 free_a_printer(&ntprinter, 2);
5835 free_devmode(devmode);
5836 SAFE_FREE(queue);
5837 SAFE_FREE(info);
5839 return result;
5843 /****************************************************************************
5844 Enumjobs.
5845 ****************************************************************************/
5847 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5849 POLICY_HND *handle = &q_u->handle;
5850 /* uint32 firstjob = q_u->firstjob; - notused. */
5851 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5852 uint32 level = q_u->level;
5853 NEW_BUFFER *buffer = NULL;
5854 uint32 offered = q_u->offered;
5855 uint32 *needed = &r_u->needed;
5856 uint32 *returned = &r_u->returned;
5858 int snum;
5859 print_status_struct prt_status;
5860 print_queue_struct *queue=NULL;
5862 /* that's an [in out] buffer */
5863 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5864 buffer = r_u->buffer;
5866 DEBUG(4,("_spoolss_enumjobs\n"));
5868 *needed=0;
5869 *returned=0;
5871 if (!get_printer_snum(p, handle, &snum))
5872 return WERR_BADFID;
5874 *returned = print_queue_status(snum, &queue, &prt_status);
5875 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5877 if (*returned == 0) {
5878 SAFE_FREE(queue);
5879 return WERR_OK;
5882 switch (level) {
5883 case 1:
5884 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5885 case 2:
5886 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5887 default:
5888 SAFE_FREE(queue);
5889 *returned=0;
5890 return WERR_UNKNOWN_LEVEL;
5894 /****************************************************************************
5895 ****************************************************************************/
5897 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5899 return WERR_OK;
5902 /****************************************************************************
5903 ****************************************************************************/
5905 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5907 POLICY_HND *handle = &q_u->handle;
5908 uint32 jobid = q_u->jobid;
5909 uint32 command = q_u->command;
5911 struct current_user user;
5912 int snum;
5913 WERROR errcode = WERR_BADFUNC;
5915 if (!get_printer_snum(p, handle, &snum)) {
5916 return WERR_BADFID;
5919 if (!print_job_exists(snum, jobid)) {
5920 return WERR_INVALID_PRINTER_NAME;
5923 get_current_user(&user, p);
5925 switch (command) {
5926 case JOB_CONTROL_CANCEL:
5927 case JOB_CONTROL_DELETE:
5928 if (print_job_delete(&user, snum, jobid, &errcode)) {
5929 errcode = WERR_OK;
5931 break;
5932 case JOB_CONTROL_PAUSE:
5933 if (print_job_pause(&user, snum, jobid, &errcode)) {
5934 errcode = WERR_OK;
5936 break;
5937 case JOB_CONTROL_RESTART:
5938 case JOB_CONTROL_RESUME:
5939 if (print_job_resume(&user, snum, jobid, &errcode)) {
5940 errcode = WERR_OK;
5942 break;
5943 default:
5944 return WERR_UNKNOWN_LEVEL;
5947 return errcode;
5950 /****************************************************************************
5951 Enumerates all printer drivers at level 1.
5952 ****************************************************************************/
5954 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5956 int i;
5957 int ndrivers;
5958 uint32 version;
5959 fstring *list = NULL;
5961 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5962 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5964 *returned=0;
5966 for (version=0; version<DRIVER_MAX_VERSION; version++) {
5967 list=NULL;
5968 ndrivers=get_ntdrivers(&list, architecture, version);
5969 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5971 if(ndrivers == -1)
5972 return WERR_NOMEM;
5974 if(ndrivers != 0) {
5975 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5976 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5977 SAFE_FREE(driver_info_1);
5978 SAFE_FREE(list);
5979 return WERR_NOMEM;
5981 else driver_info_1 = tdi1;
5984 for (i=0; i<ndrivers; i++) {
5985 WERROR status;
5986 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5987 ZERO_STRUCT(driver);
5988 status = get_a_printer_driver(&driver, 3, list[i],
5989 architecture, version);
5990 if (!W_ERROR_IS_OK(status)) {
5991 SAFE_FREE(list);
5992 return status;
5994 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5995 free_a_printer_driver(driver, 3);
5998 *returned+=ndrivers;
5999 SAFE_FREE(list);
6002 /* check the required size. */
6003 for (i=0; i<*returned; i++) {
6004 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6005 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6008 if (!alloc_buffer_size(buffer, *needed)) {
6009 SAFE_FREE(driver_info_1);
6010 return WERR_INSUFFICIENT_BUFFER;
6013 /* fill the buffer with the driver structures */
6014 for (i=0; i<*returned; i++) {
6015 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6016 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6019 SAFE_FREE(driver_info_1);
6021 if (*needed > offered) {
6022 *returned=0;
6023 return WERR_INSUFFICIENT_BUFFER;
6026 return WERR_OK;
6029 /****************************************************************************
6030 Enumerates all printer drivers at level 2.
6031 ****************************************************************************/
6033 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6035 int i;
6036 int ndrivers;
6037 uint32 version;
6038 fstring *list = NULL;
6040 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6041 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6043 *returned=0;
6045 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6046 list=NULL;
6047 ndrivers=get_ntdrivers(&list, architecture, version);
6048 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6050 if(ndrivers == -1)
6051 return WERR_NOMEM;
6053 if(ndrivers != 0) {
6054 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6055 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6056 SAFE_FREE(driver_info_2);
6057 SAFE_FREE(list);
6058 return WERR_NOMEM;
6060 else driver_info_2 = tdi2;
6063 for (i=0; i<ndrivers; i++) {
6064 WERROR status;
6066 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6067 ZERO_STRUCT(driver);
6068 status = get_a_printer_driver(&driver, 3, list[i],
6069 architecture, version);
6070 if (!W_ERROR_IS_OK(status)) {
6071 SAFE_FREE(list);
6072 return status;
6074 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6075 free_a_printer_driver(driver, 3);
6078 *returned+=ndrivers;
6079 SAFE_FREE(list);
6082 /* check the required size. */
6083 for (i=0; i<*returned; i++) {
6084 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6085 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6088 if (!alloc_buffer_size(buffer, *needed)) {
6089 SAFE_FREE(driver_info_2);
6090 return WERR_INSUFFICIENT_BUFFER;
6093 /* fill the buffer with the form structures */
6094 for (i=0; i<*returned; i++) {
6095 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6096 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6099 SAFE_FREE(driver_info_2);
6101 if (*needed > offered) {
6102 *returned=0;
6103 return WERR_INSUFFICIENT_BUFFER;
6106 return WERR_OK;
6109 /****************************************************************************
6110 Enumerates all printer drivers at level 3.
6111 ****************************************************************************/
6113 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6115 int i;
6116 int ndrivers;
6117 uint32 version;
6118 fstring *list = NULL;
6120 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6121 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6123 *returned=0;
6125 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6126 list=NULL;
6127 ndrivers=get_ntdrivers(&list, architecture, version);
6128 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6130 if(ndrivers == -1)
6131 return WERR_NOMEM;
6133 if(ndrivers != 0) {
6134 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6135 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6136 SAFE_FREE(driver_info_3);
6137 SAFE_FREE(list);
6138 return WERR_NOMEM;
6140 else driver_info_3 = tdi3;
6143 for (i=0; i<ndrivers; i++) {
6144 WERROR status;
6146 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6147 ZERO_STRUCT(driver);
6148 status = get_a_printer_driver(&driver, 3, list[i],
6149 architecture, version);
6150 if (!W_ERROR_IS_OK(status)) {
6151 SAFE_FREE(list);
6152 return status;
6154 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6155 free_a_printer_driver(driver, 3);
6158 *returned+=ndrivers;
6159 SAFE_FREE(list);
6162 /* check the required size. */
6163 for (i=0; i<*returned; i++) {
6164 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6165 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6168 if (!alloc_buffer_size(buffer, *needed)) {
6169 SAFE_FREE(driver_info_3);
6170 return WERR_INSUFFICIENT_BUFFER;
6173 /* fill the buffer with the driver structures */
6174 for (i=0; i<*returned; i++) {
6175 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6176 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6179 for (i=0; i<*returned; i++)
6180 SAFE_FREE(driver_info_3[i].dependentfiles);
6182 SAFE_FREE(driver_info_3);
6184 if (*needed > offered) {
6185 *returned=0;
6186 return WERR_INSUFFICIENT_BUFFER;
6189 return WERR_OK;
6192 /****************************************************************************
6193 Enumerates all printer drivers.
6194 ****************************************************************************/
6196 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6198 /* UNISTR2 *name = &q_u->name; - notused. */
6199 UNISTR2 *environment = &q_u->environment;
6200 uint32 level = q_u->level;
6201 NEW_BUFFER *buffer = NULL;
6202 uint32 offered = q_u->offered;
6203 uint32 *needed = &r_u->needed;
6204 uint32 *returned = &r_u->returned;
6206 fstring *list = NULL;
6207 fstring servername;
6208 fstring architecture;
6210 /* that's an [in out] buffer */
6211 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6212 buffer = r_u->buffer;
6214 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6215 fstrcpy(servername, get_called_name());
6216 *needed=0;
6217 *returned=0;
6219 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6221 switch (level) {
6222 case 1:
6223 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6224 case 2:
6225 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6226 case 3:
6227 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6228 default:
6229 *returned=0;
6230 SAFE_FREE(list);
6231 return WERR_UNKNOWN_LEVEL;
6235 /****************************************************************************
6236 ****************************************************************************/
6238 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6240 form->flag=list->flag;
6241 init_unistr(&form->name, list->name);
6242 form->width=list->width;
6243 form->length=list->length;
6244 form->left=list->left;
6245 form->top=list->top;
6246 form->right=list->right;
6247 form->bottom=list->bottom;
6250 /****************************************************************************
6251 ****************************************************************************/
6253 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6255 /* POLICY_HND *handle = &q_u->handle; - notused. */
6256 uint32 level = q_u->level;
6257 NEW_BUFFER *buffer = NULL;
6258 uint32 offered = q_u->offered;
6259 uint32 *needed = &r_u->needed;
6260 uint32 *numofforms = &r_u->numofforms;
6261 uint32 numbuiltinforms;
6263 nt_forms_struct *list=NULL;
6264 nt_forms_struct *builtinlist=NULL;
6265 FORM_1 *forms_1;
6266 int buffer_size=0;
6267 int i;
6269 /* that's an [in out] buffer */
6270 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6271 buffer = r_u->buffer;
6273 DEBUG(4,("_spoolss_enumforms\n"));
6274 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6275 DEBUGADD(5,("Info level [%d]\n", level));
6277 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6278 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6279 *numofforms = get_ntforms(&list);
6280 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6281 *numofforms += numbuiltinforms;
6283 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6285 switch (level) {
6286 case 1:
6287 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6288 *numofforms=0;
6289 return WERR_NOMEM;
6292 /* construct the list of form structures */
6293 for (i=0; i<numbuiltinforms; i++) {
6294 DEBUGADD(6,("Filling form number [%d]\n",i));
6295 fill_form_1(&forms_1[i], &builtinlist[i]);
6298 SAFE_FREE(builtinlist);
6300 for (; i<*numofforms; i++) {
6301 DEBUGADD(6,("Filling form number [%d]\n",i));
6302 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6305 SAFE_FREE(list);
6307 /* check the required size. */
6308 for (i=0; i<numbuiltinforms; i++) {
6309 DEBUGADD(6,("adding form [%d]'s size\n",i));
6310 buffer_size += spoolss_size_form_1(&forms_1[i]);
6312 for (; i<*numofforms; i++) {
6313 DEBUGADD(6,("adding form [%d]'s size\n",i));
6314 buffer_size += spoolss_size_form_1(&forms_1[i]);
6317 *needed=buffer_size;
6319 if (!alloc_buffer_size(buffer, buffer_size)){
6320 SAFE_FREE(forms_1);
6321 return WERR_INSUFFICIENT_BUFFER;
6324 /* fill the buffer with the form structures */
6325 for (i=0; i<numbuiltinforms; i++) {
6326 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6327 smb_io_form_1("", buffer, &forms_1[i], 0);
6329 for (; i<*numofforms; i++) {
6330 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6331 smb_io_form_1("", buffer, &forms_1[i], 0);
6334 SAFE_FREE(forms_1);
6336 if (*needed > offered) {
6337 *numofforms=0;
6338 return WERR_INSUFFICIENT_BUFFER;
6340 else
6341 return WERR_OK;
6343 default:
6344 SAFE_FREE(list);
6345 SAFE_FREE(builtinlist);
6346 return WERR_UNKNOWN_LEVEL;
6351 /****************************************************************************
6352 ****************************************************************************/
6354 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6356 /* POLICY_HND *handle = &q_u->handle; - notused. */
6357 uint32 level = q_u->level;
6358 UNISTR2 *uni_formname = &q_u->formname;
6359 NEW_BUFFER *buffer = NULL;
6360 uint32 offered = q_u->offered;
6361 uint32 *needed = &r_u->needed;
6363 nt_forms_struct *list=NULL;
6364 nt_forms_struct builtin_form;
6365 BOOL foundBuiltin;
6366 FORM_1 form_1;
6367 fstring form_name;
6368 int buffer_size=0;
6369 int numofforms=0, i=0;
6371 /* that's an [in out] buffer */
6372 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6373 buffer = r_u->buffer;
6375 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6377 DEBUG(4,("_spoolss_getform\n"));
6378 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6379 DEBUGADD(5,("Info level [%d]\n", level));
6381 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6382 if (!foundBuiltin) {
6383 numofforms = get_ntforms(&list);
6384 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6386 if (numofforms == 0)
6387 return WERR_BADFID;
6390 switch (level) {
6391 case 1:
6392 if (foundBuiltin) {
6393 fill_form_1(&form_1, &builtin_form);
6394 } else {
6396 /* Check if the requested name is in the list of form structures */
6397 for (i=0; i<numofforms; i++) {
6399 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6401 if (strequal(form_name, list[i].name)) {
6402 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6403 fill_form_1(&form_1, &list[i]);
6404 break;
6408 SAFE_FREE(list);
6409 if (i == numofforms) {
6410 return WERR_BADFID;
6413 /* check the required size. */
6415 *needed=spoolss_size_form_1(&form_1);
6417 if (!alloc_buffer_size(buffer, buffer_size)){
6418 return WERR_INSUFFICIENT_BUFFER;
6421 if (*needed > offered) {
6422 return WERR_INSUFFICIENT_BUFFER;
6425 /* fill the buffer with the form structures */
6426 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6427 smb_io_form_1("", buffer, &form_1, 0);
6429 return WERR_OK;
6431 default:
6432 SAFE_FREE(list);
6433 return WERR_UNKNOWN_LEVEL;
6437 /****************************************************************************
6438 ****************************************************************************/
6440 static void fill_port_1(PORT_INFO_1 *port, char *name)
6442 init_unistr(&port->port_name, name);
6445 /****************************************************************************
6446 ****************************************************************************/
6448 static void fill_port_2(PORT_INFO_2 *port, char *name)
6450 init_unistr(&port->port_name, name);
6451 init_unistr(&port->monitor_name, "Local Monitor");
6452 init_unistr(&port->description, "Local Port");
6453 #define PORT_TYPE_WRITE 1
6454 port->port_type=PORT_TYPE_WRITE;
6455 port->reserved=0x0;
6458 /****************************************************************************
6459 enumports level 1.
6460 ****************************************************************************/
6462 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6464 PORT_INFO_1 *ports=NULL;
6465 int i=0;
6467 if (*lp_enumports_cmd()) {
6468 char *cmd = lp_enumports_cmd();
6469 char **qlines;
6470 pstring command;
6471 int numlines;
6472 int ret;
6473 int fd;
6475 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6477 DEBUG(10,("Running [%s]\n", command));
6478 ret = smbrun(command, &fd);
6479 DEBUG(10,("Returned [%d]\n", ret));
6480 if (ret != 0) {
6481 if (fd != -1)
6482 close(fd);
6483 /* Is this the best error to return here? */
6484 return WERR_ACCESS_DENIED;
6487 numlines = 0;
6488 qlines = fd_lines_load(fd, &numlines);
6489 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6490 close(fd);
6492 if(numlines) {
6493 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6494 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6495 dos_errstr(WERR_NOMEM)));
6496 file_lines_free(qlines);
6497 return WERR_NOMEM;
6500 for (i=0; i<numlines; i++) {
6501 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6502 fill_port_1(&ports[i], qlines[i]);
6505 file_lines_free(qlines);
6508 *returned = numlines;
6510 } else {
6511 *returned = 1; /* Sole Samba port returned. */
6513 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6514 return WERR_NOMEM;
6516 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6518 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6521 /* check the required size. */
6522 for (i=0; i<*returned; i++) {
6523 DEBUGADD(6,("adding port [%d]'s size\n", i));
6524 *needed += spoolss_size_port_info_1(&ports[i]);
6527 if (!alloc_buffer_size(buffer, *needed)) {
6528 SAFE_FREE(ports);
6529 return WERR_INSUFFICIENT_BUFFER;
6532 /* fill the buffer with the ports structures */
6533 for (i=0; i<*returned; i++) {
6534 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6535 smb_io_port_1("", buffer, &ports[i], 0);
6538 SAFE_FREE(ports);
6540 if (*needed > offered) {
6541 *returned=0;
6542 return WERR_INSUFFICIENT_BUFFER;
6545 return WERR_OK;
6548 /****************************************************************************
6549 enumports level 2.
6550 ****************************************************************************/
6552 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6554 PORT_INFO_2 *ports=NULL;
6555 int i=0;
6557 if (*lp_enumports_cmd()) {
6558 char *cmd = lp_enumports_cmd();
6559 char *path;
6560 char **qlines;
6561 pstring tmp_file;
6562 pstring command;
6563 int numlines;
6564 int ret;
6565 int fd;
6567 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6568 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6569 else
6570 path = lp_lockdir();
6572 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6573 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6575 unlink(tmp_file);
6576 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6577 ret = smbrun(command, &fd);
6578 DEBUGADD(10,("returned [%d]\n", ret));
6579 if (ret != 0) {
6580 if (fd != -1)
6581 close(fd);
6582 /* Is this the best error to return here? */
6583 return WERR_ACCESS_DENIED;
6586 numlines = 0;
6587 qlines = fd_lines_load(fd, &numlines);
6588 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6589 close(fd);
6591 if(numlines) {
6592 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6593 file_lines_free(qlines);
6594 return WERR_NOMEM;
6597 for (i=0; i<numlines; i++) {
6598 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6599 fill_port_2(&(ports[i]), qlines[i]);
6602 file_lines_free(qlines);
6605 *returned = numlines;
6607 } else {
6609 *returned = 1;
6611 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6612 return WERR_NOMEM;
6614 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6616 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6619 /* check the required size. */
6620 for (i=0; i<*returned; i++) {
6621 DEBUGADD(6,("adding port [%d]'s size\n", i));
6622 *needed += spoolss_size_port_info_2(&ports[i]);
6625 if (!alloc_buffer_size(buffer, *needed)) {
6626 SAFE_FREE(ports);
6627 return WERR_INSUFFICIENT_BUFFER;
6630 /* fill the buffer with the ports structures */
6631 for (i=0; i<*returned; i++) {
6632 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6633 smb_io_port_2("", buffer, &ports[i], 0);
6636 SAFE_FREE(ports);
6638 if (*needed > offered) {
6639 *returned=0;
6640 return WERR_INSUFFICIENT_BUFFER;
6643 return WERR_OK;
6646 /****************************************************************************
6647 enumports.
6648 ****************************************************************************/
6650 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6652 /* UNISTR2 *name = &q_u->name; - notused. */
6653 uint32 level = q_u->level;
6654 NEW_BUFFER *buffer = NULL;
6655 uint32 offered = q_u->offered;
6656 uint32 *needed = &r_u->needed;
6657 uint32 *returned = &r_u->returned;
6659 /* that's an [in out] buffer */
6660 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6661 buffer = r_u->buffer;
6663 DEBUG(4,("_spoolss_enumports\n"));
6665 *returned=0;
6666 *needed=0;
6668 switch (level) {
6669 case 1:
6670 return enumports_level_1(buffer, offered, needed, returned);
6671 case 2:
6672 return enumports_level_2(buffer, offered, needed, returned);
6673 default:
6674 return WERR_UNKNOWN_LEVEL;
6678 /****************************************************************************
6679 ****************************************************************************/
6681 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6682 const SPOOL_PRINTER_INFO_LEVEL *info,
6683 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6684 uint32 user_switch, const SPOOL_USER_CTR *user,
6685 POLICY_HND *handle)
6687 NT_PRINTER_INFO_LEVEL *printer = NULL;
6688 fstring name;
6689 int snum;
6690 WERROR err = WERR_OK;
6692 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6693 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6694 return WERR_NOMEM;
6697 ZERO_STRUCTP(printer);
6699 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6700 if (!convert_printer_info(info, printer, 2)) {
6701 free_a_printer(&printer, 2);
6702 return WERR_NOMEM;
6705 /* check to see if the printer already exists */
6707 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6708 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6709 printer->info_2->sharename));
6710 free_a_printer(&printer, 2);
6711 return WERR_PRINTER_ALREADY_EXISTS;
6714 if (*lp_addprinter_cmd() )
6715 if ( !add_printer_hook(printer) ) {
6716 free_a_printer(&printer,2);
6717 return WERR_ACCESS_DENIED;
6720 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6721 printer->info_2->sharename);
6723 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6724 free_a_printer(&printer,2);
6725 return WERR_ACCESS_DENIED;
6728 /* you must be a printer admin to add a new printer */
6729 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6730 free_a_printer(&printer,2);
6731 return WERR_ACCESS_DENIED;
6735 * Do sanity check on the requested changes for Samba.
6738 if (!check_printer_ok(printer->info_2, snum)) {
6739 free_a_printer(&printer,2);
6740 return WERR_INVALID_PARAM;
6744 * When a printer is created, the drivername bound to the printer is used
6745 * to lookup previously saved driver initialization info, which is then
6746 * bound to the new printer, simulating what happens in the Windows arch.
6749 if (!devmode)
6750 set_driver_init(printer, 2);
6751 else {
6752 /* A valid devmode was included, convert and link it
6754 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6756 if (!convert_devicemode(printer->info_2->printername, devmode,
6757 &printer->info_2->devmode))
6758 return WERR_NOMEM;
6761 set_driver_init(printer, 2);
6763 /* write the ASCII on disk */
6764 err = mod_a_printer(*printer, 2);
6765 if (!W_ERROR_IS_OK(err)) {
6766 free_a_printer(&printer,2);
6767 return err;
6770 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6771 /* Handle open failed - remove addition. */
6772 del_a_printer(printer->info_2->sharename);
6773 free_a_printer(&printer,2);
6774 return WERR_ACCESS_DENIED;
6777 update_c_setprinter(False);
6778 free_a_printer(&printer,2);
6780 return WERR_OK;
6783 /****************************************************************************
6784 ****************************************************************************/
6786 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6788 UNISTR2 *uni_srv_name = &q_u->server_name;
6789 uint32 level = q_u->level;
6790 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6791 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6792 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6793 uint32 user_switch = q_u->user_switch;
6794 SPOOL_USER_CTR *user = &q_u->user_ctr;
6795 POLICY_HND *handle = &r_u->handle;
6797 switch (level) {
6798 case 1:
6799 /* we don't handle yet */
6800 /* but I know what to do ... */
6801 return WERR_UNKNOWN_LEVEL;
6802 case 2:
6803 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6804 devmode, sdb,
6805 user_switch, user, handle);
6806 default:
6807 return WERR_UNKNOWN_LEVEL;
6811 /****************************************************************************
6812 ****************************************************************************/
6814 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6816 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6817 uint32 level = q_u->level;
6818 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6819 WERROR err = WERR_OK;
6820 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6821 struct current_user user;
6822 fstring driver_name;
6823 uint32 version;
6825 ZERO_STRUCT(driver);
6827 get_current_user(&user, p);
6829 if (!convert_printer_driver_info(info, &driver, level)) {
6830 err = WERR_NOMEM;
6831 goto done;
6834 DEBUG(5,("Cleaning driver's information\n"));
6835 err = clean_up_driver_struct(driver, level, &user);
6836 if (!W_ERROR_IS_OK(err))
6837 goto done;
6839 DEBUG(5,("Moving driver to final destination\n"));
6840 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6841 if (W_ERROR_IS_OK(err))
6842 err = WERR_ACCESS_DENIED;
6843 goto done;
6846 if (add_a_printer_driver(driver, level)!=0) {
6847 err = WERR_ACCESS_DENIED;
6848 goto done;
6851 /* BEGIN_ADMIN_LOG */
6852 switch(level) {
6853 case 3:
6854 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6855 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6856 fstrcpy(driver_name, driver.info_3->name);
6857 break;
6858 case 6:
6859 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6860 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6861 fstrcpy(driver_name, driver.info_6->name);
6862 break;
6864 /* END_ADMIN_LOG */
6867 * I think this is where he DrvUpgradePrinter() hook would be
6868 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6869 * server. Right now, we just need to send ourselves a message
6870 * to update each printer bound to this driver. --jerry
6873 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6874 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6875 driver_name));
6879 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6880 * decide if the driver init data should be deleted. The rules are:
6881 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6882 * 2) delete init data only if there is no 2k/Xp driver
6883 * 3) always delete init data
6884 * The generalized rule is always use init data from the highest order driver.
6885 * It is necessary to follow the driver install by an initialization step to
6886 * finish off this process.
6888 if (level == 3)
6889 version = driver.info_3->cversion;
6890 else if (level == 6)
6891 version = driver.info_6->version;
6892 else
6893 version = -1;
6894 switch (version) {
6896 * 9x printer driver - never delete init data
6898 case 0:
6899 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6900 driver_name));
6901 break;
6904 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6905 * there is no 2k/Xp driver init data for this driver name.
6907 case 2:
6909 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
6911 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
6913 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6915 if (!del_driver_init(driver_name))
6916 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
6917 } else {
6919 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6921 free_a_printer_driver(driver1,3);
6922 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6923 driver_name));
6926 break;
6929 * 2k or Xp printer driver - always delete init data
6931 case 3:
6932 if (!del_driver_init(driver_name))
6933 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
6934 break;
6936 default:
6937 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
6938 break;
6942 done:
6943 free_a_printer_driver(driver, level);
6944 return err;
6947 /********************************************************************
6948 * spoolss_addprinterdriverex
6949 ********************************************************************/
6951 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
6953 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
6954 SPOOL_R_ADDPRINTERDRIVER r_u_local;
6957 * we only support the semantics of AddPrinterDriver()
6958 * i.e. only copy files that are newer than existing ones
6961 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
6962 return WERR_ACCESS_DENIED;
6964 /* just pass the information off to _spoolss_addprinterdriver() */
6965 ZERO_STRUCT(q_u_local);
6966 ZERO_STRUCT(r_u_local);
6968 q_u_local.server_name_ptr = q_u->server_name_ptr;
6969 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
6970 q_u_local.level = q_u->level;
6971 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
6973 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
6976 /****************************************************************************
6977 ****************************************************************************/
6979 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6981 init_unistr(&info->name, name);
6984 /****************************************************************************
6985 ****************************************************************************/
6987 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6989 pstring path;
6990 pstring long_archi;
6991 pstring short_archi;
6992 DRIVER_DIRECTORY_1 *info=NULL;
6994 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6996 if (get_short_archi(short_archi, long_archi)==False)
6997 return WERR_INVALID_ENVIRONMENT;
6999 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7000 return WERR_NOMEM;
7002 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7004 DEBUG(4,("printer driver directory: [%s]\n", path));
7006 fill_driverdir_1(info, path);
7008 *needed += spoolss_size_driverdir_info_1(info);
7010 if (!alloc_buffer_size(buffer, *needed)) {
7011 SAFE_FREE(info);
7012 return WERR_INSUFFICIENT_BUFFER;
7015 smb_io_driverdir_1("", buffer, info, 0);
7017 SAFE_FREE(info);
7019 if (*needed > offered)
7020 return WERR_INSUFFICIENT_BUFFER;
7022 return WERR_OK;
7025 /****************************************************************************
7026 ****************************************************************************/
7028 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7030 UNISTR2 *name = &q_u->name;
7031 UNISTR2 *uni_environment = &q_u->environment;
7032 uint32 level = q_u->level;
7033 NEW_BUFFER *buffer = NULL;
7034 uint32 offered = q_u->offered;
7035 uint32 *needed = &r_u->needed;
7037 /* that's an [in out] buffer */
7038 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7039 buffer = r_u->buffer;
7041 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7043 *needed=0;
7045 switch(level) {
7046 case 1:
7047 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7048 default:
7049 return WERR_UNKNOWN_LEVEL;
7053 /****************************************************************************
7054 ****************************************************************************/
7056 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7058 POLICY_HND *handle = &q_u->handle;
7059 uint32 idx = q_u->index;
7060 uint32 in_value_len = q_u->valuesize;
7061 uint32 in_data_len = q_u->datasize;
7062 uint32 *out_max_value_len = &r_u->valuesize;
7063 uint16 **out_value = &r_u->value;
7064 uint32 *out_value_len = &r_u->realvaluesize;
7065 uint32 *out_type = &r_u->type;
7066 uint32 *out_max_data_len = &r_u->datasize;
7067 uint8 **data_out = &r_u->data;
7068 uint32 *out_data_len = &r_u->realdatasize;
7070 NT_PRINTER_INFO_LEVEL *printer = NULL;
7072 fstring value;
7074 uint32 param_index;
7075 uint32 biggest_valuesize;
7076 uint32 biggest_datasize;
7077 uint32 data_len;
7078 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7079 int snum;
7080 uint8 *data=NULL;
7081 uint32 type;
7082 WERROR result;
7084 ZERO_STRUCT(printer);
7086 *out_type=0;
7088 *out_max_data_len=0;
7089 *data_out=NULL;
7090 *out_data_len=0;
7092 DEBUG(5,("spoolss_enumprinterdata\n"));
7094 if (!Printer) {
7095 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7096 return WERR_BADFID;
7099 if (!get_printer_snum(p,handle, &snum))
7100 return WERR_BADFID;
7102 result = get_a_printer(&printer, 2, lp_servicename(snum));
7103 if (!W_ERROR_IS_OK(result))
7104 return result;
7107 * The NT machine wants to know the biggest size of value and data
7109 * cf: MSDN EnumPrinterData remark section
7111 if ( (in_value_len==0) && (in_data_len==0) ) {
7112 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7114 SAFE_FREE(data);
7116 param_index=0;
7117 biggest_valuesize=0;
7118 biggest_datasize=0;
7120 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
7121 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
7122 if (data_len > biggest_datasize) biggest_datasize=data_len;
7124 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
7126 SAFE_FREE(data);
7127 param_index++;
7130 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
7131 *out_value_len=2*(1+biggest_valuesize);
7132 *out_data_len=biggest_datasize;
7134 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7136 free_a_printer(&printer, 2);
7137 return WERR_OK;
7141 * the value len is wrong in NT sp3
7142 * that's the number of bytes not the number of unicode chars
7145 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
7147 SAFE_FREE(data);
7148 free_a_printer(&printer, 2);
7150 /* out_value should default to "" or else NT4 has
7151 problems unmarshalling the response */
7153 *out_max_value_len=(in_value_len/sizeof(uint16));
7154 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7155 return WERR_NOMEM;
7157 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7159 /* the data is counted in bytes */
7160 *out_max_data_len = in_data_len;
7161 *out_data_len = in_data_len;
7162 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7163 return WERR_NOMEM;
7165 return WERR_NO_MORE_ITEMS;
7168 free_a_printer(&printer, 2);
7171 * the value is:
7172 * - counted in bytes in the request
7173 * - counted in UNICODE chars in the max reply
7174 * - counted in bytes in the real size
7176 * take a pause *before* coding not *during* coding
7179 *out_max_value_len=(in_value_len/sizeof(uint16));
7180 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
7181 SAFE_FREE(data);
7182 return WERR_NOMEM;
7185 *out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0);
7187 *out_type=type;
7189 /* the data is counted in bytes */
7190 *out_max_data_len=in_data_len;
7191 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
7192 SAFE_FREE(data);
7193 return WERR_NOMEM;
7196 memcpy(*data_out, data, (size_t)data_len);
7197 *out_data_len=data_len;
7199 SAFE_FREE(data);
7201 return WERR_OK;
7204 /****************************************************************************
7205 ****************************************************************************/
7207 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7209 POLICY_HND *handle = &q_u->handle;
7210 UNISTR2 *value = &q_u->value;
7211 uint32 type = q_u->type;
7212 uint8 *data = q_u->data;
7213 uint32 real_len = q_u->real_len;
7215 NT_PRINTER_INFO_LEVEL *printer = NULL;
7216 NT_PRINTER_PARAM *param = NULL, old_param;
7217 int snum=0;
7218 WERROR status = WERR_OK;
7219 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7221 DEBUG(5,("spoolss_setprinterdata\n"));
7223 if (!Printer) {
7224 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7225 return WERR_BADFID;
7228 if (!get_printer_snum(p,handle, &snum))
7229 return WERR_BADFID;
7231 ZERO_STRUCT(old_param);
7234 * Access check : NT returns "access denied" if you make a
7235 * SetPrinterData call without the necessary privildge.
7236 * we were originally returning OK if nothing changed
7237 * which made Win2k issue **a lot** of SetPrinterData
7238 * when connecting to a printer --jerry
7241 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7242 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7243 status = WERR_ACCESS_DENIED;
7244 goto done;
7247 /* Check if we are making any changes or not. Return true if
7248 nothing is actually changing. This is not needed anymore but
7249 has been left in as an optimization to keep from from
7250 writing to disk as often --jerry */
7252 status = get_a_printer(&printer, 2, lp_servicename(snum));
7253 if (!W_ERROR_IS_OK(status))
7254 return status;
7256 convert_specific_param(&param, value , type, data, real_len);
7258 unlink_specific_param_if_exist(printer->info_2, param);
7261 * When client side code sets a magic printer data key, detect it and save
7262 * the current printer data and the magic key's data (its the DEVMODE) for
7263 * future printer/driver initializations.
7265 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
7267 * Set devmode and printer initialization info
7269 status = save_driver_init(printer, 2, param);
7271 else {
7272 add_a_specific_param(printer->info_2, &param);
7273 status = mod_a_printer(*printer, 2);
7276 done:
7277 free_a_printer(&printer, 2);
7278 if (param)
7279 free_nt_printer_param(&param);
7280 SAFE_FREE(old_param.data);
7282 return status;
7285 /****************************************************************************
7286 ****************************************************************************/
7288 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7290 POLICY_HND *handle = &q_u->handle;
7291 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7292 int snum;
7294 DEBUG(5,("_spoolss_resetprinter\n"));
7297 * All we do is to check to see if the handle and queue is valid.
7298 * This call really doesn't mean anything to us because we only
7299 * support RAW printing. --jerry
7302 if (!Printer) {
7303 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7304 return WERR_BADFID;
7307 if (!get_printer_snum(p,handle, &snum))
7308 return WERR_BADFID;
7311 /* blindly return success */
7312 return WERR_OK;
7316 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7318 POLICY_HND *handle = &q_u->handle;
7319 UNISTR2 *value = &q_u->valuename;
7321 NT_PRINTER_INFO_LEVEL *printer = NULL;
7322 NT_PRINTER_PARAM param;
7323 int snum=0;
7324 WERROR status = WERR_OK;
7325 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7327 DEBUG(5,("spoolss_deleteprinterdata\n"));
7329 if (!Printer) {
7330 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7331 return WERR_BADFID;
7334 if (!get_printer_snum(p, handle, &snum))
7335 return WERR_BADFID;
7337 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7338 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7339 return WERR_ACCESS_DENIED;
7342 status = get_a_printer(&printer, 2, lp_servicename(snum));
7343 if (!W_ERROR_IS_OK(status))
7344 return status;
7346 ZERO_STRUCTP(&param);
7347 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
7349 if(!unlink_specific_param_if_exist(printer->info_2, &param))
7350 status = WERR_INVALID_PARAM;
7351 else
7352 status = mod_a_printer(*printer, 2);
7354 free_a_printer(&printer, 2);
7355 return status;
7358 /****************************************************************************
7359 ****************************************************************************/
7361 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7363 POLICY_HND *handle = &q_u->handle;
7364 /* uint32 level = q_u->level; - notused. */
7365 FORM *form = &q_u->form;
7366 nt_forms_struct tmpForm;
7367 int snum;
7368 WERROR status = WERR_OK;
7369 NT_PRINTER_INFO_LEVEL *printer = NULL;
7371 int count=0;
7372 nt_forms_struct *list=NULL;
7373 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7375 DEBUG(5,("spoolss_addform\n"));
7377 if (!Printer) {
7378 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7379 return WERR_BADFID;
7382 if (!get_printer_snum(p,handle, &snum))
7383 return WERR_BADFID;
7385 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7386 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7387 status = WERR_ACCESS_DENIED;
7388 goto done;
7391 /* can't add if builtin */
7392 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7393 return WERR_ALREADY_EXISTS;
7396 count=get_ntforms(&list);
7397 if(!add_a_form(&list, form, &count))
7398 return WERR_NOMEM;
7399 write_ntforms(&list, count);
7402 * ChangeID must always be set
7405 status = get_a_printer(&printer, 2, lp_servicename(snum));
7406 if (!W_ERROR_IS_OK(status))
7407 goto done;
7409 status = mod_a_printer(*printer, 2);
7410 if (!W_ERROR_IS_OK(status))
7411 goto done;
7413 done:
7414 free_a_printer(&printer, 2);
7415 SAFE_FREE(list);
7417 return status;
7420 /****************************************************************************
7421 ****************************************************************************/
7423 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7425 POLICY_HND *handle = &q_u->handle;
7426 UNISTR2 *form_name = &q_u->name;
7427 nt_forms_struct tmpForm;
7428 int count=0;
7429 WERROR ret = WERR_OK;
7430 nt_forms_struct *list=NULL;
7431 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7432 int snum;
7433 WERROR status = WERR_OK;
7434 NT_PRINTER_INFO_LEVEL *printer = NULL;
7436 DEBUG(5,("spoolss_deleteform\n"));
7438 if (!Printer) {
7439 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7440 return WERR_BADFID;
7443 if (!get_printer_snum(p, handle, &snum))
7444 return WERR_BADFID;
7446 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7447 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7448 return WERR_ACCESS_DENIED;
7451 /* can't delete if builtin */
7452 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7453 return WERR_INVALID_PARAM;
7456 count = get_ntforms(&list);
7457 if(!delete_a_form(&list, form_name, &count, &ret))
7458 return WERR_INVALID_PARAM;
7461 * ChangeID must always be set
7464 status = get_a_printer(&printer, 2, lp_servicename(snum));
7465 if (!W_ERROR_IS_OK(status))
7466 goto done;
7468 status = mod_a_printer(*printer, 2);
7469 if (!W_ERROR_IS_OK(status))
7470 goto done;
7472 done:
7473 free_a_printer(&printer, 2);
7474 SAFE_FREE(list);
7476 return ret;
7479 /****************************************************************************
7480 ****************************************************************************/
7482 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7484 POLICY_HND *handle = &q_u->handle;
7485 FORM *form = &q_u->form;
7486 nt_forms_struct tmpForm;
7487 int snum;
7488 WERROR status = WERR_OK;
7489 NT_PRINTER_INFO_LEVEL *printer = NULL;
7491 int count=0;
7492 nt_forms_struct *list=NULL;
7493 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7495 DEBUG(5,("spoolss_setform\n"));
7497 if (!Printer) {
7498 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7499 return WERR_BADFID;
7502 if (!get_printer_snum(p, handle, &snum))
7503 return WERR_BADFID;
7505 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7506 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7507 return WERR_ACCESS_DENIED;
7510 /* can't set if builtin */
7511 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7512 return WERR_INVALID_PARAM;
7515 count=get_ntforms(&list);
7516 update_a_form(&list, form, count);
7517 write_ntforms(&list, count);
7520 * ChangeID must always be set
7523 status = get_a_printer(&printer, 2, lp_servicename(snum));
7524 if (!W_ERROR_IS_OK(status))
7525 goto done;
7527 status = mod_a_printer(*printer, 2);
7528 if (!W_ERROR_IS_OK(status))
7529 goto done;
7531 done:
7532 free_a_printer(&printer, 2);
7533 SAFE_FREE(list);
7535 return WERR_OK;
7538 /****************************************************************************
7539 enumprintprocessors level 1.
7540 ****************************************************************************/
7542 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7544 PRINTPROCESSOR_1 *info_1=NULL;
7546 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7547 return WERR_NOMEM;
7549 (*returned) = 0x1;
7551 init_unistr(&info_1->name, "winprint");
7553 *needed += spoolss_size_printprocessor_info_1(info_1);
7555 if (!alloc_buffer_size(buffer, *needed))
7556 return WERR_INSUFFICIENT_BUFFER;
7558 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7560 SAFE_FREE(info_1);
7562 if (*needed > offered) {
7563 *returned=0;
7564 return WERR_INSUFFICIENT_BUFFER;
7567 return WERR_OK;
7570 /****************************************************************************
7571 ****************************************************************************/
7573 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7575 uint32 level = q_u->level;
7576 NEW_BUFFER *buffer = NULL;
7577 uint32 offered = q_u->offered;
7578 uint32 *needed = &r_u->needed;
7579 uint32 *returned = &r_u->returned;
7581 /* that's an [in out] buffer */
7582 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7583 buffer = r_u->buffer;
7585 DEBUG(5,("spoolss_enumprintprocessors\n"));
7588 * Enumerate the print processors ...
7590 * Just reply with "winprint", to keep NT happy
7591 * and I can use my nice printer checker.
7594 *returned=0;
7595 *needed=0;
7597 switch (level) {
7598 case 1:
7599 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7600 default:
7601 return WERR_UNKNOWN_LEVEL;
7605 /****************************************************************************
7606 enumprintprocdatatypes level 1.
7607 ****************************************************************************/
7609 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7611 PRINTPROCDATATYPE_1 *info_1=NULL;
7613 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7614 return WERR_NOMEM;
7616 (*returned) = 0x1;
7618 init_unistr(&info_1->name, "RAW");
7620 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7622 if (!alloc_buffer_size(buffer, *needed))
7623 return WERR_INSUFFICIENT_BUFFER;
7625 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7627 SAFE_FREE(info_1);
7629 if (*needed > offered) {
7630 *returned=0;
7631 return WERR_INSUFFICIENT_BUFFER;
7634 return WERR_OK;
7637 /****************************************************************************
7638 ****************************************************************************/
7640 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7642 uint32 level = q_u->level;
7643 NEW_BUFFER *buffer = NULL;
7644 uint32 offered = q_u->offered;
7645 uint32 *needed = &r_u->needed;
7646 uint32 *returned = &r_u->returned;
7648 /* that's an [in out] buffer */
7649 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7650 buffer = r_u->buffer;
7652 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7654 *returned=0;
7655 *needed=0;
7657 switch (level) {
7658 case 1:
7659 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7660 default:
7661 return WERR_UNKNOWN_LEVEL;
7665 /****************************************************************************
7666 enumprintmonitors level 1.
7667 ****************************************************************************/
7669 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7671 PRINTMONITOR_1 *info_1=NULL;
7673 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7674 return WERR_NOMEM;
7676 (*returned) = 0x1;
7678 init_unistr(&info_1->name, "Local Port");
7680 *needed += spoolss_size_printmonitor_info_1(info_1);
7682 if (!alloc_buffer_size(buffer, *needed))
7683 return WERR_INSUFFICIENT_BUFFER;
7685 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7687 SAFE_FREE(info_1);
7689 if (*needed > offered) {
7690 *returned=0;
7691 return WERR_INSUFFICIENT_BUFFER;
7694 return WERR_OK;
7697 /****************************************************************************
7698 enumprintmonitors level 2.
7699 ****************************************************************************/
7701 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7703 PRINTMONITOR_2 *info_2=NULL;
7705 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7706 return WERR_NOMEM;
7708 (*returned) = 0x1;
7710 init_unistr(&info_2->name, "Local Port");
7711 init_unistr(&info_2->environment, "Windows NT X86");
7712 init_unistr(&info_2->dll_name, "localmon.dll");
7714 *needed += spoolss_size_printmonitor_info_2(info_2);
7716 if (!alloc_buffer_size(buffer, *needed))
7717 return WERR_INSUFFICIENT_BUFFER;
7719 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7721 SAFE_FREE(info_2);
7723 if (*needed > offered) {
7724 *returned=0;
7725 return WERR_INSUFFICIENT_BUFFER;
7728 return WERR_OK;
7731 /****************************************************************************
7732 ****************************************************************************/
7734 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7736 uint32 level = q_u->level;
7737 NEW_BUFFER *buffer = NULL;
7738 uint32 offered = q_u->offered;
7739 uint32 *needed = &r_u->needed;
7740 uint32 *returned = &r_u->returned;
7742 /* that's an [in out] buffer */
7743 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7744 buffer = r_u->buffer;
7746 DEBUG(5,("spoolss_enumprintmonitors\n"));
7749 * Enumerate the print monitors ...
7751 * Just reply with "Local Port", to keep NT happy
7752 * and I can use my nice printer checker.
7755 *returned=0;
7756 *needed=0;
7758 switch (level) {
7759 case 1:
7760 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7761 case 2:
7762 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7763 default:
7764 return WERR_UNKNOWN_LEVEL;
7768 /****************************************************************************
7769 ****************************************************************************/
7771 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7773 int i=0;
7774 BOOL found=False;
7775 JOB_INFO_1 *info_1=NULL;
7777 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7779 if (info_1 == NULL) {
7780 SAFE_FREE(queue);
7781 return WERR_NOMEM;
7784 for (i=0; i<count && found==False; i++) {
7785 if (queue[i].job==(int)jobid)
7786 found=True;
7789 if (found==False) {
7790 SAFE_FREE(queue);
7791 SAFE_FREE(info_1);
7792 /* NT treats not found as bad param... yet another bad choice */
7793 return WERR_INVALID_PARAM;
7796 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7798 SAFE_FREE(queue);
7800 *needed += spoolss_size_job_info_1(info_1);
7802 if (!alloc_buffer_size(buffer, *needed)) {
7803 SAFE_FREE(info_1);
7804 return WERR_INSUFFICIENT_BUFFER;
7807 smb_io_job_info_1("", buffer, info_1, 0);
7809 SAFE_FREE(info_1);
7811 if (*needed > offered)
7812 return WERR_INSUFFICIENT_BUFFER;
7814 return WERR_OK;
7817 /****************************************************************************
7818 ****************************************************************************/
7820 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7822 int i=0;
7823 BOOL found=False;
7824 JOB_INFO_2 *info_2;
7825 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7826 WERROR ret;
7827 DEVICEMODE *devmode = NULL;
7829 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7831 ZERO_STRUCTP(info_2);
7833 if (info_2 == NULL) {
7834 ret = WERR_NOMEM;
7835 goto done;
7838 for (i=0; i<count && found==False; i++) {
7839 if (queue[i].job==(int)jobid)
7840 found=True;
7843 if (found==False) {
7844 /* NT treats not found as bad param... yet another bad
7845 choice */
7846 ret = WERR_INVALID_PARAM;
7847 goto done;
7850 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7851 if (!W_ERROR_IS_OK(ret))
7852 goto done;
7853 if (construct_dev_mode(snum) == NULL) {
7854 ret = WERR_NOMEM;
7855 goto done;
7858 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7860 *needed += spoolss_size_job_info_2(info_2);
7862 if (!alloc_buffer_size(buffer, *needed)) {
7863 ret = WERR_INSUFFICIENT_BUFFER;
7864 goto done;
7867 smb_io_job_info_2("", buffer, info_2, 0);
7869 if (*needed > offered) {
7870 ret = WERR_INSUFFICIENT_BUFFER;
7871 goto done;
7874 ret = WERR_OK;
7876 done:
7877 /* Cleanup allocated memory */
7879 SAFE_FREE(queue);
7880 free_job_info_2(info_2); /* Also frees devmode */
7881 SAFE_FREE(info_2);
7882 free_a_printer(&ntprinter, 2);
7884 return ret;
7887 /****************************************************************************
7888 ****************************************************************************/
7890 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7892 POLICY_HND *handle = &q_u->handle;
7893 uint32 jobid = q_u->jobid;
7894 uint32 level = q_u->level;
7895 NEW_BUFFER *buffer = NULL;
7896 uint32 offered = q_u->offered;
7897 uint32 *needed = &r_u->needed;
7899 int snum;
7900 int count;
7901 print_queue_struct *queue=NULL;
7902 print_status_struct prt_status;
7904 /* that's an [in out] buffer */
7905 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7906 buffer = r_u->buffer;
7908 DEBUG(5,("spoolss_getjob\n"));
7910 *needed=0;
7912 if (!get_printer_snum(p, handle, &snum))
7913 return WERR_BADFID;
7915 count = print_queue_status(snum, &queue, &prt_status);
7917 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7918 count, prt_status.status, prt_status.message));
7920 switch (level) {
7921 case 1:
7922 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7923 case 2:
7924 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7925 default:
7926 SAFE_FREE(queue);
7927 return WERR_UNKNOWN_LEVEL;
7931 /********************************************************************
7932 * spoolss_getprinterdataex
7933 ********************************************************************/
7935 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7937 POLICY_HND *handle = &q_u->handle;
7938 uint32 in_size = q_u->size;
7939 uint32 *type = &r_u->type;
7940 uint32 *out_size = &r_u->size;
7941 uint8 **data = &r_u->data;
7942 uint32 *needed = &r_u->needed;
7944 fstring key, value;
7945 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7946 BOOL found = False;
7948 DEBUG(4,("_spoolss_getprinterdataex\n"));
7950 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7951 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7953 /* in case of problem, return some default values */
7954 *needed=0;
7955 *type=0;
7956 *out_size=0;
7959 if (!Printer) {
7960 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7961 return WERR_NOMEM;
7962 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7963 return WERR_BADFID;
7967 /* Is the handle to a printer or to the server? */
7969 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7971 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7972 return WERR_INVALID_PARAM;
7974 else
7977 * From MSDN documentation of GetPrinterDataEx: pass request
7978 * to GetPrinterData if key is "PrinterDriverData". This is
7979 * the only key we really support. Other keys to implement:
7980 * (a) DsDriver
7981 * (b) DsSpooler
7982 * (c) PnPData
7985 if (strcmp(key, "PrinterDriverData") != 0)
7986 return WERR_BADFILE;
7988 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7989 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7990 type, data, needed, in_size);
7994 if (!found) {
7995 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7997 /* reply this param doesn't exist */
7998 if (*out_size) {
7999 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
8000 return WERR_NOMEM;
8001 } else {
8002 *data = NULL;
8005 return WERR_INVALID_PARAM;
8008 if (*needed > *out_size)
8009 return WERR_MORE_DATA;
8010 else
8011 return WERR_OK;
8014 /********************************************************************
8015 * spoolss_setprinterdata
8016 ********************************************************************/
8018 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8020 SPOOL_Q_SETPRINTERDATA q_u_local;
8021 SPOOL_R_SETPRINTERDATA r_u_local;
8022 fstring key;
8024 DEBUG(4,("_spoolss_setprinterdataex\n"));
8026 /* From MSDN documentation of SetPrinterDataEx: pass request to
8027 SetPrinterData if key is "PrinterDriverData" */
8029 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8031 if (strcmp(key, "PrinterDriverData") != 0)
8032 return WERR_INVALID_PARAM;
8034 ZERO_STRUCT(q_u_local);
8035 ZERO_STRUCT(r_u_local);
8037 /* make a copy to call _spoolss_setprinterdata() */
8039 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
8040 copy_unistr2(&q_u_local.value, &q_u->value);
8041 q_u_local.type = q_u->type;
8042 q_u_local.max_len = q_u->max_len;
8043 q_u_local.data = q_u->data;
8044 q_u_local.real_len = q_u->real_len;
8045 q_u_local.numeric_data = q_u->numeric_data;
8047 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
8051 /********************************************************************
8052 * spoolss_deleteprinterdataex
8053 ********************************************************************/
8055 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8057 SPOOL_Q_DELETEPRINTERDATA q_u_local;
8058 SPOOL_R_DELETEPRINTERDATA r_u_local;
8059 fstring key;
8061 /* From MSDN documentation of SetPrinterDataEx: pass request to
8062 SetPrinterData if key is "PrinterDriverData" */
8064 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8066 if (strcmp(key, "PrinterDriverData") != 0)
8067 return WERR_INVALID_PARAM;
8069 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
8070 copy_unistr2(&q_u_local.valuename, &q_u->valuename);
8072 return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
8078 /********************************************************************
8079 * spoolss_enumprinterkey
8080 ********************************************************************/
8082 /* constants for EnumPrinterKey() */
8083 #define ENUMERATED_KEY_SIZE 19
8085 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8087 fstring key;
8088 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
8089 char* ptr = NULL;
8090 int i;
8091 char *PrinterKey = "PrinterDriverData";
8093 DEBUG(4,("_spoolss_enumprinterkey\n"));
8095 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8098 * we only support enumating all keys (key == "")
8099 * Of course, the only key we support is the "PrinterDriverData"
8100 * key
8102 if (strlen(key) == 0)
8104 r_u->needed = ENUMERATED_KEY_SIZE *2;
8105 if (q_u->size < r_u->needed)
8106 return WERR_MORE_DATA;
8108 ptr = PrinterKey;
8109 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
8111 enumkeys[i] = (uint16)(*ptr);
8112 ptr++;
8115 /* tag of with 2 '\0's */
8116 enumkeys[i++] = '\0';
8117 enumkeys[i] = '\0';
8119 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
8120 return WERR_BADFILE;
8122 return WERR_OK;
8125 /* The "PrinterDriverData" key should have no subkeys */
8126 if (strcmp(key, PrinterKey) == 0)
8128 r_u-> needed = 2;
8129 if (q_u->size < r_u->needed)
8130 return WERR_MORE_DATA;
8131 enumkeys[0] = 0x0;
8132 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
8133 return WERR_BADFILE;
8135 return WERR_OK;
8139 /* The return value for an unknown key is documented in MSDN
8140 EnumPrinterKey description */
8141 return WERR_BADFILE;
8144 /********************************************************************
8145 * spoolss_deleteprinterkey
8146 ********************************************************************/
8148 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8150 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8151 fstring key;
8153 if (!Printer) {
8154 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
8155 return WERR_BADFID;
8158 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8160 if (strcmp(key, "PrinterDriverData") != 0)
8161 return WERR_INVALID_PARAM;
8164 * this is what 2k returns when you try to delete the "PrinterDriverData"
8165 * key
8168 return WERR_ACCESS_DENIED;
8172 /********************************************************************
8173 * spoolss_enumprinterdataex
8174 ********************************************************************/
8176 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8178 POLICY_HND *handle = &q_u->handle;
8179 uint32 in_size = q_u->size;
8180 uint32 num_entries,
8181 needed;
8182 NT_PRINTER_INFO_LEVEL *printer = NULL;
8183 PRINTER_ENUM_VALUES *enum_values = NULL;
8184 fstring key, value;
8185 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8186 int snum;
8187 uint32 param_index,
8188 data_len,
8189 type;
8190 WERROR result;
8191 uint8 *data=NULL;
8194 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8196 if (!Printer) {
8197 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8198 return WERR_BADFID;
8203 * The only key we support is "PrinterDriverData". This should return
8204 > an array of all the key/value pairs returned by EnumPrinterDataSee
8205 * _spoolss_getprinterdataex() for details --jerry
8208 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8209 if (strcmp(key, "PrinterDriverData") != 0)
8211 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8212 return WERR_INVALID_PARAM;
8216 if (!get_printer_snum(p,handle, &snum))
8217 return WERR_BADFID;
8219 ZERO_STRUCT(printer);
8220 result = get_a_printer(&printer, 2, lp_servicename(snum));
8221 if (!W_ERROR_IS_OK(result))
8222 return result;
8226 * loop through all params and build the array to pass
8227 * back to the client
8229 result = WERR_OK;
8230 param_index = 0;
8231 needed = 0;
8232 num_entries = 0;
8234 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
8236 PRINTER_ENUM_VALUES *ptr;
8237 uint32 add_len = 0;
8239 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
8241 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
8243 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
8244 result = WERR_NOMEM;
8245 goto done;
8247 enum_values = ptr;
8249 /* copy the data */
8250 init_unistr(&enum_values[num_entries].valuename, value);
8251 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
8252 enum_values[num_entries].type = type;
8254 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
8255 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
8256 result = WERR_NOMEM;
8257 goto done;
8259 memcpy(enum_values[num_entries].data, data, data_len);
8260 enum_values[num_entries].data_len = data_len + add_len;
8262 /* keep track of the size of the array in bytes */
8264 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
8266 num_entries++;
8267 param_index++;
8270 r_u->needed = needed;
8271 r_u->returned = num_entries;
8273 if (needed > in_size) {
8274 result = WERR_MORE_DATA;
8275 goto done;
8278 /* copy data into the reply */
8280 r_u->ctr.size = r_u->needed;
8281 r_u->ctr.size_of_array = r_u->returned;
8282 r_u->ctr.values = enum_values;
8286 done:
8287 free_a_printer(&printer, 2);
8289 return result;
8292 /****************************************************************************
8293 ****************************************************************************/
8295 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8297 init_unistr(&info->name, name);
8300 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8301 UNISTR2 *environment,
8302 NEW_BUFFER *buffer,
8303 uint32 offered,
8304 uint32 *needed)
8306 pstring path;
8307 pstring long_archi;
8308 pstring short_archi;
8309 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8311 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8313 if (get_short_archi(short_archi, long_archi)==False)
8314 return WERR_INVALID_ENVIRONMENT;
8316 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8317 return WERR_NOMEM;
8319 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8321 fill_printprocessordirectory_1(info, path);
8323 *needed += spoolss_size_printprocessordirectory_info_1(info);
8325 if (!alloc_buffer_size(buffer, *needed)) {
8326 safe_free(info);
8327 return WERR_INSUFFICIENT_BUFFER;
8330 smb_io_printprocessordirectory_1("", buffer, info, 0);
8332 safe_free(info);
8334 if (*needed > offered)
8335 return WERR_INSUFFICIENT_BUFFER;
8336 else
8337 return WERR_OK;
8340 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8342 uint32 level = q_u->level;
8343 NEW_BUFFER *buffer = NULL;
8344 uint32 offered = q_u->offered;
8345 uint32 *needed = &r_u->needed;
8346 WERROR result;
8348 /* that's an [in out] buffer */
8349 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8350 buffer = r_u->buffer;
8352 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8354 *needed=0;
8356 switch(level) {
8357 case 1:
8358 result = getprintprocessordirectory_level_1
8359 (&q_u->name, &q_u->environment, buffer, offered, needed);
8360 default:
8361 result = WERR_UNKNOWN_LEVEL;
8364 return result;