sync'ing up for 3.0alpha20 release
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob2190215107af553f5e11072aa88b3a8260af3732
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-2002,
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;
91 /* devmode sent in the OpenPrinter() call */
92 NT_DEVICEMODE *nt_devmode;
94 } Printer_entry;
96 static Printer_entry *printers_list;
98 typedef struct _counter_printer_0 {
99 ubi_dlNode Next;
100 ubi_dlNode Prev;
102 int snum;
103 uint32 counter;
104 } counter_printer_0;
106 static ubi_dlList counter_list;
108 static struct cli_state notify_cli; /* print notify back-channel */
109 static uint32 smb_connections=0;
112 /* in printing/nt_printing.c */
114 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
116 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
117 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
119 /* translate between internal status numbers and NT status numbers */
120 static int nt_printj_status(int v)
122 switch (v) {
123 case LPQ_QUEUED:
124 return 0;
125 case LPQ_PAUSED:
126 return JOB_STATUS_PAUSED;
127 case LPQ_SPOOLING:
128 return JOB_STATUS_SPOOLING;
129 case LPQ_PRINTING:
130 return JOB_STATUS_PRINTING;
131 case LPQ_ERROR:
132 return JOB_STATUS_ERROR;
133 case LPQ_DELETING:
134 return JOB_STATUS_DELETING;
135 case LPQ_OFFLINE:
136 return JOB_STATUS_OFFLINE;
137 case LPQ_PAPEROUT:
138 return JOB_STATUS_PAPEROUT;
139 case LPQ_PRINTED:
140 return JOB_STATUS_PRINTED;
141 case LPQ_DELETED:
142 return JOB_STATUS_DELETED;
143 case LPQ_BLOCKED:
144 return JOB_STATUS_BLOCKED;
145 case LPQ_USER_INTERVENTION:
146 return JOB_STATUS_USER_INTERVENTION;
148 return 0;
151 static int nt_printq_status(int v)
153 switch (v) {
154 case LPQ_PAUSED:
155 return PRINTER_STATUS_PAUSED;
156 case LPQ_QUEUED:
157 case LPQ_SPOOLING:
158 case LPQ_PRINTING:
159 return 0;
161 return 0;
164 /****************************************************************************
165 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
166 ****************************************************************************/
168 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
170 if (*pp == NULL)
171 return;
173 SAFE_FREE((*pp)->ctr.type);
174 SAFE_FREE(*pp);
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
181 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
183 WERROR result;
185 /* weird if the test succeds !!! */
186 if (smb_connections==0) {
187 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
188 return;
191 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
193 if (!W_ERROR_IS_OK(result))
194 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
195 dos_errstr(result)));
197 /* if it's the last connection, deconnect the IPC$ share */
198 if (smb_connections==1) {
199 cli_nt_session_close(&notify_cli);
200 cli_ulogoff(&notify_cli);
201 cli_shutdown(&notify_cli);
202 message_deregister(MSG_PRINTER_NOTIFY2);
204 /* Tell the connections db we're no longer interested in
205 * printer notify messages. */
207 register_message_flags( False, FLAG_MSG_PRINTING );
210 smb_connections--;
213 /****************************************************************************
214 Functions to free a printer entry datastruct.
215 ****************************************************************************/
217 static void free_printer_entry(void *ptr)
219 Printer_entry *Printer = (Printer_entry *)ptr;
221 if (Printer->notify.client_connected==True)
222 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
224 Printer->notify.flags=0;
225 Printer->notify.options=0;
226 Printer->notify.localmachine[0]='\0';
227 Printer->notify.printerlocal=0;
228 free_spool_notify_option(&Printer->notify.option);
229 Printer->notify.option=NULL;
230 Printer->notify.client_connected=False;
232 free_nt_devicemode( &Printer->nt_devmode );
234 /* Remove from the internal list. */
235 DLIST_REMOVE(printers_list, Printer);
237 SAFE_FREE(Printer);
240 /****************************************************************************
241 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
242 ****************************************************************************/
244 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
246 SPOOL_NOTIFY_OPTION *new_sp = NULL;
248 if (!sp)
249 return NULL;
251 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
252 if (!new_sp)
253 return NULL;
255 *new_sp = *sp;
257 if (sp->ctr.count) {
258 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
260 if (!new_sp->ctr.type) {
261 SAFE_FREE(new_sp);
262 return NULL;
266 return new_sp;
269 /****************************************************************************
270 find printer index by handle
271 ****************************************************************************/
273 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
275 Printer_entry *find_printer = NULL;
277 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
278 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
279 return NULL;
282 return find_printer;
285 /****************************************************************************
286 Close printer index by handle.
287 ****************************************************************************/
289 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
291 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
293 if (!Printer) {
294 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
295 return False;
298 close_policy_hnd(p, hnd);
300 return True;
303 /****************************************************************************
304 Delete a printer given a handle.
305 ****************************************************************************/
307 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
309 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
311 if (!Printer) {
312 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
313 return WERR_BADFID;
316 if (del_a_printer(Printer->dev.handlename) != 0) {
317 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
318 return WERR_BADFID;
321 /* Check calling user has permission to delete printer. Note that
322 since we set the snum parameter to -1 only administrators can
323 delete the printer. This stops people with the Full Control
324 permission from deleting the printer. */
326 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
327 DEBUG(3, ("printer delete denied by security descriptor\n"));
328 return WERR_ACCESS_DENIED;
331 if (*lp_deleteprinter_cmd()) {
333 char *cmd = lp_deleteprinter_cmd();
334 pstring command;
335 int ret;
336 int i;
338 /* Printer->dev.handlename equals portname equals sharename */
339 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
340 Printer->dev.handlename);
342 DEBUG(10,("Running [%s]\n", command));
343 ret = smbrun(command, NULL);
344 if (ret != 0) {
345 return WERR_BADFID; /* What to return here? */
347 DEBUGADD(10,("returned [%d]\n", ret));
349 /* Send SIGHUP to process group... is there a better way? */
350 kill(0, SIGHUP);
352 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
353 lp_killservice( i );
354 return WERR_OK;
355 } else
356 return WERR_ACCESS_DENIED;
359 return WERR_OK;
362 /****************************************************************************
363 Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
366 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
368 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370 if (!Printer) {
371 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
372 return False;
375 switch (Printer->printer_type) {
376 case PRINTER_HANDLE_IS_PRINTER:
377 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
378 *number = print_queue_snum(Printer->dev.handlename);
379 return (*number != -1);
380 case PRINTER_HANDLE_IS_PRINTSERVER:
381 return False;
382 default:
383 return False;
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
398 return False;
401 /* it's a print server */
402 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
406 /* it's a printer */
407 else {
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
412 return True;
415 /****************************************************************************
416 Set printer handle name.
417 ****************************************************************************/
419 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
421 int snum;
422 int n_services=lp_numservices();
423 char *aprinter;
424 fstring sname;
425 BOOL found=False;
427 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
429 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
430 ZERO_STRUCT(Printer->dev.printerservername);
431 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
432 return True;
435 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
436 return False;
438 if (*handlename=='\\') {
439 aprinter=strchr_m(handlename+2, '\\');
440 aprinter++;
442 else {
443 aprinter=handlename;
446 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
449 * The original code allowed smbd to store a printer name that
450 * was different from the share name. This is not possible
451 * anymore, so I've simplified this loop greatly. Here
452 * we are just verifying that the printer name is a valid
453 * printer service defined in smb.conf
454 * --jerry [Fri Feb 15 11:17:46 CST 2002]
457 for (snum=0; snum<n_services; snum++) {
459 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
460 continue;
462 fstrcpy(sname, lp_servicename(snum));
464 DEBUGADD(5,("share:%s\n",sname));
466 if (! StrCaseCmp(sname, aprinter)) {
467 found = True;
468 break;
474 if (!found) {
475 DEBUGADD(4,("Printer not found\n"));
476 return False;
479 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
481 ZERO_STRUCT(Printer->dev.handlename);
482 fstrcpy(Printer->dev.handlename, sname);
484 return True;
487 /****************************************************************************
488 Find first available printer slot. creates a printer handle for you.
489 ****************************************************************************/
491 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
493 Printer_entry *new_printer;
495 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
497 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
498 return False;
500 ZERO_STRUCTP(new_printer);
502 new_printer->notify.option=NULL;
504 /* Add to the internal list. */
505 DLIST_ADD(printers_list, new_printer);
507 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
508 SAFE_FREE(new_printer);
509 return False;
512 if (!set_printer_hnd_printertype(new_printer, name)) {
513 close_printer_handle(p, hnd);
514 return False;
517 if (!set_printer_hnd_name(new_printer, name)) {
518 close_printer_handle(p, hnd);
519 return False;
522 new_printer->access_granted = access_granted;
524 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
526 return True;
529 /****************************************************************************
530 Allocate more memory for a BUFFER.
531 ****************************************************************************/
533 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
535 prs_struct *ps;
536 uint32 extra_space;
537 uint32 old_offset;
539 ps= &buffer->prs;
541 /* damn, I'm doing the reverse operation of prs_grow() :) */
542 if (buffer_size < prs_data_size(ps))
543 extra_space=0;
544 else
545 extra_space = buffer_size - prs_data_size(ps);
548 * save the offset and move to the end of the buffer
549 * prs_grow() checks the extra_space against the offset
551 old_offset=prs_offset(ps);
552 prs_set_offset(ps, prs_data_size(ps));
554 if (!prs_grow(ps, extra_space))
555 return False;
557 prs_set_offset(ps, old_offset);
559 buffer->string_at_end=prs_data_size(ps);
561 return True;
564 /***************************************************************************
565 check to see if the client motify handle is monitoring the notification
566 given by (notify_type, notify_field).
567 **************************************************************************/
569 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
570 uint16 notify_field)
572 return True;
575 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
576 uint16 notify_field)
578 SPOOL_NOTIFY_OPTION *option = p->notify.option;
579 uint32 i, j;
582 * Flags should always be zero when the change notify
583 * is registered by the cliebnt's spooler. A user Win32 app
584 * might use the flags though instead of the NOTIFY_OPTION_INFO
585 * --jerry
588 if (p->notify.flags)
589 return is_monitoring_event_flags(
590 p->notify.flags, notify_type, notify_field);
592 for (i = 0; i < option->count; i++) {
594 /* Check match for notify_type */
596 if (option->ctr.type[i].type != notify_type)
597 continue;
599 /* Check match for field */
601 for (j = 0; j < option->ctr.type[i].count; j++) {
602 if (option->ctr.type[i].fields[j] == notify_field) {
603 return True;
608 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
609 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
610 p->dev.handlename : p->dev.printerservername,
611 notify_type, notify_field));
613 return False;
616 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
618 static void notify_one_value(struct spoolss_notify_msg *msg,
619 SPOOL_NOTIFY_INFO_DATA *data,
620 TALLOC_CTX *mem_ctx)
622 data->notify_data.value[0] = msg->notify.value[0];
623 data->notify_data.value[1] = 0;
626 static void notify_string(struct spoolss_notify_msg *msg,
627 SPOOL_NOTIFY_INFO_DATA *data,
628 TALLOC_CTX *mem_ctx)
630 UNISTR2 unistr;
632 /* The length of the message includes the trailing \0 */
634 init_unistr2(&unistr, msg->notify.data, msg->len);
636 data->notify_data.data.length = msg->len * 2;
637 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
639 if (!data->notify_data.data.string) {
640 data->notify_data.data.length = 0;
641 return;
644 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
647 static void notify_system_time(struct spoolss_notify_msg *msg,
648 SPOOL_NOTIFY_INFO_DATA *data,
649 TALLOC_CTX *mem_ctx)
651 SYSTEMTIME systime;
652 prs_struct ps;
654 if (msg->len != sizeof(time_t)) {
655 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
656 msg->len));
657 return;
660 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
661 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
662 return;
665 if (!make_systemtime(&systime, localtime((time_t *)msg->notify.data))) {
666 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
667 return;
670 if (!spoolss_io_system_time("", &ps, 0, &systime))
671 return;
673 data->notify_data.data.length = prs_offset(&ps);
674 data->notify_data.data.string =
675 talloc(mem_ctx, prs_offset(&ps));
677 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
679 prs_mem_free(&ps);
682 struct notify2_message_table {
683 char *name;
684 void (*fn)(struct spoolss_notify_msg *msg,
685 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
688 static struct notify2_message_table printer_notify_table[] = {
689 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
690 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
691 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
692 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
693 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
694 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
695 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
696 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
697 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
698 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
699 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
700 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
701 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
702 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
703 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
704 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
705 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
706 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
707 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
710 static struct notify2_message_table job_notify_table[] = {
711 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
712 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
713 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
714 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
715 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
716 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
717 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
718 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
719 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
720 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
721 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
722 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
723 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
724 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
725 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
726 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
727 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
728 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
729 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
730 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
731 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
732 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
733 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
734 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
738 /***********************************************************************
739 Allocate talloc context for container object
740 **********************************************************************/
742 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
744 if ( !ctr )
745 return;
747 ctr->ctx = talloc_init();
749 return;
752 /***********************************************************************
753 release all allocated memory and zero out structure
754 **********************************************************************/
756 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
758 if ( !ctr )
759 return;
761 if ( ctr->ctx )
762 talloc_destroy(ctr->ctx);
764 ZERO_STRUCTP(ctr);
766 return;
769 /***********************************************************************
770 **********************************************************************/
772 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
774 if ( !ctr )
775 return NULL;
777 return ctr->ctx;
780 /***********************************************************************
781 **********************************************************************/
783 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
785 if ( !ctr || !ctr->msg_groups )
786 return NULL;
788 if ( idx >= ctr->num_groups )
789 return NULL;
791 return &ctr->msg_groups[idx];
795 /***********************************************************************
796 How many groups of change messages do we have ?
797 **********************************************************************/
799 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
801 if ( !ctr )
802 return 0;
804 return ctr->num_groups;
807 /***********************************************************************
808 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
809 **********************************************************************/
811 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
813 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
814 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
815 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
816 int i, new_slot;
818 if ( !ctr || !msg )
819 return 0;
821 /* loop over all groups looking for a matching printer name */
823 for ( i=0; i<ctr->num_groups; i++ ) {
824 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
825 break;
828 /* add a new group? */
830 if ( i == ctr->num_groups )
832 ctr->num_groups++;
834 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
835 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
836 return 0;
838 ctr->msg_groups = groups;
840 /* clear the new entry and set the printer name */
842 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
843 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
846 /* add the change messages; 'i' is the correct index now regardless */
848 msg_grp = &ctr->msg_groups[i];
850 msg_grp->num_msgs++;
852 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
853 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
854 return 0;
856 msg_grp->msgs = msg_list;
858 new_slot = msg_grp->num_msgs-1;
859 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
861 /* need to allocate own copy of data */
863 if ( msg->len != 0 )
864 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
866 return ctr->num_groups;
869 /***********************************************************************
870 Send a change notication message on all handles which have a call
871 back registered
872 **********************************************************************/
874 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
876 Printer_entry *p;
877 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
878 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
879 SPOOLSS_NOTIFY_MSG *messages;
882 if ( !msg_group ) {
883 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
884 return;
887 messages = msg_group->msgs;
889 if ( !messages ) {
890 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
891 return;
894 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
896 /* loop over all printers */
898 for (p = printers_list; p; p = p->next)
900 SPOOL_NOTIFY_INFO_DATA *data;
901 uint32 data_len = 0;
902 uint32 id;
903 int i;
905 /* Is there notification on this handle? */
907 if ( !p->notify.client_connected )
908 continue;
910 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
912 /* For this printer? Print servers always receive
913 notifications. */
915 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
916 ( !strequal(msg_group->printername, p->dev.handlename) ) )
917 continue;
919 DEBUG(10,("Our printer\n"));
921 /* allocate the max entries possible */
923 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
924 ZERO_STRUCTP(data);
926 /* build the array of change notifications */
928 for ( i=0; i<msg_group->num_msgs; i++ )
930 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
932 /* Are we monitoring this event? */
934 if (!is_monitoring_event(p, msg->type, msg->field))
935 continue;
938 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
939 msg->type, msg->field, p->dev.handlename));
942 * if the is a printer notification handle and not a job notification
943 * type, then set the id to 0. Other wise just use what was specified
944 * in the message.
946 * When registering change notification on a print server handle
947 * we always need to send back the id (snum) matching the printer
948 * for which the change took place. For change notify registered
949 * on a printer handle, this does not matter and the id should be 0.
951 * --jerry
954 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
955 id = 0;
956 else
957 id = msg->id;
960 /* Convert unix jobid to smb jobid */
962 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
964 id = sysjob_to_jobid(msg->id);
966 if (id == -1) {
967 DEBUG(3, ("no such unix jobid %d\n", msg->id));
968 goto done;
972 construct_info_data( &data[data_len], msg->type, msg->field, id );
974 switch(msg->type) {
975 case PRINTER_NOTIFY_TYPE:
976 if ( !printer_notify_table[msg->field].fn )
977 goto done;
978 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
980 break;
982 case JOB_NOTIFY_TYPE:
983 if ( !job_notify_table[msg->field].fn )
984 goto done;
985 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
987 break;
989 default:
990 DEBUG(5, ("Unknown notification type %d\n", msg->type));
991 goto done;
994 data_len++;
997 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
998 data_len, data, p->notify.change, 0 );
1001 done:
1002 DEBUG(8,("send_notify2_changes: Exit...\n"));
1003 return;
1006 /***********************************************************************
1007 **********************************************************************/
1009 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1012 int offset = 0;
1014 /* Unpack message */
1016 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1017 msg->printer);
1019 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1020 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1022 if (msg->len == 0)
1023 tdb_unpack((char *)buf + offset, len - offset, "dd",
1024 &msg->notify.value[0], &msg->notify.value[1]);
1025 else
1026 tdb_unpack((char *)buf + offset, len - offset, "B",
1027 &msg->len, &msg->notify.data);
1029 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1030 msg->type, msg->field, msg->flags));
1032 if (msg->len == 0)
1033 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1034 msg->notify.value[1]));
1035 else
1036 dump_data(3, msg->notify.data, msg->len);
1038 return True;
1041 /********************************************************************
1042 Receive a notify2 message list
1043 ********************************************************************/
1045 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1047 size_t msg_count, i;
1048 char *buf = (char *)msg;
1049 char *msg_ptr;
1050 size_t msg_len;
1051 SPOOLSS_NOTIFY_MSG notify;
1052 SPOOLSS_NOTIFY_MSG_CTR messages;
1053 int num_groups;
1055 if (len < 4) {
1056 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1057 return;
1060 msg_count = IVAL(buf, 0);
1061 msg_ptr = buf + 4;
1063 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1065 if (msg_count == 0) {
1066 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1067 return;
1070 /* initialize the container */
1072 ZERO_STRUCT( messages );
1073 notify_msg_ctr_init( &messages );
1076 * build message groups for each printer identified
1077 * in a change_notify msg. Remember that a PCN message
1078 * includes the handle returned for the srv_spoolss_replyopenprinter()
1079 * call. Therefore messages are grouped according to printer handle.
1082 for ( i=0; i<msg_count; i++ )
1084 if (msg_ptr + 4 - buf > len) {
1085 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1086 return;
1089 msg_len = IVAL(msg_ptr,0);
1090 msg_ptr += 4;
1092 if (msg_ptr + msg_len - buf > len) {
1093 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1094 return;
1097 /* unpack messages */
1099 ZERO_STRUCT( notify );
1100 notify2_unpack_msg( &notify, msg_ptr, msg_len );
1101 msg_ptr += msg_len;
1103 /* add to correct list in container */
1105 notify_msg_ctr_addmsg( &messages, &notify );
1107 /* free memory that might have been allocated by notify2_unpack_msg() */
1109 if ( notify.len != 0 )
1110 SAFE_FREE( notify.notify.data );
1113 /* process each group of messages */
1115 num_groups = notify_msg_ctr_numgroups( &messages );
1116 for ( i=0; i<num_groups; i++ )
1117 send_notify2_changes( &messages, i );
1120 /* cleanup */
1122 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1124 notify_msg_ctr_destroy( &messages );
1126 return;
1129 /********************************************************************
1130 Send a message to ourself about new driver being installed
1131 so we can upgrade the information for each printer bound to this
1132 driver
1133 ********************************************************************/
1135 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1137 int len = strlen(drivername);
1139 if (!len)
1140 return False;
1142 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1143 drivername));
1145 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1147 return True;
1150 /**********************************************************************
1151 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1152 over all printers, upgrading ones as neessary
1153 **********************************************************************/
1155 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1157 fstring drivername;
1158 int snum;
1159 int n_services = lp_numservices();
1161 len = MIN(len,sizeof(drivername)-1);
1162 strncpy(drivername, buf, len);
1164 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1166 /* Iterate the printer list */
1168 for (snum=0; snum<n_services; snum++)
1170 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1172 WERROR result;
1173 NT_PRINTER_INFO_LEVEL *printer = NULL;
1175 result = get_a_printer(&printer, 2, lp_servicename(snum));
1176 if (!W_ERROR_IS_OK(result))
1177 continue;
1179 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1181 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1183 /* all we care about currently is the change_id */
1185 result = mod_a_printer(*printer, 2);
1186 if (!W_ERROR_IS_OK(result)) {
1187 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1188 dos_errstr(result)));
1192 free_a_printer(&printer, 2);
1196 /* all done */
1199 /********************************************************************
1200 Send a message to ourself about new driver being installed
1201 so we can upgrade the information for each printer bound to this
1202 driver
1203 ********************************************************************/
1205 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1207 int len = strlen(drivername);
1209 if (!len)
1210 return False;
1212 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1213 drivername));
1215 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1217 return True;
1220 /**********************************************************************
1221 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1222 over all printers, resetting printer data as neessary
1223 **********************************************************************/
1225 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1227 fstring drivername;
1228 int snum;
1229 int n_services = lp_numservices();
1231 len = MIN( len, sizeof(drivername)-1 );
1232 strncpy( drivername, buf, len );
1234 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1236 /* Iterate the printer list */
1238 for ( snum=0; snum<n_services; snum++ )
1240 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1242 WERROR result;
1243 NT_PRINTER_INFO_LEVEL *printer = NULL;
1245 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1246 if ( !W_ERROR_IS_OK(result) )
1247 continue;
1250 * if the printer is bound to the driver,
1251 * then reset to the new driver initdata
1254 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1256 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1258 if ( !set_driver_init(printer, 2) ) {
1259 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1260 printer->info_2->printername, printer->info_2->drivername));
1264 free_a_printer( &printer, 2 );
1268 /* all done */
1270 return;
1273 /********************************************************************
1274 Copy routines used by convert_to_openprinterex()
1275 *******************************************************************/
1277 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1279 DEVICEMODE *d;
1280 int len;
1282 if (!devmode)
1283 return NULL;
1285 DEBUG (8,("dup_devmode\n"));
1287 /* bulk copy first */
1289 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1290 if (!d)
1291 return NULL;
1293 /* dup the pointer members separately */
1295 len = unistrlen(devmode->devicename.buffer);
1296 if (len != -1) {
1297 d->devicename.buffer = talloc(ctx, len*2);
1298 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1299 return NULL;
1303 len = unistrlen(devmode->formname.buffer);
1304 if (len != -1) {
1305 d->devicename.buffer = talloc(ctx, len*2);
1306 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1307 return NULL;
1310 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1312 return d;
1315 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1317 if (!new_ctr || !ctr)
1318 return;
1320 DEBUG(8,("copy_devmode_ctr\n"));
1322 new_ctr->size = ctr->size;
1323 new_ctr->devmode_ptr = ctr->devmode_ptr;
1325 if(ctr->devmode_ptr)
1326 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1329 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1331 if (!new_def || !def)
1332 return;
1334 DEBUG(8,("copy_printer_defaults\n"));
1336 new_def->datatype_ptr = def->datatype_ptr;
1338 if (def->datatype_ptr)
1339 copy_unistr2(&new_def->datatype, &def->datatype);
1341 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1343 new_def->access_required = def->access_required;
1346 /********************************************************************
1347 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1348 * SPOOL_Q_OPEN_PRINTER_EX structure
1349 ********************************************************************/
1351 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1353 if (!q_u_ex || !q_u)
1354 return;
1356 DEBUG(8,("convert_to_openprinterex\n"));
1358 q_u_ex->printername_ptr = q_u->printername_ptr;
1360 if (q_u->printername_ptr)
1361 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1363 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1366 /********************************************************************
1367 * spoolss_open_printer
1369 * called from the spoolss dispatcher
1370 ********************************************************************/
1372 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1374 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1375 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1377 if (!q_u || !r_u)
1378 return WERR_NOMEM;
1380 ZERO_STRUCT(q_u_ex);
1381 ZERO_STRUCT(r_u_ex);
1383 /* convert the OpenPrinter() call to OpenPrinterEx() */
1385 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1387 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1389 /* convert back to OpenPrinter() */
1391 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1393 return r_u->status;
1396 /********************************************************************
1397 * spoolss_open_printer
1399 * If the openprinterex rpc call contains a devmode,
1400 * it's a per-user one. This per-user devmode is derivated
1401 * from the global devmode. Openprinterex() contains a per-user
1402 * devmode for when you do EMF printing and spooling.
1403 * In the EMF case, the NT workstation is only doing half the job
1404 * of rendering the page. The other half is done by running the printer
1405 * driver on the server.
1406 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1407 * The EMF file only contains what is to be printed on the page.
1408 * So in order for the server to know how to print, the NT client sends
1409 * a devicemode attached to the openprinterex call.
1410 * But this devicemode is short lived, it's only valid for the current print job.
1412 * If Samba would have supported EMF spooling, this devicemode would
1413 * have been attached to the handle, to sent it to the driver to correctly
1414 * rasterize the EMF file.
1416 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1417 * we just act as a pass-thru between windows and the printer.
1419 * In order to know that Samba supports only RAW spooling, NT has to call
1420 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1421 * and until NT sends a RAW job, we refuse it.
1423 * But to call getprinter() or startdoc(), you first need a valid handle,
1424 * and to get an handle you have to call openprintex(). Hence why you have
1425 * a devicemode in the openprinterex() call.
1428 * Differences between NT4 and NT 2000.
1429 * NT4:
1430 * ---
1431 * On NT4, you only have a global devicemode. This global devicemode can be changed
1432 * by the administrator (or by a user with enough privs). Everytime a user
1433 * wants to print, the devicemode is resetted to the default. In Word, everytime
1434 * you print, the printer's characteristics are always reset to the global devicemode.
1436 * NT 2000:
1437 * -------
1438 * In W2K, there is the notion of per-user devicemode. The first time you use
1439 * a printer, a per-user devicemode is build from the global devicemode.
1440 * If you change your per-user devicemode, it is saved in the registry, under the
1441 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1442 * printer preferences available.
1444 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1445 * on the General Tab of the printer properties windows.
1447 * To change the global devicemode: it's the "Printing Defaults..." button
1448 * on the Advanced Tab of the printer properties window.
1450 * JFM.
1451 ********************************************************************/
1453 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1455 UNISTR2 *printername = NULL;
1456 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1457 POLICY_HND *handle = &r_u->handle;
1459 fstring name;
1460 int snum;
1461 struct current_user user;
1462 Printer_entry *Printer=NULL;
1464 if (q_u->printername_ptr != 0)
1465 printername = &q_u->printername;
1467 if (printername == NULL)
1468 return WERR_INVALID_PRINTER_NAME;
1470 /* some sanity check because you can open a printer or a print server */
1471 /* aka: \\server\printer or \\server */
1472 unistr2_to_ascii(name, printername, sizeof(name)-1);
1474 DEBUGADD(3,("checking name: %s\n",name));
1476 if (!open_printer_hnd(p, handle, name, 0))
1477 return WERR_INVALID_PRINTER_NAME;
1479 Printer=find_printer_index_by_hnd(p, handle);
1480 if (!Printer) {
1481 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1482 Can't find printer handle we created for printer %s\n", name ));
1483 close_printer_handle(p,handle);
1484 return WERR_INVALID_PRINTER_NAME;
1487 get_current_user(&user, p);
1490 * First case: the user is opening the print server:
1492 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1493 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1495 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1496 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1497 * or if the user is listed in the smb.conf printer admin parameter.
1499 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1500 * client view printer folder, but does not show the MSAPW.
1502 * Note: this test needs code to check access rights here too. Jeremy
1503 * could you look at this?
1505 * Second case: the user is opening a printer:
1506 * NT doesn't let us connect to a printer if the connecting user
1507 * doesn't have print permission.
1510 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1512 /* Printserver handles use global struct... */
1514 snum = -1;
1516 /* Map standard access rights to object specific access rights */
1518 se_map_standard(&printer_default->access_required,
1519 &printserver_std_mapping);
1521 /* Deny any object specific bits that don't apply to print
1522 servers (i.e printer and job specific bits) */
1524 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1526 if (printer_default->access_required &
1527 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1528 DEBUG(3, ("access DENIED for non-printserver bits"));
1529 close_printer_handle(p, handle);
1530 return WERR_ACCESS_DENIED;
1533 /* Allow admin access */
1535 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1537 if (!lp_ms_add_printer_wizard()) {
1538 close_printer_handle(p, handle);
1539 return WERR_ACCESS_DENIED;
1542 /* if the user is not root and not a printer admin, then fail */
1544 if ( user.uid != 0
1545 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1547 close_printer_handle(p, handle);
1548 return WERR_ACCESS_DENIED;
1551 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1553 else
1555 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1558 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1559 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1561 /* We fall through to return WERR_OK */
1564 else
1566 /* NT doesn't let us connect to a printer if the connecting user
1567 doesn't have print permission. */
1569 if (!get_printer_snum(p, handle, &snum))
1570 return WERR_BADFID;
1572 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1574 /* map an empty access mask to the minimum access mask */
1575 if (printer_default->access_required == 0x0)
1576 printer_default->access_required = PRINTER_ACCESS_USE;
1579 * If we are not serving the printer driver for this printer,
1580 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1581 * will keep NT clients happy --jerry
1584 if (lp_use_client_driver(snum)
1585 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1587 printer_default->access_required = PRINTER_ACCESS_USE;
1590 /* check smb.conf parameters and the the sec_desc */
1592 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1593 DEBUG(3, ("access DENIED for printer open\n"));
1594 close_printer_handle(p, handle);
1595 return WERR_ACCESS_DENIED;
1598 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1599 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1600 close_printer_handle(p, handle);
1601 return WERR_ACCESS_DENIED;
1604 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1605 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1606 else
1607 printer_default->access_required = PRINTER_ACCESS_USE;
1609 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1610 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1614 Printer->access_granted = printer_default->access_required;
1617 * If the client sent a devmode in the OpenPrinter() call, then
1618 * save it here in case we get a job submission on this handle
1621 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1622 && q_u->printer_default.devmode_cont.devmode_ptr )
1624 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1625 &Printer->nt_devmode );
1628 return WERR_OK;
1631 /****************************************************************************
1632 ****************************************************************************/
1634 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1635 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1637 BOOL ret = True;
1639 switch (level) {
1640 case 2:
1641 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1642 break;
1643 default:
1644 break;
1647 return ret;
1650 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1651 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1653 BOOL result = True;
1655 switch (level) {
1656 case 3:
1657 printer->info_3=NULL;
1658 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1659 result = False;
1660 break;
1661 case 6:
1662 printer->info_6=NULL;
1663 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1664 result = False;
1665 break;
1666 default:
1667 break;
1670 return result;
1673 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1674 NT_DEVICEMODE **pp_nt_devmode)
1676 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1679 * Ensure nt_devmode is a valid pointer
1680 * as we will be overwriting it.
1683 if (nt_devmode == NULL) {
1684 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1685 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1686 return False;
1689 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1690 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1692 nt_devmode->specversion=devmode->specversion;
1693 nt_devmode->driverversion=devmode->driverversion;
1694 nt_devmode->size=devmode->size;
1695 nt_devmode->fields=devmode->fields;
1696 nt_devmode->orientation=devmode->orientation;
1697 nt_devmode->papersize=devmode->papersize;
1698 nt_devmode->paperlength=devmode->paperlength;
1699 nt_devmode->paperwidth=devmode->paperwidth;
1700 nt_devmode->scale=devmode->scale;
1701 nt_devmode->copies=devmode->copies;
1702 nt_devmode->defaultsource=devmode->defaultsource;
1703 nt_devmode->printquality=devmode->printquality;
1704 nt_devmode->color=devmode->color;
1705 nt_devmode->duplex=devmode->duplex;
1706 nt_devmode->yresolution=devmode->yresolution;
1707 nt_devmode->ttoption=devmode->ttoption;
1708 nt_devmode->collate=devmode->collate;
1710 nt_devmode->logpixels=devmode->logpixels;
1711 nt_devmode->bitsperpel=devmode->bitsperpel;
1712 nt_devmode->pelswidth=devmode->pelswidth;
1713 nt_devmode->pelsheight=devmode->pelsheight;
1714 nt_devmode->displayflags=devmode->displayflags;
1715 nt_devmode->displayfrequency=devmode->displayfrequency;
1716 nt_devmode->icmmethod=devmode->icmmethod;
1717 nt_devmode->icmintent=devmode->icmintent;
1718 nt_devmode->mediatype=devmode->mediatype;
1719 nt_devmode->dithertype=devmode->dithertype;
1720 nt_devmode->reserved1=devmode->reserved1;
1721 nt_devmode->reserved2=devmode->reserved2;
1722 nt_devmode->panningwidth=devmode->panningwidth;
1723 nt_devmode->panningheight=devmode->panningheight;
1726 * Only change private and driverextra if the incoming devmode
1727 * has a new one. JRA.
1730 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1731 SAFE_FREE(nt_devmode->private);
1732 nt_devmode->driverextra=devmode->driverextra;
1733 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1734 return False;
1735 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1738 *pp_nt_devmode = nt_devmode;
1740 return True;
1743 /********************************************************************
1744 * _spoolss_enddocprinter_internal.
1745 ********************************************************************/
1747 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1749 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1750 int snum;
1752 if (!Printer) {
1753 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1754 return WERR_BADFID;
1757 if (!get_printer_snum(p, handle, &snum))
1758 return WERR_BADFID;
1760 Printer->document_started=False;
1761 print_job_end(snum, Printer->jobid,True);
1762 /* error codes unhandled so far ... */
1764 return WERR_OK;
1767 /********************************************************************
1768 * api_spoolss_closeprinter
1769 ********************************************************************/
1771 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1773 POLICY_HND *handle = &q_u->handle;
1775 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1777 if (Printer && Printer->document_started)
1778 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1780 if (!close_printer_handle(p, handle))
1781 return WERR_BADFID;
1783 /* clear the returned printer handle. Observed behavior
1784 from Win2k server. Don't think this really matters.
1785 Previous code just copied the value of the closed
1786 handle. --jerry */
1788 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1790 return WERR_OK;
1793 /********************************************************************
1794 * api_spoolss_deleteprinter
1796 ********************************************************************/
1798 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1800 POLICY_HND *handle = &q_u->handle;
1801 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1802 WERROR result;
1804 if (Printer && Printer->document_started)
1805 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1807 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1809 result = delete_printer_handle(p, handle);
1811 update_c_setprinter(False);
1813 return result;
1816 /*******************************************************************
1817 * static function to lookup the version id corresponding to an
1818 * long architecture string
1819 ******************************************************************/
1821 static int get_version_id (char * arch)
1823 int i;
1824 struct table_node archi_table[]= {
1826 {"Windows 4.0", "WIN40", 0 },
1827 {"Windows NT x86", "W32X86", 2 },
1828 {"Windows NT R4000", "W32MIPS", 2 },
1829 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1830 {"Windows NT PowerPC", "W32PPC", 2 },
1831 {NULL, "", -1 }
1834 for (i=0; archi_table[i].long_archi != NULL; i++)
1836 if (strcmp(arch, archi_table[i].long_archi) == 0)
1837 return (archi_table[i].version);
1840 return -1;
1843 /********************************************************************
1844 * _spoolss_deleteprinterdriver
1845 ********************************************************************/
1847 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1849 fstring driver;
1850 fstring arch;
1851 NT_PRINTER_DRIVER_INFO_LEVEL info;
1852 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1853 int version;
1854 struct current_user user;
1855 WERROR status;
1856 WERROR status_win2k = WERR_ACCESS_DENIED;
1858 get_current_user(&user, p);
1860 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1861 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1863 /* check that we have a valid driver name first */
1865 if ((version=get_version_id(arch)) == -1)
1866 return WERR_INVALID_ENVIRONMENT;
1868 ZERO_STRUCT(info);
1869 ZERO_STRUCT(info_win2k);
1871 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1873 /* try for Win2k driver if "Windows NT x86" */
1875 if ( version == 2 ) {
1876 version = 3;
1877 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1878 status = WERR_UNKNOWN_PRINTER_DRIVER;
1879 goto done;
1884 if (printer_driver_in_use(info.info_3)) {
1885 status = WERR_PRINTER_DRIVER_IN_USE;
1886 goto done;
1889 if ( version == 2 )
1891 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1893 /* if we get to here, we now have 2 driver info structures to remove */
1894 /* remove the Win2k driver first*/
1896 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1897 free_a_printer_driver( info_win2k, 3 );
1899 /* this should not have failed---if it did, report to client */
1900 if ( !W_ERROR_IS_OK(status_win2k) )
1901 goto done;
1905 status = delete_printer_driver(info.info_3, &user, version, False);
1907 /* if at least one of the deletes succeeded return OK */
1909 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1910 status = WERR_OK;
1912 done:
1913 free_a_printer_driver( info, 3 );
1915 return status;
1918 /********************************************************************
1919 * spoolss_deleteprinterdriverex
1920 ********************************************************************/
1922 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1924 fstring driver;
1925 fstring arch;
1926 NT_PRINTER_DRIVER_INFO_LEVEL info;
1927 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1928 int version;
1929 uint32 flags = q_u->delete_flags;
1930 BOOL delete_files;
1931 struct current_user user;
1932 WERROR status;
1933 WERROR status_win2k = WERR_ACCESS_DENIED;
1935 get_current_user(&user, p);
1937 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1938 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1940 /* check that we have a valid driver name first */
1941 if ((version=get_version_id(arch)) == -1) {
1942 /* this is what NT returns */
1943 return WERR_INVALID_ENVIRONMENT;
1946 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1947 version = q_u->version;
1949 ZERO_STRUCT(info);
1950 ZERO_STRUCT(info_win2k);
1952 status = get_a_printer_driver(&info, 3, driver, arch, version);
1954 if ( !W_ERROR_IS_OK(status) )
1957 * if the client asked for a specific version,
1958 * or this is something other than Windows NT x86,
1959 * then we've failed
1962 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1963 goto done;
1965 /* try for Win2k driver if "Windows NT x86" */
1967 version = 3;
1968 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1969 status = WERR_UNKNOWN_PRINTER_DRIVER;
1970 goto done;
1974 if ( printer_driver_in_use(info.info_3) ) {
1975 status = WERR_PRINTER_DRIVER_IN_USE;
1976 goto done;
1980 * we have a couple of cases to consider.
1981 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1982 * then the delete should fail if **any** files overlap with
1983 * other drivers
1984 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1985 * non-overlapping files
1986 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1987 * is set, the do not delete any files
1988 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1991 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1993 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1995 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
1996 /* no idea of the correct error here */
1997 status = WERR_ACCESS_DENIED;
1998 goto done;
2002 /* also check for W32X86/3 if necessary; maybe we already have? */
2004 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2005 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2008 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2009 /* no idea of the correct error here */
2010 free_a_printer_driver( info_win2k, 3 );
2011 status = WERR_ACCESS_DENIED;
2012 goto done;
2015 /* if we get to here, we now have 2 driver info structures to remove */
2016 /* remove the Win2k driver first*/
2018 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2019 free_a_printer_driver( info_win2k, 3 );
2021 /* this should not have failed---if it did, report to client */
2023 if ( !W_ERROR_IS_OK(status_win2k) )
2024 goto done;
2028 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2030 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2031 status = WERR_OK;
2032 done:
2033 free_a_printer_driver( info, 3 );
2035 return status;
2039 /****************************************************************************
2040 Internal routine for retreiving printerdata
2041 ***************************************************************************/
2043 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2044 char *key, char *value, uint32 *type, uint8 **data,
2045 uint32 *needed, uint32 in_size )
2047 REGISTRY_VALUE *val;
2048 int size, data_len;
2050 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2051 return WERR_BADFILE;
2053 *type = regval_type( val );
2055 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2057 size = regval_size( val );
2059 /* copy the min(in_size, len) */
2061 if ( in_size ) {
2062 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2063 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2064 return WERR_NOMEM;
2066 else
2067 *data = NULL;
2069 *needed = size;
2071 DEBUG(5,("get_printer_dataex: copy done\n"));
2073 return WERR_OK;
2076 /****************************************************************************
2077 Internal routine for removing printerdata
2078 ***************************************************************************/
2080 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value )
2082 delete_printer_data( printer->info_2, key, value );
2084 return mod_a_printer(*printer, 2);
2087 /****************************************************************************
2088 Internal routine for storing printerdata
2089 ***************************************************************************/
2091 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value,
2092 uint32 type, uint8 *data, int real_len )
2094 delete_printer_data( printer->info_2, key, value );
2096 add_printer_data( printer->info_2, key, value, type, data, real_len );
2098 return mod_a_printer(*printer, 2);
2101 /********************************************************************
2102 GetPrinterData on a printer server Handle.
2103 ********************************************************************/
2105 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2107 int i;
2109 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2111 if (!strcmp(value, "W3SvcInstalled")) {
2112 *type = 0x4;
2113 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2114 return WERR_NOMEM;
2115 *needed = 0x4;
2116 return WERR_OK;
2119 if (!strcmp(value, "BeepEnabled")) {
2120 *type = 0x4;
2121 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2122 return WERR_NOMEM;
2123 SIVAL(*data, 0, 0x00);
2124 *needed = 0x4;
2125 return WERR_OK;
2128 if (!strcmp(value, "EventLog")) {
2129 *type = 0x4;
2130 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2131 return WERR_NOMEM;
2132 /* formally was 0x1b */
2133 SIVAL(*data, 0, 0x0);
2134 *needed = 0x4;
2135 return WERR_OK;
2138 if (!strcmp(value, "NetPopup")) {
2139 *type = 0x4;
2140 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2141 return WERR_NOMEM;
2142 SIVAL(*data, 0, 0x00);
2143 *needed = 0x4;
2144 return WERR_OK;
2147 if (!strcmp(value, "MajorVersion")) {
2148 *type = 0x4;
2149 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2150 return WERR_NOMEM;
2151 #ifndef EMULATE_WIN2K_HACK /* JERRY */
2152 SIVAL(*data, 0, 2);
2153 #else
2154 SIVAL(*data, 0, 3);
2155 #endif
2156 *needed = 0x4;
2157 return WERR_OK;
2160 if (!strcmp(value, "DefaultSpoolDirectory")) {
2161 fstring string;
2163 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2164 *type = 0x1;
2165 *needed = 2*(strlen(string)+1);
2166 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2167 return WERR_NOMEM;
2168 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2170 /* it's done by hand ready to go on the wire */
2171 for (i=0; i<strlen(string); i++) {
2172 (*data)[2*i]=string[i];
2173 (*data)[2*i+1]='\0';
2175 return WERR_OK;
2178 if (!strcmp(value, "Architecture")) {
2179 pstring string="Windows NT x86";
2180 *type = 0x1;
2181 *needed = 2*(strlen(string)+1);
2182 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2183 return WERR_NOMEM;
2184 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2185 for (i=0; i<strlen(string); i++) {
2186 (*data)[2*i]=string[i];
2187 (*data)[2*i+1]='\0';
2189 return WERR_OK;
2192 return WERR_INVALID_PARAM;
2195 /********************************************************************
2196 * spoolss_getprinterdata
2197 ********************************************************************/
2199 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2201 POLICY_HND *handle = &q_u->handle;
2202 UNISTR2 *valuename = &q_u->valuename;
2203 uint32 in_size = q_u->size;
2204 uint32 *type = &r_u->type;
2205 uint32 *out_size = &r_u->size;
2206 uint8 **data = &r_u->data;
2207 uint32 *needed = &r_u->needed;
2208 WERROR status;
2209 fstring value;
2210 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2211 NT_PRINTER_INFO_LEVEL *printer = NULL;
2212 int snum = 0;
2215 * Reminder: when it's a string, the length is in BYTES
2216 * even if UNICODE is negociated.
2218 * JFM, 4/19/1999
2221 *out_size = in_size;
2223 /* in case of problem, return some default values */
2225 *needed = 0;
2226 *type = 0;
2228 DEBUG(4,("_spoolss_getprinterdata\n"));
2230 if ( !Printer ) {
2231 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2232 status = WERR_BADFID;
2233 goto done;
2236 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2238 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2239 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2240 else
2242 if ( !get_printer_snum(p,handle, &snum) ) {
2243 status = WERR_BADFID;
2244 goto done;
2247 status = get_a_printer(&printer, 2, lp_servicename(snum));
2248 if ( !W_ERROR_IS_OK(status) )
2249 goto done;
2251 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2254 if (*needed > *out_size)
2255 status = WERR_MORE_DATA;
2257 done:
2258 if ( !W_ERROR_IS_OK(status) )
2260 DEBUG(5, ("error: allocating %d\n", *out_size));
2262 /* reply this param doesn't exist */
2264 if ( *out_size ) {
2265 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2266 if ( printer )
2267 free_a_printer( &printer, 2 );
2268 return WERR_NOMEM;
2271 else {
2272 *data = NULL;
2276 /* cleanup & exit */
2278 if ( printer )
2279 free_a_printer( &printer, 2 );
2281 return status;
2284 /*********************************************************
2285 Connect to the client machine.
2286 **********************************************************/
2288 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
2290 extern pstring global_myname;
2292 ZERO_STRUCTP(the_cli);
2293 if(cli_initialise(the_cli) == NULL) {
2294 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2295 return False;
2298 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2299 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2300 cli_shutdown(the_cli);
2301 return False;
2304 if (ismyip(the_cli->dest_ip)) {
2305 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2306 cli_shutdown(the_cli);
2307 return False;
2310 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2311 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2312 cli_shutdown(the_cli);
2313 return False;
2316 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
2317 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2318 remote_machine));
2319 cli_shutdown(the_cli);
2320 return False;
2323 the_cli->protocol = PROTOCOL_NT1;
2325 if (!cli_negprot(the_cli)) {
2326 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2327 cli_shutdown(the_cli);
2328 return False;
2331 if (the_cli->protocol != PROTOCOL_NT1) {
2332 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2333 cli_shutdown(the_cli);
2334 return False;
2338 * Do an anonymous session setup.
2341 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2342 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2343 cli_shutdown(the_cli);
2344 return False;
2347 if (!(the_cli->sec_mode & 1)) {
2348 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2349 cli_shutdown(the_cli);
2350 return False;
2353 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2354 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2355 cli_shutdown(the_cli);
2356 return False;
2360 * Ok - we have an anonymous connection to the IPC$ share.
2361 * Now start the NT Domain stuff :-).
2364 if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
2365 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)));
2366 cli_nt_session_close(the_cli);
2367 cli_ulogoff(the_cli);
2368 cli_shutdown(the_cli);
2369 return False;
2372 return True;
2375 /***************************************************************************
2376 Connect to the client.
2377 ****************************************************************************/
2379 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2381 WERROR result;
2384 * If it's the first connection, contact the client
2385 * and connect to the IPC$ share anonumously
2387 if (smb_connections==0) {
2388 fstring unix_printer;
2390 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2392 if(!spoolss_connect_to_client(&notify_cli, unix_printer))
2393 return False;
2395 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2396 /* Tell the connections db we're now interested in printer
2397 * notify messages. */
2398 register_message_flags( True, FLAG_MSG_PRINTING );
2401 smb_connections++;
2403 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2404 type, handle);
2406 if (!W_ERROR_IS_OK(result))
2407 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2408 dos_errstr(result)));
2410 return (W_ERROR_IS_OK(result));
2413 /********************************************************************
2414 * _spoolss_rffpcnex
2415 * ReplyFindFirstPrinterChangeNotifyEx
2417 * before replying OK: status=0 a rpc call is made to the workstation
2418 * asking ReplyOpenPrinter
2420 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2421 * called from api_spoolss_rffpcnex
2422 ********************************************************************/
2424 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2426 POLICY_HND *handle = &q_u->handle;
2427 uint32 flags = q_u->flags;
2428 uint32 options = q_u->options;
2429 UNISTR2 *localmachine = &q_u->localmachine;
2430 uint32 printerlocal = q_u->printerlocal;
2431 SPOOL_NOTIFY_OPTION *option = q_u->option;
2433 /* store the notify value in the printer struct */
2435 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2437 if (!Printer) {
2438 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2439 return WERR_BADFID;
2442 Printer->notify.flags=flags;
2443 Printer->notify.options=options;
2444 Printer->notify.printerlocal=printerlocal;
2446 if (Printer->notify.option)
2447 free_spool_notify_option(&Printer->notify.option);
2449 Printer->notify.option=dup_spool_notify_option(option);
2451 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2452 sizeof(Printer->notify.localmachine)-1);
2454 /* Connect to the client machine and send a ReplyOpenPrinter */
2456 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
2457 Printer->notify.printerlocal, 1,
2458 &Printer->notify.client_hnd))
2459 return WERR_SERVER_UNAVAILABLE;
2461 Printer->notify.client_connected=True;
2463 return WERR_OK;
2466 /*******************************************************************
2467 * fill a notify_info_data with the servername
2468 ********************************************************************/
2470 void spoolss_notify_server_name(int snum,
2471 SPOOL_NOTIFY_INFO_DATA *data,
2472 print_queue_struct *queue,
2473 NT_PRINTER_INFO_LEVEL *printer,
2474 TALLOC_CTX *mem_ctx)
2476 pstring temp_name, temp;
2477 uint32 len;
2479 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2481 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2483 data->notify_data.data.length = len;
2484 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2486 if (!data->notify_data.data.string) {
2487 data->notify_data.data.length = 0;
2488 return;
2491 memcpy(data->notify_data.data.string, temp, len);
2494 /*******************************************************************
2495 * fill a notify_info_data with the printername (not including the servername).
2496 ********************************************************************/
2498 void spoolss_notify_printer_name(int snum,
2499 SPOOL_NOTIFY_INFO_DATA *data,
2500 print_queue_struct *queue,
2501 NT_PRINTER_INFO_LEVEL *printer,
2502 TALLOC_CTX *mem_ctx)
2504 pstring temp;
2505 uint32 len;
2507 /* the notify name should not contain the \\server\ part */
2508 char *p = strrchr(printer->info_2->printername, '\\');
2510 if (!p) {
2511 p = printer->info_2->printername;
2512 } else {
2513 p++;
2516 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2518 data->notify_data.data.length = len;
2519 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2521 if (!data->notify_data.data.string) {
2522 data->notify_data.data.length = 0;
2523 return;
2526 memcpy(data->notify_data.data.string, temp, len);
2529 /*******************************************************************
2530 * fill a notify_info_data with the servicename
2531 ********************************************************************/
2533 void spoolss_notify_share_name(int snum,
2534 SPOOL_NOTIFY_INFO_DATA *data,
2535 print_queue_struct *queue,
2536 NT_PRINTER_INFO_LEVEL *printer,
2537 TALLOC_CTX *mem_ctx)
2539 pstring temp;
2540 uint32 len;
2542 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2544 data->notify_data.data.length = len;
2545 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2547 if (!data->notify_data.data.string) {
2548 data->notify_data.data.length = 0;
2549 return;
2552 memcpy(data->notify_data.data.string, temp, len);
2555 /*******************************************************************
2556 * fill a notify_info_data with the port name
2557 ********************************************************************/
2559 void spoolss_notify_port_name(int snum,
2560 SPOOL_NOTIFY_INFO_DATA *data,
2561 print_queue_struct *queue,
2562 NT_PRINTER_INFO_LEVEL *printer,
2563 TALLOC_CTX *mem_ctx)
2565 pstring temp;
2566 uint32 len;
2568 /* even if it's strange, that's consistant in all the code */
2570 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2572 data->notify_data.data.length = len;
2573 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2575 if (!data->notify_data.data.string) {
2576 data->notify_data.data.length = 0;
2577 return;
2580 memcpy(data->notify_data.data.string, temp, len);
2583 /*******************************************************************
2584 * fill a notify_info_data with the printername
2585 * but it doesn't exist, have to see what to do
2586 ********************************************************************/
2588 void spoolss_notify_driver_name(int snum,
2589 SPOOL_NOTIFY_INFO_DATA *data,
2590 print_queue_struct *queue,
2591 NT_PRINTER_INFO_LEVEL *printer,
2592 TALLOC_CTX *mem_ctx)
2594 pstring temp;
2595 uint32 len;
2597 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2599 data->notify_data.data.length = len;
2600 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2602 if (!data->notify_data.data.string) {
2603 data->notify_data.data.length = 0;
2604 return;
2607 memcpy(data->notify_data.data.string, temp, len);
2610 /*******************************************************************
2611 * fill a notify_info_data with the comment
2612 ********************************************************************/
2614 void spoolss_notify_comment(int snum,
2615 SPOOL_NOTIFY_INFO_DATA *data,
2616 print_queue_struct *queue,
2617 NT_PRINTER_INFO_LEVEL *printer,
2618 TALLOC_CTX *mem_ctx)
2620 pstring temp;
2621 uint32 len;
2623 if (*printer->info_2->comment == '\0')
2624 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2625 else
2626 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2628 data->notify_data.data.length = len;
2629 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2631 if (!data->notify_data.data.string) {
2632 data->notify_data.data.length = 0;
2633 return;
2636 memcpy(data->notify_data.data.string, temp, len);
2639 /*******************************************************************
2640 * fill a notify_info_data with the comment
2641 * location = "Room 1, floor 2, building 3"
2642 ********************************************************************/
2644 void spoolss_notify_location(int snum,
2645 SPOOL_NOTIFY_INFO_DATA *data,
2646 print_queue_struct *queue,
2647 NT_PRINTER_INFO_LEVEL *printer,
2648 TALLOC_CTX *mem_ctx)
2650 pstring temp;
2651 uint32 len;
2653 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2655 data->notify_data.data.length = len;
2656 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2658 if (!data->notify_data.data.string) {
2659 data->notify_data.data.length = 0;
2660 return;
2663 memcpy(data->notify_data.data.string, temp, len);
2666 /*******************************************************************
2667 * fill a notify_info_data with the device mode
2668 * jfm:xxxx don't to it for know but that's a real problem !!!
2669 ********************************************************************/
2671 static void spoolss_notify_devmode(int snum,
2672 SPOOL_NOTIFY_INFO_DATA *data,
2673 print_queue_struct *queue,
2674 NT_PRINTER_INFO_LEVEL *printer,
2675 TALLOC_CTX *mem_ctx)
2679 /*******************************************************************
2680 * fill a notify_info_data with the separator file name
2681 ********************************************************************/
2683 void spoolss_notify_sepfile(int snum,
2684 SPOOL_NOTIFY_INFO_DATA *data,
2685 print_queue_struct *queue,
2686 NT_PRINTER_INFO_LEVEL *printer,
2687 TALLOC_CTX *mem_ctx)
2689 pstring temp;
2690 uint32 len;
2692 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2694 data->notify_data.data.length = len;
2695 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2697 if (!data->notify_data.data.string) {
2698 data->notify_data.data.length = 0;
2699 return;
2702 memcpy(data->notify_data.data.string, temp, len);
2705 /*******************************************************************
2706 * fill a notify_info_data with the print processor
2707 * jfm:xxxx return always winprint to indicate we don't do anything to it
2708 ********************************************************************/
2710 void spoolss_notify_print_processor(int snum,
2711 SPOOL_NOTIFY_INFO_DATA *data,
2712 print_queue_struct *queue,
2713 NT_PRINTER_INFO_LEVEL *printer,
2714 TALLOC_CTX *mem_ctx)
2716 pstring temp;
2717 uint32 len;
2719 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2721 data->notify_data.data.length = len;
2722 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2724 if (!data->notify_data.data.string) {
2725 data->notify_data.data.length = 0;
2726 return;
2729 memcpy(data->notify_data.data.string, temp, len);
2732 /*******************************************************************
2733 * fill a notify_info_data with the print processor options
2734 * jfm:xxxx send an empty string
2735 ********************************************************************/
2737 void spoolss_notify_parameters(int snum,
2738 SPOOL_NOTIFY_INFO_DATA *data,
2739 print_queue_struct *queue,
2740 NT_PRINTER_INFO_LEVEL *printer,
2741 TALLOC_CTX *mem_ctx)
2743 pstring temp;
2744 uint32 len;
2746 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2748 data->notify_data.data.length = len;
2749 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2751 if (!data->notify_data.data.string) {
2752 data->notify_data.data.length = 0;
2753 return;
2756 memcpy(data->notify_data.data.string, temp, len);
2759 /*******************************************************************
2760 * fill a notify_info_data with the data type
2761 * jfm:xxxx always send RAW as data type
2762 ********************************************************************/
2764 void spoolss_notify_datatype(int snum,
2765 SPOOL_NOTIFY_INFO_DATA *data,
2766 print_queue_struct *queue,
2767 NT_PRINTER_INFO_LEVEL *printer,
2768 TALLOC_CTX *mem_ctx)
2770 pstring temp;
2771 uint32 len;
2773 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2775 data->notify_data.data.length = len;
2776 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2778 if (!data->notify_data.data.string) {
2779 data->notify_data.data.length = 0;
2780 return;
2783 memcpy(data->notify_data.data.string, temp, len);
2786 /*******************************************************************
2787 * fill a notify_info_data with the security descriptor
2788 * jfm:xxxx send an null pointer to say no security desc
2789 * have to implement security before !
2790 ********************************************************************/
2792 static void spoolss_notify_security_desc(int snum,
2793 SPOOL_NOTIFY_INFO_DATA *data,
2794 print_queue_struct *queue,
2795 NT_PRINTER_INFO_LEVEL *printer,
2796 TALLOC_CTX *mem_ctx)
2798 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2799 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2802 /*******************************************************************
2803 * fill a notify_info_data with the attributes
2804 * jfm:xxxx a samba printer is always shared
2805 ********************************************************************/
2807 void spoolss_notify_attributes(int snum,
2808 SPOOL_NOTIFY_INFO_DATA *data,
2809 print_queue_struct *queue,
2810 NT_PRINTER_INFO_LEVEL *printer,
2811 TALLOC_CTX *mem_ctx)
2813 data->notify_data.value[0] = printer->info_2->attributes;
2814 data->notify_data.value[1] = 0;
2817 /*******************************************************************
2818 * fill a notify_info_data with the priority
2819 ********************************************************************/
2821 static void spoolss_notify_priority(int snum,
2822 SPOOL_NOTIFY_INFO_DATA *data,
2823 print_queue_struct *queue,
2824 NT_PRINTER_INFO_LEVEL *printer,
2825 TALLOC_CTX *mem_ctx)
2827 data->notify_data.value[0] = printer->info_2->priority;
2828 data->notify_data.value[1] = 0;
2831 /*******************************************************************
2832 * fill a notify_info_data with the default priority
2833 ********************************************************************/
2835 static void spoolss_notify_default_priority(int snum,
2836 SPOOL_NOTIFY_INFO_DATA *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2841 data->notify_data.value[0] = printer->info_2->default_priority;
2842 data->notify_data.value[1] = 0;
2845 /*******************************************************************
2846 * fill a notify_info_data with the start time
2847 ********************************************************************/
2849 static void spoolss_notify_start_time(int snum,
2850 SPOOL_NOTIFY_INFO_DATA *data,
2851 print_queue_struct *queue,
2852 NT_PRINTER_INFO_LEVEL *printer,
2853 TALLOC_CTX *mem_ctx)
2855 data->notify_data.value[0] = printer->info_2->starttime;
2856 data->notify_data.value[1] = 0;
2859 /*******************************************************************
2860 * fill a notify_info_data with the until time
2861 ********************************************************************/
2863 static void spoolss_notify_until_time(int snum,
2864 SPOOL_NOTIFY_INFO_DATA *data,
2865 print_queue_struct *queue,
2866 NT_PRINTER_INFO_LEVEL *printer,
2867 TALLOC_CTX *mem_ctx)
2869 data->notify_data.value[0] = printer->info_2->untiltime;
2870 data->notify_data.value[1] = 0;
2873 /*******************************************************************
2874 * fill a notify_info_data with the status
2875 ********************************************************************/
2877 static void spoolss_notify_status(int snum,
2878 SPOOL_NOTIFY_INFO_DATA *data,
2879 print_queue_struct *queue,
2880 NT_PRINTER_INFO_LEVEL *printer,
2881 TALLOC_CTX *mem_ctx)
2883 print_status_struct status;
2885 print_queue_length(snum, &status);
2886 data->notify_data.value[0]=(uint32) status.status;
2887 data->notify_data.value[1] = 0;
2890 /*******************************************************************
2891 * fill a notify_info_data with the number of jobs queued
2892 ********************************************************************/
2894 void spoolss_notify_cjobs(int snum,
2895 SPOOL_NOTIFY_INFO_DATA *data,
2896 print_queue_struct *queue,
2897 NT_PRINTER_INFO_LEVEL *printer,
2898 TALLOC_CTX *mem_ctx)
2900 data->notify_data.value[0] = print_queue_length(snum, NULL);
2901 data->notify_data.value[1] = 0;
2904 /*******************************************************************
2905 * fill a notify_info_data with the average ppm
2906 ********************************************************************/
2908 static void spoolss_notify_average_ppm(int snum,
2909 SPOOL_NOTIFY_INFO_DATA *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2914 /* always respond 8 pages per minutes */
2915 /* a little hard ! */
2916 data->notify_data.value[0] = printer->info_2->averageppm;
2917 data->notify_data.value[1] = 0;
2920 /*******************************************************************
2921 * fill a notify_info_data with username
2922 ********************************************************************/
2924 static void spoolss_notify_username(int snum,
2925 SPOOL_NOTIFY_INFO_DATA *data,
2926 print_queue_struct *queue,
2927 NT_PRINTER_INFO_LEVEL *printer,
2928 TALLOC_CTX *mem_ctx)
2930 pstring temp;
2931 uint32 len;
2933 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2935 data->notify_data.data.length = len;
2936 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2938 if (!data->notify_data.data.string) {
2939 data->notify_data.data.length = 0;
2940 return;
2943 memcpy(data->notify_data.data.string, temp, len);
2946 /*******************************************************************
2947 * fill a notify_info_data with job status
2948 ********************************************************************/
2950 static void spoolss_notify_job_status(int snum,
2951 SPOOL_NOTIFY_INFO_DATA *data,
2952 print_queue_struct *queue,
2953 NT_PRINTER_INFO_LEVEL *printer,
2954 TALLOC_CTX *mem_ctx)
2956 data->notify_data.value[0]=nt_printj_status(queue->status);
2957 data->notify_data.value[1] = 0;
2960 /*******************************************************************
2961 * fill a notify_info_data with job name
2962 ********************************************************************/
2964 static void spoolss_notify_job_name(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2970 pstring temp;
2971 uint32 len;
2973 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2975 data->notify_data.data.length = len;
2976 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2978 if (!data->notify_data.data.string) {
2979 data->notify_data.data.length = 0;
2980 return;
2983 memcpy(data->notify_data.data.string, temp, len);
2986 /*******************************************************************
2987 * fill a notify_info_data with job status
2988 ********************************************************************/
2990 static void spoolss_notify_job_status_string(int snum,
2991 SPOOL_NOTIFY_INFO_DATA *data,
2992 print_queue_struct *queue,
2993 NT_PRINTER_INFO_LEVEL *printer,
2994 TALLOC_CTX *mem_ctx)
2997 * Now we're returning job status codes we just return a "" here. JRA.
3000 char *p = "";
3001 pstring temp;
3002 uint32 len;
3004 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3005 p = "unknown";
3007 switch (queue->status) {
3008 case LPQ_QUEUED:
3009 p = "Queued";
3010 break;
3011 case LPQ_PAUSED:
3012 p = ""; /* NT provides the paused string */
3013 break;
3014 case LPQ_SPOOLING:
3015 p = "Spooling";
3016 break;
3017 case LPQ_PRINTING:
3018 p = "Printing";
3019 break;
3021 #endif /* NO LONGER NEEDED. */
3023 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3025 data->notify_data.data.length = len;
3026 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3028 if (!data->notify_data.data.string) {
3029 data->notify_data.data.length = 0;
3030 return;
3033 memcpy(data->notify_data.data.string, temp, len);
3036 /*******************************************************************
3037 * fill a notify_info_data with job time
3038 ********************************************************************/
3040 static void spoolss_notify_job_time(int snum,
3041 SPOOL_NOTIFY_INFO_DATA *data,
3042 print_queue_struct *queue,
3043 NT_PRINTER_INFO_LEVEL *printer,
3044 TALLOC_CTX *mem_ctx)
3046 data->notify_data.value[0]=0x0;
3047 data->notify_data.value[1]=0;
3050 /*******************************************************************
3051 * fill a notify_info_data with job size
3052 ********************************************************************/
3054 static void spoolss_notify_job_size(int snum,
3055 SPOOL_NOTIFY_INFO_DATA *data,
3056 print_queue_struct *queue,
3057 NT_PRINTER_INFO_LEVEL *printer,
3058 TALLOC_CTX *mem_ctx)
3060 data->notify_data.value[0]=queue->size;
3061 data->notify_data.value[1]=0;
3064 /*******************************************************************
3065 * fill a notify_info_data with page info
3066 ********************************************************************/
3067 static void spoolss_notify_total_pages(int snum,
3068 SPOOL_NOTIFY_INFO_DATA *data,
3069 print_queue_struct *queue,
3070 NT_PRINTER_INFO_LEVEL *printer,
3071 TALLOC_CTX *mem_ctx)
3073 data->notify_data.value[0]=queue->page_count;
3074 data->notify_data.value[1]=0;
3077 /*******************************************************************
3078 * fill a notify_info_data with pages printed info.
3079 ********************************************************************/
3080 static void spoolss_notify_pages_printed(int snum,
3081 SPOOL_NOTIFY_INFO_DATA *data,
3082 print_queue_struct *queue,
3083 NT_PRINTER_INFO_LEVEL *printer,
3084 TALLOC_CTX *mem_ctx)
3086 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3087 data->notify_data.value[1]=0;
3090 /*******************************************************************
3091 Fill a notify_info_data with job position.
3092 ********************************************************************/
3094 static void spoolss_notify_job_position(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0]=queue->job;
3101 data->notify_data.value[1]=0;
3104 /*******************************************************************
3105 Fill a notify_info_data with submitted time.
3106 ********************************************************************/
3108 static void spoolss_notify_submitted_time(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 struct tm *t;
3115 uint32 len;
3116 SYSTEMTIME st;
3117 char *p;
3119 t=gmtime(&queue->time);
3121 len = sizeof(SYSTEMTIME);
3123 data->notify_data.data.length = len;
3124 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3126 if (!data->notify_data.data.string) {
3127 data->notify_data.data.length = 0;
3128 return;
3131 make_systemtime(&st, t);
3134 * Systemtime must be linearized as a set of UINT16's.
3135 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3138 p = (char *)data->notify_data.data.string;
3139 SSVAL(p, 0, st.year);
3140 SSVAL(p, 2, st.month);
3141 SSVAL(p, 4, st.dayofweek);
3142 SSVAL(p, 6, st.day);
3143 SSVAL(p, 8, st.hour);
3144 SSVAL(p, 10, st.minute);
3145 SSVAL(p, 12, st.second);
3146 SSVAL(p, 14, st.milliseconds);
3149 struct s_notify_info_data_table
3151 uint16 type;
3152 uint16 field;
3153 char *name;
3154 uint32 size;
3155 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3156 print_queue_struct *queue,
3157 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3160 /* A table describing the various print notification constants and
3161 whether the notification data is a pointer to a variable sized
3162 buffer, a one value uint32 or a two value uint32. */
3164 struct s_notify_info_data_table notify_info_data_table[] =
3166 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3167 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3168 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3169 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3170 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3171 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3172 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3173 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3174 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3175 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3176 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3177 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3178 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3179 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3180 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3181 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3182 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3183 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3184 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3185 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3186 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3187 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3188 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3189 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3190 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3191 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3192 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3193 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3194 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3195 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3196 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3197 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3198 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3199 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3200 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3201 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3202 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3203 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3204 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3205 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3206 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3207 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3208 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3209 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3210 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3211 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3212 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3213 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3214 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3217 /*******************************************************************
3218 Return the size of info_data structure.
3219 ********************************************************************/
3221 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3223 int i=0;
3225 for (i = 0; i < sizeof(notify_info_data_table); i++)
3227 if ( (notify_info_data_table[i].type == type)
3228 && (notify_info_data_table[i].field == field) )
3230 switch(notify_info_data_table[i].size)
3232 case NOTIFY_ONE_VALUE:
3233 case NOTIFY_TWO_VALUE:
3234 return 1;
3235 case NOTIFY_STRING:
3236 return 2;
3238 /* The only pointer notify data I have seen on
3239 the wire is the submitted time and this has
3240 the notify size set to 4. -tpot */
3242 case NOTIFY_POINTER:
3243 return 4;
3245 case NOTIFY_SECDESC:
3246 return 5;
3251 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3253 return 0;
3256 /*******************************************************************
3257 Return the type of notify_info_data.
3258 ********************************************************************/
3260 static int type_of_notify_info_data(uint16 type, uint16 field)
3262 int i=0;
3264 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3265 if (notify_info_data_table[i].type == type &&
3266 notify_info_data_table[i].field == field)
3267 return notify_info_data_table[i].size;
3270 return False;
3273 /****************************************************************************
3274 ****************************************************************************/
3276 static int search_notify(uint16 type, uint16 field, int *value)
3278 int i;
3280 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3281 if (notify_info_data_table[i].type == type &&
3282 notify_info_data_table[i].field == field &&
3283 notify_info_data_table[i].fn != NULL) {
3284 *value = i;
3285 return True;
3289 return False;
3292 /****************************************************************************
3293 ****************************************************************************/
3295 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3297 info_data->type = type;
3298 info_data->field = field;
3299 info_data->reserved = 0;
3301 info_data->size = size_of_notify_info_data(type, field);
3302 info_data->enc_type = type_of_notify_info_data(type, field);
3304 info_data->id = id;
3309 /*******************************************************************
3311 * fill a notify_info struct with info asked
3313 ********************************************************************/
3315 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3316 snum, SPOOL_NOTIFY_OPTION_TYPE
3317 *option_type, uint32 id,
3318 TALLOC_CTX *mem_ctx)
3320 int field_num,j;
3321 uint16 type;
3322 uint16 field;
3324 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3325 NT_PRINTER_INFO_LEVEL *printer = NULL;
3326 print_queue_struct *queue=NULL;
3328 type=option_type->type;
3330 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3331 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3332 option_type->count, lp_servicename(snum)));
3334 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3335 return False;
3337 for(field_num=0; field_num<option_type->count; field_num++)
3339 field = option_type->fields[field_num];
3341 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3343 if (!search_notify(type, field, &j) )
3344 continue;
3346 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3348 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3349 return False;
3351 else
3352 info->data = tid;
3354 current_data = &info->data[info->count];
3356 construct_info_data(current_data, type, field, id);
3358 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3359 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3361 notify_info_data_table[j].fn(snum, current_data, queue,
3362 printer, mem_ctx);
3364 info->count++;
3367 free_a_printer(&printer, 2);
3368 return True;
3371 /*******************************************************************
3373 * fill a notify_info struct with info asked
3375 ********************************************************************/
3377 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3378 SPOOL_NOTIFY_INFO *info,
3379 NT_PRINTER_INFO_LEVEL *printer,
3380 int snum, SPOOL_NOTIFY_OPTION_TYPE
3381 *option_type, uint32 id,
3382 TALLOC_CTX *mem_ctx)
3384 int field_num,j;
3385 uint16 type;
3386 uint16 field;
3388 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3390 DEBUG(4,("construct_notify_jobs_info\n"));
3392 type = option_type->type;
3394 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3395 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3396 option_type->count));
3398 for(field_num=0; field_num<option_type->count; field_num++) {
3399 field = option_type->fields[field_num];
3401 if (!search_notify(type, field, &j) )
3402 continue;
3404 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3405 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3406 return False;
3408 else info->data = tid;
3410 current_data=&(info->data[info->count]);
3412 construct_info_data(current_data, type, field, id);
3413 notify_info_data_table[j].fn(snum, current_data, queue,
3414 printer, mem_ctx);
3415 info->count++;
3418 return True;
3422 * JFM: The enumeration is not that simple, it's even non obvious.
3424 * let's take an example: I want to monitor the PRINTER SERVER for
3425 * the printer's name and the number of jobs currently queued.
3426 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3427 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3429 * I have 3 printers on the back of my server.
3431 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3432 * structures.
3433 * Number Data Id
3434 * 1 printer 1 name 1
3435 * 2 printer 1 cjob 1
3436 * 3 printer 2 name 2
3437 * 4 printer 2 cjob 2
3438 * 5 printer 3 name 3
3439 * 6 printer 3 name 3
3441 * that's the print server case, the printer case is even worse.
3444 /*******************************************************************
3446 * enumerate all printers on the printserver
3447 * fill a notify_info struct with info asked
3449 ********************************************************************/
3451 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3452 SPOOL_NOTIFY_INFO *info,
3453 TALLOC_CTX *mem_ctx)
3455 int snum;
3456 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3457 int n_services=lp_numservices();
3458 int i;
3459 uint32 id;
3460 SPOOL_NOTIFY_OPTION *option;
3461 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3463 DEBUG(4,("printserver_notify_info\n"));
3465 if (!Printer)
3466 return WERR_BADFID;
3468 option=Printer->notify.option;
3469 id=1;
3470 info->version=2;
3471 info->data=NULL;
3472 info->count=0;
3474 for (i=0; i<option->count; i++) {
3475 option_type=&(option->ctr.type[i]);
3477 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3478 continue;
3480 for (snum=0; snum<n_services; snum++)
3482 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3483 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3487 #if 0
3489 * Debugging information, don't delete.
3492 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3493 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3494 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3496 for (i=0; i<info->count; i++) {
3497 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3498 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3499 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3501 #endif
3503 return WERR_OK;
3506 /*******************************************************************
3508 * fill a notify_info struct with info asked
3510 ********************************************************************/
3512 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3513 TALLOC_CTX *mem_ctx)
3515 int snum;
3516 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3517 int i;
3518 uint32 id;
3519 SPOOL_NOTIFY_OPTION *option;
3520 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3521 int count,j;
3522 print_queue_struct *queue=NULL;
3523 print_status_struct status;
3525 DEBUG(4,("printer_notify_info\n"));
3527 if (!Printer)
3528 return WERR_BADFID;
3530 option=Printer->notify.option;
3531 id = 0x0;
3532 info->version=2;
3533 info->data=NULL;
3534 info->count=0;
3536 get_printer_snum(p, hnd, &snum);
3538 for (i=0; i<option->count; i++) {
3539 option_type=&option->ctr.type[i];
3541 switch ( option_type->type ) {
3542 case PRINTER_NOTIFY_TYPE:
3543 if(construct_notify_printer_info(info, snum,
3544 option_type, id,
3545 mem_ctx))
3546 id--;
3547 break;
3549 case JOB_NOTIFY_TYPE: {
3550 NT_PRINTER_INFO_LEVEL *printer = NULL;
3552 count = print_queue_status(snum, &queue, &status);
3554 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3555 lp_servicename(snum))))
3556 goto done;
3558 for (j=0; j<count; j++) {
3559 construct_notify_jobs_info(&queue[j], info,
3560 printer, snum,
3561 option_type,
3562 queue[j].job,
3563 mem_ctx);
3566 free_a_printer(&printer, 2);
3568 done:
3569 SAFE_FREE(queue);
3570 break;
3576 * Debugging information, don't delete.
3579 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3580 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3581 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3583 for (i=0; i<info->count; i++) {
3584 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3585 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3586 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3589 return WERR_OK;
3592 /********************************************************************
3593 * spoolss_rfnpcnex
3594 ********************************************************************/
3596 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3598 POLICY_HND *handle = &q_u->handle;
3599 SPOOL_NOTIFY_INFO *info = &r_u->info;
3601 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3602 WERROR result = WERR_BADFID;
3604 /* we always have a NOTIFY_INFO struct */
3605 r_u->info_ptr=0x1;
3607 if (!Printer) {
3608 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3609 OUR_HANDLE(handle)));
3610 goto done;
3613 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3616 * We are now using the change value, and
3617 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3618 * I don't have a global notification system, I'm sending back all the
3619 * informations even when _NOTHING_ has changed.
3622 /* We need to keep track of the change value to send back in
3623 RRPCN replies otherwise our updates are ignored. */
3625 if (Printer->notify.client_connected) {
3626 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3627 Printer->notify.change = q_u->change;
3630 /* just ignore the SPOOL_NOTIFY_OPTION */
3632 switch (Printer->printer_type) {
3633 case PRINTER_HANDLE_IS_PRINTSERVER:
3634 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3635 break;
3637 case PRINTER_HANDLE_IS_PRINTER:
3638 result = printer_notify_info(p, handle, info, p->mem_ctx);
3639 break;
3642 done:
3643 return result;
3646 /********************************************************************
3647 * construct_printer_info_0
3648 * fill a printer_info_0 struct
3649 ********************************************************************/
3651 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3653 pstring chaine;
3654 int count;
3655 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3656 counter_printer_0 *session_counter;
3657 uint32 global_counter;
3658 struct tm *t;
3659 time_t setuptime;
3660 print_status_struct status;
3662 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3663 return False;
3665 count = print_queue_length(snum, &status);
3667 /* check if we already have a counter for this printer */
3668 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3670 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3671 if (session_counter->snum == snum)
3672 break;
3675 /* it's the first time, add it to the list */
3676 if (session_counter==NULL) {
3677 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3678 free_a_printer(&ntprinter, 2);
3679 return False;
3681 ZERO_STRUCTP(session_counter);
3682 session_counter->snum=snum;
3683 session_counter->counter=0;
3684 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3687 /* increment it */
3688 session_counter->counter++;
3690 /* JFM:
3691 * the global_counter should be stored in a TDB as it's common to all the clients
3692 * and should be zeroed on samba startup
3694 global_counter=session_counter->counter;
3696 pstrcpy(chaine,ntprinter->info_2->printername);
3698 init_unistr(&printer->printername, chaine);
3700 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3701 init_unistr(&printer->servername, chaine);
3703 printer->cjobs = count;
3704 printer->total_jobs = 0;
3705 printer->total_bytes = 0;
3707 setuptime = (time_t)ntprinter->info_2->setuptime;
3708 t=gmtime(&setuptime);
3710 printer->year = t->tm_year+1900;
3711 printer->month = t->tm_mon+1;
3712 printer->dayofweek = t->tm_wday;
3713 printer->day = t->tm_mday;
3714 printer->hour = t->tm_hour;
3715 printer->minute = t->tm_min;
3716 printer->second = t->tm_sec;
3717 printer->milliseconds = 0;
3719 printer->global_counter = global_counter;
3720 printer->total_pages = 0;
3721 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3722 printer->major_version = 0x0004; /* NT 4 */
3723 printer->build_version = 0x0565; /* build 1381 */
3724 #else
3725 printer->major_version = 0x0005; /* NT 5 */
3726 printer->build_version = 0x0893; /* build 2195 */
3727 #endif
3728 printer->unknown7 = 0x1;
3729 printer->unknown8 = 0x0;
3730 printer->unknown9 = 0x0;
3731 printer->session_counter = session_counter->counter;
3732 printer->unknown11 = 0x0;
3733 printer->printer_errors = 0x0; /* number of print failure */
3734 printer->unknown13 = 0x0;
3735 printer->unknown14 = 0x1;
3736 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3737 printer->unknown16 = 0x0;
3738 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3739 printer->unknown18 = 0x0;
3740 printer->status = nt_printq_status(status.status);
3741 printer->unknown20 = 0x0;
3742 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3743 printer->unknown22 = 0x0;
3744 printer->unknown23 = 0x6; /* 6 ???*/
3745 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3746 printer->unknown25 = 0;
3747 printer->unknown26 = 0;
3748 printer->unknown27 = 0;
3749 printer->unknown28 = 0;
3750 printer->unknown29 = 0;
3752 free_a_printer(&ntprinter,2);
3753 return (True);
3756 /********************************************************************
3757 * construct_printer_info_1
3758 * fill a printer_info_1 struct
3759 ********************************************************************/
3760 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3762 pstring chaine;
3763 pstring chaine2;
3764 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3766 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3767 return False;
3769 printer->flags=flags;
3771 if (*ntprinter->info_2->comment == '\0') {
3772 init_unistr(&printer->comment, lp_comment(snum));
3773 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3774 ntprinter->info_2->drivername, lp_comment(snum));
3776 else {
3777 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3778 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3779 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3782 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3784 init_unistr(&printer->description, chaine);
3785 init_unistr(&printer->name, chaine2);
3787 free_a_printer(&ntprinter,2);
3789 return True;
3792 /****************************************************************************
3793 Free a DEVMODE struct.
3794 ****************************************************************************/
3796 static void free_dev_mode(DEVICEMODE *dev)
3798 if (dev == NULL)
3799 return;
3801 SAFE_FREE(dev->private);
3802 SAFE_FREE(dev);
3806 /****************************************************************************
3807 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3808 should be valid upon entry
3809 ****************************************************************************/
3811 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3813 if ( !devmode || !ntdevmode )
3814 return False;
3816 init_unistr(&devmode->devicename, ntdevmode->devicename);
3818 init_unistr(&devmode->formname, ntdevmode->formname);
3820 devmode->specversion = ntdevmode->specversion;
3821 devmode->driverversion = ntdevmode->driverversion;
3822 devmode->size = ntdevmode->size;
3823 devmode->driverextra = ntdevmode->driverextra;
3824 devmode->fields = ntdevmode->fields;
3826 devmode->orientation = ntdevmode->orientation;
3827 devmode->papersize = ntdevmode->papersize;
3828 devmode->paperlength = ntdevmode->paperlength;
3829 devmode->paperwidth = ntdevmode->paperwidth;
3830 devmode->scale = ntdevmode->scale;
3831 devmode->copies = ntdevmode->copies;
3832 devmode->defaultsource = ntdevmode->defaultsource;
3833 devmode->printquality = ntdevmode->printquality;
3834 devmode->color = ntdevmode->color;
3835 devmode->duplex = ntdevmode->duplex;
3836 devmode->yresolution = ntdevmode->yresolution;
3837 devmode->ttoption = ntdevmode->ttoption;
3838 devmode->collate = ntdevmode->collate;
3839 devmode->icmmethod = ntdevmode->icmmethod;
3840 devmode->icmintent = ntdevmode->icmintent;
3841 devmode->mediatype = ntdevmode->mediatype;
3842 devmode->dithertype = ntdevmode->dithertype;
3844 if (ntdevmode->private != NULL) {
3845 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3846 return False;
3849 return True;
3852 /****************************************************************************
3853 Create a DEVMODE struct. Returns malloced memory.
3854 ****************************************************************************/
3856 DEVICEMODE *construct_dev_mode(int snum)
3858 NT_PRINTER_INFO_LEVEL *printer = NULL;
3859 DEVICEMODE *devmode = NULL;
3861 DEBUG(7,("construct_dev_mode\n"));
3863 DEBUGADD(8,("getting printer characteristics\n"));
3865 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3866 return NULL;
3868 if ( !printer->info_2->devmode ) {
3869 DEBUG(5, ("BONG! There was no device mode!\n"));
3870 goto done;
3873 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3874 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3875 goto done;
3878 ZERO_STRUCTP(devmode);
3880 DEBUGADD(8,("loading DEVICEMODE\n"));
3882 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
3883 free_dev_mode( devmode );
3884 devmode = NULL;
3887 done:
3888 free_a_printer(&printer,2);
3890 return devmode;
3893 /********************************************************************
3894 * construct_printer_info_2
3895 * fill a printer_info_2 struct
3896 ********************************************************************/
3898 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3900 int count;
3901 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3903 print_status_struct status;
3905 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3906 return False;
3908 count = print_queue_length(snum, &status);
3910 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3911 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3912 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3913 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3914 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3916 if (*ntprinter->info_2->comment == '\0')
3917 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3918 else
3919 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3921 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3922 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3923 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3924 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3925 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3927 printer->attributes = ntprinter->info_2->attributes;
3929 printer->priority = ntprinter->info_2->priority; /* priority */
3930 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3931 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3932 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3933 printer->status = nt_printq_status(status.status); /* status */
3934 printer->cjobs = count; /* jobs */
3935 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3937 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3938 DEBUG(8, ("Returning NULL Devicemode!\n"));
3941 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3942 /* steal the printer info sec_desc structure. [badly done]. */
3943 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3944 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3945 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3946 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3948 else {
3949 printer->secdesc = NULL;
3952 free_a_printer(&ntprinter, 2);
3953 return True;
3956 /********************************************************************
3957 * construct_printer_info_3
3958 * fill a printer_info_3 struct
3959 ********************************************************************/
3961 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3963 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3964 PRINTER_INFO_3 *printer = NULL;
3966 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3967 return False;
3969 *pp_printer = NULL;
3970 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3971 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3972 return False;
3975 ZERO_STRUCTP(printer);
3977 printer->flags = 4; /* These are the components of the SD we are returning. */
3978 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3979 /* steal the printer info sec_desc structure. [badly done]. */
3980 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3982 #if 0
3984 * Set the flags for the components we are returning.
3987 if (printer->secdesc->owner_sid)
3988 printer->flags |= OWNER_SECURITY_INFORMATION;
3990 if (printer->secdesc->grp_sid)
3991 printer->flags |= GROUP_SECURITY_INFORMATION;
3993 if (printer->secdesc->dacl)
3994 printer->flags |= DACL_SECURITY_INFORMATION;
3996 if (printer->secdesc->sacl)
3997 printer->flags |= SACL_SECURITY_INFORMATION;
3998 #endif
4000 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4001 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4002 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4005 free_a_printer(&ntprinter, 2);
4007 *pp_printer = printer;
4008 return True;
4011 /********************************************************************
4012 * construct_printer_info_4
4013 * fill a printer_info_4 struct
4014 ********************************************************************/
4016 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4018 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4020 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4021 return False;
4023 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4024 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4025 printer->attributes = ntprinter->info_2->attributes;
4027 free_a_printer(&ntprinter, 2);
4028 return True;
4031 /********************************************************************
4032 * construct_printer_info_5
4033 * fill a printer_info_5 struct
4034 ********************************************************************/
4036 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4038 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4040 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4041 return False;
4043 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4044 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4045 printer->attributes = ntprinter->info_2->attributes;
4046 printer->device_not_selected_timeout = 0x3a98;
4047 printer->transmission_retry_timeout = 0xafc8;
4049 free_a_printer(&ntprinter, 2);
4050 return True;
4053 /********************************************************************
4054 Spoolss_enumprinters.
4055 ********************************************************************/
4057 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4059 int snum;
4060 int i;
4061 int n_services=lp_numservices();
4062 PRINTER_INFO_1 *tp, *printers=NULL;
4063 PRINTER_INFO_1 current_prt;
4065 DEBUG(4,("enum_all_printers_info_1\n"));
4067 for (snum=0; snum<n_services; snum++) {
4068 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4069 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4071 if (construct_printer_info_1(flags, &current_prt, snum)) {
4072 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4073 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4074 SAFE_FREE(printers);
4075 *returned=0;
4076 return WERR_NOMEM;
4078 else printers = tp;
4079 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4081 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4082 (*returned)++;
4087 /* check the required size. */
4088 for (i=0; i<*returned; i++)
4089 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4091 if (!alloc_buffer_size(buffer, *needed))
4092 return WERR_INSUFFICIENT_BUFFER;
4094 /* fill the buffer with the structures */
4095 for (i=0; i<*returned; i++)
4096 smb_io_printer_info_1("", buffer, &printers[i], 0);
4098 /* clear memory */
4099 SAFE_FREE(printers);
4101 if (*needed > offered) {
4102 *returned=0;
4103 return WERR_INSUFFICIENT_BUFFER;
4105 else
4106 return WERR_OK;
4109 /********************************************************************
4110 enum_all_printers_info_1_local.
4111 *********************************************************************/
4113 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4115 DEBUG(4,("enum_all_printers_info_1_local\n"));
4117 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4120 /********************************************************************
4121 enum_all_printers_info_1_name.
4122 *********************************************************************/
4124 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4126 char *s = name;
4128 DEBUG(4,("enum_all_printers_info_1_name\n"));
4130 if ((name[0] == '\\') && (name[1] == '\\'))
4131 s = name + 2;
4133 if (is_myname_or_ipaddr(s)) {
4134 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4136 else
4137 return WERR_INVALID_NAME;
4140 /********************************************************************
4141 enum_all_printers_info_1_remote.
4142 *********************************************************************/
4144 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4146 PRINTER_INFO_1 *printer;
4147 fstring printername;
4148 fstring desc;
4149 fstring comment;
4150 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4152 /* JFM: currently it's more a place holder than anything else.
4153 * In the spooler world there is a notion of server registration.
4154 * the print servers are registring (sp ?) on the PDC (in the same domain)
4156 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4159 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4160 return WERR_NOMEM;
4162 *returned=1;
4164 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4165 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4166 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4168 init_unistr(&printer->description, desc);
4169 init_unistr(&printer->name, printername);
4170 init_unistr(&printer->comment, comment);
4171 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4173 /* check the required size. */
4174 *needed += spoolss_size_printer_info_1(printer);
4176 if (!alloc_buffer_size(buffer, *needed)) {
4177 SAFE_FREE(printer);
4178 return WERR_INSUFFICIENT_BUFFER;
4181 /* fill the buffer with the structures */
4182 smb_io_printer_info_1("", buffer, printer, 0);
4184 /* clear memory */
4185 SAFE_FREE(printer);
4187 if (*needed > offered) {
4188 *returned=0;
4189 return WERR_INSUFFICIENT_BUFFER;
4191 else
4192 return WERR_OK;
4195 /********************************************************************
4196 enum_all_printers_info_1_network.
4197 *********************************************************************/
4199 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4201 char *s = name;
4203 DEBUG(4,("enum_all_printers_info_1_network\n"));
4205 /* If we respond to a enum_printers level 1 on our name with flags
4206 set to PRINTER_ENUM_REMOTE with a list of printers then these
4207 printers incorrectly appear in the APW browse list.
4208 Specifically the printers for the server appear at the workgroup
4209 level where all the other servers in the domain are
4210 listed. Windows responds to this call with a
4211 WERR_CAN_NOT_COMPLETE so we should do the same. */
4213 if (name[0] == '\\' && name[1] == '\\')
4214 s = name + 2;
4216 if (is_myname_or_ipaddr(s))
4217 return WERR_CAN_NOT_COMPLETE;
4219 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4222 /********************************************************************
4223 * api_spoolss_enumprinters
4225 * called from api_spoolss_enumprinters (see this to understand)
4226 ********************************************************************/
4228 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4230 int snum;
4231 int i;
4232 int n_services=lp_numservices();
4233 PRINTER_INFO_2 *tp, *printers=NULL;
4234 PRINTER_INFO_2 current_prt;
4236 for (snum=0; snum<n_services; snum++) {
4237 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4238 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4240 if (construct_printer_info_2(&current_prt, snum)) {
4241 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4242 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4243 SAFE_FREE(printers);
4244 *returned = 0;
4245 return WERR_NOMEM;
4247 else printers = tp;
4248 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4249 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4250 (*returned)++;
4255 /* check the required size. */
4256 for (i=0; i<*returned; i++)
4257 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4259 if (!alloc_buffer_size(buffer, *needed)) {
4260 for (i=0; i<*returned; i++) {
4261 free_devmode(printers[i].devmode);
4263 SAFE_FREE(printers);
4264 return WERR_INSUFFICIENT_BUFFER;
4267 /* fill the buffer with the structures */
4268 for (i=0; i<*returned; i++)
4269 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4271 /* clear memory */
4272 for (i=0; i<*returned; i++) {
4273 free_devmode(printers[i].devmode);
4275 SAFE_FREE(printers);
4277 if (*needed > offered) {
4278 *returned=0;
4279 return WERR_INSUFFICIENT_BUFFER;
4281 else
4282 return WERR_OK;
4285 /********************************************************************
4286 * handle enumeration of printers at level 1
4287 ********************************************************************/
4289 static WERROR enumprinters_level1( uint32 flags, fstring name,
4290 NEW_BUFFER *buffer, uint32 offered,
4291 uint32 *needed, uint32 *returned)
4293 /* Not all the flags are equals */
4295 if (flags & PRINTER_ENUM_LOCAL)
4296 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4298 if (flags & PRINTER_ENUM_NAME)
4299 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4301 if (flags & PRINTER_ENUM_REMOTE)
4302 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4304 if (flags & PRINTER_ENUM_NETWORK)
4305 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4307 return WERR_OK; /* NT4sp5 does that */
4310 /********************************************************************
4311 * handle enumeration of printers at level 2
4312 ********************************************************************/
4314 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4315 NEW_BUFFER *buffer, uint32 offered,
4316 uint32 *needed, uint32 *returned)
4318 char *s = servername;
4320 if (flags & PRINTER_ENUM_LOCAL) {
4321 return enum_all_printers_info_2(buffer, offered, needed, returned);
4324 if (flags & PRINTER_ENUM_NAME) {
4325 if ((servername[0] == '\\') && (servername[1] == '\\'))
4326 s = servername + 2;
4327 if (is_myname_or_ipaddr(s))
4328 return enum_all_printers_info_2(buffer, offered, needed, returned);
4329 else
4330 return WERR_INVALID_NAME;
4333 if (flags & PRINTER_ENUM_REMOTE)
4334 return WERR_UNKNOWN_LEVEL;
4336 return WERR_OK;
4339 /********************************************************************
4340 * handle enumeration of printers at level 5
4341 ********************************************************************/
4343 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4344 NEW_BUFFER *buffer, uint32 offered,
4345 uint32 *needed, uint32 *returned)
4347 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4348 return WERR_OK;
4351 /********************************************************************
4352 * api_spoolss_enumprinters
4354 * called from api_spoolss_enumprinters (see this to understand)
4355 ********************************************************************/
4357 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4359 uint32 flags = q_u->flags;
4360 UNISTR2 *servername = &q_u->servername;
4361 uint32 level = q_u->level;
4362 NEW_BUFFER *buffer = NULL;
4363 uint32 offered = q_u->offered;
4364 uint32 *needed = &r_u->needed;
4365 uint32 *returned = &r_u->returned;
4367 fstring name;
4369 /* that's an [in out] buffer */
4370 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4371 buffer = r_u->buffer;
4373 DEBUG(4,("_spoolss_enumprinters\n"));
4375 *needed=0;
4376 *returned=0;
4379 * Level 1:
4380 * flags==PRINTER_ENUM_NAME
4381 * if name=="" then enumerates all printers
4382 * if name!="" then enumerate the printer
4383 * flags==PRINTER_ENUM_REMOTE
4384 * name is NULL, enumerate printers
4385 * Level 2: name!="" enumerates printers, name can't be NULL
4386 * Level 3: doesn't exist
4387 * Level 4: does a local registry lookup
4388 * Level 5: same as Level 2
4391 unistr2_to_ascii(name, servername, sizeof(name)-1);
4392 strupper(name);
4394 switch (level) {
4395 case 1:
4396 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4397 case 2:
4398 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4399 case 5:
4400 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4401 case 3:
4402 case 4:
4403 break;
4405 return WERR_UNKNOWN_LEVEL;
4408 /****************************************************************************
4409 ****************************************************************************/
4411 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4413 PRINTER_INFO_0 *printer=NULL;
4415 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4416 return WERR_NOMEM;
4418 construct_printer_info_0(printer, snum);
4420 /* check the required size. */
4421 *needed += spoolss_size_printer_info_0(printer);
4423 if (!alloc_buffer_size(buffer, *needed)) {
4424 SAFE_FREE(printer);
4425 return WERR_INSUFFICIENT_BUFFER;
4428 /* fill the buffer with the structures */
4429 smb_io_printer_info_0("", buffer, printer, 0);
4431 /* clear memory */
4432 SAFE_FREE(printer);
4434 if (*needed > offered) {
4435 return WERR_INSUFFICIENT_BUFFER;
4438 return WERR_OK;
4441 /****************************************************************************
4442 ****************************************************************************/
4444 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4446 PRINTER_INFO_1 *printer=NULL;
4448 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4449 return WERR_NOMEM;
4451 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4453 /* check the required size. */
4454 *needed += spoolss_size_printer_info_1(printer);
4456 if (!alloc_buffer_size(buffer, *needed)) {
4457 SAFE_FREE(printer);
4458 return WERR_INSUFFICIENT_BUFFER;
4461 /* fill the buffer with the structures */
4462 smb_io_printer_info_1("", buffer, printer, 0);
4464 /* clear memory */
4465 SAFE_FREE(printer);
4467 if (*needed > offered) {
4468 return WERR_INSUFFICIENT_BUFFER;
4471 return WERR_OK;
4474 /****************************************************************************
4475 ****************************************************************************/
4477 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4479 PRINTER_INFO_2 *printer=NULL;
4481 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4482 return WERR_NOMEM;
4484 construct_printer_info_2(printer, snum);
4486 /* check the required size. */
4487 *needed += spoolss_size_printer_info_2(printer);
4489 if (!alloc_buffer_size(buffer, *needed)) {
4490 free_printer_info_2(printer);
4491 return WERR_INSUFFICIENT_BUFFER;
4494 /* fill the buffer with the structures */
4495 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4496 free_printer_info_2(printer);
4497 return WERR_NOMEM;
4500 /* clear memory */
4501 free_printer_info_2(printer);
4503 if (*needed > offered) {
4504 return WERR_INSUFFICIENT_BUFFER;
4507 return WERR_OK;
4510 /****************************************************************************
4511 ****************************************************************************/
4513 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4515 PRINTER_INFO_3 *printer=NULL;
4517 if (!construct_printer_info_3(&printer, snum))
4518 return WERR_NOMEM;
4520 /* check the required size. */
4521 *needed += spoolss_size_printer_info_3(printer);
4523 if (!alloc_buffer_size(buffer, *needed)) {
4524 free_printer_info_3(printer);
4525 return WERR_INSUFFICIENT_BUFFER;
4528 /* fill the buffer with the structures */
4529 smb_io_printer_info_3("", buffer, printer, 0);
4531 /* clear memory */
4532 free_printer_info_3(printer);
4534 if (*needed > offered) {
4535 return WERR_INSUFFICIENT_BUFFER;
4538 return WERR_OK;
4541 /****************************************************************************
4542 ****************************************************************************/
4544 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4546 PRINTER_INFO_4 *printer=NULL;
4548 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4549 return WERR_NOMEM;
4551 if (!construct_printer_info_4(printer, snum))
4552 return WERR_NOMEM;
4554 /* check the required size. */
4555 *needed += spoolss_size_printer_info_4(printer);
4557 if (!alloc_buffer_size(buffer, *needed)) {
4558 free_printer_info_4(printer);
4559 return WERR_INSUFFICIENT_BUFFER;
4562 /* fill the buffer with the structures */
4563 smb_io_printer_info_4("", buffer, printer, 0);
4565 /* clear memory */
4566 free_printer_info_4(printer);
4568 if (*needed > offered) {
4569 return WERR_INSUFFICIENT_BUFFER;
4572 return WERR_OK;
4575 /****************************************************************************
4576 ****************************************************************************/
4578 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4580 PRINTER_INFO_5 *printer=NULL;
4582 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4583 return WERR_NOMEM;
4585 if (!construct_printer_info_5(printer, snum))
4586 return WERR_NOMEM;
4588 /* check the required size. */
4589 *needed += spoolss_size_printer_info_5(printer);
4591 if (!alloc_buffer_size(buffer, *needed)) {
4592 free_printer_info_5(printer);
4593 return WERR_INSUFFICIENT_BUFFER;
4596 /* fill the buffer with the structures */
4597 smb_io_printer_info_5("", buffer, printer, 0);
4599 /* clear memory */
4600 free_printer_info_5(printer);
4602 if (*needed > offered) {
4603 return WERR_INSUFFICIENT_BUFFER;
4606 return WERR_OK;
4609 /****************************************************************************
4610 ****************************************************************************/
4612 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4614 POLICY_HND *handle = &q_u->handle;
4615 uint32 level = q_u->level;
4616 NEW_BUFFER *buffer = NULL;
4617 uint32 offered = q_u->offered;
4618 uint32 *needed = &r_u->needed;
4620 int snum;
4622 /* that's an [in out] buffer */
4623 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4624 buffer = r_u->buffer;
4626 *needed=0;
4628 if (!get_printer_snum(p, handle, &snum))
4629 return WERR_BADFID;
4631 switch (level) {
4632 case 0:
4633 return getprinter_level_0(snum, buffer, offered, needed);
4634 case 1:
4635 return getprinter_level_1(snum, buffer, offered, needed);
4636 case 2:
4637 return getprinter_level_2(snum, buffer, offered, needed);
4638 case 3:
4639 return getprinter_level_3(snum, buffer, offered, needed);
4640 case 4:
4641 return getprinter_level_4(snum, buffer, offered, needed);
4642 case 5:
4643 return getprinter_level_5(snum, buffer, offered, needed);
4645 return WERR_UNKNOWN_LEVEL;
4648 /********************************************************************
4649 * fill a DRIVER_INFO_1 struct
4650 ********************************************************************/
4652 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4654 init_unistr( &info->name, driver.info_3->name);
4657 /********************************************************************
4658 * construct_printer_driver_info_1
4659 ********************************************************************/
4661 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4663 NT_PRINTER_INFO_LEVEL *printer = NULL;
4664 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4666 ZERO_STRUCT(driver);
4668 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4669 return WERR_INVALID_PRINTER_NAME;
4671 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4672 return WERR_UNKNOWN_PRINTER_DRIVER;
4674 fill_printer_driver_info_1(info, driver, servername, architecture);
4676 free_a_printer(&printer,2);
4678 return WERR_OK;
4681 /********************************************************************
4682 * construct_printer_driver_info_2
4683 * fill a printer_info_2 struct
4684 ********************************************************************/
4686 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4688 pstring temp;
4690 info->version=driver.info_3->cversion;
4692 init_unistr( &info->name, driver.info_3->name );
4693 init_unistr( &info->architecture, driver.info_3->environment );
4696 if (strlen(driver.info_3->driverpath)) {
4697 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4698 init_unistr( &info->driverpath, temp );
4699 } else
4700 init_unistr( &info->driverpath, "" );
4702 if (strlen(driver.info_3->datafile)) {
4703 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4704 init_unistr( &info->datafile, temp );
4705 } else
4706 init_unistr( &info->datafile, "" );
4708 if (strlen(driver.info_3->configfile)) {
4709 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4710 init_unistr( &info->configfile, temp );
4711 } else
4712 init_unistr( &info->configfile, "" );
4715 /********************************************************************
4716 * construct_printer_driver_info_2
4717 * fill a printer_info_2 struct
4718 ********************************************************************/
4720 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4722 NT_PRINTER_INFO_LEVEL *printer = NULL;
4723 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4725 ZERO_STRUCT(printer);
4726 ZERO_STRUCT(driver);
4728 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4729 return WERR_INVALID_PRINTER_NAME;
4731 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4732 return WERR_UNKNOWN_PRINTER_DRIVER;
4734 fill_printer_driver_info_2(info, driver, servername);
4736 free_a_printer(&printer,2);
4738 return WERR_OK;
4741 /********************************************************************
4742 * copy a strings array and convert to UNICODE
4744 * convert an array of ascii string to a UNICODE string
4745 ********************************************************************/
4747 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4749 int i=0;
4750 int j=0;
4751 char *v;
4752 pstring line;
4753 uint16 *tuary;
4755 DEBUG(6,("init_unistr_array\n"));
4756 *uni_array=NULL;
4758 while (True)
4760 if ( !char_array )
4761 v = "";
4762 else
4764 v = char_array[i];
4765 if (!v)
4766 v = ""; /* hack to handle null lists */
4769 /* hack to allow this to be used in places other than when generating
4770 the list of dependent files */
4772 if ( servername )
4773 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4774 else
4775 pstrcpy( line, v );
4777 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4779 if ( (tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4780 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4781 return 0;
4782 } else
4783 *uni_array = tuary;
4785 if ( !strlen(v) )
4786 break;
4788 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4789 i++;
4792 if (*uni_array) {
4793 (*uni_array)[j]=0x0000;
4796 DEBUGADD(6,("last one:done\n"));
4798 /* return size of array in uint16's */
4800 return j+1;
4803 /********************************************************************
4804 * construct_printer_info_3
4805 * fill a printer_info_3 struct
4806 ********************************************************************/
4808 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4810 pstring temp;
4812 ZERO_STRUCTP(info);
4814 info->version=driver.info_3->cversion;
4816 init_unistr( &info->name, driver.info_3->name );
4817 init_unistr( &info->architecture, driver.info_3->environment );
4819 if (strlen(driver.info_3->driverpath)) {
4820 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4821 init_unistr( &info->driverpath, temp );
4822 } else
4823 init_unistr( &info->driverpath, "" );
4825 if (strlen(driver.info_3->datafile)) {
4826 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4827 init_unistr( &info->datafile, temp );
4828 } else
4829 init_unistr( &info->datafile, "" );
4831 if (strlen(driver.info_3->configfile)) {
4832 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4833 init_unistr( &info->configfile, temp );
4834 } else
4835 init_unistr( &info->configfile, "" );
4837 if (strlen(driver.info_3->helpfile)) {
4838 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4839 init_unistr( &info->helpfile, temp );
4840 } else
4841 init_unistr( &info->helpfile, "" );
4843 init_unistr( &info->monitorname, driver.info_3->monitorname );
4844 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4846 info->dependentfiles=NULL;
4847 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4850 /********************************************************************
4851 * construct_printer_info_3
4852 * fill a printer_info_3 struct
4853 ********************************************************************/
4855 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4857 NT_PRINTER_INFO_LEVEL *printer = NULL;
4858 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4859 WERROR status;
4860 ZERO_STRUCT(driver);
4862 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4863 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4864 if (!W_ERROR_IS_OK(status))
4865 return WERR_INVALID_PRINTER_NAME;
4867 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4868 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4870 #if 0 /* JERRY */
4873 * I put this code in during testing. Helpful when commenting out the
4874 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4875 * as win2k always queries the driver using an infor level of 6.
4876 * I've left it in (but ifdef'd out) because I'll probably
4877 * use it in experimentation again in the future. --jerry 22/01/2002
4880 if (!W_ERROR_IS_OK(status)) {
4882 * Is this a W2k client ?
4884 if (version == 3) {
4885 /* Yes - try again with a WinNT driver. */
4886 version = 2;
4887 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4888 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4890 #endif
4892 if (!W_ERROR_IS_OK(status)) {
4893 free_a_printer(&printer,2);
4894 return WERR_UNKNOWN_PRINTER_DRIVER;
4897 #if 0 /* JERRY */
4899 #endif
4902 fill_printer_driver_info_3(info, driver, servername);
4904 free_a_printer(&printer,2);
4906 return WERR_OK;
4909 /********************************************************************
4910 * construct_printer_info_6
4911 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4912 ********************************************************************/
4914 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4916 pstring temp;
4917 fstring nullstr;
4919 ZERO_STRUCTP(info);
4920 memset(&nullstr, '\0', sizeof(fstring));
4922 info->version=driver.info_3->cversion;
4924 init_unistr( &info->name, driver.info_3->name );
4925 init_unistr( &info->architecture, driver.info_3->environment );
4927 if (strlen(driver.info_3->driverpath)) {
4928 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4929 init_unistr( &info->driverpath, temp );
4930 } else
4931 init_unistr( &info->driverpath, "" );
4933 if (strlen(driver.info_3->datafile)) {
4934 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4935 init_unistr( &info->datafile, temp );
4936 } else
4937 init_unistr( &info->datafile, "" );
4939 if (strlen(driver.info_3->configfile)) {
4940 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4941 init_unistr( &info->configfile, temp );
4942 } else
4943 init_unistr( &info->configfile, "" );
4945 if (strlen(driver.info_3->helpfile)) {
4946 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4947 init_unistr( &info->helpfile, temp );
4948 } else
4949 init_unistr( &info->helpfile, "" );
4951 init_unistr( &info->monitorname, driver.info_3->monitorname );
4952 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4954 info->dependentfiles = NULL;
4955 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
4957 info->previousdrivernames=NULL;
4958 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4960 info->driver_date.low=0;
4961 info->driver_date.high=0;
4963 info->padding=0;
4964 info->driver_version_low=0;
4965 info->driver_version_high=0;
4967 init_unistr( &info->mfgname, "");
4968 init_unistr( &info->oem_url, "");
4969 init_unistr( &info->hardware_id, "");
4970 init_unistr( &info->provider, "");
4973 /********************************************************************
4974 * construct_printer_info_6
4975 * fill a printer_info_6 struct
4976 ********************************************************************/
4978 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
4979 fstring servername, fstring architecture, uint32 version)
4981 NT_PRINTER_INFO_LEVEL *printer = NULL;
4982 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4983 WERROR status;
4985 ZERO_STRUCT(driver);
4987 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4989 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4991 if (!W_ERROR_IS_OK(status))
4992 return WERR_INVALID_PRINTER_NAME;
4994 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4996 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4998 if (!W_ERROR_IS_OK(status))
5001 * Is this a W2k client ?
5004 if (version < 3) {
5005 free_a_printer(&printer,2);
5006 return WERR_UNKNOWN_PRINTER_DRIVER;
5009 /* Yes - try again with a WinNT driver. */
5010 version = 2;
5011 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5012 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5013 if (!W_ERROR_IS_OK(status)) {
5014 free_a_printer(&printer,2);
5015 return WERR_UNKNOWN_PRINTER_DRIVER;
5019 fill_printer_driver_info_6(info, driver, servername);
5021 free_a_printer(&printer,2);
5023 return WERR_OK;
5026 /****************************************************************************
5027 ****************************************************************************/
5029 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5031 SAFE_FREE(info->dependentfiles);
5034 /****************************************************************************
5035 ****************************************************************************/
5037 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5039 SAFE_FREE(info->dependentfiles);
5043 /****************************************************************************
5044 ****************************************************************************/
5046 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5048 DRIVER_INFO_1 *info=NULL;
5049 WERROR status;
5051 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5052 return WERR_NOMEM;
5054 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5055 if (!W_ERROR_IS_OK(status)) {
5056 SAFE_FREE(info);
5057 return status;
5060 /* check the required size. */
5061 *needed += spoolss_size_printer_driver_info_1(info);
5063 if (!alloc_buffer_size(buffer, *needed)) {
5064 SAFE_FREE(info);
5065 return WERR_INSUFFICIENT_BUFFER;
5068 /* fill the buffer with the structures */
5069 smb_io_printer_driver_info_1("", buffer, info, 0);
5071 /* clear memory */
5072 SAFE_FREE(info);
5074 if (*needed > offered)
5075 return WERR_INSUFFICIENT_BUFFER;
5077 return WERR_OK;
5080 /****************************************************************************
5081 ****************************************************************************/
5083 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5085 DRIVER_INFO_2 *info=NULL;
5086 WERROR status;
5088 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5089 return WERR_NOMEM;
5091 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5092 if (!W_ERROR_IS_OK(status)) {
5093 SAFE_FREE(info);
5094 return status;
5097 /* check the required size. */
5098 *needed += spoolss_size_printer_driver_info_2(info);
5100 if (!alloc_buffer_size(buffer, *needed)) {
5101 SAFE_FREE(info);
5102 return WERR_INSUFFICIENT_BUFFER;
5105 /* fill the buffer with the structures */
5106 smb_io_printer_driver_info_2("", buffer, info, 0);
5108 /* clear memory */
5109 SAFE_FREE(info);
5111 if (*needed > offered)
5112 return WERR_INSUFFICIENT_BUFFER;
5114 return WERR_OK;
5117 /****************************************************************************
5118 ****************************************************************************/
5120 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5122 DRIVER_INFO_3 info;
5123 WERROR status;
5125 ZERO_STRUCT(info);
5127 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5128 if (!W_ERROR_IS_OK(status)) {
5129 return status;
5132 /* check the required size. */
5133 *needed += spoolss_size_printer_driver_info_3(&info);
5135 if (!alloc_buffer_size(buffer, *needed)) {
5136 free_printer_driver_info_3(&info);
5137 return WERR_INSUFFICIENT_BUFFER;
5140 /* fill the buffer with the structures */
5141 smb_io_printer_driver_info_3("", buffer, &info, 0);
5143 free_printer_driver_info_3(&info);
5145 if (*needed > offered)
5146 return WERR_INSUFFICIENT_BUFFER;
5148 return WERR_OK;
5151 /****************************************************************************
5152 ****************************************************************************/
5154 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5156 DRIVER_INFO_6 info;
5157 WERROR status;
5159 ZERO_STRUCT(info);
5161 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5162 if (!W_ERROR_IS_OK(status)) {
5163 return status;
5166 /* check the required size. */
5167 *needed += spoolss_size_printer_driver_info_6(&info);
5169 if (!alloc_buffer_size(buffer, *needed)) {
5170 free_printer_driver_info_6(&info);
5171 return WERR_INSUFFICIENT_BUFFER;
5174 /* fill the buffer with the structures */
5175 smb_io_printer_driver_info_6("", buffer, &info, 0);
5177 free_printer_driver_info_6(&info);
5179 if (*needed > offered)
5180 return WERR_INSUFFICIENT_BUFFER;
5182 return WERR_OK;
5185 /****************************************************************************
5186 ****************************************************************************/
5188 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5190 POLICY_HND *handle = &q_u->handle;
5191 UNISTR2 *uni_arch = &q_u->architecture;
5192 uint32 level = q_u->level;
5193 uint32 clientmajorversion = q_u->clientmajorversion;
5194 NEW_BUFFER *buffer = NULL;
5195 uint32 offered = q_u->offered;
5196 uint32 *needed = &r_u->needed;
5197 uint32 *servermajorversion = &r_u->servermajorversion;
5198 uint32 *serverminorversion = &r_u->serverminorversion;
5200 fstring servername;
5201 fstring architecture;
5202 int snum;
5204 /* that's an [in out] buffer */
5205 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5206 buffer = r_u->buffer;
5208 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5210 *needed = 0;
5211 *servermajorversion = 0;
5212 *serverminorversion = 0;
5214 pstrcpy(servername, get_called_name());
5215 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5217 if (!get_printer_snum(p, handle, &snum))
5218 return WERR_BADFID;
5220 switch (level) {
5221 case 1:
5222 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5223 case 2:
5224 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5225 case 3:
5226 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5227 case 6:
5228 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5231 return WERR_UNKNOWN_LEVEL;
5234 /****************************************************************************
5235 ****************************************************************************/
5237 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5239 POLICY_HND *handle = &q_u->handle;
5241 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5243 if (!Printer) {
5244 DEBUG(3,("Error in startpageprinter printer handle\n"));
5245 return WERR_BADFID;
5248 Printer->page_started=True;
5249 return WERR_OK;
5252 /****************************************************************************
5253 ****************************************************************************/
5255 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5257 POLICY_HND *handle = &q_u->handle;
5258 int snum;
5260 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5262 if (!Printer) {
5263 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5264 return WERR_BADFID;
5267 if (!get_printer_snum(p, handle, &snum))
5268 return WERR_BADFID;
5270 Printer->page_started=False;
5271 print_job_endpage(snum, Printer->jobid);
5273 return WERR_OK;
5276 /********************************************************************
5277 * api_spoolss_getprinter
5278 * called from the spoolss dispatcher
5280 ********************************************************************/
5282 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5284 POLICY_HND *handle = &q_u->handle;
5285 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5286 uint32 *jobid = &r_u->jobid;
5288 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5289 int snum;
5290 pstring jobname;
5291 fstring datatype;
5292 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5293 struct current_user user;
5295 if (!Printer) {
5296 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5297 return WERR_BADFID;
5300 get_current_user(&user, p);
5303 * a nice thing with NT is it doesn't listen to what you tell it.
5304 * when asked to send _only_ RAW datas, it tries to send datas
5305 * in EMF format.
5307 * So I add checks like in NT Server ...
5310 if (info_1->p_datatype != 0) {
5311 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5312 if (strcmp(datatype, "RAW") != 0) {
5313 (*jobid)=0;
5314 return WERR_INVALID_DATATYPE;
5318 /* get the share number of the printer */
5319 if (!get_printer_snum(p, handle, &snum)) {
5320 return WERR_BADFID;
5323 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5325 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5327 /* An error occured in print_job_start() so return an appropriate
5328 NT error code. */
5330 if (Printer->jobid == -1) {
5331 return map_werror_from_unix(errno);
5334 Printer->document_started=True;
5335 (*jobid) = Printer->jobid;
5337 return WERR_OK;
5340 /********************************************************************
5341 * api_spoolss_getprinter
5342 * called from the spoolss dispatcher
5344 ********************************************************************/
5346 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5348 POLICY_HND *handle = &q_u->handle;
5350 return _spoolss_enddocprinter_internal(p, handle);
5353 /****************************************************************************
5354 ****************************************************************************/
5356 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5358 POLICY_HND *handle = &q_u->handle;
5359 uint32 buffer_size = q_u->buffer_size;
5360 uint8 *buffer = q_u->buffer;
5361 uint32 *buffer_written = &q_u->buffer_size2;
5362 int snum;
5363 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5365 if (!Printer) {
5366 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5367 r_u->buffer_written = q_u->buffer_size2;
5368 return WERR_BADFID;
5371 if (!get_printer_snum(p, handle, &snum))
5372 return WERR_BADFID;
5374 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5375 if (*buffer_written == -1) {
5376 r_u->buffer_written = 0;
5377 if (errno == ENOSPC)
5378 return WERR_NO_SPOOL_SPACE;
5379 else
5380 return WERR_ACCESS_DENIED;
5383 r_u->buffer_written = q_u->buffer_size2;
5385 return WERR_OK;
5388 /********************************************************************
5389 * api_spoolss_getprinter
5390 * called from the spoolss dispatcher
5392 ********************************************************************/
5394 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5395 pipes_struct *p)
5397 struct current_user user;
5398 int snum;
5399 WERROR errcode = WERR_BADFUNC;
5400 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5402 get_current_user(&user, p);
5404 if (!Printer) {
5405 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5406 return WERR_BADFID;
5409 if (!get_printer_snum(p, handle, &snum))
5410 return WERR_BADFID;
5412 switch (command) {
5413 case PRINTER_CONTROL_PAUSE:
5414 if (print_queue_pause(&user, snum, &errcode)) {
5415 errcode = WERR_OK;
5417 break;
5418 case PRINTER_CONTROL_RESUME:
5419 case PRINTER_CONTROL_UNPAUSE:
5420 if (print_queue_resume(&user, snum, &errcode)) {
5421 errcode = WERR_OK;
5423 break;
5424 #if 0 /* JERRY - Never called */
5425 case PRINTER_CONTROL_PURGE:
5426 if (print_queue_purge(&user, snum, &errcode)) {
5427 errcode = WERR_OK;
5429 break;
5430 #endif
5431 default:
5432 return WERR_UNKNOWN_LEVEL;
5435 return errcode;
5438 /********************************************************************
5439 * api_spoolss_abortprinter
5440 * From MSDN: "Deletes printer's spool file if printer is configured
5441 * for spooling"
5442 ********************************************************************/
5444 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5446 POLICY_HND *handle = &q_u->handle;
5447 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5448 int snum;
5449 struct current_user user;
5450 WERROR errcode = WERR_OK;
5452 if (!Printer) {
5453 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5454 return WERR_BADFID;
5457 if (!get_printer_snum(p, handle, &snum))
5458 return WERR_BADFID;
5460 get_current_user( &user, p );
5462 print_job_delete( &user, snum, Printer->jobid, &errcode );
5464 return errcode;
5467 /********************************************************************
5468 * called by spoolss_api_setprinter
5469 * when updating a printer description
5470 ********************************************************************/
5472 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5473 const SPOOL_PRINTER_INFO_LEVEL *info,
5474 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5476 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5477 struct current_user user;
5478 WERROR result;
5479 int snum;
5481 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5483 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5484 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5485 OUR_HANDLE(handle)));
5487 result = WERR_BADFID;
5488 goto done;
5491 /* NT seems to like setting the security descriptor even though
5492 nothing may have actually changed. This causes annoying
5493 dialog boxes when the user doesn't have permission to change
5494 the security descriptor. */
5496 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5498 if (DEBUGLEVEL >= 10) {
5499 SEC_ACL *the_acl;
5500 int i;
5502 the_acl = old_secdesc_ctr->sec->dacl;
5503 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5504 PRINTERNAME(snum), the_acl->num_aces));
5506 for (i = 0; i < the_acl->num_aces; i++) {
5507 fstring sid_str;
5509 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5511 DEBUG(10, ("%s 0x%08x\n", sid_str,
5512 the_acl->ace[i].info.mask));
5515 the_acl = secdesc_ctr->sec->dacl;
5517 if (the_acl) {
5518 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5519 PRINTERNAME(snum), the_acl->num_aces));
5521 for (i = 0; i < the_acl->num_aces; i++) {
5522 fstring sid_str;
5524 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5526 DEBUG(10, ("%s 0x%08x\n", sid_str,
5527 the_acl->ace[i].info.mask));
5529 } else {
5530 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5534 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5536 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5537 result = WERR_OK;
5538 goto done;
5541 /* Work out which user is performing the operation */
5543 get_current_user(&user, p);
5545 /* Check the user has permissions to change the security
5546 descriptor. By experimentation with two NT machines, the user
5547 requires Full Access to the printer to change security
5548 information. */
5550 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5551 result = WERR_ACCESS_DENIED;
5552 goto done;
5555 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5557 done:
5559 return result;
5562 /********************************************************************
5563 Do Samba sanity checks on a printer info struct.
5564 this has changed purpose: it now "canonicalises" printer
5565 info from a client rather than just checking it is correct
5566 ********************************************************************/
5568 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5570 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5571 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5573 /* we force some elements to "correct" values */
5574 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5575 fstrcpy(info->sharename, lp_servicename(snum));
5576 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5577 get_called_name(), info->sharename);
5578 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5580 return True;
5583 /****************************************************************************
5584 ****************************************************************************/
5586 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5588 extern userdom_struct current_user_info;
5589 char *cmd = lp_addprinter_cmd();
5590 char **qlines;
5591 pstring command;
5592 pstring driverlocation;
5593 int numlines;
5594 int ret;
5595 int fd;
5596 fstring remote_machine = "%m";
5598 /* build driver path... only 9X architecture is needed for legacy reasons */
5599 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
5600 get_called_name());
5601 /* change \ to \\ for the shell */
5602 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
5603 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5605 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5606 cmd, printer->info_2->printername, printer->info_2->sharename,
5607 printer->info_2->portname, printer->info_2->drivername,
5608 printer->info_2->location, driverlocation, remote_machine);
5610 DEBUG(10,("Running [%s]\n", command));
5611 ret = smbrun(command, &fd);
5612 DEBUGADD(10,("returned [%d]\n", ret));
5614 if ( ret != 0 ) {
5615 if (fd != -1)
5616 close(fd);
5617 return False;
5620 numlines = 0;
5621 /* Get lines and convert them back to dos-codepage */
5622 qlines = fd_lines_load(fd, &numlines);
5623 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5624 close(fd);
5626 if(numlines) {
5627 /* Set the portname to what the script says the portname should be. */
5628 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5629 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5631 /* Send SIGHUP to process group... is there a better way? */
5632 kill(0, SIGHUP);
5633 add_all_printers();
5636 file_lines_free(qlines);
5637 return True;
5640 /********************************************************************
5641 * Called by spoolss_api_setprinter
5642 * when updating a printer description.
5643 ********************************************************************/
5645 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5646 const SPOOL_PRINTER_INFO_LEVEL *info,
5647 DEVICEMODE *devmode)
5649 int snum;
5650 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5651 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5652 WERROR result;
5654 DEBUG(8,("update_printer\n"));
5656 result = WERR_OK;
5658 if (level!=2) {
5659 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5660 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5661 result = WERR_UNKNOWN_LEVEL;
5662 goto done;
5665 if (!Printer) {
5666 result = WERR_BADFID;
5667 goto done;
5670 if (!get_printer_snum(p, handle, &snum)) {
5671 result = WERR_BADFID;
5672 goto done;
5675 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5676 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5677 result = WERR_BADFID;
5678 goto done;
5681 DEBUGADD(8,("Converting info_2 struct\n"));
5684 * convert_printer_info converts the incoming
5685 * info from the client and overwrites the info
5686 * just read from the tdb in the pointer 'printer'.
5689 if (!convert_printer_info(info, printer, level)) {
5690 result = WERR_NOMEM;
5691 goto done;
5694 if (devmode) {
5695 /* we have a valid devmode
5696 convert it and link it*/
5698 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5699 if (!convert_devicemode(printer->info_2->printername, devmode,
5700 &printer->info_2->devmode)) {
5701 result = WERR_NOMEM;
5702 goto done;
5706 /* Do sanity check on the requested changes for Samba */
5708 if (!check_printer_ok(printer->info_2, snum)) {
5709 result = WERR_INVALID_PARAM;
5710 goto done;
5713 /* Check calling user has permission to update printer description */
5715 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5716 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5717 result = WERR_ACCESS_DENIED;
5718 goto done;
5721 /* Call addprinter hook */
5723 if (*lp_addprinter_cmd()) {
5724 if ( !add_printer_hook(printer) ) {
5725 result = WERR_ACCESS_DENIED;
5726 goto done;
5731 * When a *new* driver is bound to a printer, the drivername is used to
5732 * lookup previously saved driver initialization info, which is then
5733 * bound to the printer, simulating what happens in the Windows arch.
5735 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5737 if (!set_driver_init(printer, 2))
5739 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5740 printer->info_2->drivername));
5743 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5744 printer->info_2->drivername));
5746 notify_printer_driver(snum, printer->info_2->drivername);
5749 /* Update printer info */
5750 result = mod_a_printer(*printer, 2);
5752 /* flag which changes actually occured. This is a small subset of
5753 all the possible changes */
5755 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5756 notify_printer_comment(snum, printer->info_2->comment);
5758 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5759 notify_printer_sharename(snum, printer->info_2->sharename);
5761 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5762 notify_printer_port(snum, printer->info_2->portname);
5764 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5765 notify_printer_location(snum, printer->info_2->location);
5767 done:
5768 free_a_printer(&printer, 2);
5769 free_a_printer(&old_printer, 2);
5772 return result;
5775 /****************************************************************************
5776 ****************************************************************************/
5778 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5780 POLICY_HND *handle = &q_u->handle;
5781 uint32 level = q_u->level;
5782 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5783 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5784 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5785 uint32 command = q_u->command;
5787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5789 if (!Printer) {
5790 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5791 return WERR_BADFID;
5794 /* check the level */
5795 switch (level) {
5796 case 0:
5797 return control_printer(handle, command, p);
5798 case 2:
5799 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5800 case 3:
5801 return update_printer_sec(handle, level, info, p,
5802 secdesc_ctr);
5803 default:
5804 return WERR_UNKNOWN_LEVEL;
5808 /****************************************************************************
5809 ****************************************************************************/
5811 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5813 POLICY_HND *handle = &q_u->handle;
5815 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5817 if (!Printer) {
5818 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5819 return WERR_BADFID;
5822 if (Printer->notify.client_connected==True)
5823 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5825 Printer->notify.flags=0;
5826 Printer->notify.options=0;
5827 Printer->notify.localmachine[0]='\0';
5828 Printer->notify.printerlocal=0;
5829 if (Printer->notify.option)
5830 free_spool_notify_option(&Printer->notify.option);
5831 Printer->notify.client_connected=False;
5833 return WERR_OK;
5836 /****************************************************************************
5837 ****************************************************************************/
5839 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5841 /* that's an [in out] buffer (despite appearences to the contrary) */
5842 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5844 r_u->needed = 0;
5845 return WERR_INVALID_PARAM; /* this is what a NT server
5846 returns for AddJob. AddJob
5847 must fail on non-local
5848 printers */
5851 /****************************************************************************
5852 ****************************************************************************/
5854 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5855 int position, int snum)
5857 pstring temp_name;
5859 struct tm *t;
5861 t=gmtime(&queue->time);
5862 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5864 job_info->jobid=queue->job;
5865 init_unistr(&job_info->printername, lp_servicename(snum));
5866 init_unistr(&job_info->machinename, temp_name);
5867 init_unistr(&job_info->username, queue->fs_user);
5868 init_unistr(&job_info->document, queue->fs_file);
5869 init_unistr(&job_info->datatype, "RAW");
5870 init_unistr(&job_info->text_status, "");
5871 job_info->status=nt_printj_status(queue->status);
5872 job_info->priority=queue->priority;
5873 job_info->position=position;
5874 job_info->totalpages=queue->page_count;
5875 job_info->pagesprinted=0;
5877 make_systemtime(&job_info->submitted, t);
5880 /****************************************************************************
5881 ****************************************************************************/
5883 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5884 int position, int snum,
5885 NT_PRINTER_INFO_LEVEL *ntprinter,
5886 DEVICEMODE *devmode)
5888 pstring temp_name;
5889 pstring chaine;
5890 struct tm *t;
5892 t=gmtime(&queue->time);
5893 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5895 job_info->jobid=queue->job;
5897 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5899 init_unistr(&job_info->printername, chaine);
5901 init_unistr(&job_info->machinename, temp_name);
5902 init_unistr(&job_info->username, queue->fs_user);
5903 init_unistr(&job_info->document, queue->fs_file);
5904 init_unistr(&job_info->notifyname, queue->fs_user);
5905 init_unistr(&job_info->datatype, "RAW");
5906 init_unistr(&job_info->printprocessor, "winprint");
5907 init_unistr(&job_info->parameters, "");
5908 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5909 init_unistr(&job_info->text_status, "");
5911 /* and here the security descriptor */
5913 job_info->status=nt_printj_status(queue->status);
5914 job_info->priority=queue->priority;
5915 job_info->position=position;
5916 job_info->starttime=0;
5917 job_info->untiltime=0;
5918 job_info->totalpages=queue->page_count;
5919 job_info->size=queue->size;
5920 make_systemtime(&(job_info->submitted), t);
5921 job_info->timeelapsed=0;
5922 job_info->pagesprinted=0;
5924 job_info->devmode = devmode;
5926 return (True);
5929 /****************************************************************************
5930 Enumjobs at level 1.
5931 ****************************************************************************/
5933 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5934 NEW_BUFFER *buffer, uint32 offered,
5935 uint32 *needed, uint32 *returned)
5937 JOB_INFO_1 *info;
5938 int i;
5940 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5941 if (info==NULL) {
5942 SAFE_FREE(queue);
5943 *returned=0;
5944 return WERR_NOMEM;
5947 for (i=0; i<*returned; i++)
5948 fill_job_info_1(&info[i], &queue[i], i, snum);
5950 SAFE_FREE(queue);
5952 /* check the required size. */
5953 for (i=0; i<*returned; i++)
5954 (*needed) += spoolss_size_job_info_1(&info[i]);
5956 if (!alloc_buffer_size(buffer, *needed)) {
5957 SAFE_FREE(info);
5958 return WERR_INSUFFICIENT_BUFFER;
5961 /* fill the buffer with the structures */
5962 for (i=0; i<*returned; i++)
5963 smb_io_job_info_1("", buffer, &info[i], 0);
5965 /* clear memory */
5966 SAFE_FREE(info);
5968 if (*needed > offered) {
5969 *returned=0;
5970 return WERR_INSUFFICIENT_BUFFER;
5973 return WERR_OK;
5976 /****************************************************************************
5977 Enumjobs at level 2.
5978 ****************************************************************************/
5980 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5981 NEW_BUFFER *buffer, uint32 offered,
5982 uint32 *needed, uint32 *returned)
5984 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5985 JOB_INFO_2 *info = NULL;
5986 int i;
5987 WERROR result;
5988 DEVICEMODE *devmode = NULL;
5990 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5991 if (info==NULL) {
5992 *returned=0;
5993 result = WERR_NOMEM;
5994 goto done;
5997 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5998 if (!W_ERROR_IS_OK(result)) {
5999 *returned = 0;
6000 goto done;
6003 if (!(devmode = construct_dev_mode(snum))) {
6004 *returned = 0;
6005 result = WERR_NOMEM;
6006 goto done;
6009 for (i=0; i<*returned; i++)
6010 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6011 devmode);
6013 free_a_printer(&ntprinter, 2);
6014 SAFE_FREE(queue);
6016 /* check the required size. */
6017 for (i=0; i<*returned; i++)
6018 (*needed) += spoolss_size_job_info_2(&info[i]);
6020 if (*needed > offered) {
6021 *returned=0;
6022 result = WERR_INSUFFICIENT_BUFFER;
6023 goto done;
6026 if (!alloc_buffer_size(buffer, *needed)) {
6027 SAFE_FREE(info);
6028 result = WERR_INSUFFICIENT_BUFFER;
6029 goto done;
6032 /* fill the buffer with the structures */
6033 for (i=0; i<*returned; i++)
6034 smb_io_job_info_2("", buffer, &info[i], 0);
6036 result = WERR_OK;
6038 done:
6039 free_a_printer(&ntprinter, 2);
6040 free_devmode(devmode);
6041 SAFE_FREE(queue);
6042 SAFE_FREE(info);
6044 return result;
6048 /****************************************************************************
6049 Enumjobs.
6050 ****************************************************************************/
6052 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6054 POLICY_HND *handle = &q_u->handle;
6055 uint32 level = q_u->level;
6056 NEW_BUFFER *buffer = NULL;
6057 uint32 offered = q_u->offered;
6058 uint32 *needed = &r_u->needed;
6059 uint32 *returned = &r_u->returned;
6061 int snum;
6062 print_status_struct prt_status;
6063 print_queue_struct *queue=NULL;
6065 /* that's an [in out] buffer */
6066 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6067 buffer = r_u->buffer;
6069 DEBUG(4,("_spoolss_enumjobs\n"));
6071 *needed=0;
6072 *returned=0;
6074 if (!get_printer_snum(p, handle, &snum))
6075 return WERR_BADFID;
6077 *returned = print_queue_status(snum, &queue, &prt_status);
6078 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6080 if (*returned == 0) {
6081 SAFE_FREE(queue);
6082 return WERR_OK;
6085 switch (level) {
6086 case 1:
6087 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6088 case 2:
6089 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6090 default:
6091 SAFE_FREE(queue);
6092 *returned=0;
6093 return WERR_UNKNOWN_LEVEL;
6097 /****************************************************************************
6098 ****************************************************************************/
6100 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6102 return WERR_OK;
6105 /****************************************************************************
6106 ****************************************************************************/
6108 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6110 POLICY_HND *handle = &q_u->handle;
6111 uint32 jobid = q_u->jobid;
6112 uint32 command = q_u->command;
6114 struct current_user user;
6115 int snum;
6116 WERROR errcode = WERR_BADFUNC;
6118 if (!get_printer_snum(p, handle, &snum)) {
6119 return WERR_BADFID;
6122 if (!print_job_exists(snum, jobid)) {
6123 return WERR_INVALID_PRINTER_NAME;
6126 get_current_user(&user, p);
6128 switch (command) {
6129 case JOB_CONTROL_CANCEL:
6130 case JOB_CONTROL_DELETE:
6131 if (print_job_delete(&user, snum, jobid, &errcode)) {
6132 errcode = WERR_OK;
6134 break;
6135 case JOB_CONTROL_PAUSE:
6136 if (print_job_pause(&user, snum, jobid, &errcode)) {
6137 errcode = WERR_OK;
6139 break;
6140 case JOB_CONTROL_RESTART:
6141 case JOB_CONTROL_RESUME:
6142 if (print_job_resume(&user, snum, jobid, &errcode)) {
6143 errcode = WERR_OK;
6145 break;
6146 default:
6147 return WERR_UNKNOWN_LEVEL;
6150 return errcode;
6153 /****************************************************************************
6154 Enumerates all printer drivers at level 1.
6155 ****************************************************************************/
6157 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6159 int i;
6160 int ndrivers;
6161 uint32 version;
6162 fstring *list = NULL;
6164 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6165 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6167 *returned=0;
6169 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6170 list=NULL;
6171 ndrivers=get_ntdrivers(&list, architecture, version);
6172 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6174 if(ndrivers == -1)
6175 return WERR_NOMEM;
6177 if(ndrivers != 0) {
6178 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6179 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6180 SAFE_FREE(driver_info_1);
6181 SAFE_FREE(list);
6182 return WERR_NOMEM;
6184 else driver_info_1 = tdi1;
6187 for (i=0; i<ndrivers; i++) {
6188 WERROR status;
6189 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6190 ZERO_STRUCT(driver);
6191 status = get_a_printer_driver(&driver, 3, list[i],
6192 architecture, version);
6193 if (!W_ERROR_IS_OK(status)) {
6194 SAFE_FREE(list);
6195 return status;
6197 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6198 free_a_printer_driver(driver, 3);
6201 *returned+=ndrivers;
6202 SAFE_FREE(list);
6205 /* check the required size. */
6206 for (i=0; i<*returned; i++) {
6207 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6208 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6211 if (!alloc_buffer_size(buffer, *needed)) {
6212 SAFE_FREE(driver_info_1);
6213 return WERR_INSUFFICIENT_BUFFER;
6216 /* fill the buffer with the driver structures */
6217 for (i=0; i<*returned; i++) {
6218 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6219 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6222 SAFE_FREE(driver_info_1);
6224 if (*needed > offered) {
6225 *returned=0;
6226 return WERR_INSUFFICIENT_BUFFER;
6229 return WERR_OK;
6232 /****************************************************************************
6233 Enumerates all printer drivers at level 2.
6234 ****************************************************************************/
6236 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6238 int i;
6239 int ndrivers;
6240 uint32 version;
6241 fstring *list = NULL;
6243 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6244 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6246 *returned=0;
6248 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6249 list=NULL;
6250 ndrivers=get_ntdrivers(&list, architecture, version);
6251 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6253 if(ndrivers == -1)
6254 return WERR_NOMEM;
6256 if(ndrivers != 0) {
6257 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6258 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6259 SAFE_FREE(driver_info_2);
6260 SAFE_FREE(list);
6261 return WERR_NOMEM;
6263 else driver_info_2 = tdi2;
6266 for (i=0; i<ndrivers; i++) {
6267 WERROR status;
6269 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6270 ZERO_STRUCT(driver);
6271 status = get_a_printer_driver(&driver, 3, list[i],
6272 architecture, version);
6273 if (!W_ERROR_IS_OK(status)) {
6274 SAFE_FREE(list);
6275 return status;
6277 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6278 free_a_printer_driver(driver, 3);
6281 *returned+=ndrivers;
6282 SAFE_FREE(list);
6285 /* check the required size. */
6286 for (i=0; i<*returned; i++) {
6287 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6288 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6291 if (!alloc_buffer_size(buffer, *needed)) {
6292 SAFE_FREE(driver_info_2);
6293 return WERR_INSUFFICIENT_BUFFER;
6296 /* fill the buffer with the form structures */
6297 for (i=0; i<*returned; i++) {
6298 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6299 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6302 SAFE_FREE(driver_info_2);
6304 if (*needed > offered) {
6305 *returned=0;
6306 return WERR_INSUFFICIENT_BUFFER;
6309 return WERR_OK;
6312 /****************************************************************************
6313 Enumerates all printer drivers at level 3.
6314 ****************************************************************************/
6316 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6318 int i;
6319 int ndrivers;
6320 uint32 version;
6321 fstring *list = NULL;
6323 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6324 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6326 *returned=0;
6328 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6329 list=NULL;
6330 ndrivers=get_ntdrivers(&list, architecture, version);
6331 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6333 if(ndrivers == -1)
6334 return WERR_NOMEM;
6336 if(ndrivers != 0) {
6337 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6338 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6339 SAFE_FREE(driver_info_3);
6340 SAFE_FREE(list);
6341 return WERR_NOMEM;
6343 else driver_info_3 = tdi3;
6346 for (i=0; i<ndrivers; i++) {
6347 WERROR status;
6349 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6350 ZERO_STRUCT(driver);
6351 status = get_a_printer_driver(&driver, 3, list[i],
6352 architecture, version);
6353 if (!W_ERROR_IS_OK(status)) {
6354 SAFE_FREE(list);
6355 return status;
6357 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6358 free_a_printer_driver(driver, 3);
6361 *returned+=ndrivers;
6362 SAFE_FREE(list);
6365 /* check the required size. */
6366 for (i=0; i<*returned; i++) {
6367 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6368 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6371 if (!alloc_buffer_size(buffer, *needed)) {
6372 SAFE_FREE(driver_info_3);
6373 return WERR_INSUFFICIENT_BUFFER;
6376 /* fill the buffer with the driver structures */
6377 for (i=0; i<*returned; i++) {
6378 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6379 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6382 for (i=0; i<*returned; i++)
6383 SAFE_FREE(driver_info_3[i].dependentfiles);
6385 SAFE_FREE(driver_info_3);
6387 if (*needed > offered) {
6388 *returned=0;
6389 return WERR_INSUFFICIENT_BUFFER;
6392 return WERR_OK;
6395 /****************************************************************************
6396 Enumerates all printer drivers.
6397 ****************************************************************************/
6399 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6401 UNISTR2 *environment = &q_u->environment;
6402 uint32 level = q_u->level;
6403 NEW_BUFFER *buffer = NULL;
6404 uint32 offered = q_u->offered;
6405 uint32 *needed = &r_u->needed;
6406 uint32 *returned = &r_u->returned;
6408 fstring *list = NULL;
6409 fstring servername;
6410 fstring architecture;
6412 /* that's an [in out] buffer */
6413 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6414 buffer = r_u->buffer;
6416 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6417 fstrcpy(servername, get_called_name());
6418 *needed=0;
6419 *returned=0;
6421 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6423 switch (level) {
6424 case 1:
6425 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6426 case 2:
6427 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6428 case 3:
6429 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6430 default:
6431 *returned=0;
6432 SAFE_FREE(list);
6433 return WERR_UNKNOWN_LEVEL;
6437 /****************************************************************************
6438 ****************************************************************************/
6440 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6442 form->flag=list->flag;
6443 init_unistr(&form->name, list->name);
6444 form->width=list->width;
6445 form->length=list->length;
6446 form->left=list->left;
6447 form->top=list->top;
6448 form->right=list->right;
6449 form->bottom=list->bottom;
6452 /****************************************************************************
6453 ****************************************************************************/
6455 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6457 uint32 level = q_u->level;
6458 NEW_BUFFER *buffer = NULL;
6459 uint32 offered = q_u->offered;
6460 uint32 *needed = &r_u->needed;
6461 uint32 *numofforms = &r_u->numofforms;
6462 uint32 numbuiltinforms;
6464 nt_forms_struct *list=NULL;
6465 nt_forms_struct *builtinlist=NULL;
6466 FORM_1 *forms_1;
6467 int buffer_size=0;
6468 int i;
6470 /* that's an [in out] buffer */
6471 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6472 buffer = r_u->buffer;
6474 DEBUG(4,("_spoolss_enumforms\n"));
6475 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6476 DEBUGADD(5,("Info level [%d]\n", level));
6478 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6479 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6480 *numofforms = get_ntforms(&list);
6481 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6482 *numofforms += numbuiltinforms;
6484 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6486 switch (level) {
6487 case 1:
6488 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6489 *numofforms=0;
6490 return WERR_NOMEM;
6493 /* construct the list of form structures */
6494 for (i=0; i<numbuiltinforms; i++) {
6495 DEBUGADD(6,("Filling form number [%d]\n",i));
6496 fill_form_1(&forms_1[i], &builtinlist[i]);
6499 SAFE_FREE(builtinlist);
6501 for (; i<*numofforms; i++) {
6502 DEBUGADD(6,("Filling form number [%d]\n",i));
6503 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6506 SAFE_FREE(list);
6508 /* check the required size. */
6509 for (i=0; i<numbuiltinforms; i++) {
6510 DEBUGADD(6,("adding form [%d]'s size\n",i));
6511 buffer_size += spoolss_size_form_1(&forms_1[i]);
6513 for (; i<*numofforms; i++) {
6514 DEBUGADD(6,("adding form [%d]'s size\n",i));
6515 buffer_size += spoolss_size_form_1(&forms_1[i]);
6518 *needed=buffer_size;
6520 if (!alloc_buffer_size(buffer, buffer_size)){
6521 SAFE_FREE(forms_1);
6522 return WERR_INSUFFICIENT_BUFFER;
6525 /* fill the buffer with the form structures */
6526 for (i=0; i<numbuiltinforms; i++) {
6527 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6528 smb_io_form_1("", buffer, &forms_1[i], 0);
6530 for (; i<*numofforms; i++) {
6531 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6532 smb_io_form_1("", buffer, &forms_1[i], 0);
6535 SAFE_FREE(forms_1);
6537 if (*needed > offered) {
6538 *numofforms=0;
6539 return WERR_INSUFFICIENT_BUFFER;
6541 else
6542 return WERR_OK;
6544 default:
6545 SAFE_FREE(list);
6546 SAFE_FREE(builtinlist);
6547 return WERR_UNKNOWN_LEVEL;
6552 /****************************************************************************
6553 ****************************************************************************/
6555 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6557 uint32 level = q_u->level;
6558 UNISTR2 *uni_formname = &q_u->formname;
6559 NEW_BUFFER *buffer = NULL;
6560 uint32 offered = q_u->offered;
6561 uint32 *needed = &r_u->needed;
6563 nt_forms_struct *list=NULL;
6564 nt_forms_struct builtin_form;
6565 BOOL foundBuiltin;
6566 FORM_1 form_1;
6567 fstring form_name;
6568 int buffer_size=0;
6569 int numofforms=0, i=0;
6571 /* that's an [in out] buffer */
6572 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6573 buffer = r_u->buffer;
6575 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6577 DEBUG(4,("_spoolss_getform\n"));
6578 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6579 DEBUGADD(5,("Info level [%d]\n", level));
6581 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6582 if (!foundBuiltin) {
6583 numofforms = get_ntforms(&list);
6584 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6586 if (numofforms == 0)
6587 return WERR_BADFID;
6590 switch (level) {
6591 case 1:
6592 if (foundBuiltin) {
6593 fill_form_1(&form_1, &builtin_form);
6594 } else {
6596 /* Check if the requested name is in the list of form structures */
6597 for (i=0; i<numofforms; i++) {
6599 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6601 if (strequal(form_name, list[i].name)) {
6602 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6603 fill_form_1(&form_1, &list[i]);
6604 break;
6608 SAFE_FREE(list);
6609 if (i == numofforms) {
6610 return WERR_BADFID;
6613 /* check the required size. */
6615 *needed=spoolss_size_form_1(&form_1);
6617 if (!alloc_buffer_size(buffer, buffer_size)){
6618 return WERR_INSUFFICIENT_BUFFER;
6621 if (*needed > offered) {
6622 return WERR_INSUFFICIENT_BUFFER;
6625 /* fill the buffer with the form structures */
6626 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6627 smb_io_form_1("", buffer, &form_1, 0);
6629 return WERR_OK;
6631 default:
6632 SAFE_FREE(list);
6633 return WERR_UNKNOWN_LEVEL;
6637 /****************************************************************************
6638 ****************************************************************************/
6640 static void fill_port_1(PORT_INFO_1 *port, char *name)
6642 init_unistr(&port->port_name, name);
6645 /****************************************************************************
6646 ****************************************************************************/
6648 static void fill_port_2(PORT_INFO_2 *port, char *name)
6650 init_unistr(&port->port_name, name);
6651 init_unistr(&port->monitor_name, "Local Monitor");
6652 init_unistr(&port->description, "Local Port");
6653 #define PORT_TYPE_WRITE 1
6654 port->port_type=PORT_TYPE_WRITE;
6655 port->reserved=0x0;
6658 /****************************************************************************
6659 enumports level 1.
6660 ****************************************************************************/
6662 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6664 PORT_INFO_1 *ports=NULL;
6665 int i=0;
6667 if (*lp_enumports_cmd()) {
6668 char *cmd = lp_enumports_cmd();
6669 char **qlines;
6670 pstring command;
6671 int numlines;
6672 int ret;
6673 int fd;
6675 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6677 DEBUG(10,("Running [%s]\n", command));
6678 ret = smbrun(command, &fd);
6679 DEBUG(10,("Returned [%d]\n", ret));
6680 if (ret != 0) {
6681 if (fd != -1)
6682 close(fd);
6683 /* Is this the best error to return here? */
6684 return WERR_ACCESS_DENIED;
6687 numlines = 0;
6688 qlines = fd_lines_load(fd, &numlines);
6689 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6690 close(fd);
6692 if(numlines) {
6693 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6694 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6695 dos_errstr(WERR_NOMEM)));
6696 file_lines_free(qlines);
6697 return WERR_NOMEM;
6700 for (i=0; i<numlines; i++) {
6701 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6702 fill_port_1(&ports[i], qlines[i]);
6705 file_lines_free(qlines);
6708 *returned = numlines;
6710 } else {
6711 *returned = 1; /* Sole Samba port returned. */
6713 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6714 return WERR_NOMEM;
6716 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6718 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6721 /* check the required size. */
6722 for (i=0; i<*returned; i++) {
6723 DEBUGADD(6,("adding port [%d]'s size\n", i));
6724 *needed += spoolss_size_port_info_1(&ports[i]);
6727 if (!alloc_buffer_size(buffer, *needed)) {
6728 SAFE_FREE(ports);
6729 return WERR_INSUFFICIENT_BUFFER;
6732 /* fill the buffer with the ports structures */
6733 for (i=0; i<*returned; i++) {
6734 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6735 smb_io_port_1("", buffer, &ports[i], 0);
6738 SAFE_FREE(ports);
6740 if (*needed > offered) {
6741 *returned=0;
6742 return WERR_INSUFFICIENT_BUFFER;
6745 return WERR_OK;
6748 /****************************************************************************
6749 enumports level 2.
6750 ****************************************************************************/
6752 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6754 PORT_INFO_2 *ports=NULL;
6755 int i=0;
6757 if (*lp_enumports_cmd()) {
6758 char *cmd = lp_enumports_cmd();
6759 char *path;
6760 char **qlines;
6761 pstring tmp_file;
6762 pstring command;
6763 int numlines;
6764 int ret;
6765 int fd;
6767 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6768 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6769 else
6770 path = lp_lockdir();
6772 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6773 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6775 unlink(tmp_file);
6776 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6777 ret = smbrun(command, &fd);
6778 DEBUGADD(10,("returned [%d]\n", ret));
6779 if (ret != 0) {
6780 if (fd != -1)
6781 close(fd);
6782 /* Is this the best error to return here? */
6783 return WERR_ACCESS_DENIED;
6786 numlines = 0;
6787 qlines = fd_lines_load(fd, &numlines);
6788 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6789 close(fd);
6791 if(numlines) {
6792 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6793 file_lines_free(qlines);
6794 return WERR_NOMEM;
6797 for (i=0; i<numlines; i++) {
6798 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6799 fill_port_2(&(ports[i]), qlines[i]);
6802 file_lines_free(qlines);
6805 *returned = numlines;
6807 } else {
6809 *returned = 1;
6811 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6812 return WERR_NOMEM;
6814 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6816 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6819 /* check the required size. */
6820 for (i=0; i<*returned; i++) {
6821 DEBUGADD(6,("adding port [%d]'s size\n", i));
6822 *needed += spoolss_size_port_info_2(&ports[i]);
6825 if (!alloc_buffer_size(buffer, *needed)) {
6826 SAFE_FREE(ports);
6827 return WERR_INSUFFICIENT_BUFFER;
6830 /* fill the buffer with the ports structures */
6831 for (i=0; i<*returned; i++) {
6832 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6833 smb_io_port_2("", buffer, &ports[i], 0);
6836 SAFE_FREE(ports);
6838 if (*needed > offered) {
6839 *returned=0;
6840 return WERR_INSUFFICIENT_BUFFER;
6843 return WERR_OK;
6846 /****************************************************************************
6847 enumports.
6848 ****************************************************************************/
6850 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6852 uint32 level = q_u->level;
6853 NEW_BUFFER *buffer = NULL;
6854 uint32 offered = q_u->offered;
6855 uint32 *needed = &r_u->needed;
6856 uint32 *returned = &r_u->returned;
6858 /* that's an [in out] buffer */
6859 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6860 buffer = r_u->buffer;
6862 DEBUG(4,("_spoolss_enumports\n"));
6864 *returned=0;
6865 *needed=0;
6867 switch (level) {
6868 case 1:
6869 return enumports_level_1(buffer, offered, needed, returned);
6870 case 2:
6871 return enumports_level_2(buffer, offered, needed, returned);
6872 default:
6873 return WERR_UNKNOWN_LEVEL;
6877 /****************************************************************************
6878 ****************************************************************************/
6880 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6881 const SPOOL_PRINTER_INFO_LEVEL *info,
6882 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6883 uint32 user_switch, const SPOOL_USER_CTR *user,
6884 POLICY_HND *handle)
6886 NT_PRINTER_INFO_LEVEL *printer = NULL;
6887 fstring name;
6888 int snum;
6889 WERROR err = WERR_OK;
6891 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6892 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6893 return WERR_NOMEM;
6896 ZERO_STRUCTP(printer);
6898 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6899 if (!convert_printer_info(info, printer, 2)) {
6900 free_a_printer(&printer, 2);
6901 return WERR_NOMEM;
6904 /* check to see if the printer already exists */
6906 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6907 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6908 printer->info_2->sharename));
6909 free_a_printer(&printer, 2);
6910 return WERR_PRINTER_ALREADY_EXISTS;
6913 if (*lp_addprinter_cmd() )
6914 if ( !add_printer_hook(printer) ) {
6915 free_a_printer(&printer,2);
6916 return WERR_ACCESS_DENIED;
6919 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6920 printer->info_2->sharename);
6922 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6923 free_a_printer(&printer,2);
6924 return WERR_ACCESS_DENIED;
6927 /* you must be a printer admin to add a new printer */
6928 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6929 free_a_printer(&printer,2);
6930 return WERR_ACCESS_DENIED;
6934 * Do sanity check on the requested changes for Samba.
6937 if (!check_printer_ok(printer->info_2, snum)) {
6938 free_a_printer(&printer,2);
6939 return WERR_INVALID_PARAM;
6943 * When a printer is created, the drivername bound to the printer is used
6944 * to lookup previously saved driver initialization info, which is then
6945 * bound to the new printer, simulating what happens in the Windows arch.
6948 if (!devmode)
6950 set_driver_init(printer, 2);
6952 else
6954 /* A valid devmode was included, convert and link it
6956 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6958 if (!convert_devicemode(printer->info_2->printername, devmode,
6959 &printer->info_2->devmode))
6960 return WERR_NOMEM;
6963 /* write the ASCII on disk */
6964 err = mod_a_printer(*printer, 2);
6965 if (!W_ERROR_IS_OK(err)) {
6966 free_a_printer(&printer,2);
6967 return err;
6970 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6971 /* Handle open failed - remove addition. */
6972 del_a_printer(printer->info_2->sharename);
6973 free_a_printer(&printer,2);
6974 return WERR_ACCESS_DENIED;
6977 update_c_setprinter(False);
6978 free_a_printer(&printer,2);
6980 return WERR_OK;
6983 /****************************************************************************
6984 ****************************************************************************/
6986 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6988 UNISTR2 *uni_srv_name = &q_u->server_name;
6989 uint32 level = q_u->level;
6990 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6991 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6992 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6993 uint32 user_switch = q_u->user_switch;
6994 SPOOL_USER_CTR *user = &q_u->user_ctr;
6995 POLICY_HND *handle = &r_u->handle;
6997 switch (level) {
6998 case 1:
6999 /* we don't handle yet */
7000 /* but I know what to do ... */
7001 return WERR_UNKNOWN_LEVEL;
7002 case 2:
7003 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7004 devmode, sdb,
7005 user_switch, user, handle);
7006 default:
7007 return WERR_UNKNOWN_LEVEL;
7011 /****************************************************************************
7012 ****************************************************************************/
7014 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7016 uint32 level = q_u->level;
7017 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7018 WERROR err = WERR_OK;
7019 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7020 struct current_user user;
7021 fstring driver_name;
7022 uint32 version;
7024 ZERO_STRUCT(driver);
7026 get_current_user(&user, p);
7028 if (!convert_printer_driver_info(info, &driver, level)) {
7029 err = WERR_NOMEM;
7030 goto done;
7033 DEBUG(5,("Cleaning driver's information\n"));
7034 err = clean_up_driver_struct(driver, level, &user);
7035 if (!W_ERROR_IS_OK(err))
7036 goto done;
7038 DEBUG(5,("Moving driver to final destination\n"));
7039 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7040 if (W_ERROR_IS_OK(err))
7041 err = WERR_ACCESS_DENIED;
7042 goto done;
7045 if (add_a_printer_driver(driver, level)!=0) {
7046 err = WERR_ACCESS_DENIED;
7047 goto done;
7050 /* BEGIN_ADMIN_LOG */
7051 switch(level) {
7052 case 3:
7053 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7054 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7055 fstrcpy(driver_name, driver.info_3->name);
7056 break;
7057 case 6:
7058 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7059 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7060 fstrcpy(driver_name, driver.info_6->name);
7061 break;
7063 /* END_ADMIN_LOG */
7066 * I think this is where he DrvUpgradePrinter() hook would be
7067 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7068 * server. Right now, we just need to send ourselves a message
7069 * to update each printer bound to this driver. --jerry
7072 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7073 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7074 driver_name));
7078 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7079 * decide if the driver init data should be deleted. The rules are:
7080 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7081 * 2) delete init data only if there is no 2k/Xp driver
7082 * 3) always delete init data
7083 * The generalized rule is always use init data from the highest order driver.
7084 * It is necessary to follow the driver install by an initialization step to
7085 * finish off this process.
7087 if (level == 3)
7088 version = driver.info_3->cversion;
7089 else if (level == 6)
7090 version = driver.info_6->version;
7091 else
7092 version = -1;
7093 switch (version) {
7095 * 9x printer driver - never delete init data
7097 case 0:
7098 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7099 driver_name));
7100 break;
7103 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7104 * there is no 2k/Xp driver init data for this driver name.
7106 case 2:
7108 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7110 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7112 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7114 if (!del_driver_init(driver_name))
7115 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7116 } else {
7118 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7120 free_a_printer_driver(driver1,3);
7121 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7122 driver_name));
7125 break;
7128 * 2k or Xp printer driver - always delete init data
7130 case 3:
7131 if (!del_driver_init(driver_name))
7132 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7133 break;
7135 default:
7136 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7137 break;
7141 done:
7142 free_a_printer_driver(driver, level);
7143 return err;
7146 /********************************************************************
7147 * spoolss_addprinterdriverex
7148 ********************************************************************/
7150 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7152 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7153 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7156 * we only support the semantics of AddPrinterDriver()
7157 * i.e. only copy files that are newer than existing ones
7160 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7161 return WERR_ACCESS_DENIED;
7163 ZERO_STRUCT(q_u_local);
7164 ZERO_STRUCT(r_u_local);
7166 /* just pass the information off to _spoolss_addprinterdriver() */
7167 q_u_local.server_name_ptr = q_u->server_name_ptr;
7168 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7169 q_u_local.level = q_u->level;
7170 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7172 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7175 /****************************************************************************
7176 ****************************************************************************/
7178 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7180 init_unistr(&info->name, name);
7183 /****************************************************************************
7184 ****************************************************************************/
7186 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7188 pstring path;
7189 pstring long_archi;
7190 pstring short_archi;
7191 DRIVER_DIRECTORY_1 *info=NULL;
7193 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7195 if (get_short_archi(short_archi, long_archi)==False)
7196 return WERR_INVALID_ENVIRONMENT;
7198 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7199 return WERR_NOMEM;
7201 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7203 DEBUG(4,("printer driver directory: [%s]\n", path));
7205 fill_driverdir_1(info, path);
7207 *needed += spoolss_size_driverdir_info_1(info);
7209 if (!alloc_buffer_size(buffer, *needed)) {
7210 SAFE_FREE(info);
7211 return WERR_INSUFFICIENT_BUFFER;
7214 smb_io_driverdir_1("", buffer, info, 0);
7216 SAFE_FREE(info);
7218 if (*needed > offered)
7219 return WERR_INSUFFICIENT_BUFFER;
7221 return WERR_OK;
7224 /****************************************************************************
7225 ****************************************************************************/
7227 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7229 UNISTR2 *name = &q_u->name;
7230 UNISTR2 *uni_environment = &q_u->environment;
7231 uint32 level = q_u->level;
7232 NEW_BUFFER *buffer = NULL;
7233 uint32 offered = q_u->offered;
7234 uint32 *needed = &r_u->needed;
7236 /* that's an [in out] buffer */
7237 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7238 buffer = r_u->buffer;
7240 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7242 *needed=0;
7244 switch(level) {
7245 case 1:
7246 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7247 default:
7248 return WERR_UNKNOWN_LEVEL;
7252 /****************************************************************************
7253 ****************************************************************************/
7255 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7257 POLICY_HND *handle = &q_u->handle;
7258 uint32 idx = q_u->index;
7259 uint32 in_value_len = q_u->valuesize;
7260 uint32 in_data_len = q_u->datasize;
7261 uint32 *out_max_value_len = &r_u->valuesize;
7262 uint16 **out_value = &r_u->value;
7263 uint32 *out_value_len = &r_u->realvaluesize;
7264 uint32 *out_type = &r_u->type;
7265 uint32 *out_max_data_len = &r_u->datasize;
7266 uint8 **data_out = &r_u->data;
7267 uint32 *out_data_len = &r_u->realdatasize;
7269 NT_PRINTER_INFO_LEVEL *printer = NULL;
7271 uint32 param_index;
7272 uint32 biggest_valuesize;
7273 uint32 biggest_datasize;
7274 uint32 data_len;
7275 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7276 int snum;
7277 WERROR result;
7278 REGISTRY_VALUE *val;
7279 NT_PRINTER_DATA *p_data;
7280 int i, key_index, num_values;
7281 int name_length;
7283 ZERO_STRUCT( printer );
7285 *out_type = 0;
7287 *out_max_data_len = 0;
7288 *data_out = NULL;
7289 *out_data_len = 0;
7291 DEBUG(5,("spoolss_enumprinterdata\n"));
7293 if (!Printer) {
7294 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7295 return WERR_BADFID;
7298 if (!get_printer_snum(p,handle, &snum))
7299 return WERR_BADFID;
7301 result = get_a_printer(&printer, 2, lp_servicename(snum));
7302 if (!W_ERROR_IS_OK(result))
7303 return result;
7305 p_data = &printer->info_2->data;
7306 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7308 result = WERR_OK;
7311 * The NT machine wants to know the biggest size of value and data
7313 * cf: MSDN EnumPrinterData remark section
7316 if ( !in_value_len && !in_data_len )
7318 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7320 param_index = 0;
7321 biggest_valuesize = 0;
7322 biggest_datasize = 0;
7324 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7326 for ( i=0; i<num_values; i++ )
7328 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7330 name_length = strlen(val->valuename);
7331 if ( strlen(val->valuename) > biggest_valuesize )
7332 biggest_valuesize = name_length;
7334 if ( val->size > biggest_datasize )
7335 biggest_datasize = val->size;
7337 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7338 biggest_datasize));
7341 /* the value is an UNICODE string but real_value_size is the length
7342 in bytes including the trailing 0 */
7344 *out_value_len = 2 * (1+biggest_valuesize);
7345 *out_data_len = biggest_datasize;
7347 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7349 goto done;
7353 * the value len is wrong in NT sp3
7354 * that's the number of bytes not the number of unicode chars
7357 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7359 if ( !val )
7362 /* out_value should default to "" or else NT4 has
7363 problems unmarshalling the response */
7365 *out_max_value_len = (in_value_len/sizeof(uint16));
7367 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7369 result = WERR_NOMEM;
7370 goto done;
7373 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7375 /* the data is counted in bytes */
7377 *out_max_data_len = in_data_len;
7378 *out_data_len = in_data_len;
7380 /* only allocate when given a non-zero data_len */
7382 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7384 result = WERR_NOMEM;
7385 goto done;
7388 result = WERR_NO_MORE_ITEMS;
7390 else
7393 * the value is:
7394 * - counted in bytes in the request
7395 * - counted in UNICODE chars in the max reply
7396 * - counted in bytes in the real size
7398 * take a pause *before* coding not *during* coding
7401 /* name */
7402 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7403 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7405 result = WERR_NOMEM;
7406 goto done;
7409 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7411 /* type */
7413 *out_type = regval_type( val );
7415 /* data - counted in bytes */
7417 *out_max_data_len = in_data_len;
7418 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7420 result = WERR_NOMEM;
7421 goto done;
7423 data_len = (size_t)regval_size(val);
7424 memcpy( *data_out, regval_data_p(val), data_len );
7425 *out_data_len = data_len;
7428 done:
7429 free_a_printer(&printer, 2);
7430 return result;
7433 /****************************************************************************
7434 ****************************************************************************/
7436 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7438 POLICY_HND *handle = &q_u->handle;
7439 UNISTR2 *value = &q_u->value;
7440 uint32 type = q_u->type;
7441 uint8 *data = q_u->data;
7442 uint32 real_len = q_u->real_len;
7444 NT_PRINTER_INFO_LEVEL *printer = NULL;
7445 int snum=0;
7446 WERROR status = WERR_OK;
7447 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7448 fstring valuename;
7450 DEBUG(5,("spoolss_setprinterdata\n"));
7452 if (!Printer) {
7453 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7454 return WERR_BADFID;
7457 if (!get_printer_snum(p,handle, &snum))
7458 return WERR_BADFID;
7461 * Access check : NT returns "access denied" if you make a
7462 * SetPrinterData call without the necessary privildge.
7463 * we were originally returning OK if nothing changed
7464 * which made Win2k issue **a lot** of SetPrinterData
7465 * when connecting to a printer --jerry
7468 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7470 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7471 status = WERR_ACCESS_DENIED;
7472 goto done;
7475 status = get_a_printer(&printer, 2, lp_servicename(snum));
7476 if (!W_ERROR_IS_OK(status))
7477 return status;
7479 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7482 * When client side code sets a magic printer data key, detect it and save
7483 * the current printer data and the magic key's data (its the DEVMODE) for
7484 * future printer/driver initializations.
7486 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7488 /* Set devmode and printer initialization info */
7489 status = save_driver_init( printer, 2, data, real_len );
7491 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7493 else
7495 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7496 type, data, real_len );
7497 if ( W_ERROR_IS_OK(status) )
7498 status = mod_a_printer(*printer, 2);
7501 done:
7502 free_a_printer(&printer, 2);
7504 return status;
7507 /****************************************************************************
7508 ****************************************************************************/
7510 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7512 POLICY_HND *handle = &q_u->handle;
7513 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7514 int snum;
7516 DEBUG(5,("_spoolss_resetprinter\n"));
7519 * All we do is to check to see if the handle and queue is valid.
7520 * This call really doesn't mean anything to us because we only
7521 * support RAW printing. --jerry
7524 if (!Printer) {
7525 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7526 return WERR_BADFID;
7529 if (!get_printer_snum(p,handle, &snum))
7530 return WERR_BADFID;
7533 /* blindly return success */
7534 return WERR_OK;
7538 /****************************************************************************
7539 ****************************************************************************/
7541 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7543 POLICY_HND *handle = &q_u->handle;
7544 UNISTR2 *value = &q_u->valuename;
7546 NT_PRINTER_INFO_LEVEL *printer = NULL;
7547 int snum=0;
7548 WERROR status = WERR_OK;
7549 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7550 pstring valuename;
7552 DEBUG(5,("spoolss_deleteprinterdata\n"));
7554 if (!Printer) {
7555 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7556 return WERR_BADFID;
7559 if (!get_printer_snum(p, handle, &snum))
7560 return WERR_BADFID;
7562 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7563 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7564 return WERR_ACCESS_DENIED;
7567 status = get_a_printer(&printer, 2, lp_servicename(snum));
7568 if (!W_ERROR_IS_OK(status))
7569 return status;
7571 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7573 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7575 free_a_printer(&printer, 2);
7577 return status;
7580 /****************************************************************************
7581 ****************************************************************************/
7583 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7585 POLICY_HND *handle = &q_u->handle;
7586 FORM *form = &q_u->form;
7587 nt_forms_struct tmpForm;
7588 int snum;
7589 WERROR status = WERR_OK;
7590 NT_PRINTER_INFO_LEVEL *printer = NULL;
7592 int count=0;
7593 nt_forms_struct *list=NULL;
7594 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7596 DEBUG(5,("spoolss_addform\n"));
7598 if (!Printer) {
7599 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7600 return WERR_BADFID;
7604 /* forms can be added on printer of on the print server handle */
7606 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7608 if (!get_printer_snum(p,handle, &snum))
7609 return WERR_BADFID;
7611 status = get_a_printer(&printer, 2, lp_servicename(snum));
7612 if (!W_ERROR_IS_OK(status))
7613 goto done;
7616 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7617 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7618 status = WERR_ACCESS_DENIED;
7619 goto done;
7622 /* can't add if builtin */
7624 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7625 status = WERR_ALREADY_EXISTS;
7626 goto done;
7629 count = get_ntforms(&list);
7631 if(!add_a_form(&list, form, &count)) {
7632 status = WERR_NOMEM;
7633 goto done;
7636 write_ntforms(&list, count);
7639 * ChangeID must always be set if this is a printer
7642 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7643 status = mod_a_printer(*printer, 2);
7645 done:
7646 if ( printer )
7647 free_a_printer(&printer, 2);
7648 SAFE_FREE(list);
7650 return status;
7653 /****************************************************************************
7654 ****************************************************************************/
7656 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7658 POLICY_HND *handle = &q_u->handle;
7659 UNISTR2 *form_name = &q_u->name;
7660 nt_forms_struct tmpForm;
7661 int count=0;
7662 nt_forms_struct *list=NULL;
7663 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7664 int snum;
7665 WERROR status = WERR_OK;
7666 NT_PRINTER_INFO_LEVEL *printer = NULL;
7668 DEBUG(5,("spoolss_deleteform\n"));
7670 if (!Printer) {
7671 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7672 return WERR_BADFID;
7675 /* forms can be deleted on printer of on the print server handle */
7677 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7679 if (!get_printer_snum(p,handle, &snum))
7680 return WERR_BADFID;
7682 status = get_a_printer(&printer, 2, lp_servicename(snum));
7683 if (!W_ERROR_IS_OK(status))
7684 goto done;
7687 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7688 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7689 status = WERR_ACCESS_DENIED;
7690 goto done;
7693 /* can't delete if builtin */
7695 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7696 status = WERR_INVALID_PARAM;
7697 goto done;
7700 count = get_ntforms(&list);
7702 if ( !delete_a_form(&list, form_name, &count, &status ))
7703 goto done;
7706 * ChangeID must always be set if this is a printer
7709 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7710 status = mod_a_printer(*printer, 2);
7712 done:
7713 if ( printer )
7714 free_a_printer(&printer, 2);
7715 SAFE_FREE(list);
7717 return status;
7720 /****************************************************************************
7721 ****************************************************************************/
7723 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7725 POLICY_HND *handle = &q_u->handle;
7726 FORM *form = &q_u->form;
7727 nt_forms_struct tmpForm;
7728 int snum;
7729 WERROR status = WERR_OK;
7730 NT_PRINTER_INFO_LEVEL *printer = NULL;
7732 int count=0;
7733 nt_forms_struct *list=NULL;
7734 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7736 DEBUG(5,("spoolss_setform\n"));
7738 if (!Printer) {
7739 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7740 return WERR_BADFID;
7743 /* forms can be modified on printer of on the print server handle */
7745 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7747 if (!get_printer_snum(p,handle, &snum))
7748 return WERR_BADFID;
7750 status = get_a_printer(&printer, 2, lp_servicename(snum));
7751 if (!W_ERROR_IS_OK(status))
7752 goto done;
7755 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7756 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7757 status = WERR_ACCESS_DENIED;
7758 goto done;
7761 /* can't set if builtin */
7762 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7763 status = WERR_INVALID_PARAM;
7764 goto done;
7767 count = get_ntforms(&list);
7768 update_a_form(&list, form, count);
7769 write_ntforms(&list, count);
7772 * ChangeID must always be set if this is a printer
7775 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7776 status = mod_a_printer(*printer, 2);
7779 done:
7780 if ( printer )
7781 free_a_printer(&printer, 2);
7782 SAFE_FREE(list);
7784 return status;
7787 /****************************************************************************
7788 enumprintprocessors level 1.
7789 ****************************************************************************/
7791 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7793 PRINTPROCESSOR_1 *info_1=NULL;
7795 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7796 return WERR_NOMEM;
7798 (*returned) = 0x1;
7800 init_unistr(&info_1->name, "winprint");
7802 *needed += spoolss_size_printprocessor_info_1(info_1);
7804 if (!alloc_buffer_size(buffer, *needed))
7805 return WERR_INSUFFICIENT_BUFFER;
7807 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7809 SAFE_FREE(info_1);
7811 if (*needed > offered) {
7812 *returned=0;
7813 return WERR_INSUFFICIENT_BUFFER;
7816 return WERR_OK;
7819 /****************************************************************************
7820 ****************************************************************************/
7822 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7824 uint32 level = q_u->level;
7825 NEW_BUFFER *buffer = NULL;
7826 uint32 offered = q_u->offered;
7827 uint32 *needed = &r_u->needed;
7828 uint32 *returned = &r_u->returned;
7830 /* that's an [in out] buffer */
7831 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7832 buffer = r_u->buffer;
7834 DEBUG(5,("spoolss_enumprintprocessors\n"));
7837 * Enumerate the print processors ...
7839 * Just reply with "winprint", to keep NT happy
7840 * and I can use my nice printer checker.
7843 *returned=0;
7844 *needed=0;
7846 switch (level) {
7847 case 1:
7848 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7849 default:
7850 return WERR_UNKNOWN_LEVEL;
7854 /****************************************************************************
7855 enumprintprocdatatypes level 1.
7856 ****************************************************************************/
7858 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7860 PRINTPROCDATATYPE_1 *info_1=NULL;
7862 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7863 return WERR_NOMEM;
7865 (*returned) = 0x1;
7867 init_unistr(&info_1->name, "RAW");
7869 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7871 if (!alloc_buffer_size(buffer, *needed))
7872 return WERR_INSUFFICIENT_BUFFER;
7874 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7876 SAFE_FREE(info_1);
7878 if (*needed > offered) {
7879 *returned=0;
7880 return WERR_INSUFFICIENT_BUFFER;
7883 return WERR_OK;
7886 /****************************************************************************
7887 ****************************************************************************/
7889 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7891 uint32 level = q_u->level;
7892 NEW_BUFFER *buffer = NULL;
7893 uint32 offered = q_u->offered;
7894 uint32 *needed = &r_u->needed;
7895 uint32 *returned = &r_u->returned;
7897 /* that's an [in out] buffer */
7898 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7899 buffer = r_u->buffer;
7901 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7903 *returned=0;
7904 *needed=0;
7906 switch (level) {
7907 case 1:
7908 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7909 default:
7910 return WERR_UNKNOWN_LEVEL;
7914 /****************************************************************************
7915 enumprintmonitors level 1.
7916 ****************************************************************************/
7918 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7920 PRINTMONITOR_1 *info_1=NULL;
7922 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7923 return WERR_NOMEM;
7925 (*returned) = 0x1;
7927 init_unistr(&info_1->name, "Local Port");
7929 *needed += spoolss_size_printmonitor_info_1(info_1);
7931 if (!alloc_buffer_size(buffer, *needed))
7932 return WERR_INSUFFICIENT_BUFFER;
7934 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7936 SAFE_FREE(info_1);
7938 if (*needed > offered) {
7939 *returned=0;
7940 return WERR_INSUFFICIENT_BUFFER;
7943 return WERR_OK;
7946 /****************************************************************************
7947 enumprintmonitors level 2.
7948 ****************************************************************************/
7950 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7952 PRINTMONITOR_2 *info_2=NULL;
7954 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7955 return WERR_NOMEM;
7957 (*returned) = 0x1;
7959 init_unistr(&info_2->name, "Local Port");
7960 init_unistr(&info_2->environment, "Windows NT X86");
7961 init_unistr(&info_2->dll_name, "localmon.dll");
7963 *needed += spoolss_size_printmonitor_info_2(info_2);
7965 if (!alloc_buffer_size(buffer, *needed))
7966 return WERR_INSUFFICIENT_BUFFER;
7968 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7970 SAFE_FREE(info_2);
7972 if (*needed > offered) {
7973 *returned=0;
7974 return WERR_INSUFFICIENT_BUFFER;
7977 return WERR_OK;
7980 /****************************************************************************
7981 ****************************************************************************/
7983 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7985 uint32 level = q_u->level;
7986 NEW_BUFFER *buffer = NULL;
7987 uint32 offered = q_u->offered;
7988 uint32 *needed = &r_u->needed;
7989 uint32 *returned = &r_u->returned;
7991 /* that's an [in out] buffer */
7992 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7993 buffer = r_u->buffer;
7995 DEBUG(5,("spoolss_enumprintmonitors\n"));
7998 * Enumerate the print monitors ...
8000 * Just reply with "Local Port", to keep NT happy
8001 * and I can use my nice printer checker.
8004 *returned=0;
8005 *needed=0;
8007 switch (level) {
8008 case 1:
8009 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8010 case 2:
8011 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8012 default:
8013 return WERR_UNKNOWN_LEVEL;
8017 /****************************************************************************
8018 ****************************************************************************/
8020 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8022 int i=0;
8023 BOOL found=False;
8024 JOB_INFO_1 *info_1=NULL;
8026 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8028 if (info_1 == NULL) {
8029 SAFE_FREE(queue);
8030 return WERR_NOMEM;
8033 for (i=0; i<count && found==False; i++) {
8034 if (queue[i].job==(int)jobid)
8035 found=True;
8038 if (found==False) {
8039 SAFE_FREE(queue);
8040 SAFE_FREE(info_1);
8041 /* NT treats not found as bad param... yet another bad choice */
8042 return WERR_INVALID_PARAM;
8045 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8047 *needed += spoolss_size_job_info_1(info_1);
8049 if (!alloc_buffer_size(buffer, *needed)) {
8050 SAFE_FREE(info_1);
8051 return WERR_INSUFFICIENT_BUFFER;
8054 smb_io_job_info_1("", buffer, info_1, 0);
8056 SAFE_FREE(info_1);
8058 if (*needed > offered)
8059 return WERR_INSUFFICIENT_BUFFER;
8061 return WERR_OK;
8064 /****************************************************************************
8065 ****************************************************************************/
8067 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8069 int i = 0;
8070 BOOL found = False;
8071 JOB_INFO_2 *info_2;
8072 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8073 WERROR ret;
8074 DEVICEMODE *devmode = NULL;
8075 NT_DEVICEMODE *nt_devmode = NULL;
8077 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8079 ZERO_STRUCTP(info_2);
8081 if (info_2 == NULL) {
8082 ret = WERR_NOMEM;
8083 goto done;
8086 for ( i=0; i<count && found==False; i++ )
8088 if (queue[i].job == (int)jobid)
8089 found = True;
8092 if ( !found )
8094 /* NT treats not found as bad param... yet another bad
8095 choice */
8096 ret = WERR_INVALID_PARAM;
8097 goto done;
8100 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8101 if (!W_ERROR_IS_OK(ret))
8102 goto done;
8105 * if the print job does not have a DEVMODE associated with it,
8106 * just use the one for the printer
8109 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8110 devmode = construct_dev_mode(snum);
8111 else {
8112 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8113 ZERO_STRUCTP( devmode );
8114 convert_nt_devicemode( devmode, nt_devmode );
8118 if ( !devmode ) {
8119 ret = WERR_NOMEM;
8120 goto done;
8123 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8125 *needed += spoolss_size_job_info_2(info_2);
8127 if (!alloc_buffer_size(buffer, *needed)) {
8128 ret = WERR_INSUFFICIENT_BUFFER;
8129 goto done;
8132 smb_io_job_info_2("", buffer, info_2, 0);
8134 if (*needed > offered) {
8135 ret = WERR_INSUFFICIENT_BUFFER;
8136 goto done;
8139 ret = WERR_OK;
8141 done:
8142 /* Cleanup allocated memory */
8144 free_job_info_2(info_2); /* Also frees devmode */
8145 SAFE_FREE(info_2);
8146 free_a_printer(&ntprinter, 2);
8148 return ret;
8151 /****************************************************************************
8152 ****************************************************************************/
8154 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8156 POLICY_HND *handle = &q_u->handle;
8157 uint32 jobid = q_u->jobid;
8158 uint32 level = q_u->level;
8159 NEW_BUFFER *buffer = NULL;
8160 uint32 offered = q_u->offered;
8161 uint32 *needed = &r_u->needed;
8162 WERROR wstatus = WERR_OK;
8164 int snum;
8165 int count;
8166 print_queue_struct *queue = NULL;
8167 print_status_struct prt_status;
8169 /* that's an [in out] buffer */
8170 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8171 buffer = r_u->buffer;
8173 DEBUG(5,("spoolss_getjob\n"));
8175 *needed = 0;
8177 if (!get_printer_snum(p, handle, &snum))
8178 return WERR_BADFID;
8180 count = print_queue_status(snum, &queue, &prt_status);
8182 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8183 count, prt_status.status, prt_status.message));
8185 switch ( level ) {
8186 case 1:
8187 wstatus = getjob_level_1(queue, count, snum, jobid,
8188 buffer, offered, needed);
8189 break;
8190 case 2:
8191 wstatus = getjob_level_2(queue, count, snum, jobid,
8192 buffer, offered, needed);
8193 break;
8194 default:
8195 wstatus = WERR_UNKNOWN_LEVEL;
8196 break;
8199 SAFE_FREE(queue);
8200 return wstatus;
8203 /********************************************************************
8204 spoolss_getprinterdataex
8206 From MSDN documentation of GetPrinterDataEx: pass request
8207 to GetPrinterData if key is "PrinterDriverData".
8208 ********************************************************************/
8210 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8212 POLICY_HND *handle = &q_u->handle;
8213 uint32 in_size = q_u->size;
8214 uint32 *type = &r_u->type;
8215 uint32 *out_size = &r_u->size;
8216 uint8 **data = &r_u->data;
8217 uint32 *needed = &r_u->needed;
8218 fstring keyname, valuename;
8220 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8222 NT_PRINTER_INFO_LEVEL *printer = NULL;
8223 int snum = 0;
8224 WERROR status = WERR_OK;
8226 DEBUG(4,("_spoolss_getprinterdataex\n"));
8228 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8229 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8231 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8232 keyname, valuename));
8234 /* in case of problem, return some default values */
8236 *needed = 0;
8237 *type = 0;
8238 *out_size = in_size;
8240 if (!Printer) {
8241 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8242 status = WERR_BADFID;
8243 goto done;
8246 /* Is the handle to a printer or to the server? */
8248 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8249 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8250 status = WERR_INVALID_PARAM;
8251 goto done;
8254 if ( !get_printer_snum(p,handle, &snum) )
8255 return WERR_BADFID;
8257 status = get_a_printer(&printer, 2, lp_servicename(snum));
8258 if ( !W_ERROR_IS_OK(status) )
8259 goto done;
8261 /* check to see if the keyname is valid */
8262 if ( !strlen(keyname) ) {
8263 status = WERR_INVALID_PARAM;
8264 goto done;
8267 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8268 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8269 free_a_printer( &printer, 2 );
8270 status = WERR_BADFILE;
8271 goto done;
8274 /* When given a new keyname, we should just create it */
8276 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8278 if (*needed > *out_size)
8279 status = WERR_MORE_DATA;
8281 done:
8282 if ( !W_ERROR_IS_OK(status) )
8284 DEBUG(5, ("error: allocating %d\n", *out_size));
8286 /* reply this param doesn't exist */
8288 if ( *out_size )
8290 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8291 status = WERR_NOMEM;
8292 goto done;
8295 else {
8296 *data = NULL;
8300 if ( printer )
8301 free_a_printer( &printer, 2 );
8303 return status;
8306 /********************************************************************
8307 * spoolss_setprinterdataex
8308 ********************************************************************/
8310 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8312 POLICY_HND *handle = &q_u->handle;
8313 uint32 type = q_u->type;
8314 uint8 *data = q_u->data;
8315 uint32 real_len = q_u->real_len;
8317 NT_PRINTER_INFO_LEVEL *printer = NULL;
8318 int snum = 0;
8319 WERROR status = WERR_OK;
8320 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8321 fstring valuename;
8322 fstring keyname;
8323 char *oid_string;
8325 DEBUG(4,("_spoolss_setprinterdataex\n"));
8327 /* From MSDN documentation of SetPrinterDataEx: pass request to
8328 SetPrinterData if key is "PrinterDriverData" */
8330 if (!Printer) {
8331 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8332 return WERR_BADFID;
8335 if ( !get_printer_snum(p,handle, &snum) )
8336 return WERR_BADFID;
8339 * Access check : NT returns "access denied" if you make a
8340 * SetPrinterData call without the necessary privildge.
8341 * we were originally returning OK if nothing changed
8342 * which made Win2k issue **a lot** of SetPrinterData
8343 * when connecting to a printer --jerry
8346 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8348 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8349 return WERR_ACCESS_DENIED;
8352 status = get_a_printer(&printer, 2, lp_servicename(snum));
8353 if (!W_ERROR_IS_OK(status))
8354 return status;
8356 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8357 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8359 /* check for OID in valuename */
8361 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8363 *oid_string = '\0';
8364 oid_string++;
8367 /* save the registry data */
8369 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8371 /* save the OID if one was specified and the previous set call succeeded */
8373 if ( W_ERROR_IS_OK(status) && oid_string )
8376 fstrcat( keyname, "\\" );
8377 fstrcat( keyname, SPOOL_OID_KEY );
8380 * I'm not checking the status here on purpose. Don't know
8381 * if this is right, but I'm returning the status from the
8382 * previous set_printer_dataex() call. I have no idea if
8383 * this is right. --jerry
8386 set_printer_dataex( printer, keyname, valuename,
8387 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8390 free_a_printer(&printer, 2);
8392 return status;
8396 /********************************************************************
8397 * spoolss_deleteprinterdataex
8398 ********************************************************************/
8400 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8402 POLICY_HND *handle = &q_u->handle;
8403 UNISTR2 *value = &q_u->valuename;
8404 UNISTR2 *key = &q_u->keyname;
8406 NT_PRINTER_INFO_LEVEL *printer = NULL;
8407 int snum=0;
8408 WERROR status = WERR_OK;
8409 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8410 pstring valuename, keyname;
8412 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8414 if (!Printer) {
8415 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8416 return WERR_BADFID;
8419 if (!get_printer_snum(p, handle, &snum))
8420 return WERR_BADFID;
8422 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8423 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8424 return WERR_ACCESS_DENIED;
8427 status = get_a_printer(&printer, 2, lp_servicename(snum));
8428 if (!W_ERROR_IS_OK(status))
8429 return status;
8431 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8432 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8434 status = delete_printer_dataex( printer, keyname, valuename );
8436 free_a_printer(&printer, 2);
8438 return status;
8441 /********************************************************************
8442 * spoolss_enumprinterkey
8443 ********************************************************************/
8446 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8448 fstring key;
8449 fstring *keynames = NULL;
8450 uint16 *enumkeys = NULL;
8451 int num_keys;
8452 int printerkey_len;
8453 POLICY_HND *handle = &q_u->handle;
8454 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8455 NT_PRINTER_DATA *data;
8456 NT_PRINTER_INFO_LEVEL *printer = NULL;
8457 int snum = 0;
8458 WERROR status = WERR_BADFILE;
8461 DEBUG(4,("_spoolss_enumprinterkey\n"));
8463 if (!Printer) {
8464 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8465 return WERR_BADFID;
8468 if ( !get_printer_snum(p,handle, &snum) )
8469 return WERR_BADFID;
8471 status = get_a_printer(&printer, 2, lp_servicename(snum));
8472 if (!W_ERROR_IS_OK(status))
8473 return status;
8475 /* get the list of subkey names */
8477 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8478 data = &printer->info_2->data;
8480 num_keys = get_printer_subkeys( data, key, &keynames );
8482 if ( num_keys == -1 ) {
8483 status = WERR_BADFILE;
8484 goto done;
8487 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8489 r_u->needed = printerkey_len*2;
8491 if ( q_u->size < r_u->needed ) {
8492 status = WERR_MORE_DATA;
8493 goto done;
8496 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8497 status = WERR_NOMEM;
8498 goto done;
8501 status = WERR_OK;
8503 if ( q_u->size < r_u->needed )
8504 status = WERR_MORE_DATA;
8506 done:
8507 free_a_printer( &printer, 2 );
8508 SAFE_FREE( keynames );
8510 return status;
8513 /********************************************************************
8514 * spoolss_deleteprinterkey
8515 ********************************************************************/
8517 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8519 POLICY_HND *handle = &q_u->handle;
8520 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8521 fstring key;
8522 NT_PRINTER_INFO_LEVEL *printer = NULL;
8523 int snum=0;
8524 WERROR status;
8526 DEBUG(5,("spoolss_deleteprinterkey\n"));
8528 if (!Printer) {
8529 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8530 return WERR_BADFID;
8533 /* if keyname == NULL, return error */
8535 if ( !q_u->keyname.buffer )
8536 return WERR_INVALID_PARAM;
8538 if (!get_printer_snum(p, handle, &snum))
8539 return WERR_BADFID;
8541 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8542 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8543 return WERR_ACCESS_DENIED;
8546 status = get_a_printer(&printer, 2, lp_servicename(snum));
8547 if (!W_ERROR_IS_OK(status))
8548 return status;
8550 /* delete the key and all subneys */
8552 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8554 status = delete_all_printer_data( printer->info_2, key );
8556 if ( W_ERROR_IS_OK(status) )
8557 status = mod_a_printer(*printer, 2);
8559 free_a_printer( &printer, 2 );
8561 return status;
8565 /********************************************************************
8566 * spoolss_enumprinterdataex
8567 ********************************************************************/
8569 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8571 POLICY_HND *handle = &q_u->handle;
8572 uint32 in_size = q_u->size;
8573 uint32 num_entries,
8574 needed;
8575 NT_PRINTER_INFO_LEVEL *printer = NULL;
8576 PRINTER_ENUM_VALUES *enum_values = NULL;
8577 NT_PRINTER_DATA *p_data;
8578 fstring key;
8579 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8580 int snum;
8581 WERROR result;
8582 int key_index;
8583 int i;
8584 REGISTRY_VALUE *val;
8585 char *value_name;
8586 int data_len;
8589 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8591 if (!Printer) {
8592 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8593 return WERR_BADFID;
8596 /* first get the printer off of disk */
8598 if (!get_printer_snum(p,handle, &snum))
8599 return WERR_BADFID;
8601 ZERO_STRUCT(printer);
8602 result = get_a_printer(&printer, 2, lp_servicename(snum));
8603 if (!W_ERROR_IS_OK(result))
8604 return result;
8606 /* now look for a match on the key name */
8608 p_data = &printer->info_2->data;
8610 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8611 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8613 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8614 result = WERR_INVALID_PARAM;
8615 goto done;
8618 result = WERR_OK;
8619 needed = 0;
8621 /* allocate the memory for the array of pointers -- if necessary */
8623 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8624 if ( num_entries )
8626 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8628 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8629 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8630 result = WERR_NOMEM;
8631 goto done;
8634 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8638 * loop through all params and build the array to pass
8639 * back to the client
8642 for ( i=0; i<num_entries; i++ )
8644 /* lookup the registry value */
8646 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8647 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8649 /* copy the data */
8651 value_name = regval_name( val );
8652 init_unistr( &enum_values[i].valuename, value_name );
8653 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8654 enum_values[i].type = regval_type( val );
8656 data_len = regval_size( val );
8657 if ( data_len ) {
8658 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8660 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8661 data_len ));
8662 result = WERR_NOMEM;
8663 goto done;
8666 enum_values[i].data_len = data_len;
8668 /* keep track of the size of the array in bytes */
8670 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8673 /* housekeeping information in the reply */
8675 r_u->needed = needed;
8676 r_u->returned = num_entries;
8678 if (needed > in_size) {
8679 result = WERR_MORE_DATA;
8680 goto done;
8683 /* copy data into the reply */
8685 r_u->ctr.size = r_u->needed;
8686 r_u->ctr.size_of_array = r_u->returned;
8687 r_u->ctr.values = enum_values;
8691 done:
8692 free_a_printer(&printer, 2);
8694 return result;
8697 /****************************************************************************
8698 ****************************************************************************/
8700 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8702 init_unistr(&info->name, name);
8705 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8706 UNISTR2 *environment,
8707 NEW_BUFFER *buffer,
8708 uint32 offered,
8709 uint32 *needed)
8711 pstring path;
8712 pstring long_archi;
8713 pstring short_archi;
8714 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8716 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8718 if (get_short_archi(short_archi, long_archi)==False)
8719 return WERR_INVALID_ENVIRONMENT;
8721 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8722 return WERR_NOMEM;
8724 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8726 fill_printprocessordirectory_1(info, path);
8728 *needed += spoolss_size_printprocessordirectory_info_1(info);
8730 if (!alloc_buffer_size(buffer, *needed)) {
8731 safe_free(info);
8732 return WERR_INSUFFICIENT_BUFFER;
8735 smb_io_printprocessordirectory_1("", buffer, info, 0);
8737 safe_free(info);
8739 if (*needed > offered)
8740 return WERR_INSUFFICIENT_BUFFER;
8741 else
8742 return WERR_OK;
8745 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8747 uint32 level = q_u->level;
8748 NEW_BUFFER *buffer = NULL;
8749 uint32 offered = q_u->offered;
8750 uint32 *needed = &r_u->needed;
8751 WERROR result;
8753 /* that's an [in out] buffer */
8754 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8755 buffer = r_u->buffer;
8757 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8759 *needed=0;
8761 switch(level) {
8762 case 1:
8763 result = getprintprocessordirectory_level_1
8764 (&q_u->name, &q_u->environment, buffer, offered, needed);
8765 default:
8766 result = WERR_UNKNOWN_LEVEL;
8769 return result;
8772 #if 0
8774 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8775 SPOOL_R_REPLYOPENPRINTER *r_u)
8777 DEBUG(5,("_spoolss_replyopenprinter\n"));
8779 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8781 return WERR_OK;
8784 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8785 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8787 DEBUG(5,("_spoolss_replycloseprinter\n"));
8788 return WERR_OK;
8791 #endif