merge from APP_HEAD to use GMT in job submission notification
[Samba/gbeck.git] / source3 / rpc_server / srv_spoolss_nt.c
bloba4dcfdcec979c1bf9cfd835e68e8181cad3b9a0f
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;
317 * It turns out that Windows allows delete printer on a handle
318 * opened by an admin user, then used on a pipe handle created
319 * by an anonymous user..... but they're working on security.... riiight !
320 * JRA.
323 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
324 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
325 return WERR_ACCESS_DENIED;
328 #if 0
329 /* Check calling user has permission to delete printer. Note that
330 since we set the snum parameter to -1 only administrators can
331 delete the printer. This stops people with the Full Control
332 permission from deleting the printer. */
334 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
335 DEBUG(3, ("printer delete denied by security descriptor\n"));
336 return WERR_ACCESS_DENIED;
338 #endif
340 if (del_a_printer(Printer->dev.handlename) != 0) {
341 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
342 return WERR_BADFID;
345 if (*lp_deleteprinter_cmd()) {
347 char *cmd = lp_deleteprinter_cmd();
348 pstring command;
349 int ret;
350 int i;
352 /* Printer->dev.handlename equals portname equals sharename */
353 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
354 Printer->dev.handlename);
356 DEBUG(10,("Running [%s]\n", command));
357 ret = smbrun(command, NULL);
358 if (ret != 0) {
359 return WERR_BADFID; /* What to return here? */
361 DEBUGADD(10,("returned [%d]\n", ret));
363 /* Send SIGHUP to process group... is there a better way? */
364 kill(0, SIGHUP);
366 /* go ahead and re-read the services immediately */
367 reload_services( False );
369 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
370 return WERR_ACCESS_DENIED;
373 return WERR_OK;
376 /****************************************************************************
377 Return the snum of a printer corresponding to an handle.
378 ****************************************************************************/
380 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
382 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
384 if (!Printer) {
385 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
386 return False;
389 switch (Printer->printer_type) {
390 case PRINTER_HANDLE_IS_PRINTER:
391 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
392 *number = print_queue_snum(Printer->dev.handlename);
393 return (*number != -1);
394 case PRINTER_HANDLE_IS_PRINTSERVER:
395 return False;
396 default:
397 return False;
401 /****************************************************************************
402 Set printer handle type.
403 Check if it's \\server or \\server\printer
404 ****************************************************************************/
406 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
408 DEBUG(3,("Setting printer type=%s\n", handlename));
410 if ( strlen(handlename) < 3 ) {
411 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
412 return False;
415 /* it's a print server */
416 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
417 DEBUGADD(4,("Printer is a print server\n"));
418 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
420 /* it's a printer */
421 else {
422 DEBUGADD(4,("Printer is a printer\n"));
423 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
426 return True;
429 /****************************************************************************
430 Set printer handle name.
431 ****************************************************************************/
433 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
435 int snum;
436 int n_services=lp_numservices();
437 char *aprinter;
438 fstring sname;
439 BOOL found=False;
441 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
443 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
444 ZERO_STRUCT(Printer->dev.printerservername);
445 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
446 return True;
449 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
450 return False;
452 if (*handlename=='\\') {
453 aprinter=strchr_m(handlename+2, '\\');
454 aprinter++;
456 else {
457 aprinter=handlename;
460 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
463 * The original code allowed smbd to store a printer name that
464 * was different from the share name. This is not possible
465 * anymore, so I've simplified this loop greatly. Here
466 * we are just verifying that the printer name is a valid
467 * printer service defined in smb.conf
468 * --jerry [Fri Feb 15 11:17:46 CST 2002]
471 for (snum=0; snum<n_services; snum++) {
473 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
474 continue;
476 fstrcpy(sname, lp_servicename(snum));
478 DEBUGADD(5,("share:%s\n",sname));
480 if (! StrCaseCmp(sname, aprinter)) {
481 found = True;
482 break;
488 if (!found) {
489 DEBUGADD(4,("Printer not found\n"));
490 return False;
493 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
495 ZERO_STRUCT(Printer->dev.handlename);
496 fstrcpy(Printer->dev.handlename, sname);
498 return True;
501 /****************************************************************************
502 Find first available printer slot. creates a printer handle for you.
503 ****************************************************************************/
505 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
507 Printer_entry *new_printer;
509 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
511 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
512 return False;
514 ZERO_STRUCTP(new_printer);
516 new_printer->notify.option=NULL;
518 /* Add to the internal list. */
519 DLIST_ADD(printers_list, new_printer);
521 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
522 SAFE_FREE(new_printer);
523 return False;
526 if (!set_printer_hnd_printertype(new_printer, name)) {
527 close_printer_handle(p, hnd);
528 return False;
531 if (!set_printer_hnd_name(new_printer, name)) {
532 close_printer_handle(p, hnd);
533 return False;
536 new_printer->access_granted = access_granted;
538 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
540 return True;
543 /****************************************************************************
544 Allocate more memory for a BUFFER.
545 ****************************************************************************/
547 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
549 prs_struct *ps;
550 uint32 extra_space;
551 uint32 old_offset;
553 ps= &buffer->prs;
555 /* damn, I'm doing the reverse operation of prs_grow() :) */
556 if (buffer_size < prs_data_size(ps))
557 extra_space=0;
558 else
559 extra_space = buffer_size - prs_data_size(ps);
562 * save the offset and move to the end of the buffer
563 * prs_grow() checks the extra_space against the offset
565 old_offset=prs_offset(ps);
566 prs_set_offset(ps, prs_data_size(ps));
568 if (!prs_grow(ps, extra_space))
569 return False;
571 prs_set_offset(ps, old_offset);
573 buffer->string_at_end=prs_data_size(ps);
575 return True;
578 /***************************************************************************
579 check to see if the client motify handle is monitoring the notification
580 given by (notify_type, notify_field).
581 **************************************************************************/
583 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
584 uint16 notify_field)
586 return True;
589 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
590 uint16 notify_field)
592 SPOOL_NOTIFY_OPTION *option = p->notify.option;
593 uint32 i, j;
596 * Flags should always be zero when the change notify
597 * is registered by the cliebnt's spooler. A user Win32 app
598 * might use the flags though instead of the NOTIFY_OPTION_INFO
599 * --jerry
602 if (p->notify.flags)
603 return is_monitoring_event_flags(
604 p->notify.flags, notify_type, notify_field);
606 for (i = 0; i < option->count; i++) {
608 /* Check match for notify_type */
610 if (option->ctr.type[i].type != notify_type)
611 continue;
613 /* Check match for field */
615 for (j = 0; j < option->ctr.type[i].count; j++) {
616 if (option->ctr.type[i].fields[j] == notify_field) {
617 return True;
622 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
623 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
624 p->dev.handlename : p->dev.printerservername,
625 notify_type, notify_field));
627 return False;
630 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
632 static void notify_one_value(struct spoolss_notify_msg *msg,
633 SPOOL_NOTIFY_INFO_DATA *data,
634 TALLOC_CTX *mem_ctx)
636 data->notify_data.value[0] = msg->notify.value[0];
637 data->notify_data.value[1] = 0;
640 static void notify_string(struct spoolss_notify_msg *msg,
641 SPOOL_NOTIFY_INFO_DATA *data,
642 TALLOC_CTX *mem_ctx)
644 UNISTR2 unistr;
646 /* The length of the message includes the trailing \0 */
648 init_unistr2(&unistr, msg->notify.data, msg->len);
650 data->notify_data.data.length = msg->len * 2;
651 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
653 if (!data->notify_data.data.string) {
654 data->notify_data.data.length = 0;
655 return;
658 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
661 static void notify_system_time(struct spoolss_notify_msg *msg,
662 SPOOL_NOTIFY_INFO_DATA *data,
663 TALLOC_CTX *mem_ctx)
665 SYSTEMTIME systime;
666 prs_struct ps;
668 if (msg->len != sizeof(time_t)) {
669 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
670 msg->len));
671 return;
674 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
675 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
676 return;
679 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
680 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
681 return;
684 if (!spoolss_io_system_time("", &ps, 0, &systime))
685 return;
687 data->notify_data.data.length = prs_offset(&ps);
688 data->notify_data.data.string =
689 talloc(mem_ctx, prs_offset(&ps));
691 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
693 prs_mem_free(&ps);
696 struct notify2_message_table {
697 char *name;
698 void (*fn)(struct spoolss_notify_msg *msg,
699 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
702 static struct notify2_message_table printer_notify_table[] = {
703 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
704 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
705 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
706 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
707 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
708 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
709 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
710 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
711 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
712 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
713 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
714 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
715 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
716 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
717 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
718 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
719 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
720 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
721 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
724 static struct notify2_message_table job_notify_table[] = {
725 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
726 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
727 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
728 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
729 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
730 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
731 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
732 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
733 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
734 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
735 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
736 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
737 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
738 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
739 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
740 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
741 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
742 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
743 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
744 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
745 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
746 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
747 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
748 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
752 /***********************************************************************
753 Allocate talloc context for container object
754 **********************************************************************/
756 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
758 if ( !ctr )
759 return;
761 ctr->ctx = talloc_init();
763 return;
766 /***********************************************************************
767 release all allocated memory and zero out structure
768 **********************************************************************/
770 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
772 if ( !ctr )
773 return;
775 if ( ctr->ctx )
776 talloc_destroy(ctr->ctx);
778 ZERO_STRUCTP(ctr);
780 return;
783 /***********************************************************************
784 **********************************************************************/
786 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
788 if ( !ctr )
789 return NULL;
791 return ctr->ctx;
794 /***********************************************************************
795 **********************************************************************/
797 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
799 if ( !ctr || !ctr->msg_groups )
800 return NULL;
802 if ( idx >= ctr->num_groups )
803 return NULL;
805 return &ctr->msg_groups[idx];
809 /***********************************************************************
810 How many groups of change messages do we have ?
811 **********************************************************************/
813 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
815 if ( !ctr )
816 return 0;
818 return ctr->num_groups;
821 /***********************************************************************
822 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
823 **********************************************************************/
825 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
827 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
828 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
829 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
830 int i, new_slot;
832 if ( !ctr || !msg )
833 return 0;
835 /* loop over all groups looking for a matching printer name */
837 for ( i=0; i<ctr->num_groups; i++ ) {
838 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
839 break;
842 /* add a new group? */
844 if ( i == ctr->num_groups )
846 ctr->num_groups++;
848 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
849 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
850 return 0;
852 ctr->msg_groups = groups;
854 /* clear the new entry and set the printer name */
856 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
857 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
860 /* add the change messages; 'i' is the correct index now regardless */
862 msg_grp = &ctr->msg_groups[i];
864 msg_grp->num_msgs++;
866 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
867 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
868 return 0;
870 msg_grp->msgs = msg_list;
872 new_slot = msg_grp->num_msgs-1;
873 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
875 /* need to allocate own copy of data */
877 if ( msg->len != 0 )
878 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
880 return ctr->num_groups;
883 /***********************************************************************
884 Send a change notication message on all handles which have a call
885 back registered
886 **********************************************************************/
888 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
890 Printer_entry *p;
891 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
892 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
893 SPOOLSS_NOTIFY_MSG *messages;
896 if ( !msg_group ) {
897 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
898 return;
901 messages = msg_group->msgs;
903 if ( !messages ) {
904 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
905 return;
908 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
910 /* loop over all printers */
912 for (p = printers_list; p; p = p->next)
914 SPOOL_NOTIFY_INFO_DATA *data;
915 uint32 data_len = 0;
916 uint32 id;
917 int i;
919 /* Is there notification on this handle? */
921 if ( !p->notify.client_connected )
922 continue;
924 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
926 /* For this printer? Print servers always receive
927 notifications. */
929 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
930 ( !strequal(msg_group->printername, p->dev.handlename) ) )
931 continue;
933 DEBUG(10,("Our printer\n"));
935 /* allocate the max entries possible */
937 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
938 ZERO_STRUCTP(data);
940 /* build the array of change notifications */
942 for ( i=0; i<msg_group->num_msgs; i++ )
944 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
946 /* Are we monitoring this event? */
948 if (!is_monitoring_event(p, msg->type, msg->field))
949 continue;
952 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
953 msg->type, msg->field, p->dev.handlename));
956 * if the is a printer notification handle and not a job notification
957 * type, then set the id to 0. Other wise just use what was specified
958 * in the message.
960 * When registering change notification on a print server handle
961 * we always need to send back the id (snum) matching the printer
962 * for which the change took place. For change notify registered
963 * on a printer handle, this does not matter and the id should be 0.
965 * --jerry
968 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
969 id = 0;
970 else
971 id = msg->id;
974 /* Convert unix jobid to smb jobid */
976 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
978 id = sysjob_to_jobid(msg->id);
980 if (id == -1) {
981 DEBUG(3, ("no such unix jobid %d\n", msg->id));
982 goto done;
986 construct_info_data( &data[data_len], msg->type, msg->field, id );
988 switch(msg->type) {
989 case PRINTER_NOTIFY_TYPE:
990 if ( !printer_notify_table[msg->field].fn )
991 goto done;
992 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
994 break;
996 case JOB_NOTIFY_TYPE:
997 if ( !job_notify_table[msg->field].fn )
998 goto done;
999 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1001 break;
1003 default:
1004 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1005 goto done;
1008 data_len++;
1011 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1012 data_len, data, p->notify.change, 0 );
1015 done:
1016 DEBUG(8,("send_notify2_changes: Exit...\n"));
1017 return;
1020 /***********************************************************************
1021 **********************************************************************/
1023 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1026 int offset = 0;
1028 /* Unpack message */
1030 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1031 msg->printer);
1033 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1034 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1036 if (msg->len == 0)
1037 tdb_unpack((char *)buf + offset, len - offset, "dd",
1038 &msg->notify.value[0], &msg->notify.value[1]);
1039 else
1040 tdb_unpack((char *)buf + offset, len - offset, "B",
1041 &msg->len, &msg->notify.data);
1043 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1044 msg->type, msg->field, msg->flags));
1046 if (msg->len == 0)
1047 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1048 msg->notify.value[1]));
1049 else
1050 dump_data(3, msg->notify.data, msg->len);
1052 return True;
1055 /********************************************************************
1056 Receive a notify2 message list
1057 ********************************************************************/
1059 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1061 size_t msg_count, i;
1062 char *buf = (char *)msg;
1063 char *msg_ptr;
1064 size_t msg_len;
1065 SPOOLSS_NOTIFY_MSG notify;
1066 SPOOLSS_NOTIFY_MSG_CTR messages;
1067 int num_groups;
1069 if (len < 4) {
1070 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1071 return;
1074 msg_count = IVAL(buf, 0);
1075 msg_ptr = buf + 4;
1077 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1079 if (msg_count == 0) {
1080 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1081 return;
1084 /* initialize the container */
1086 ZERO_STRUCT( messages );
1087 notify_msg_ctr_init( &messages );
1090 * build message groups for each printer identified
1091 * in a change_notify msg. Remember that a PCN message
1092 * includes the handle returned for the srv_spoolss_replyopenprinter()
1093 * call. Therefore messages are grouped according to printer handle.
1096 for ( i=0; i<msg_count; i++ )
1098 if (msg_ptr + 4 - buf > len) {
1099 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1100 return;
1103 msg_len = IVAL(msg_ptr,0);
1104 msg_ptr += 4;
1106 if (msg_ptr + msg_len - buf > len) {
1107 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1108 return;
1111 /* unpack messages */
1113 ZERO_STRUCT( notify );
1114 notify2_unpack_msg( &notify, msg_ptr, msg_len );
1115 msg_ptr += msg_len;
1117 /* add to correct list in container */
1119 notify_msg_ctr_addmsg( &messages, &notify );
1121 /* free memory that might have been allocated by notify2_unpack_msg() */
1123 if ( notify.len != 0 )
1124 SAFE_FREE( notify.notify.data );
1127 /* process each group of messages */
1129 num_groups = notify_msg_ctr_numgroups( &messages );
1130 for ( i=0; i<num_groups; i++ )
1131 send_notify2_changes( &messages, i );
1134 /* cleanup */
1136 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1138 notify_msg_ctr_destroy( &messages );
1140 return;
1143 /********************************************************************
1144 Send a message to ourself about new driver being installed
1145 so we can upgrade the information for each printer bound to this
1146 driver
1147 ********************************************************************/
1149 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1151 int len = strlen(drivername);
1153 if (!len)
1154 return False;
1156 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1157 drivername));
1159 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1161 return True;
1164 /**********************************************************************
1165 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1166 over all printers, upgrading ones as neessary
1167 **********************************************************************/
1169 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1171 fstring drivername;
1172 int snum;
1173 int n_services = lp_numservices();
1175 len = MIN(len,sizeof(drivername)-1);
1176 strncpy(drivername, buf, len);
1178 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1180 /* Iterate the printer list */
1182 for (snum=0; snum<n_services; snum++)
1184 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1186 WERROR result;
1187 NT_PRINTER_INFO_LEVEL *printer = NULL;
1189 result = get_a_printer(&printer, 2, lp_servicename(snum));
1190 if (!W_ERROR_IS_OK(result))
1191 continue;
1193 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1195 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1197 /* all we care about currently is the change_id */
1199 result = mod_a_printer(*printer, 2);
1200 if (!W_ERROR_IS_OK(result)) {
1201 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1202 dos_errstr(result)));
1206 free_a_printer(&printer, 2);
1210 /* all done */
1213 /********************************************************************
1214 Send a message to ourself about new driver being installed
1215 so we can upgrade the information for each printer bound to this
1216 driver
1217 ********************************************************************/
1219 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1221 int len = strlen(drivername);
1223 if (!len)
1224 return False;
1226 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1227 drivername));
1229 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1231 return True;
1234 /**********************************************************************
1235 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1236 over all printers, resetting printer data as neessary
1237 **********************************************************************/
1239 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1241 fstring drivername;
1242 int snum;
1243 int n_services = lp_numservices();
1245 len = MIN( len, sizeof(drivername)-1 );
1246 strncpy( drivername, buf, len );
1248 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1250 /* Iterate the printer list */
1252 for ( snum=0; snum<n_services; snum++ )
1254 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1256 WERROR result;
1257 NT_PRINTER_INFO_LEVEL *printer = NULL;
1259 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1260 if ( !W_ERROR_IS_OK(result) )
1261 continue;
1264 * if the printer is bound to the driver,
1265 * then reset to the new driver initdata
1268 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1270 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1272 if ( !set_driver_init(printer, 2) ) {
1273 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1274 printer->info_2->printername, printer->info_2->drivername));
1278 free_a_printer( &printer, 2 );
1282 /* all done */
1284 return;
1287 /********************************************************************
1288 Copy routines used by convert_to_openprinterex()
1289 *******************************************************************/
1291 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1293 DEVICEMODE *d;
1294 int len;
1296 if (!devmode)
1297 return NULL;
1299 DEBUG (8,("dup_devmode\n"));
1301 /* bulk copy first */
1303 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1304 if (!d)
1305 return NULL;
1307 /* dup the pointer members separately */
1309 len = unistrlen(devmode->devicename.buffer);
1310 if (len != -1) {
1311 d->devicename.buffer = talloc(ctx, len*2);
1312 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1313 return NULL;
1317 len = unistrlen(devmode->formname.buffer);
1318 if (len != -1) {
1319 d->devicename.buffer = talloc(ctx, len*2);
1320 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1321 return NULL;
1324 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1326 return d;
1329 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1331 if (!new_ctr || !ctr)
1332 return;
1334 DEBUG(8,("copy_devmode_ctr\n"));
1336 new_ctr->size = ctr->size;
1337 new_ctr->devmode_ptr = ctr->devmode_ptr;
1339 if(ctr->devmode_ptr)
1340 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1343 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1345 if (!new_def || !def)
1346 return;
1348 DEBUG(8,("copy_printer_defaults\n"));
1350 new_def->datatype_ptr = def->datatype_ptr;
1352 if (def->datatype_ptr)
1353 copy_unistr2(&new_def->datatype, &def->datatype);
1355 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1357 new_def->access_required = def->access_required;
1360 /********************************************************************
1361 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1362 * SPOOL_Q_OPEN_PRINTER_EX structure
1363 ********************************************************************/
1365 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1367 if (!q_u_ex || !q_u)
1368 return;
1370 DEBUG(8,("convert_to_openprinterex\n"));
1372 q_u_ex->printername_ptr = q_u->printername_ptr;
1374 if (q_u->printername_ptr)
1375 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1377 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1380 /********************************************************************
1381 * spoolss_open_printer
1383 * called from the spoolss dispatcher
1384 ********************************************************************/
1386 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1388 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1389 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1391 if (!q_u || !r_u)
1392 return WERR_NOMEM;
1394 ZERO_STRUCT(q_u_ex);
1395 ZERO_STRUCT(r_u_ex);
1397 /* convert the OpenPrinter() call to OpenPrinterEx() */
1399 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1401 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1403 /* convert back to OpenPrinter() */
1405 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1407 return r_u->status;
1410 /********************************************************************
1411 * spoolss_open_printer
1413 * If the openprinterex rpc call contains a devmode,
1414 * it's a per-user one. This per-user devmode is derivated
1415 * from the global devmode. Openprinterex() contains a per-user
1416 * devmode for when you do EMF printing and spooling.
1417 * In the EMF case, the NT workstation is only doing half the job
1418 * of rendering the page. The other half is done by running the printer
1419 * driver on the server.
1420 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1421 * The EMF file only contains what is to be printed on the page.
1422 * So in order for the server to know how to print, the NT client sends
1423 * a devicemode attached to the openprinterex call.
1424 * But this devicemode is short lived, it's only valid for the current print job.
1426 * If Samba would have supported EMF spooling, this devicemode would
1427 * have been attached to the handle, to sent it to the driver to correctly
1428 * rasterize the EMF file.
1430 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1431 * we just act as a pass-thru between windows and the printer.
1433 * In order to know that Samba supports only RAW spooling, NT has to call
1434 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1435 * and until NT sends a RAW job, we refuse it.
1437 * But to call getprinter() or startdoc(), you first need a valid handle,
1438 * and to get an handle you have to call openprintex(). Hence why you have
1439 * a devicemode in the openprinterex() call.
1442 * Differences between NT4 and NT 2000.
1443 * NT4:
1444 * ---
1445 * On NT4, you only have a global devicemode. This global devicemode can be changed
1446 * by the administrator (or by a user with enough privs). Everytime a user
1447 * wants to print, the devicemode is resetted to the default. In Word, everytime
1448 * you print, the printer's characteristics are always reset to the global devicemode.
1450 * NT 2000:
1451 * -------
1452 * In W2K, there is the notion of per-user devicemode. The first time you use
1453 * a printer, a per-user devicemode is build from the global devicemode.
1454 * If you change your per-user devicemode, it is saved in the registry, under the
1455 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1456 * printer preferences available.
1458 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1459 * on the General Tab of the printer properties windows.
1461 * To change the global devicemode: it's the "Printing Defaults..." button
1462 * on the Advanced Tab of the printer properties window.
1464 * JFM.
1465 ********************************************************************/
1467 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1469 UNISTR2 *printername = NULL;
1470 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1471 POLICY_HND *handle = &r_u->handle;
1473 fstring name;
1474 int snum;
1475 struct current_user user;
1476 Printer_entry *Printer=NULL;
1478 if (q_u->printername_ptr != 0)
1479 printername = &q_u->printername;
1481 if (printername == NULL)
1482 return WERR_INVALID_PRINTER_NAME;
1484 /* some sanity check because you can open a printer or a print server */
1485 /* aka: \\server\printer or \\server */
1486 unistr2_to_ascii(name, printername, sizeof(name)-1);
1488 DEBUGADD(3,("checking name: %s\n",name));
1490 if (!open_printer_hnd(p, handle, name, 0))
1491 return WERR_INVALID_PRINTER_NAME;
1493 Printer=find_printer_index_by_hnd(p, handle);
1494 if (!Printer) {
1495 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1496 Can't find printer handle we created for printer %s\n", name ));
1497 close_printer_handle(p,handle);
1498 return WERR_INVALID_PRINTER_NAME;
1501 get_current_user(&user, p);
1504 * First case: the user is opening the print server:
1506 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1507 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1509 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1510 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1511 * or if the user is listed in the smb.conf printer admin parameter.
1513 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1514 * client view printer folder, but does not show the MSAPW.
1516 * Note: this test needs code to check access rights here too. Jeremy
1517 * could you look at this?
1519 * Second case: the user is opening a printer:
1520 * NT doesn't let us connect to a printer if the connecting user
1521 * doesn't have print permission.
1524 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1526 /* Printserver handles use global struct... */
1528 snum = -1;
1530 /* Map standard access rights to object specific access rights */
1532 se_map_standard(&printer_default->access_required,
1533 &printserver_std_mapping);
1535 /* Deny any object specific bits that don't apply to print
1536 servers (i.e printer and job specific bits) */
1538 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1540 if (printer_default->access_required &
1541 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1542 DEBUG(3, ("access DENIED for non-printserver bits"));
1543 close_printer_handle(p, handle);
1544 return WERR_ACCESS_DENIED;
1547 /* Allow admin access */
1549 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1551 if (!lp_ms_add_printer_wizard()) {
1552 close_printer_handle(p, handle);
1553 return WERR_ACCESS_DENIED;
1556 /* if the user is not root and not a printer admin, then fail */
1558 if ( user.uid != 0
1559 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1561 close_printer_handle(p, handle);
1562 return WERR_ACCESS_DENIED;
1565 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1567 else
1569 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1572 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1573 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1575 /* We fall through to return WERR_OK */
1578 else
1580 /* NT doesn't let us connect to a printer if the connecting user
1581 doesn't have print permission. */
1583 if (!get_printer_snum(p, handle, &snum))
1584 return WERR_BADFID;
1586 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1588 /* map an empty access mask to the minimum access mask */
1589 if (printer_default->access_required == 0x0)
1590 printer_default->access_required = PRINTER_ACCESS_USE;
1593 * If we are not serving the printer driver for this printer,
1594 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1595 * will keep NT clients happy --jerry
1598 if (lp_use_client_driver(snum)
1599 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1601 printer_default->access_required = PRINTER_ACCESS_USE;
1604 /* check smb.conf parameters and the the sec_desc */
1606 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1607 DEBUG(3, ("access DENIED for printer open\n"));
1608 close_printer_handle(p, handle);
1609 return WERR_ACCESS_DENIED;
1612 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1613 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1614 close_printer_handle(p, handle);
1615 return WERR_ACCESS_DENIED;
1618 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1619 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1620 else
1621 printer_default->access_required = PRINTER_ACCESS_USE;
1623 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1624 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1628 Printer->access_granted = printer_default->access_required;
1631 * If the client sent a devmode in the OpenPrinter() call, then
1632 * save it here in case we get a job submission on this handle
1635 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1636 && q_u->printer_default.devmode_cont.devmode_ptr )
1638 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1639 &Printer->nt_devmode );
1642 return WERR_OK;
1645 /****************************************************************************
1646 ****************************************************************************/
1648 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1649 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1651 BOOL ret = True;
1653 switch (level) {
1654 case 2:
1655 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1656 break;
1657 default:
1658 break;
1661 return ret;
1664 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1665 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1667 BOOL result = True;
1669 switch (level) {
1670 case 3:
1671 printer->info_3=NULL;
1672 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1673 result = False;
1674 break;
1675 case 6:
1676 printer->info_6=NULL;
1677 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1678 result = False;
1679 break;
1680 default:
1681 break;
1684 return result;
1687 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1688 NT_DEVICEMODE **pp_nt_devmode)
1690 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1693 * Ensure nt_devmode is a valid pointer
1694 * as we will be overwriting it.
1697 if (nt_devmode == NULL) {
1698 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1699 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1700 return False;
1703 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1704 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1706 nt_devmode->specversion=devmode->specversion;
1707 nt_devmode->driverversion=devmode->driverversion;
1708 nt_devmode->size=devmode->size;
1709 nt_devmode->fields=devmode->fields;
1710 nt_devmode->orientation=devmode->orientation;
1711 nt_devmode->papersize=devmode->papersize;
1712 nt_devmode->paperlength=devmode->paperlength;
1713 nt_devmode->paperwidth=devmode->paperwidth;
1714 nt_devmode->scale=devmode->scale;
1715 nt_devmode->copies=devmode->copies;
1716 nt_devmode->defaultsource=devmode->defaultsource;
1717 nt_devmode->printquality=devmode->printquality;
1718 nt_devmode->color=devmode->color;
1719 nt_devmode->duplex=devmode->duplex;
1720 nt_devmode->yresolution=devmode->yresolution;
1721 nt_devmode->ttoption=devmode->ttoption;
1722 nt_devmode->collate=devmode->collate;
1724 nt_devmode->logpixels=devmode->logpixels;
1725 nt_devmode->bitsperpel=devmode->bitsperpel;
1726 nt_devmode->pelswidth=devmode->pelswidth;
1727 nt_devmode->pelsheight=devmode->pelsheight;
1728 nt_devmode->displayflags=devmode->displayflags;
1729 nt_devmode->displayfrequency=devmode->displayfrequency;
1730 nt_devmode->icmmethod=devmode->icmmethod;
1731 nt_devmode->icmintent=devmode->icmintent;
1732 nt_devmode->mediatype=devmode->mediatype;
1733 nt_devmode->dithertype=devmode->dithertype;
1734 nt_devmode->reserved1=devmode->reserved1;
1735 nt_devmode->reserved2=devmode->reserved2;
1736 nt_devmode->panningwidth=devmode->panningwidth;
1737 nt_devmode->panningheight=devmode->panningheight;
1740 * Only change private and driverextra if the incoming devmode
1741 * has a new one. JRA.
1744 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1745 SAFE_FREE(nt_devmode->private);
1746 nt_devmode->driverextra=devmode->driverextra;
1747 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1748 return False;
1749 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1752 *pp_nt_devmode = nt_devmode;
1754 return True;
1757 /********************************************************************
1758 * _spoolss_enddocprinter_internal.
1759 ********************************************************************/
1761 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1763 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1764 int snum;
1766 if (!Printer) {
1767 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1768 return WERR_BADFID;
1771 if (!get_printer_snum(p, handle, &snum))
1772 return WERR_BADFID;
1774 Printer->document_started=False;
1775 print_job_end(snum, Printer->jobid,True);
1776 /* error codes unhandled so far ... */
1778 return WERR_OK;
1781 /********************************************************************
1782 * api_spoolss_closeprinter
1783 ********************************************************************/
1785 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1787 POLICY_HND *handle = &q_u->handle;
1789 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1791 if (Printer && Printer->document_started)
1792 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1794 if (!close_printer_handle(p, handle))
1795 return WERR_BADFID;
1797 /* clear the returned printer handle. Observed behavior
1798 from Win2k server. Don't think this really matters.
1799 Previous code just copied the value of the closed
1800 handle. --jerry */
1802 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1804 return WERR_OK;
1807 /********************************************************************
1808 * api_spoolss_deleteprinter
1810 ********************************************************************/
1812 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1814 POLICY_HND *handle = &q_u->handle;
1815 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1816 WERROR result;
1818 if (Printer && Printer->document_started)
1819 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1821 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1823 result = delete_printer_handle(p, handle);
1825 update_c_setprinter(False);
1827 return result;
1830 /*******************************************************************
1831 * static function to lookup the version id corresponding to an
1832 * long architecture string
1833 ******************************************************************/
1835 static int get_version_id (char * arch)
1837 int i;
1838 struct table_node archi_table[]= {
1840 {"Windows 4.0", "WIN40", 0 },
1841 {"Windows NT x86", "W32X86", 2 },
1842 {"Windows NT R4000", "W32MIPS", 2 },
1843 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1844 {"Windows NT PowerPC", "W32PPC", 2 },
1845 {NULL, "", -1 }
1848 for (i=0; archi_table[i].long_archi != NULL; i++)
1850 if (strcmp(arch, archi_table[i].long_archi) == 0)
1851 return (archi_table[i].version);
1854 return -1;
1857 /********************************************************************
1858 * _spoolss_deleteprinterdriver
1859 ********************************************************************/
1861 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1863 fstring driver;
1864 fstring arch;
1865 NT_PRINTER_DRIVER_INFO_LEVEL info;
1866 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1867 int version;
1868 struct current_user user;
1869 WERROR status;
1870 WERROR status_win2k = WERR_ACCESS_DENIED;
1872 get_current_user(&user, p);
1874 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1875 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1877 /* check that we have a valid driver name first */
1879 if ((version=get_version_id(arch)) == -1)
1880 return WERR_INVALID_ENVIRONMENT;
1882 ZERO_STRUCT(info);
1883 ZERO_STRUCT(info_win2k);
1885 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1887 /* try for Win2k driver if "Windows NT x86" */
1889 if ( version == 2 ) {
1890 version = 3;
1891 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1892 status = WERR_UNKNOWN_PRINTER_DRIVER;
1893 goto done;
1898 if (printer_driver_in_use(info.info_3)) {
1899 status = WERR_PRINTER_DRIVER_IN_USE;
1900 goto done;
1903 if ( version == 2 )
1905 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1907 /* if we get to here, we now have 2 driver info structures to remove */
1908 /* remove the Win2k driver first*/
1910 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1911 free_a_printer_driver( info_win2k, 3 );
1913 /* this should not have failed---if it did, report to client */
1914 if ( !W_ERROR_IS_OK(status_win2k) )
1915 goto done;
1919 status = delete_printer_driver(info.info_3, &user, version, False);
1921 /* if at least one of the deletes succeeded return OK */
1923 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1924 status = WERR_OK;
1926 done:
1927 free_a_printer_driver( info, 3 );
1929 return status;
1932 /********************************************************************
1933 * spoolss_deleteprinterdriverex
1934 ********************************************************************/
1936 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1938 fstring driver;
1939 fstring arch;
1940 NT_PRINTER_DRIVER_INFO_LEVEL info;
1941 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1942 int version;
1943 uint32 flags = q_u->delete_flags;
1944 BOOL delete_files;
1945 struct current_user user;
1946 WERROR status;
1947 WERROR status_win2k = WERR_ACCESS_DENIED;
1949 get_current_user(&user, p);
1951 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1952 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1954 /* check that we have a valid driver name first */
1955 if ((version=get_version_id(arch)) == -1) {
1956 /* this is what NT returns */
1957 return WERR_INVALID_ENVIRONMENT;
1960 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1961 version = q_u->version;
1963 ZERO_STRUCT(info);
1964 ZERO_STRUCT(info_win2k);
1966 status = get_a_printer_driver(&info, 3, driver, arch, version);
1968 if ( !W_ERROR_IS_OK(status) )
1971 * if the client asked for a specific version,
1972 * or this is something other than Windows NT x86,
1973 * then we've failed
1976 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1977 goto done;
1979 /* try for Win2k driver if "Windows NT x86" */
1981 version = 3;
1982 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1983 status = WERR_UNKNOWN_PRINTER_DRIVER;
1984 goto done;
1988 if ( printer_driver_in_use(info.info_3) ) {
1989 status = WERR_PRINTER_DRIVER_IN_USE;
1990 goto done;
1994 * we have a couple of cases to consider.
1995 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1996 * then the delete should fail if **any** files overlap with
1997 * other drivers
1998 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1999 * non-overlapping files
2000 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2001 * is set, the do not delete any files
2002 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2005 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2007 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2009 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2010 /* no idea of the correct error here */
2011 status = WERR_ACCESS_DENIED;
2012 goto done;
2016 /* also check for W32X86/3 if necessary; maybe we already have? */
2018 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2019 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2022 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2023 /* no idea of the correct error here */
2024 free_a_printer_driver( info_win2k, 3 );
2025 status = WERR_ACCESS_DENIED;
2026 goto done;
2029 /* if we get to here, we now have 2 driver info structures to remove */
2030 /* remove the Win2k driver first*/
2032 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2033 free_a_printer_driver( info_win2k, 3 );
2035 /* this should not have failed---if it did, report to client */
2037 if ( !W_ERROR_IS_OK(status_win2k) )
2038 goto done;
2042 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2044 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2045 status = WERR_OK;
2046 done:
2047 free_a_printer_driver( info, 3 );
2049 return status;
2053 /****************************************************************************
2054 Internal routine for retreiving printerdata
2055 ***************************************************************************/
2057 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2058 char *key, char *value, uint32 *type, uint8 **data,
2059 uint32 *needed, uint32 in_size )
2061 REGISTRY_VALUE *val;
2062 int size, data_len;
2064 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2065 return WERR_BADFILE;
2067 *type = regval_type( val );
2069 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2071 size = regval_size( val );
2073 /* copy the min(in_size, len) */
2075 if ( in_size ) {
2076 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2077 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2078 return WERR_NOMEM;
2080 else
2081 *data = NULL;
2083 *needed = size;
2085 DEBUG(5,("get_printer_dataex: copy done\n"));
2087 return WERR_OK;
2090 /****************************************************************************
2091 Internal routine for removing printerdata
2092 ***************************************************************************/
2094 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value )
2096 delete_printer_data( printer->info_2, key, value );
2098 return mod_a_printer(*printer, 2);
2101 /****************************************************************************
2102 Internal routine for storing printerdata
2103 ***************************************************************************/
2105 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value,
2106 uint32 type, uint8 *data, int real_len )
2108 delete_printer_data( printer->info_2, key, value );
2110 add_printer_data( printer->info_2, key, value, type, data, real_len );
2112 return mod_a_printer(*printer, 2);
2115 /********************************************************************
2116 GetPrinterData on a printer server Handle.
2117 ********************************************************************/
2119 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2121 int i;
2123 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2125 if (!strcmp(value, "W3SvcInstalled")) {
2126 *type = 0x4;
2127 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2128 return WERR_NOMEM;
2129 *needed = 0x4;
2130 return WERR_OK;
2133 if (!strcmp(value, "BeepEnabled")) {
2134 *type = 0x4;
2135 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2136 return WERR_NOMEM;
2137 SIVAL(*data, 0, 0x00);
2138 *needed = 0x4;
2139 return WERR_OK;
2142 if (!strcmp(value, "EventLog")) {
2143 *type = 0x4;
2144 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2145 return WERR_NOMEM;
2146 /* formally was 0x1b */
2147 SIVAL(*data, 0, 0x0);
2148 *needed = 0x4;
2149 return WERR_OK;
2152 if (!strcmp(value, "NetPopup")) {
2153 *type = 0x4;
2154 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2155 return WERR_NOMEM;
2156 SIVAL(*data, 0, 0x00);
2157 *needed = 0x4;
2158 return WERR_OK;
2161 if (!strcmp(value, "MajorVersion")) {
2162 *type = 0x4;
2163 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2164 return WERR_NOMEM;
2165 #ifndef EMULATE_WIN2K_HACK /* JERRY */
2166 SIVAL(*data, 0, 2);
2167 #else
2168 SIVAL(*data, 0, 3);
2169 #endif
2170 *needed = 0x4;
2171 return WERR_OK;
2174 if (!strcmp(value, "DefaultSpoolDirectory")) {
2175 fstring string;
2177 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2178 *type = 0x1;
2179 *needed = 2*(strlen(string)+1);
2180 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2181 return WERR_NOMEM;
2182 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2184 /* it's done by hand ready to go on the wire */
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 if (!strcmp(value, "Architecture")) {
2193 pstring string="Windows NT x86";
2194 *type = 0x1;
2195 *needed = 2*(strlen(string)+1);
2196 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2197 return WERR_NOMEM;
2198 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2199 for (i=0; i<strlen(string); i++) {
2200 (*data)[2*i]=string[i];
2201 (*data)[2*i+1]='\0';
2203 return WERR_OK;
2206 return WERR_INVALID_PARAM;
2209 /********************************************************************
2210 * spoolss_getprinterdata
2211 ********************************************************************/
2213 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2215 POLICY_HND *handle = &q_u->handle;
2216 UNISTR2 *valuename = &q_u->valuename;
2217 uint32 in_size = q_u->size;
2218 uint32 *type = &r_u->type;
2219 uint32 *out_size = &r_u->size;
2220 uint8 **data = &r_u->data;
2221 uint32 *needed = &r_u->needed;
2222 WERROR status;
2223 fstring value;
2224 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2225 NT_PRINTER_INFO_LEVEL *printer = NULL;
2226 int snum = 0;
2229 * Reminder: when it's a string, the length is in BYTES
2230 * even if UNICODE is negociated.
2232 * JFM, 4/19/1999
2235 *out_size = in_size;
2237 /* in case of problem, return some default values */
2239 *needed = 0;
2240 *type = 0;
2242 DEBUG(4,("_spoolss_getprinterdata\n"));
2244 if ( !Printer ) {
2245 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2246 status = WERR_BADFID;
2247 goto done;
2250 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2252 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2253 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2254 else
2256 if ( !get_printer_snum(p,handle, &snum) ) {
2257 status = WERR_BADFID;
2258 goto done;
2261 status = get_a_printer(&printer, 2, lp_servicename(snum));
2262 if ( !W_ERROR_IS_OK(status) )
2263 goto done;
2265 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2268 if (*needed > *out_size)
2269 status = WERR_MORE_DATA;
2271 done:
2272 if ( !W_ERROR_IS_OK(status) )
2274 DEBUG(5, ("error: allocating %d\n", *out_size));
2276 /* reply this param doesn't exist */
2278 if ( *out_size ) {
2279 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2280 if ( printer )
2281 free_a_printer( &printer, 2 );
2282 return WERR_NOMEM;
2285 else {
2286 *data = NULL;
2290 /* cleanup & exit */
2292 if ( printer )
2293 free_a_printer( &printer, 2 );
2295 return status;
2298 /*********************************************************
2299 Connect to the client machine.
2300 **********************************************************/
2302 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
2304 extern pstring global_myname;
2306 ZERO_STRUCTP(the_cli);
2307 if(cli_initialise(the_cli) == NULL) {
2308 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2309 return False;
2312 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2313 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2314 cli_shutdown(the_cli);
2315 return False;
2318 if (ismyip(the_cli->dest_ip)) {
2319 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2320 cli_shutdown(the_cli);
2321 return False;
2324 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2325 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2326 cli_shutdown(the_cli);
2327 return False;
2330 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
2331 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2332 remote_machine));
2333 cli_shutdown(the_cli);
2334 return False;
2337 the_cli->protocol = PROTOCOL_NT1;
2339 if (!cli_negprot(the_cli)) {
2340 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2341 cli_shutdown(the_cli);
2342 return False;
2345 if (the_cli->protocol != PROTOCOL_NT1) {
2346 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2347 cli_shutdown(the_cli);
2348 return False;
2352 * Do an anonymous session setup.
2355 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2356 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2357 cli_shutdown(the_cli);
2358 return False;
2361 if (!(the_cli->sec_mode & 1)) {
2362 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2363 cli_shutdown(the_cli);
2364 return False;
2367 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2368 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2369 cli_shutdown(the_cli);
2370 return False;
2374 * Ok - we have an anonymous connection to the IPC$ share.
2375 * Now start the NT Domain stuff :-).
2378 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2379 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)));
2380 cli_nt_session_close(the_cli);
2381 cli_ulogoff(the_cli);
2382 cli_shutdown(the_cli);
2383 return False;
2386 return True;
2389 /***************************************************************************
2390 Connect to the client.
2391 ****************************************************************************/
2393 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2395 WERROR result;
2398 * If it's the first connection, contact the client
2399 * and connect to the IPC$ share anonumously
2401 if (smb_connections==0) {
2402 fstring unix_printer;
2404 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2406 if(!spoolss_connect_to_client(&notify_cli, unix_printer))
2407 return False;
2409 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2410 /* Tell the connections db we're now interested in printer
2411 * notify messages. */
2412 register_message_flags( True, FLAG_MSG_PRINTING );
2415 smb_connections++;
2417 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2418 type, handle);
2420 if (!W_ERROR_IS_OK(result))
2421 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2422 dos_errstr(result)));
2424 return (W_ERROR_IS_OK(result));
2427 /********************************************************************
2428 * _spoolss_rffpcnex
2429 * ReplyFindFirstPrinterChangeNotifyEx
2431 * before replying OK: status=0 a rpc call is made to the workstation
2432 * asking ReplyOpenPrinter
2434 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2435 * called from api_spoolss_rffpcnex
2436 ********************************************************************/
2438 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2440 POLICY_HND *handle = &q_u->handle;
2441 uint32 flags = q_u->flags;
2442 uint32 options = q_u->options;
2443 UNISTR2 *localmachine = &q_u->localmachine;
2444 uint32 printerlocal = q_u->printerlocal;
2445 SPOOL_NOTIFY_OPTION *option = q_u->option;
2447 /* store the notify value in the printer struct */
2449 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2451 if (!Printer) {
2452 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2453 return WERR_BADFID;
2456 Printer->notify.flags=flags;
2457 Printer->notify.options=options;
2458 Printer->notify.printerlocal=printerlocal;
2460 if (Printer->notify.option)
2461 free_spool_notify_option(&Printer->notify.option);
2463 Printer->notify.option=dup_spool_notify_option(option);
2465 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2466 sizeof(Printer->notify.localmachine)-1);
2468 /* Connect to the client machine and send a ReplyOpenPrinter */
2470 if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
2471 Printer->notify.printerlocal, 1,
2472 &Printer->notify.client_hnd))
2473 return WERR_SERVER_UNAVAILABLE;
2475 Printer->notify.client_connected=True;
2477 return WERR_OK;
2480 /*******************************************************************
2481 * fill a notify_info_data with the servername
2482 ********************************************************************/
2484 void spoolss_notify_server_name(int snum,
2485 SPOOL_NOTIFY_INFO_DATA *data,
2486 print_queue_struct *queue,
2487 NT_PRINTER_INFO_LEVEL *printer,
2488 TALLOC_CTX *mem_ctx)
2490 pstring temp_name, temp;
2491 uint32 len;
2493 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2495 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2497 data->notify_data.data.length = len;
2498 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2500 if (!data->notify_data.data.string) {
2501 data->notify_data.data.length = 0;
2502 return;
2505 memcpy(data->notify_data.data.string, temp, len);
2508 /*******************************************************************
2509 * fill a notify_info_data with the printername (not including the servername).
2510 ********************************************************************/
2512 void spoolss_notify_printer_name(int snum,
2513 SPOOL_NOTIFY_INFO_DATA *data,
2514 print_queue_struct *queue,
2515 NT_PRINTER_INFO_LEVEL *printer,
2516 TALLOC_CTX *mem_ctx)
2518 pstring temp;
2519 uint32 len;
2521 /* the notify name should not contain the \\server\ part */
2522 char *p = strrchr(printer->info_2->printername, '\\');
2524 if (!p) {
2525 p = printer->info_2->printername;
2526 } else {
2527 p++;
2530 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2532 data->notify_data.data.length = len;
2533 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2535 if (!data->notify_data.data.string) {
2536 data->notify_data.data.length = 0;
2537 return;
2540 memcpy(data->notify_data.data.string, temp, len);
2543 /*******************************************************************
2544 * fill a notify_info_data with the servicename
2545 ********************************************************************/
2547 void spoolss_notify_share_name(int snum,
2548 SPOOL_NOTIFY_INFO_DATA *data,
2549 print_queue_struct *queue,
2550 NT_PRINTER_INFO_LEVEL *printer,
2551 TALLOC_CTX *mem_ctx)
2553 pstring temp;
2554 uint32 len;
2556 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2558 data->notify_data.data.length = len;
2559 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2561 if (!data->notify_data.data.string) {
2562 data->notify_data.data.length = 0;
2563 return;
2566 memcpy(data->notify_data.data.string, temp, len);
2569 /*******************************************************************
2570 * fill a notify_info_data with the port name
2571 ********************************************************************/
2573 void spoolss_notify_port_name(int snum,
2574 SPOOL_NOTIFY_INFO_DATA *data,
2575 print_queue_struct *queue,
2576 NT_PRINTER_INFO_LEVEL *printer,
2577 TALLOC_CTX *mem_ctx)
2579 pstring temp;
2580 uint32 len;
2582 /* even if it's strange, that's consistant in all the code */
2584 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2586 data->notify_data.data.length = len;
2587 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2589 if (!data->notify_data.data.string) {
2590 data->notify_data.data.length = 0;
2591 return;
2594 memcpy(data->notify_data.data.string, temp, len);
2597 /*******************************************************************
2598 * fill a notify_info_data with the printername
2599 * but it doesn't exist, have to see what to do
2600 ********************************************************************/
2602 void spoolss_notify_driver_name(int snum,
2603 SPOOL_NOTIFY_INFO_DATA *data,
2604 print_queue_struct *queue,
2605 NT_PRINTER_INFO_LEVEL *printer,
2606 TALLOC_CTX *mem_ctx)
2608 pstring temp;
2609 uint32 len;
2611 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2613 data->notify_data.data.length = len;
2614 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2616 if (!data->notify_data.data.string) {
2617 data->notify_data.data.length = 0;
2618 return;
2621 memcpy(data->notify_data.data.string, temp, len);
2624 /*******************************************************************
2625 * fill a notify_info_data with the comment
2626 ********************************************************************/
2628 void spoolss_notify_comment(int snum,
2629 SPOOL_NOTIFY_INFO_DATA *data,
2630 print_queue_struct *queue,
2631 NT_PRINTER_INFO_LEVEL *printer,
2632 TALLOC_CTX *mem_ctx)
2634 pstring temp;
2635 uint32 len;
2637 if (*printer->info_2->comment == '\0')
2638 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2639 else
2640 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2642 data->notify_data.data.length = len;
2643 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2645 if (!data->notify_data.data.string) {
2646 data->notify_data.data.length = 0;
2647 return;
2650 memcpy(data->notify_data.data.string, temp, len);
2653 /*******************************************************************
2654 * fill a notify_info_data with the comment
2655 * location = "Room 1, floor 2, building 3"
2656 ********************************************************************/
2658 void spoolss_notify_location(int snum,
2659 SPOOL_NOTIFY_INFO_DATA *data,
2660 print_queue_struct *queue,
2661 NT_PRINTER_INFO_LEVEL *printer,
2662 TALLOC_CTX *mem_ctx)
2664 pstring temp;
2665 uint32 len;
2667 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2669 data->notify_data.data.length = len;
2670 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2672 if (!data->notify_data.data.string) {
2673 data->notify_data.data.length = 0;
2674 return;
2677 memcpy(data->notify_data.data.string, temp, len);
2680 /*******************************************************************
2681 * fill a notify_info_data with the device mode
2682 * jfm:xxxx don't to it for know but that's a real problem !!!
2683 ********************************************************************/
2685 static void spoolss_notify_devmode(int snum,
2686 SPOOL_NOTIFY_INFO_DATA *data,
2687 print_queue_struct *queue,
2688 NT_PRINTER_INFO_LEVEL *printer,
2689 TALLOC_CTX *mem_ctx)
2693 /*******************************************************************
2694 * fill a notify_info_data with the separator file name
2695 ********************************************************************/
2697 void spoolss_notify_sepfile(int snum,
2698 SPOOL_NOTIFY_INFO_DATA *data,
2699 print_queue_struct *queue,
2700 NT_PRINTER_INFO_LEVEL *printer,
2701 TALLOC_CTX *mem_ctx)
2703 pstring temp;
2704 uint32 len;
2706 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2708 data->notify_data.data.length = len;
2709 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2711 if (!data->notify_data.data.string) {
2712 data->notify_data.data.length = 0;
2713 return;
2716 memcpy(data->notify_data.data.string, temp, len);
2719 /*******************************************************************
2720 * fill a notify_info_data with the print processor
2721 * jfm:xxxx return always winprint to indicate we don't do anything to it
2722 ********************************************************************/
2724 void spoolss_notify_print_processor(int snum,
2725 SPOOL_NOTIFY_INFO_DATA *data,
2726 print_queue_struct *queue,
2727 NT_PRINTER_INFO_LEVEL *printer,
2728 TALLOC_CTX *mem_ctx)
2730 pstring temp;
2731 uint32 len;
2733 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2735 data->notify_data.data.length = len;
2736 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2738 if (!data->notify_data.data.string) {
2739 data->notify_data.data.length = 0;
2740 return;
2743 memcpy(data->notify_data.data.string, temp, len);
2746 /*******************************************************************
2747 * fill a notify_info_data with the print processor options
2748 * jfm:xxxx send an empty string
2749 ********************************************************************/
2751 void spoolss_notify_parameters(int snum,
2752 SPOOL_NOTIFY_INFO_DATA *data,
2753 print_queue_struct *queue,
2754 NT_PRINTER_INFO_LEVEL *printer,
2755 TALLOC_CTX *mem_ctx)
2757 pstring temp;
2758 uint32 len;
2760 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2762 data->notify_data.data.length = len;
2763 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2765 if (!data->notify_data.data.string) {
2766 data->notify_data.data.length = 0;
2767 return;
2770 memcpy(data->notify_data.data.string, temp, len);
2773 /*******************************************************************
2774 * fill a notify_info_data with the data type
2775 * jfm:xxxx always send RAW as data type
2776 ********************************************************************/
2778 void spoolss_notify_datatype(int snum,
2779 SPOOL_NOTIFY_INFO_DATA *data,
2780 print_queue_struct *queue,
2781 NT_PRINTER_INFO_LEVEL *printer,
2782 TALLOC_CTX *mem_ctx)
2784 pstring temp;
2785 uint32 len;
2787 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2789 data->notify_data.data.length = len;
2790 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2792 if (!data->notify_data.data.string) {
2793 data->notify_data.data.length = 0;
2794 return;
2797 memcpy(data->notify_data.data.string, temp, len);
2800 /*******************************************************************
2801 * fill a notify_info_data with the security descriptor
2802 * jfm:xxxx send an null pointer to say no security desc
2803 * have to implement security before !
2804 ********************************************************************/
2806 static void spoolss_notify_security_desc(int snum,
2807 SPOOL_NOTIFY_INFO_DATA *data,
2808 print_queue_struct *queue,
2809 NT_PRINTER_INFO_LEVEL *printer,
2810 TALLOC_CTX *mem_ctx)
2812 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2813 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2816 /*******************************************************************
2817 * fill a notify_info_data with the attributes
2818 * jfm:xxxx a samba printer is always shared
2819 ********************************************************************/
2821 void spoolss_notify_attributes(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->attributes;
2828 data->notify_data.value[1] = 0;
2831 /*******************************************************************
2832 * fill a notify_info_data with the priority
2833 ********************************************************************/
2835 static void spoolss_notify_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->priority;
2842 data->notify_data.value[1] = 0;
2845 /*******************************************************************
2846 * fill a notify_info_data with the default priority
2847 ********************************************************************/
2849 static void spoolss_notify_default_priority(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->default_priority;
2856 data->notify_data.value[1] = 0;
2859 /*******************************************************************
2860 * fill a notify_info_data with the start time
2861 ********************************************************************/
2863 static void spoolss_notify_start_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->starttime;
2870 data->notify_data.value[1] = 0;
2873 /*******************************************************************
2874 * fill a notify_info_data with the until time
2875 ********************************************************************/
2877 static void spoolss_notify_until_time(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 data->notify_data.value[0] = printer->info_2->untiltime;
2884 data->notify_data.value[1] = 0;
2887 /*******************************************************************
2888 * fill a notify_info_data with the status
2889 ********************************************************************/
2891 static void spoolss_notify_status(int snum,
2892 SPOOL_NOTIFY_INFO_DATA *data,
2893 print_queue_struct *queue,
2894 NT_PRINTER_INFO_LEVEL *printer,
2895 TALLOC_CTX *mem_ctx)
2897 print_status_struct status;
2899 print_queue_length(snum, &status);
2900 data->notify_data.value[0]=(uint32) status.status;
2901 data->notify_data.value[1] = 0;
2904 /*******************************************************************
2905 * fill a notify_info_data with the number of jobs queued
2906 ********************************************************************/
2908 void spoolss_notify_cjobs(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 data->notify_data.value[0] = print_queue_length(snum, NULL);
2915 data->notify_data.value[1] = 0;
2918 /*******************************************************************
2919 * fill a notify_info_data with the average ppm
2920 ********************************************************************/
2922 static void spoolss_notify_average_ppm(int snum,
2923 SPOOL_NOTIFY_INFO_DATA *data,
2924 print_queue_struct *queue,
2925 NT_PRINTER_INFO_LEVEL *printer,
2926 TALLOC_CTX *mem_ctx)
2928 /* always respond 8 pages per minutes */
2929 /* a little hard ! */
2930 data->notify_data.value[0] = printer->info_2->averageppm;
2931 data->notify_data.value[1] = 0;
2934 /*******************************************************************
2935 * fill a notify_info_data with username
2936 ********************************************************************/
2938 static void spoolss_notify_username(int snum,
2939 SPOOL_NOTIFY_INFO_DATA *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2944 pstring temp;
2945 uint32 len;
2947 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2949 data->notify_data.data.length = len;
2950 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2952 if (!data->notify_data.data.string) {
2953 data->notify_data.data.length = 0;
2954 return;
2957 memcpy(data->notify_data.data.string, temp, len);
2960 /*******************************************************************
2961 * fill a notify_info_data with job status
2962 ********************************************************************/
2964 static void spoolss_notify_job_status(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 data->notify_data.value[0]=nt_printj_status(queue->status);
2971 data->notify_data.value[1] = 0;
2974 /*******************************************************************
2975 * fill a notify_info_data with job name
2976 ********************************************************************/
2978 static void spoolss_notify_job_name(int snum,
2979 SPOOL_NOTIFY_INFO_DATA *data,
2980 print_queue_struct *queue,
2981 NT_PRINTER_INFO_LEVEL *printer,
2982 TALLOC_CTX *mem_ctx)
2984 pstring temp;
2985 uint32 len;
2987 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2989 data->notify_data.data.length = len;
2990 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2992 if (!data->notify_data.data.string) {
2993 data->notify_data.data.length = 0;
2994 return;
2997 memcpy(data->notify_data.data.string, temp, len);
3000 /*******************************************************************
3001 * fill a notify_info_data with job status
3002 ********************************************************************/
3004 static void spoolss_notify_job_status_string(int snum,
3005 SPOOL_NOTIFY_INFO_DATA *data,
3006 print_queue_struct *queue,
3007 NT_PRINTER_INFO_LEVEL *printer,
3008 TALLOC_CTX *mem_ctx)
3011 * Now we're returning job status codes we just return a "" here. JRA.
3014 char *p = "";
3015 pstring temp;
3016 uint32 len;
3018 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3019 p = "unknown";
3021 switch (queue->status) {
3022 case LPQ_QUEUED:
3023 p = "Queued";
3024 break;
3025 case LPQ_PAUSED:
3026 p = ""; /* NT provides the paused string */
3027 break;
3028 case LPQ_SPOOLING:
3029 p = "Spooling";
3030 break;
3031 case LPQ_PRINTING:
3032 p = "Printing";
3033 break;
3035 #endif /* NO LONGER NEEDED. */
3037 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3039 data->notify_data.data.length = len;
3040 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3042 if (!data->notify_data.data.string) {
3043 data->notify_data.data.length = 0;
3044 return;
3047 memcpy(data->notify_data.data.string, temp, len);
3050 /*******************************************************************
3051 * fill a notify_info_data with job time
3052 ********************************************************************/
3054 static void spoolss_notify_job_time(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]=0x0;
3061 data->notify_data.value[1]=0;
3064 /*******************************************************************
3065 * fill a notify_info_data with job size
3066 ********************************************************************/
3068 static void spoolss_notify_job_size(int snum,
3069 SPOOL_NOTIFY_INFO_DATA *data,
3070 print_queue_struct *queue,
3071 NT_PRINTER_INFO_LEVEL *printer,
3072 TALLOC_CTX *mem_ctx)
3074 data->notify_data.value[0]=queue->size;
3075 data->notify_data.value[1]=0;
3078 /*******************************************************************
3079 * fill a notify_info_data with page info
3080 ********************************************************************/
3081 static void spoolss_notify_total_pages(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0]=queue->page_count;
3088 data->notify_data.value[1]=0;
3091 /*******************************************************************
3092 * fill a notify_info_data with pages printed info.
3093 ********************************************************************/
3094 static void spoolss_notify_pages_printed(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]=0; /* Add code when back-end tracks this */
3101 data->notify_data.value[1]=0;
3104 /*******************************************************************
3105 Fill a notify_info_data with job position.
3106 ********************************************************************/
3108 static void spoolss_notify_job_position(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 data->notify_data.value[0]=queue->job;
3115 data->notify_data.value[1]=0;
3118 /*******************************************************************
3119 Fill a notify_info_data with submitted time.
3120 ********************************************************************/
3122 static void spoolss_notify_submitted_time(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 struct tm *t;
3129 uint32 len;
3130 SYSTEMTIME st;
3131 char *p;
3133 t=gmtime(&queue->time);
3135 len = sizeof(SYSTEMTIME);
3137 data->notify_data.data.length = len;
3138 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3140 if (!data->notify_data.data.string) {
3141 data->notify_data.data.length = 0;
3142 return;
3145 make_systemtime(&st, t);
3148 * Systemtime must be linearized as a set of UINT16's.
3149 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3152 p = (char *)data->notify_data.data.string;
3153 SSVAL(p, 0, st.year);
3154 SSVAL(p, 2, st.month);
3155 SSVAL(p, 4, st.dayofweek);
3156 SSVAL(p, 6, st.day);
3157 SSVAL(p, 8, st.hour);
3158 SSVAL(p, 10, st.minute);
3159 SSVAL(p, 12, st.second);
3160 SSVAL(p, 14, st.milliseconds);
3163 struct s_notify_info_data_table
3165 uint16 type;
3166 uint16 field;
3167 char *name;
3168 uint32 size;
3169 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3174 /* A table describing the various print notification constants and
3175 whether the notification data is a pointer to a variable sized
3176 buffer, a one value uint32 or a two value uint32. */
3178 struct s_notify_info_data_table notify_info_data_table[] =
3180 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3181 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3182 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3183 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3184 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3185 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3186 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3187 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3188 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3189 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3190 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3191 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3192 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3193 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3194 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3195 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3196 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3197 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3198 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3199 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3200 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3201 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3202 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3203 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3204 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3205 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3206 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3207 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3208 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3209 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3210 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3211 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3212 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3213 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3214 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3215 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3216 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3217 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3218 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3219 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3220 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3221 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3222 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3223 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3224 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3225 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3226 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3227 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3228 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3231 /*******************************************************************
3232 Return the size of info_data structure.
3233 ********************************************************************/
3235 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3237 int i=0;
3239 for (i = 0; i < sizeof(notify_info_data_table); i++)
3241 if ( (notify_info_data_table[i].type == type)
3242 && (notify_info_data_table[i].field == field) )
3244 switch(notify_info_data_table[i].size)
3246 case NOTIFY_ONE_VALUE:
3247 case NOTIFY_TWO_VALUE:
3248 return 1;
3249 case NOTIFY_STRING:
3250 return 2;
3252 /* The only pointer notify data I have seen on
3253 the wire is the submitted time and this has
3254 the notify size set to 4. -tpot */
3256 case NOTIFY_POINTER:
3257 return 4;
3259 case NOTIFY_SECDESC:
3260 return 5;
3265 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3267 return 0;
3270 /*******************************************************************
3271 Return the type of notify_info_data.
3272 ********************************************************************/
3274 static int type_of_notify_info_data(uint16 type, uint16 field)
3276 int i=0;
3278 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3279 if (notify_info_data_table[i].type == type &&
3280 notify_info_data_table[i].field == field)
3281 return notify_info_data_table[i].size;
3284 return False;
3287 /****************************************************************************
3288 ****************************************************************************/
3290 static int search_notify(uint16 type, uint16 field, int *value)
3292 int i;
3294 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3295 if (notify_info_data_table[i].type == type &&
3296 notify_info_data_table[i].field == field &&
3297 notify_info_data_table[i].fn != NULL) {
3298 *value = i;
3299 return True;
3303 return False;
3306 /****************************************************************************
3307 ****************************************************************************/
3309 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3311 info_data->type = type;
3312 info_data->field = field;
3313 info_data->reserved = 0;
3315 info_data->size = size_of_notify_info_data(type, field);
3316 info_data->enc_type = type_of_notify_info_data(type, field);
3318 info_data->id = id;
3323 /*******************************************************************
3325 * fill a notify_info struct with info asked
3327 ********************************************************************/
3329 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3330 snum, SPOOL_NOTIFY_OPTION_TYPE
3331 *option_type, uint32 id,
3332 TALLOC_CTX *mem_ctx)
3334 int field_num,j;
3335 uint16 type;
3336 uint16 field;
3338 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3339 NT_PRINTER_INFO_LEVEL *printer = NULL;
3340 print_queue_struct *queue=NULL;
3342 type=option_type->type;
3344 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3345 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3346 option_type->count, lp_servicename(snum)));
3348 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3349 return False;
3351 for(field_num=0; field_num<option_type->count; field_num++)
3353 field = option_type->fields[field_num];
3355 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3357 if (!search_notify(type, field, &j) )
3358 continue;
3360 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3362 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3363 return False;
3365 else
3366 info->data = tid;
3368 current_data = &info->data[info->count];
3370 construct_info_data(current_data, type, field, id);
3372 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3373 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3375 notify_info_data_table[j].fn(snum, current_data, queue,
3376 printer, mem_ctx);
3378 info->count++;
3381 free_a_printer(&printer, 2);
3382 return True;
3385 /*******************************************************************
3387 * fill a notify_info struct with info asked
3389 ********************************************************************/
3391 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3392 SPOOL_NOTIFY_INFO *info,
3393 NT_PRINTER_INFO_LEVEL *printer,
3394 int snum, SPOOL_NOTIFY_OPTION_TYPE
3395 *option_type, uint32 id,
3396 TALLOC_CTX *mem_ctx)
3398 int field_num,j;
3399 uint16 type;
3400 uint16 field;
3402 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3404 DEBUG(4,("construct_notify_jobs_info\n"));
3406 type = option_type->type;
3408 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3409 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3410 option_type->count));
3412 for(field_num=0; field_num<option_type->count; field_num++) {
3413 field = option_type->fields[field_num];
3415 if (!search_notify(type, field, &j) )
3416 continue;
3418 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3419 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3420 return False;
3422 else info->data = tid;
3424 current_data=&(info->data[info->count]);
3426 construct_info_data(current_data, type, field, id);
3427 notify_info_data_table[j].fn(snum, current_data, queue,
3428 printer, mem_ctx);
3429 info->count++;
3432 return True;
3436 * JFM: The enumeration is not that simple, it's even non obvious.
3438 * let's take an example: I want to monitor the PRINTER SERVER for
3439 * the printer's name and the number of jobs currently queued.
3440 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3441 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3443 * I have 3 printers on the back of my server.
3445 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3446 * structures.
3447 * Number Data Id
3448 * 1 printer 1 name 1
3449 * 2 printer 1 cjob 1
3450 * 3 printer 2 name 2
3451 * 4 printer 2 cjob 2
3452 * 5 printer 3 name 3
3453 * 6 printer 3 name 3
3455 * that's the print server case, the printer case is even worse.
3458 /*******************************************************************
3460 * enumerate all printers on the printserver
3461 * fill a notify_info struct with info asked
3463 ********************************************************************/
3465 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3466 SPOOL_NOTIFY_INFO *info,
3467 TALLOC_CTX *mem_ctx)
3469 int snum;
3470 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3471 int n_services=lp_numservices();
3472 int i;
3473 uint32 id;
3474 SPOOL_NOTIFY_OPTION *option;
3475 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3477 DEBUG(4,("printserver_notify_info\n"));
3479 if (!Printer)
3480 return WERR_BADFID;
3482 option=Printer->notify.option;
3483 id=1;
3484 info->version=2;
3485 info->data=NULL;
3486 info->count=0;
3488 for (i=0; i<option->count; i++) {
3489 option_type=&(option->ctr.type[i]);
3491 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3492 continue;
3494 for (snum=0; snum<n_services; snum++)
3496 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3497 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3501 #if 0
3503 * Debugging information, don't delete.
3506 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3507 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3508 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3510 for (i=0; i<info->count; i++) {
3511 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3512 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3513 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3515 #endif
3517 return WERR_OK;
3520 /*******************************************************************
3522 * fill a notify_info struct with info asked
3524 ********************************************************************/
3526 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3527 TALLOC_CTX *mem_ctx)
3529 int snum;
3530 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3531 int i;
3532 uint32 id;
3533 SPOOL_NOTIFY_OPTION *option;
3534 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3535 int count,j;
3536 print_queue_struct *queue=NULL;
3537 print_status_struct status;
3539 DEBUG(4,("printer_notify_info\n"));
3541 if (!Printer)
3542 return WERR_BADFID;
3544 option=Printer->notify.option;
3545 id = 0x0;
3546 info->version=2;
3547 info->data=NULL;
3548 info->count=0;
3550 get_printer_snum(p, hnd, &snum);
3552 for (i=0; i<option->count; i++) {
3553 option_type=&option->ctr.type[i];
3555 switch ( option_type->type ) {
3556 case PRINTER_NOTIFY_TYPE:
3557 if(construct_notify_printer_info(info, snum,
3558 option_type, id,
3559 mem_ctx))
3560 id--;
3561 break;
3563 case JOB_NOTIFY_TYPE: {
3564 NT_PRINTER_INFO_LEVEL *printer = NULL;
3566 count = print_queue_status(snum, &queue, &status);
3568 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3569 lp_servicename(snum))))
3570 goto done;
3572 for (j=0; j<count; j++) {
3573 construct_notify_jobs_info(&queue[j], info,
3574 printer, snum,
3575 option_type,
3576 queue[j].job,
3577 mem_ctx);
3580 free_a_printer(&printer, 2);
3582 done:
3583 SAFE_FREE(queue);
3584 break;
3590 * Debugging information, don't delete.
3593 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3594 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3595 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3597 for (i=0; i<info->count; i++) {
3598 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3599 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3600 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3603 return WERR_OK;
3606 /********************************************************************
3607 * spoolss_rfnpcnex
3608 ********************************************************************/
3610 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3612 POLICY_HND *handle = &q_u->handle;
3613 SPOOL_NOTIFY_INFO *info = &r_u->info;
3615 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3616 WERROR result = WERR_BADFID;
3618 /* we always have a NOTIFY_INFO struct */
3619 r_u->info_ptr=0x1;
3621 if (!Printer) {
3622 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3623 OUR_HANDLE(handle)));
3624 goto done;
3627 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3630 * We are now using the change value, and
3631 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3632 * I don't have a global notification system, I'm sending back all the
3633 * informations even when _NOTHING_ has changed.
3636 /* We need to keep track of the change value to send back in
3637 RRPCN replies otherwise our updates are ignored. */
3639 if (Printer->notify.client_connected) {
3640 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3641 Printer->notify.change = q_u->change;
3644 /* just ignore the SPOOL_NOTIFY_OPTION */
3646 switch (Printer->printer_type) {
3647 case PRINTER_HANDLE_IS_PRINTSERVER:
3648 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3649 break;
3651 case PRINTER_HANDLE_IS_PRINTER:
3652 result = printer_notify_info(p, handle, info, p->mem_ctx);
3653 break;
3656 done:
3657 return result;
3660 /********************************************************************
3661 * construct_printer_info_0
3662 * fill a printer_info_0 struct
3663 ********************************************************************/
3665 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3667 pstring chaine;
3668 int count;
3669 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3670 counter_printer_0 *session_counter;
3671 uint32 global_counter;
3672 struct tm *t;
3673 time_t setuptime;
3674 print_status_struct status;
3676 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3677 return False;
3679 count = print_queue_length(snum, &status);
3681 /* check if we already have a counter for this printer */
3682 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3684 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3685 if (session_counter->snum == snum)
3686 break;
3689 /* it's the first time, add it to the list */
3690 if (session_counter==NULL) {
3691 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3692 free_a_printer(&ntprinter, 2);
3693 return False;
3695 ZERO_STRUCTP(session_counter);
3696 session_counter->snum=snum;
3697 session_counter->counter=0;
3698 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3701 /* increment it */
3702 session_counter->counter++;
3704 /* JFM:
3705 * the global_counter should be stored in a TDB as it's common to all the clients
3706 * and should be zeroed on samba startup
3708 global_counter=session_counter->counter;
3710 pstrcpy(chaine,ntprinter->info_2->printername);
3712 init_unistr(&printer->printername, chaine);
3714 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3715 init_unistr(&printer->servername, chaine);
3717 printer->cjobs = count;
3718 printer->total_jobs = 0;
3719 printer->total_bytes = 0;
3721 setuptime = (time_t)ntprinter->info_2->setuptime;
3722 t=gmtime(&setuptime);
3724 printer->year = t->tm_year+1900;
3725 printer->month = t->tm_mon+1;
3726 printer->dayofweek = t->tm_wday;
3727 printer->day = t->tm_mday;
3728 printer->hour = t->tm_hour;
3729 printer->minute = t->tm_min;
3730 printer->second = t->tm_sec;
3731 printer->milliseconds = 0;
3733 printer->global_counter = global_counter;
3734 printer->total_pages = 0;
3735 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3736 printer->major_version = 0x0004; /* NT 4 */
3737 printer->build_version = 0x0565; /* build 1381 */
3738 #else
3739 printer->major_version = 0x0005; /* NT 5 */
3740 printer->build_version = 0x0893; /* build 2195 */
3741 #endif
3742 printer->unknown7 = 0x1;
3743 printer->unknown8 = 0x0;
3744 printer->unknown9 = 0x0;
3745 printer->session_counter = session_counter->counter;
3746 printer->unknown11 = 0x0;
3747 printer->printer_errors = 0x0; /* number of print failure */
3748 printer->unknown13 = 0x0;
3749 printer->unknown14 = 0x1;
3750 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3751 printer->unknown16 = 0x0;
3752 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3753 printer->unknown18 = 0x0;
3754 printer->status = nt_printq_status(status.status);
3755 printer->unknown20 = 0x0;
3756 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3757 printer->unknown22 = 0x0;
3758 printer->unknown23 = 0x6; /* 6 ???*/
3759 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3760 printer->unknown25 = 0;
3761 printer->unknown26 = 0;
3762 printer->unknown27 = 0;
3763 printer->unknown28 = 0;
3764 printer->unknown29 = 0;
3766 free_a_printer(&ntprinter,2);
3767 return (True);
3770 /********************************************************************
3771 * construct_printer_info_1
3772 * fill a printer_info_1 struct
3773 ********************************************************************/
3774 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3776 pstring chaine;
3777 pstring chaine2;
3778 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3780 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3781 return False;
3783 printer->flags=flags;
3785 if (*ntprinter->info_2->comment == '\0') {
3786 init_unistr(&printer->comment, lp_comment(snum));
3787 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3788 ntprinter->info_2->drivername, lp_comment(snum));
3790 else {
3791 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3792 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3793 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3796 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3798 init_unistr(&printer->description, chaine);
3799 init_unistr(&printer->name, chaine2);
3801 free_a_printer(&ntprinter,2);
3803 return True;
3806 /****************************************************************************
3807 Free a DEVMODE struct.
3808 ****************************************************************************/
3810 static void free_dev_mode(DEVICEMODE *dev)
3812 if (dev == NULL)
3813 return;
3815 SAFE_FREE(dev->private);
3816 SAFE_FREE(dev);
3820 /****************************************************************************
3821 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3822 should be valid upon entry
3823 ****************************************************************************/
3825 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3827 if ( !devmode || !ntdevmode )
3828 return False;
3830 init_unistr(&devmode->devicename, ntdevmode->devicename);
3832 init_unistr(&devmode->formname, ntdevmode->formname);
3834 devmode->specversion = ntdevmode->specversion;
3835 devmode->driverversion = ntdevmode->driverversion;
3836 devmode->size = ntdevmode->size;
3837 devmode->driverextra = ntdevmode->driverextra;
3838 devmode->fields = ntdevmode->fields;
3840 devmode->orientation = ntdevmode->orientation;
3841 devmode->papersize = ntdevmode->papersize;
3842 devmode->paperlength = ntdevmode->paperlength;
3843 devmode->paperwidth = ntdevmode->paperwidth;
3844 devmode->scale = ntdevmode->scale;
3845 devmode->copies = ntdevmode->copies;
3846 devmode->defaultsource = ntdevmode->defaultsource;
3847 devmode->printquality = ntdevmode->printquality;
3848 devmode->color = ntdevmode->color;
3849 devmode->duplex = ntdevmode->duplex;
3850 devmode->yresolution = ntdevmode->yresolution;
3851 devmode->ttoption = ntdevmode->ttoption;
3852 devmode->collate = ntdevmode->collate;
3853 devmode->icmmethod = ntdevmode->icmmethod;
3854 devmode->icmintent = ntdevmode->icmintent;
3855 devmode->mediatype = ntdevmode->mediatype;
3856 devmode->dithertype = ntdevmode->dithertype;
3858 if (ntdevmode->private != NULL) {
3859 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3860 return False;
3863 return True;
3866 /****************************************************************************
3867 Create a DEVMODE struct. Returns malloced memory.
3868 ****************************************************************************/
3870 DEVICEMODE *construct_dev_mode(int snum)
3872 NT_PRINTER_INFO_LEVEL *printer = NULL;
3873 DEVICEMODE *devmode = NULL;
3875 DEBUG(7,("construct_dev_mode\n"));
3877 DEBUGADD(8,("getting printer characteristics\n"));
3879 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3880 return NULL;
3882 if ( !printer->info_2->devmode ) {
3883 DEBUG(5, ("BONG! There was no device mode!\n"));
3884 goto done;
3887 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3888 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3889 goto done;
3892 ZERO_STRUCTP(devmode);
3894 DEBUGADD(8,("loading DEVICEMODE\n"));
3896 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
3897 free_dev_mode( devmode );
3898 devmode = NULL;
3901 done:
3902 free_a_printer(&printer,2);
3904 return devmode;
3907 /********************************************************************
3908 * construct_printer_info_2
3909 * fill a printer_info_2 struct
3910 ********************************************************************/
3912 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3914 int count;
3915 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3917 print_status_struct status;
3919 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3920 return False;
3922 count = print_queue_length(snum, &status);
3924 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3925 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3926 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3927 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3928 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3930 if (*ntprinter->info_2->comment == '\0')
3931 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3932 else
3933 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3935 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3936 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3937 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3938 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3939 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3941 printer->attributes = ntprinter->info_2->attributes;
3943 printer->priority = ntprinter->info_2->priority; /* priority */
3944 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3945 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3946 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3947 printer->status = nt_printq_status(status.status); /* status */
3948 printer->cjobs = count; /* jobs */
3949 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3951 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3952 DEBUG(8, ("Returning NULL Devicemode!\n"));
3955 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3956 /* steal the printer info sec_desc structure. [badly done]. */
3957 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3958 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3959 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3960 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3962 else {
3963 printer->secdesc = NULL;
3966 free_a_printer(&ntprinter, 2);
3967 return True;
3970 /********************************************************************
3971 * construct_printer_info_3
3972 * fill a printer_info_3 struct
3973 ********************************************************************/
3975 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3977 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3978 PRINTER_INFO_3 *printer = NULL;
3980 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3981 return False;
3983 *pp_printer = NULL;
3984 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3985 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3986 return False;
3989 ZERO_STRUCTP(printer);
3991 printer->flags = 4; /* These are the components of the SD we are returning. */
3992 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3993 /* steal the printer info sec_desc structure. [badly done]. */
3994 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3996 #if 0
3998 * Set the flags for the components we are returning.
4001 if (printer->secdesc->owner_sid)
4002 printer->flags |= OWNER_SECURITY_INFORMATION;
4004 if (printer->secdesc->grp_sid)
4005 printer->flags |= GROUP_SECURITY_INFORMATION;
4007 if (printer->secdesc->dacl)
4008 printer->flags |= DACL_SECURITY_INFORMATION;
4010 if (printer->secdesc->sacl)
4011 printer->flags |= SACL_SECURITY_INFORMATION;
4012 #endif
4014 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4015 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4016 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4019 free_a_printer(&ntprinter, 2);
4021 *pp_printer = printer;
4022 return True;
4025 /********************************************************************
4026 * construct_printer_info_4
4027 * fill a printer_info_4 struct
4028 ********************************************************************/
4030 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4032 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4034 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4035 return False;
4037 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4038 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4039 printer->attributes = ntprinter->info_2->attributes;
4041 free_a_printer(&ntprinter, 2);
4042 return True;
4045 /********************************************************************
4046 * construct_printer_info_5
4047 * fill a printer_info_5 struct
4048 ********************************************************************/
4050 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4052 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4054 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4055 return False;
4057 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4058 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4059 printer->attributes = ntprinter->info_2->attributes;
4060 printer->device_not_selected_timeout = 0x3a98;
4061 printer->transmission_retry_timeout = 0xafc8;
4063 free_a_printer(&ntprinter, 2);
4064 return True;
4067 /********************************************************************
4068 Spoolss_enumprinters.
4069 ********************************************************************/
4071 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4073 int snum;
4074 int i;
4075 int n_services=lp_numservices();
4076 PRINTER_INFO_1 *tp, *printers=NULL;
4077 PRINTER_INFO_1 current_prt;
4079 DEBUG(4,("enum_all_printers_info_1\n"));
4081 for (snum=0; snum<n_services; snum++) {
4082 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4083 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4085 if (construct_printer_info_1(flags, &current_prt, snum)) {
4086 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4087 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4088 SAFE_FREE(printers);
4089 *returned=0;
4090 return WERR_NOMEM;
4092 else printers = tp;
4093 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4095 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4096 (*returned)++;
4101 /* check the required size. */
4102 for (i=0; i<*returned; i++)
4103 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4105 if (!alloc_buffer_size(buffer, *needed))
4106 return WERR_INSUFFICIENT_BUFFER;
4108 /* fill the buffer with the structures */
4109 for (i=0; i<*returned; i++)
4110 smb_io_printer_info_1("", buffer, &printers[i], 0);
4112 /* clear memory */
4113 SAFE_FREE(printers);
4115 if (*needed > offered) {
4116 *returned=0;
4117 return WERR_INSUFFICIENT_BUFFER;
4119 else
4120 return WERR_OK;
4123 /********************************************************************
4124 enum_all_printers_info_1_local.
4125 *********************************************************************/
4127 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4129 DEBUG(4,("enum_all_printers_info_1_local\n"));
4131 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4134 /********************************************************************
4135 enum_all_printers_info_1_name.
4136 *********************************************************************/
4138 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4140 char *s = name;
4142 DEBUG(4,("enum_all_printers_info_1_name\n"));
4144 if ((name[0] == '\\') && (name[1] == '\\'))
4145 s = name + 2;
4147 if (is_myname_or_ipaddr(s)) {
4148 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4150 else
4151 return WERR_INVALID_NAME;
4154 /********************************************************************
4155 enum_all_printers_info_1_remote.
4156 *********************************************************************/
4158 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4160 PRINTER_INFO_1 *printer;
4161 fstring printername;
4162 fstring desc;
4163 fstring comment;
4164 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4166 /* JFM: currently it's more a place holder than anything else.
4167 * In the spooler world there is a notion of server registration.
4168 * the print servers are registring (sp ?) on the PDC (in the same domain)
4170 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4173 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4174 return WERR_NOMEM;
4176 *returned=1;
4178 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4179 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4180 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4182 init_unistr(&printer->description, desc);
4183 init_unistr(&printer->name, printername);
4184 init_unistr(&printer->comment, comment);
4185 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4187 /* check the required size. */
4188 *needed += spoolss_size_printer_info_1(printer);
4190 if (!alloc_buffer_size(buffer, *needed)) {
4191 SAFE_FREE(printer);
4192 return WERR_INSUFFICIENT_BUFFER;
4195 /* fill the buffer with the structures */
4196 smb_io_printer_info_1("", buffer, printer, 0);
4198 /* clear memory */
4199 SAFE_FREE(printer);
4201 if (*needed > offered) {
4202 *returned=0;
4203 return WERR_INSUFFICIENT_BUFFER;
4205 else
4206 return WERR_OK;
4209 /********************************************************************
4210 enum_all_printers_info_1_network.
4211 *********************************************************************/
4213 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4215 char *s = name;
4217 DEBUG(4,("enum_all_printers_info_1_network\n"));
4219 /* If we respond to a enum_printers level 1 on our name with flags
4220 set to PRINTER_ENUM_REMOTE with a list of printers then these
4221 printers incorrectly appear in the APW browse list.
4222 Specifically the printers for the server appear at the workgroup
4223 level where all the other servers in the domain are
4224 listed. Windows responds to this call with a
4225 WERR_CAN_NOT_COMPLETE so we should do the same. */
4227 if (name[0] == '\\' && name[1] == '\\')
4228 s = name + 2;
4230 if (is_myname_or_ipaddr(s))
4231 return WERR_CAN_NOT_COMPLETE;
4233 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4236 /********************************************************************
4237 * api_spoolss_enumprinters
4239 * called from api_spoolss_enumprinters (see this to understand)
4240 ********************************************************************/
4242 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4244 int snum;
4245 int i;
4246 int n_services=lp_numservices();
4247 PRINTER_INFO_2 *tp, *printers=NULL;
4248 PRINTER_INFO_2 current_prt;
4250 for (snum=0; snum<n_services; snum++) {
4251 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4252 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4254 if (construct_printer_info_2(&current_prt, snum)) {
4255 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4256 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4257 SAFE_FREE(printers);
4258 *returned = 0;
4259 return WERR_NOMEM;
4261 else printers = tp;
4262 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4263 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4264 (*returned)++;
4269 /* check the required size. */
4270 for (i=0; i<*returned; i++)
4271 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4273 if (!alloc_buffer_size(buffer, *needed)) {
4274 for (i=0; i<*returned; i++) {
4275 free_devmode(printers[i].devmode);
4277 SAFE_FREE(printers);
4278 return WERR_INSUFFICIENT_BUFFER;
4281 /* fill the buffer with the structures */
4282 for (i=0; i<*returned; i++)
4283 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4285 /* clear memory */
4286 for (i=0; i<*returned; i++) {
4287 free_devmode(printers[i].devmode);
4289 SAFE_FREE(printers);
4291 if (*needed > offered) {
4292 *returned=0;
4293 return WERR_INSUFFICIENT_BUFFER;
4295 else
4296 return WERR_OK;
4299 /********************************************************************
4300 * handle enumeration of printers at level 1
4301 ********************************************************************/
4303 static WERROR enumprinters_level1( uint32 flags, fstring name,
4304 NEW_BUFFER *buffer, uint32 offered,
4305 uint32 *needed, uint32 *returned)
4307 /* Not all the flags are equals */
4309 if (flags & PRINTER_ENUM_LOCAL)
4310 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4312 if (flags & PRINTER_ENUM_NAME)
4313 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4315 if (flags & PRINTER_ENUM_REMOTE)
4316 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4318 if (flags & PRINTER_ENUM_NETWORK)
4319 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4321 return WERR_OK; /* NT4sp5 does that */
4324 /********************************************************************
4325 * handle enumeration of printers at level 2
4326 ********************************************************************/
4328 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4329 NEW_BUFFER *buffer, uint32 offered,
4330 uint32 *needed, uint32 *returned)
4332 char *s = servername;
4334 if (flags & PRINTER_ENUM_LOCAL) {
4335 return enum_all_printers_info_2(buffer, offered, needed, returned);
4338 if (flags & PRINTER_ENUM_NAME) {
4339 if ((servername[0] == '\\') && (servername[1] == '\\'))
4340 s = servername + 2;
4341 if (is_myname_or_ipaddr(s))
4342 return enum_all_printers_info_2(buffer, offered, needed, returned);
4343 else
4344 return WERR_INVALID_NAME;
4347 if (flags & PRINTER_ENUM_REMOTE)
4348 return WERR_UNKNOWN_LEVEL;
4350 return WERR_OK;
4353 /********************************************************************
4354 * handle enumeration of printers at level 5
4355 ********************************************************************/
4357 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4358 NEW_BUFFER *buffer, uint32 offered,
4359 uint32 *needed, uint32 *returned)
4361 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4362 return WERR_OK;
4365 /********************************************************************
4366 * api_spoolss_enumprinters
4368 * called from api_spoolss_enumprinters (see this to understand)
4369 ********************************************************************/
4371 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4373 uint32 flags = q_u->flags;
4374 UNISTR2 *servername = &q_u->servername;
4375 uint32 level = q_u->level;
4376 NEW_BUFFER *buffer = NULL;
4377 uint32 offered = q_u->offered;
4378 uint32 *needed = &r_u->needed;
4379 uint32 *returned = &r_u->returned;
4381 fstring name;
4383 /* that's an [in out] buffer */
4384 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4385 buffer = r_u->buffer;
4387 DEBUG(4,("_spoolss_enumprinters\n"));
4389 *needed=0;
4390 *returned=0;
4393 * Level 1:
4394 * flags==PRINTER_ENUM_NAME
4395 * if name=="" then enumerates all printers
4396 * if name!="" then enumerate the printer
4397 * flags==PRINTER_ENUM_REMOTE
4398 * name is NULL, enumerate printers
4399 * Level 2: name!="" enumerates printers, name can't be NULL
4400 * Level 3: doesn't exist
4401 * Level 4: does a local registry lookup
4402 * Level 5: same as Level 2
4405 unistr2_to_ascii(name, servername, sizeof(name)-1);
4406 strupper(name);
4408 switch (level) {
4409 case 1:
4410 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4411 case 2:
4412 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4413 case 5:
4414 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4415 case 3:
4416 case 4:
4417 break;
4419 return WERR_UNKNOWN_LEVEL;
4422 /****************************************************************************
4423 ****************************************************************************/
4425 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4427 PRINTER_INFO_0 *printer=NULL;
4429 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4430 return WERR_NOMEM;
4432 construct_printer_info_0(printer, snum);
4434 /* check the required size. */
4435 *needed += spoolss_size_printer_info_0(printer);
4437 if (!alloc_buffer_size(buffer, *needed)) {
4438 SAFE_FREE(printer);
4439 return WERR_INSUFFICIENT_BUFFER;
4442 /* fill the buffer with the structures */
4443 smb_io_printer_info_0("", buffer, printer, 0);
4445 /* clear memory */
4446 SAFE_FREE(printer);
4448 if (*needed > offered) {
4449 return WERR_INSUFFICIENT_BUFFER;
4452 return WERR_OK;
4455 /****************************************************************************
4456 ****************************************************************************/
4458 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4460 PRINTER_INFO_1 *printer=NULL;
4462 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4463 return WERR_NOMEM;
4465 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4467 /* check the required size. */
4468 *needed += spoolss_size_printer_info_1(printer);
4470 if (!alloc_buffer_size(buffer, *needed)) {
4471 SAFE_FREE(printer);
4472 return WERR_INSUFFICIENT_BUFFER;
4475 /* fill the buffer with the structures */
4476 smb_io_printer_info_1("", buffer, printer, 0);
4478 /* clear memory */
4479 SAFE_FREE(printer);
4481 if (*needed > offered) {
4482 return WERR_INSUFFICIENT_BUFFER;
4485 return WERR_OK;
4488 /****************************************************************************
4489 ****************************************************************************/
4491 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4493 PRINTER_INFO_2 *printer=NULL;
4495 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4496 return WERR_NOMEM;
4498 construct_printer_info_2(printer, snum);
4500 /* check the required size. */
4501 *needed += spoolss_size_printer_info_2(printer);
4503 if (!alloc_buffer_size(buffer, *needed)) {
4504 free_printer_info_2(printer);
4505 return WERR_INSUFFICIENT_BUFFER;
4508 /* fill the buffer with the structures */
4509 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4510 free_printer_info_2(printer);
4511 return WERR_NOMEM;
4514 /* clear memory */
4515 free_printer_info_2(printer);
4517 if (*needed > offered) {
4518 return WERR_INSUFFICIENT_BUFFER;
4521 return WERR_OK;
4524 /****************************************************************************
4525 ****************************************************************************/
4527 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4529 PRINTER_INFO_3 *printer=NULL;
4531 if (!construct_printer_info_3(&printer, snum))
4532 return WERR_NOMEM;
4534 /* check the required size. */
4535 *needed += spoolss_size_printer_info_3(printer);
4537 if (!alloc_buffer_size(buffer, *needed)) {
4538 free_printer_info_3(printer);
4539 return WERR_INSUFFICIENT_BUFFER;
4542 /* fill the buffer with the structures */
4543 smb_io_printer_info_3("", buffer, printer, 0);
4545 /* clear memory */
4546 free_printer_info_3(printer);
4548 if (*needed > offered) {
4549 return WERR_INSUFFICIENT_BUFFER;
4552 return WERR_OK;
4555 /****************************************************************************
4556 ****************************************************************************/
4558 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4560 PRINTER_INFO_4 *printer=NULL;
4562 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4563 return WERR_NOMEM;
4565 if (!construct_printer_info_4(printer, snum))
4566 return WERR_NOMEM;
4568 /* check the required size. */
4569 *needed += spoolss_size_printer_info_4(printer);
4571 if (!alloc_buffer_size(buffer, *needed)) {
4572 free_printer_info_4(printer);
4573 return WERR_INSUFFICIENT_BUFFER;
4576 /* fill the buffer with the structures */
4577 smb_io_printer_info_4("", buffer, printer, 0);
4579 /* clear memory */
4580 free_printer_info_4(printer);
4582 if (*needed > offered) {
4583 return WERR_INSUFFICIENT_BUFFER;
4586 return WERR_OK;
4589 /****************************************************************************
4590 ****************************************************************************/
4592 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4594 PRINTER_INFO_5 *printer=NULL;
4596 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4597 return WERR_NOMEM;
4599 if (!construct_printer_info_5(printer, snum))
4600 return WERR_NOMEM;
4602 /* check the required size. */
4603 *needed += spoolss_size_printer_info_5(printer);
4605 if (!alloc_buffer_size(buffer, *needed)) {
4606 free_printer_info_5(printer);
4607 return WERR_INSUFFICIENT_BUFFER;
4610 /* fill the buffer with the structures */
4611 smb_io_printer_info_5("", buffer, printer, 0);
4613 /* clear memory */
4614 free_printer_info_5(printer);
4616 if (*needed > offered) {
4617 return WERR_INSUFFICIENT_BUFFER;
4620 return WERR_OK;
4623 /****************************************************************************
4624 ****************************************************************************/
4626 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4628 POLICY_HND *handle = &q_u->handle;
4629 uint32 level = q_u->level;
4630 NEW_BUFFER *buffer = NULL;
4631 uint32 offered = q_u->offered;
4632 uint32 *needed = &r_u->needed;
4634 int snum;
4636 /* that's an [in out] buffer */
4637 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4638 buffer = r_u->buffer;
4640 *needed=0;
4642 if (!get_printer_snum(p, handle, &snum))
4643 return WERR_BADFID;
4645 switch (level) {
4646 case 0:
4647 return getprinter_level_0(snum, buffer, offered, needed);
4648 case 1:
4649 return getprinter_level_1(snum, buffer, offered, needed);
4650 case 2:
4651 return getprinter_level_2(snum, buffer, offered, needed);
4652 case 3:
4653 return getprinter_level_3(snum, buffer, offered, needed);
4654 case 4:
4655 return getprinter_level_4(snum, buffer, offered, needed);
4656 case 5:
4657 return getprinter_level_5(snum, buffer, offered, needed);
4659 return WERR_UNKNOWN_LEVEL;
4662 /********************************************************************
4663 * fill a DRIVER_INFO_1 struct
4664 ********************************************************************/
4666 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4668 init_unistr( &info->name, driver.info_3->name);
4671 /********************************************************************
4672 * construct_printer_driver_info_1
4673 ********************************************************************/
4675 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4677 NT_PRINTER_INFO_LEVEL *printer = NULL;
4678 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4680 ZERO_STRUCT(driver);
4682 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4683 return WERR_INVALID_PRINTER_NAME;
4685 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4686 return WERR_UNKNOWN_PRINTER_DRIVER;
4688 fill_printer_driver_info_1(info, driver, servername, architecture);
4690 free_a_printer(&printer,2);
4692 return WERR_OK;
4695 /********************************************************************
4696 * construct_printer_driver_info_2
4697 * fill a printer_info_2 struct
4698 ********************************************************************/
4700 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4702 pstring temp;
4704 info->version=driver.info_3->cversion;
4706 init_unistr( &info->name, driver.info_3->name );
4707 init_unistr( &info->architecture, driver.info_3->environment );
4710 if (strlen(driver.info_3->driverpath)) {
4711 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4712 init_unistr( &info->driverpath, temp );
4713 } else
4714 init_unistr( &info->driverpath, "" );
4716 if (strlen(driver.info_3->datafile)) {
4717 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4718 init_unistr( &info->datafile, temp );
4719 } else
4720 init_unistr( &info->datafile, "" );
4722 if (strlen(driver.info_3->configfile)) {
4723 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4724 init_unistr( &info->configfile, temp );
4725 } else
4726 init_unistr( &info->configfile, "" );
4729 /********************************************************************
4730 * construct_printer_driver_info_2
4731 * fill a printer_info_2 struct
4732 ********************************************************************/
4734 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4736 NT_PRINTER_INFO_LEVEL *printer = NULL;
4737 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4739 ZERO_STRUCT(printer);
4740 ZERO_STRUCT(driver);
4742 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4743 return WERR_INVALID_PRINTER_NAME;
4745 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4746 return WERR_UNKNOWN_PRINTER_DRIVER;
4748 fill_printer_driver_info_2(info, driver, servername);
4750 free_a_printer(&printer,2);
4752 return WERR_OK;
4755 /********************************************************************
4756 * copy a strings array and convert to UNICODE
4758 * convert an array of ascii string to a UNICODE string
4759 ********************************************************************/
4761 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4763 int i=0;
4764 int j=0;
4765 char *v;
4766 pstring line;
4767 uint16 *tuary;
4769 DEBUG(6,("init_unistr_array\n"));
4770 *uni_array=NULL;
4772 while (True)
4774 if ( !char_array )
4775 v = "";
4776 else
4778 v = char_array[i];
4779 if (!v)
4780 v = ""; /* hack to handle null lists */
4783 /* hack to allow this to be used in places other than when generating
4784 the list of dependent files */
4786 if ( servername )
4787 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4788 else
4789 pstrcpy( line, v );
4791 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4793 if ( (tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4794 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4795 return 0;
4796 } else
4797 *uni_array = tuary;
4799 if ( !strlen(v) )
4800 break;
4802 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4803 i++;
4806 if (*uni_array) {
4807 (*uni_array)[j]=0x0000;
4810 DEBUGADD(6,("last one:done\n"));
4812 /* return size of array in uint16's */
4814 return j+1;
4817 /********************************************************************
4818 * construct_printer_info_3
4819 * fill a printer_info_3 struct
4820 ********************************************************************/
4822 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4824 pstring temp;
4826 ZERO_STRUCTP(info);
4828 info->version=driver.info_3->cversion;
4830 init_unistr( &info->name, driver.info_3->name );
4831 init_unistr( &info->architecture, driver.info_3->environment );
4833 if (strlen(driver.info_3->driverpath)) {
4834 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4835 init_unistr( &info->driverpath, temp );
4836 } else
4837 init_unistr( &info->driverpath, "" );
4839 if (strlen(driver.info_3->datafile)) {
4840 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4841 init_unistr( &info->datafile, temp );
4842 } else
4843 init_unistr( &info->datafile, "" );
4845 if (strlen(driver.info_3->configfile)) {
4846 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4847 init_unistr( &info->configfile, temp );
4848 } else
4849 init_unistr( &info->configfile, "" );
4851 if (strlen(driver.info_3->helpfile)) {
4852 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4853 init_unistr( &info->helpfile, temp );
4854 } else
4855 init_unistr( &info->helpfile, "" );
4857 init_unistr( &info->monitorname, driver.info_3->monitorname );
4858 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4860 info->dependentfiles=NULL;
4861 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4864 /********************************************************************
4865 * construct_printer_info_3
4866 * fill a printer_info_3 struct
4867 ********************************************************************/
4869 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4871 NT_PRINTER_INFO_LEVEL *printer = NULL;
4872 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4873 WERROR status;
4874 ZERO_STRUCT(driver);
4876 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4877 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4878 if (!W_ERROR_IS_OK(status))
4879 return WERR_INVALID_PRINTER_NAME;
4881 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4882 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4884 #if 0 /* JERRY */
4887 * I put this code in during testing. Helpful when commenting out the
4888 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4889 * as win2k always queries the driver using an infor level of 6.
4890 * I've left it in (but ifdef'd out) because I'll probably
4891 * use it in experimentation again in the future. --jerry 22/01/2002
4894 if (!W_ERROR_IS_OK(status)) {
4896 * Is this a W2k client ?
4898 if (version == 3) {
4899 /* Yes - try again with a WinNT driver. */
4900 version = 2;
4901 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4902 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4904 #endif
4906 if (!W_ERROR_IS_OK(status)) {
4907 free_a_printer(&printer,2);
4908 return WERR_UNKNOWN_PRINTER_DRIVER;
4911 #if 0 /* JERRY */
4913 #endif
4916 fill_printer_driver_info_3(info, driver, servername);
4918 free_a_printer(&printer,2);
4920 return WERR_OK;
4923 /********************************************************************
4924 * construct_printer_info_6
4925 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4926 ********************************************************************/
4928 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4930 pstring temp;
4931 fstring nullstr;
4933 ZERO_STRUCTP(info);
4934 memset(&nullstr, '\0', sizeof(fstring));
4936 info->version=driver.info_3->cversion;
4938 init_unistr( &info->name, driver.info_3->name );
4939 init_unistr( &info->architecture, driver.info_3->environment );
4941 if (strlen(driver.info_3->driverpath)) {
4942 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4943 init_unistr( &info->driverpath, temp );
4944 } else
4945 init_unistr( &info->driverpath, "" );
4947 if (strlen(driver.info_3->datafile)) {
4948 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4949 init_unistr( &info->datafile, temp );
4950 } else
4951 init_unistr( &info->datafile, "" );
4953 if (strlen(driver.info_3->configfile)) {
4954 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4955 init_unistr( &info->configfile, temp );
4956 } else
4957 init_unistr( &info->configfile, "" );
4959 if (strlen(driver.info_3->helpfile)) {
4960 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4961 init_unistr( &info->helpfile, temp );
4962 } else
4963 init_unistr( &info->helpfile, "" );
4965 init_unistr( &info->monitorname, driver.info_3->monitorname );
4966 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4968 info->dependentfiles = NULL;
4969 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
4971 info->previousdrivernames=NULL;
4972 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4974 info->driver_date.low=0;
4975 info->driver_date.high=0;
4977 info->padding=0;
4978 info->driver_version_low=0;
4979 info->driver_version_high=0;
4981 init_unistr( &info->mfgname, "");
4982 init_unistr( &info->oem_url, "");
4983 init_unistr( &info->hardware_id, "");
4984 init_unistr( &info->provider, "");
4987 /********************************************************************
4988 * construct_printer_info_6
4989 * fill a printer_info_6 struct
4990 ********************************************************************/
4992 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
4993 fstring servername, fstring architecture, uint32 version)
4995 NT_PRINTER_INFO_LEVEL *printer = NULL;
4996 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4997 WERROR status;
4999 ZERO_STRUCT(driver);
5001 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5003 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5005 if (!W_ERROR_IS_OK(status))
5006 return WERR_INVALID_PRINTER_NAME;
5008 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5010 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5012 if (!W_ERROR_IS_OK(status))
5015 * Is this a W2k client ?
5018 if (version < 3) {
5019 free_a_printer(&printer,2);
5020 return WERR_UNKNOWN_PRINTER_DRIVER;
5023 /* Yes - try again with a WinNT driver. */
5024 version = 2;
5025 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5026 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5027 if (!W_ERROR_IS_OK(status)) {
5028 free_a_printer(&printer,2);
5029 return WERR_UNKNOWN_PRINTER_DRIVER;
5033 fill_printer_driver_info_6(info, driver, servername);
5035 free_a_printer(&printer,2);
5037 return WERR_OK;
5040 /****************************************************************************
5041 ****************************************************************************/
5043 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5045 SAFE_FREE(info->dependentfiles);
5048 /****************************************************************************
5049 ****************************************************************************/
5051 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5053 SAFE_FREE(info->dependentfiles);
5057 /****************************************************************************
5058 ****************************************************************************/
5060 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5062 DRIVER_INFO_1 *info=NULL;
5063 WERROR status;
5065 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5066 return WERR_NOMEM;
5068 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5069 if (!W_ERROR_IS_OK(status)) {
5070 SAFE_FREE(info);
5071 return status;
5074 /* check the required size. */
5075 *needed += spoolss_size_printer_driver_info_1(info);
5077 if (!alloc_buffer_size(buffer, *needed)) {
5078 SAFE_FREE(info);
5079 return WERR_INSUFFICIENT_BUFFER;
5082 /* fill the buffer with the structures */
5083 smb_io_printer_driver_info_1("", buffer, info, 0);
5085 /* clear memory */
5086 SAFE_FREE(info);
5088 if (*needed > offered)
5089 return WERR_INSUFFICIENT_BUFFER;
5091 return WERR_OK;
5094 /****************************************************************************
5095 ****************************************************************************/
5097 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5099 DRIVER_INFO_2 *info=NULL;
5100 WERROR status;
5102 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5103 return WERR_NOMEM;
5105 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5106 if (!W_ERROR_IS_OK(status)) {
5107 SAFE_FREE(info);
5108 return status;
5111 /* check the required size. */
5112 *needed += spoolss_size_printer_driver_info_2(info);
5114 if (!alloc_buffer_size(buffer, *needed)) {
5115 SAFE_FREE(info);
5116 return WERR_INSUFFICIENT_BUFFER;
5119 /* fill the buffer with the structures */
5120 smb_io_printer_driver_info_2("", buffer, info, 0);
5122 /* clear memory */
5123 SAFE_FREE(info);
5125 if (*needed > offered)
5126 return WERR_INSUFFICIENT_BUFFER;
5128 return WERR_OK;
5131 /****************************************************************************
5132 ****************************************************************************/
5134 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5136 DRIVER_INFO_3 info;
5137 WERROR status;
5139 ZERO_STRUCT(info);
5141 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5142 if (!W_ERROR_IS_OK(status)) {
5143 return status;
5146 /* check the required size. */
5147 *needed += spoolss_size_printer_driver_info_3(&info);
5149 if (!alloc_buffer_size(buffer, *needed)) {
5150 free_printer_driver_info_3(&info);
5151 return WERR_INSUFFICIENT_BUFFER;
5154 /* fill the buffer with the structures */
5155 smb_io_printer_driver_info_3("", buffer, &info, 0);
5157 free_printer_driver_info_3(&info);
5159 if (*needed > offered)
5160 return WERR_INSUFFICIENT_BUFFER;
5162 return WERR_OK;
5165 /****************************************************************************
5166 ****************************************************************************/
5168 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5170 DRIVER_INFO_6 info;
5171 WERROR status;
5173 ZERO_STRUCT(info);
5175 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5176 if (!W_ERROR_IS_OK(status)) {
5177 return status;
5180 /* check the required size. */
5181 *needed += spoolss_size_printer_driver_info_6(&info);
5183 if (!alloc_buffer_size(buffer, *needed)) {
5184 free_printer_driver_info_6(&info);
5185 return WERR_INSUFFICIENT_BUFFER;
5188 /* fill the buffer with the structures */
5189 smb_io_printer_driver_info_6("", buffer, &info, 0);
5191 free_printer_driver_info_6(&info);
5193 if (*needed > offered)
5194 return WERR_INSUFFICIENT_BUFFER;
5196 return WERR_OK;
5199 /****************************************************************************
5200 ****************************************************************************/
5202 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5204 POLICY_HND *handle = &q_u->handle;
5205 UNISTR2 *uni_arch = &q_u->architecture;
5206 uint32 level = q_u->level;
5207 uint32 clientmajorversion = q_u->clientmajorversion;
5208 NEW_BUFFER *buffer = NULL;
5209 uint32 offered = q_u->offered;
5210 uint32 *needed = &r_u->needed;
5211 uint32 *servermajorversion = &r_u->servermajorversion;
5212 uint32 *serverminorversion = &r_u->serverminorversion;
5214 fstring servername;
5215 fstring architecture;
5216 int snum;
5218 /* that's an [in out] buffer */
5219 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5220 buffer = r_u->buffer;
5222 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5224 *needed = 0;
5225 *servermajorversion = 0;
5226 *serverminorversion = 0;
5228 pstrcpy(servername, get_called_name());
5229 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5231 if (!get_printer_snum(p, handle, &snum))
5232 return WERR_BADFID;
5234 switch (level) {
5235 case 1:
5236 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5237 case 2:
5238 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5239 case 3:
5240 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5241 case 6:
5242 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5245 return WERR_UNKNOWN_LEVEL;
5248 /****************************************************************************
5249 ****************************************************************************/
5251 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5253 POLICY_HND *handle = &q_u->handle;
5255 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5257 if (!Printer) {
5258 DEBUG(3,("Error in startpageprinter printer handle\n"));
5259 return WERR_BADFID;
5262 Printer->page_started=True;
5263 return WERR_OK;
5266 /****************************************************************************
5267 ****************************************************************************/
5269 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5271 POLICY_HND *handle = &q_u->handle;
5272 int snum;
5274 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5276 if (!Printer) {
5277 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5278 return WERR_BADFID;
5281 if (!get_printer_snum(p, handle, &snum))
5282 return WERR_BADFID;
5284 Printer->page_started=False;
5285 print_job_endpage(snum, Printer->jobid);
5287 return WERR_OK;
5290 /********************************************************************
5291 * api_spoolss_getprinter
5292 * called from the spoolss dispatcher
5294 ********************************************************************/
5296 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5298 POLICY_HND *handle = &q_u->handle;
5299 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5300 uint32 *jobid = &r_u->jobid;
5302 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5303 int snum;
5304 pstring jobname;
5305 fstring datatype;
5306 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5307 struct current_user user;
5309 if (!Printer) {
5310 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5311 return WERR_BADFID;
5314 get_current_user(&user, p);
5317 * a nice thing with NT is it doesn't listen to what you tell it.
5318 * when asked to send _only_ RAW datas, it tries to send datas
5319 * in EMF format.
5321 * So I add checks like in NT Server ...
5324 if (info_1->p_datatype != 0) {
5325 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5326 if (strcmp(datatype, "RAW") != 0) {
5327 (*jobid)=0;
5328 return WERR_INVALID_DATATYPE;
5332 /* get the share number of the printer */
5333 if (!get_printer_snum(p, handle, &snum)) {
5334 return WERR_BADFID;
5337 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5339 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5341 /* An error occured in print_job_start() so return an appropriate
5342 NT error code. */
5344 if (Printer->jobid == -1) {
5345 return map_werror_from_unix(errno);
5348 Printer->document_started=True;
5349 (*jobid) = Printer->jobid;
5351 return WERR_OK;
5354 /********************************************************************
5355 * api_spoolss_getprinter
5356 * called from the spoolss dispatcher
5358 ********************************************************************/
5360 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5362 POLICY_HND *handle = &q_u->handle;
5364 return _spoolss_enddocprinter_internal(p, handle);
5367 /****************************************************************************
5368 ****************************************************************************/
5370 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5372 POLICY_HND *handle = &q_u->handle;
5373 uint32 buffer_size = q_u->buffer_size;
5374 uint8 *buffer = q_u->buffer;
5375 uint32 *buffer_written = &q_u->buffer_size2;
5376 int snum;
5377 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5379 if (!Printer) {
5380 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5381 r_u->buffer_written = q_u->buffer_size2;
5382 return WERR_BADFID;
5385 if (!get_printer_snum(p, handle, &snum))
5386 return WERR_BADFID;
5388 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5389 if (*buffer_written == -1) {
5390 r_u->buffer_written = 0;
5391 if (errno == ENOSPC)
5392 return WERR_NO_SPOOL_SPACE;
5393 else
5394 return WERR_ACCESS_DENIED;
5397 r_u->buffer_written = q_u->buffer_size2;
5399 return WERR_OK;
5402 /********************************************************************
5403 * api_spoolss_getprinter
5404 * called from the spoolss dispatcher
5406 ********************************************************************/
5408 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5409 pipes_struct *p)
5411 struct current_user user;
5412 int snum;
5413 WERROR errcode = WERR_BADFUNC;
5414 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5416 get_current_user(&user, p);
5418 if (!Printer) {
5419 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5420 return WERR_BADFID;
5423 if (!get_printer_snum(p, handle, &snum))
5424 return WERR_BADFID;
5426 switch (command) {
5427 case PRINTER_CONTROL_PAUSE:
5428 if (print_queue_pause(&user, snum, &errcode)) {
5429 errcode = WERR_OK;
5431 break;
5432 case PRINTER_CONTROL_RESUME:
5433 case PRINTER_CONTROL_UNPAUSE:
5434 if (print_queue_resume(&user, snum, &errcode)) {
5435 errcode = WERR_OK;
5437 break;
5438 #if 0 /* JERRY - Never called */
5439 case PRINTER_CONTROL_PURGE:
5440 if (print_queue_purge(&user, snum, &errcode)) {
5441 errcode = WERR_OK;
5443 break;
5444 #endif
5445 default:
5446 return WERR_UNKNOWN_LEVEL;
5449 return errcode;
5452 /********************************************************************
5453 * api_spoolss_abortprinter
5454 * From MSDN: "Deletes printer's spool file if printer is configured
5455 * for spooling"
5456 ********************************************************************/
5458 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5460 POLICY_HND *handle = &q_u->handle;
5461 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5462 int snum;
5463 struct current_user user;
5464 WERROR errcode = WERR_OK;
5466 if (!Printer) {
5467 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5468 return WERR_BADFID;
5471 if (!get_printer_snum(p, handle, &snum))
5472 return WERR_BADFID;
5474 get_current_user( &user, p );
5476 print_job_delete( &user, snum, Printer->jobid, &errcode );
5478 return errcode;
5481 /********************************************************************
5482 * called by spoolss_api_setprinter
5483 * when updating a printer description
5484 ********************************************************************/
5486 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5487 const SPOOL_PRINTER_INFO_LEVEL *info,
5488 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5490 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5491 struct current_user user;
5492 WERROR result;
5493 int snum;
5495 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5497 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5498 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5499 OUR_HANDLE(handle)));
5501 result = WERR_BADFID;
5502 goto done;
5505 /* NT seems to like setting the security descriptor even though
5506 nothing may have actually changed. This causes annoying
5507 dialog boxes when the user doesn't have permission to change
5508 the security descriptor. */
5510 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5512 if (DEBUGLEVEL >= 10) {
5513 SEC_ACL *the_acl;
5514 int i;
5516 the_acl = old_secdesc_ctr->sec->dacl;
5517 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5518 PRINTERNAME(snum), the_acl->num_aces));
5520 for (i = 0; i < the_acl->num_aces; i++) {
5521 fstring sid_str;
5523 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5525 DEBUG(10, ("%s 0x%08x\n", sid_str,
5526 the_acl->ace[i].info.mask));
5529 the_acl = secdesc_ctr->sec->dacl;
5531 if (the_acl) {
5532 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5533 PRINTERNAME(snum), the_acl->num_aces));
5535 for (i = 0; i < the_acl->num_aces; i++) {
5536 fstring sid_str;
5538 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5540 DEBUG(10, ("%s 0x%08x\n", sid_str,
5541 the_acl->ace[i].info.mask));
5543 } else {
5544 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5548 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5550 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5551 result = WERR_OK;
5552 goto done;
5555 /* Work out which user is performing the operation */
5557 get_current_user(&user, p);
5559 /* Check the user has permissions to change the security
5560 descriptor. By experimentation with two NT machines, the user
5561 requires Full Access to the printer to change security
5562 information. */
5564 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5565 result = WERR_ACCESS_DENIED;
5566 goto done;
5569 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5571 done:
5573 return result;
5576 /********************************************************************
5577 Do Samba sanity checks on a printer info struct.
5578 this has changed purpose: it now "canonicalises" printer
5579 info from a client rather than just checking it is correct
5580 ********************************************************************/
5582 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5584 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5585 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5587 /* we force some elements to "correct" values */
5588 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5589 fstrcpy(info->sharename, lp_servicename(snum));
5590 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5591 get_called_name(), info->sharename);
5592 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5594 return True;
5597 /****************************************************************************
5598 ****************************************************************************/
5600 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5602 extern userdom_struct current_user_info;
5603 char *cmd = lp_addprinter_cmd();
5604 char **qlines;
5605 pstring command;
5606 int numlines;
5607 int ret;
5608 int fd;
5609 fstring remote_machine = "%m";
5611 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5613 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5614 cmd, printer->info_2->printername, printer->info_2->sharename,
5615 printer->info_2->portname, printer->info_2->drivername,
5616 printer->info_2->location, printer->info_2->comment, remote_machine);
5618 DEBUG(10,("Running [%s]\n", command));
5619 ret = smbrun(command, &fd);
5620 DEBUGADD(10,("returned [%d]\n", ret));
5622 if ( ret != 0 ) {
5623 if (fd != -1)
5624 close(fd);
5625 return False;
5628 numlines = 0;
5629 /* Get lines and convert them back to dos-codepage */
5630 qlines = fd_lines_load(fd, &numlines);
5631 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5632 close(fd);
5634 if(numlines) {
5635 /* Set the portname to what the script says the portname should be. */
5636 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5637 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5639 /* Send SIGHUP to process group... is there a better way? */
5640 kill(0, SIGHUP);
5642 /* reload our services immediately */
5643 reload_services( False );
5646 file_lines_free(qlines);
5647 return True;
5650 /********************************************************************
5651 * Called by spoolss_api_setprinter
5652 * when updating a printer description.
5653 ********************************************************************/
5655 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5656 const SPOOL_PRINTER_INFO_LEVEL *info,
5657 DEVICEMODE *devmode)
5659 int snum;
5660 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5661 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5662 WERROR result;
5664 DEBUG(8,("update_printer\n"));
5666 result = WERR_OK;
5668 if (level!=2) {
5669 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5670 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5671 result = WERR_UNKNOWN_LEVEL;
5672 goto done;
5675 if (!Printer) {
5676 result = WERR_BADFID;
5677 goto done;
5680 if (!get_printer_snum(p, handle, &snum)) {
5681 result = WERR_BADFID;
5682 goto done;
5685 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5686 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5687 result = WERR_BADFID;
5688 goto done;
5691 DEBUGADD(8,("Converting info_2 struct\n"));
5694 * convert_printer_info converts the incoming
5695 * info from the client and overwrites the info
5696 * just read from the tdb in the pointer 'printer'.
5699 if (!convert_printer_info(info, printer, level)) {
5700 result = WERR_NOMEM;
5701 goto done;
5704 if (devmode) {
5705 /* we have a valid devmode
5706 convert it and link it*/
5708 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5709 if (!convert_devicemode(printer->info_2->printername, devmode,
5710 &printer->info_2->devmode)) {
5711 result = WERR_NOMEM;
5712 goto done;
5716 * make sure we actually reload the services after
5717 * this as smb.conf could have a new section in it
5718 * .... shouldn't .... but could
5720 reload_services(False);
5723 /* Do sanity check on the requested changes for Samba */
5725 if (!check_printer_ok(printer->info_2, snum)) {
5726 result = WERR_INVALID_PARAM;
5727 goto done;
5730 /* Check calling user has permission to update printer description */
5732 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5733 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5734 result = WERR_ACCESS_DENIED;
5735 goto done;
5738 /* Call addprinter hook */
5740 if (*lp_addprinter_cmd()) {
5741 if ( !add_printer_hook(printer) ) {
5742 result = WERR_ACCESS_DENIED;
5743 goto done;
5748 * When a *new* driver is bound to a printer, the drivername is used to
5749 * lookup previously saved driver initialization info, which is then
5750 * bound to the printer, simulating what happens in the Windows arch.
5752 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5754 if (!set_driver_init(printer, 2))
5756 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5757 printer->info_2->drivername));
5760 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5761 printer->info_2->drivername));
5763 notify_printer_driver(snum, printer->info_2->drivername);
5766 /* Update printer info */
5767 result = mod_a_printer(*printer, 2);
5769 /* flag which changes actually occured. This is a small subset of
5770 all the possible changes */
5772 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5773 notify_printer_comment(snum, printer->info_2->comment);
5775 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5776 notify_printer_sharename(snum, printer->info_2->sharename);
5778 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5779 notify_printer_port(snum, printer->info_2->portname);
5781 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5782 notify_printer_location(snum, printer->info_2->location);
5784 done:
5785 free_a_printer(&printer, 2);
5786 free_a_printer(&old_printer, 2);
5789 return result;
5792 /****************************************************************************
5793 ****************************************************************************/
5795 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5797 POLICY_HND *handle = &q_u->handle;
5798 uint32 level = q_u->level;
5799 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5800 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5801 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5802 uint32 command = q_u->command;
5804 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5806 if (!Printer) {
5807 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5808 return WERR_BADFID;
5811 /* check the level */
5812 switch (level) {
5813 case 0:
5814 return control_printer(handle, command, p);
5815 case 2:
5816 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5817 case 3:
5818 return update_printer_sec(handle, level, info, p,
5819 secdesc_ctr);
5820 default:
5821 return WERR_UNKNOWN_LEVEL;
5825 /****************************************************************************
5826 ****************************************************************************/
5828 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5830 POLICY_HND *handle = &q_u->handle;
5832 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5834 if (!Printer) {
5835 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5836 return WERR_BADFID;
5839 if (Printer->notify.client_connected==True)
5840 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5842 Printer->notify.flags=0;
5843 Printer->notify.options=0;
5844 Printer->notify.localmachine[0]='\0';
5845 Printer->notify.printerlocal=0;
5846 if (Printer->notify.option)
5847 free_spool_notify_option(&Printer->notify.option);
5848 Printer->notify.client_connected=False;
5850 return WERR_OK;
5853 /****************************************************************************
5854 ****************************************************************************/
5856 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5858 /* that's an [in out] buffer (despite appearences to the contrary) */
5859 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5861 r_u->needed = 0;
5862 return WERR_INVALID_PARAM; /* this is what a NT server
5863 returns for AddJob. AddJob
5864 must fail on non-local
5865 printers */
5868 /****************************************************************************
5869 ****************************************************************************/
5871 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5872 int position, int snum)
5874 pstring temp_name;
5876 struct tm *t;
5878 t=gmtime(&queue->time);
5879 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5881 job_info->jobid=queue->job;
5882 init_unistr(&job_info->printername, lp_servicename(snum));
5883 init_unistr(&job_info->machinename, temp_name);
5884 init_unistr(&job_info->username, queue->fs_user);
5885 init_unistr(&job_info->document, queue->fs_file);
5886 init_unistr(&job_info->datatype, "RAW");
5887 init_unistr(&job_info->text_status, "");
5888 job_info->status=nt_printj_status(queue->status);
5889 job_info->priority=queue->priority;
5890 job_info->position=position;
5891 job_info->totalpages=queue->page_count;
5892 job_info->pagesprinted=0;
5894 make_systemtime(&job_info->submitted, t);
5897 /****************************************************************************
5898 ****************************************************************************/
5900 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5901 int position, int snum,
5902 NT_PRINTER_INFO_LEVEL *ntprinter,
5903 DEVICEMODE *devmode)
5905 pstring temp_name;
5906 pstring chaine;
5907 struct tm *t;
5909 t=gmtime(&queue->time);
5910 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5912 job_info->jobid=queue->job;
5914 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5916 init_unistr(&job_info->printername, chaine);
5918 init_unistr(&job_info->machinename, temp_name);
5919 init_unistr(&job_info->username, queue->fs_user);
5920 init_unistr(&job_info->document, queue->fs_file);
5921 init_unistr(&job_info->notifyname, queue->fs_user);
5922 init_unistr(&job_info->datatype, "RAW");
5923 init_unistr(&job_info->printprocessor, "winprint");
5924 init_unistr(&job_info->parameters, "");
5925 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5926 init_unistr(&job_info->text_status, "");
5928 /* and here the security descriptor */
5930 job_info->status=nt_printj_status(queue->status);
5931 job_info->priority=queue->priority;
5932 job_info->position=position;
5933 job_info->starttime=0;
5934 job_info->untiltime=0;
5935 job_info->totalpages=queue->page_count;
5936 job_info->size=queue->size;
5937 make_systemtime(&(job_info->submitted), t);
5938 job_info->timeelapsed=0;
5939 job_info->pagesprinted=0;
5941 job_info->devmode = devmode;
5943 return (True);
5946 /****************************************************************************
5947 Enumjobs at level 1.
5948 ****************************************************************************/
5950 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5951 NEW_BUFFER *buffer, uint32 offered,
5952 uint32 *needed, uint32 *returned)
5954 JOB_INFO_1 *info;
5955 int i;
5957 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5958 if (info==NULL) {
5959 SAFE_FREE(queue);
5960 *returned=0;
5961 return WERR_NOMEM;
5964 for (i=0; i<*returned; i++)
5965 fill_job_info_1(&info[i], &queue[i], i, snum);
5967 SAFE_FREE(queue);
5969 /* check the required size. */
5970 for (i=0; i<*returned; i++)
5971 (*needed) += spoolss_size_job_info_1(&info[i]);
5973 if (!alloc_buffer_size(buffer, *needed)) {
5974 SAFE_FREE(info);
5975 return WERR_INSUFFICIENT_BUFFER;
5978 /* fill the buffer with the structures */
5979 for (i=0; i<*returned; i++)
5980 smb_io_job_info_1("", buffer, &info[i], 0);
5982 /* clear memory */
5983 SAFE_FREE(info);
5985 if (*needed > offered) {
5986 *returned=0;
5987 return WERR_INSUFFICIENT_BUFFER;
5990 return WERR_OK;
5993 /****************************************************************************
5994 Enumjobs at level 2.
5995 ****************************************************************************/
5997 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5998 NEW_BUFFER *buffer, uint32 offered,
5999 uint32 *needed, uint32 *returned)
6001 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6002 JOB_INFO_2 *info = NULL;
6003 int i;
6004 WERROR result;
6005 DEVICEMODE *devmode = NULL;
6007 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6008 if (info==NULL) {
6009 *returned=0;
6010 result = WERR_NOMEM;
6011 goto done;
6014 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6015 if (!W_ERROR_IS_OK(result)) {
6016 *returned = 0;
6017 goto done;
6020 /* this should not be a failure condition if the devmode is NULL */
6022 devmode = construct_dev_mode(snum);
6024 for (i=0; i<*returned; i++)
6025 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6026 devmode);
6028 free_a_printer(&ntprinter, 2);
6029 SAFE_FREE(queue);
6031 /* check the required size. */
6032 for (i=0; i<*returned; i++)
6033 (*needed) += spoolss_size_job_info_2(&info[i]);
6035 if (*needed > offered) {
6036 *returned=0;
6037 result = WERR_INSUFFICIENT_BUFFER;
6038 goto done;
6041 if (!alloc_buffer_size(buffer, *needed)) {
6042 SAFE_FREE(info);
6043 result = WERR_INSUFFICIENT_BUFFER;
6044 goto done;
6047 /* fill the buffer with the structures */
6048 for (i=0; i<*returned; i++)
6049 smb_io_job_info_2("", buffer, &info[i], 0);
6051 result = WERR_OK;
6053 done:
6054 free_a_printer(&ntprinter, 2);
6055 free_devmode(devmode);
6056 SAFE_FREE(queue);
6057 SAFE_FREE(info);
6059 return result;
6063 /****************************************************************************
6064 Enumjobs.
6065 ****************************************************************************/
6067 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6069 POLICY_HND *handle = &q_u->handle;
6070 uint32 level = q_u->level;
6071 NEW_BUFFER *buffer = NULL;
6072 uint32 offered = q_u->offered;
6073 uint32 *needed = &r_u->needed;
6074 uint32 *returned = &r_u->returned;
6076 int snum;
6077 print_status_struct prt_status;
6078 print_queue_struct *queue=NULL;
6080 /* that's an [in out] buffer */
6081 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6082 buffer = r_u->buffer;
6084 DEBUG(4,("_spoolss_enumjobs\n"));
6086 *needed=0;
6087 *returned=0;
6089 if (!get_printer_snum(p, handle, &snum))
6090 return WERR_BADFID;
6092 *returned = print_queue_status(snum, &queue, &prt_status);
6093 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6095 if (*returned == 0) {
6096 SAFE_FREE(queue);
6097 return WERR_OK;
6100 switch (level) {
6101 case 1:
6102 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6103 case 2:
6104 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6105 default:
6106 SAFE_FREE(queue);
6107 *returned=0;
6108 return WERR_UNKNOWN_LEVEL;
6112 /****************************************************************************
6113 ****************************************************************************/
6115 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6117 return WERR_OK;
6120 /****************************************************************************
6121 ****************************************************************************/
6123 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6125 POLICY_HND *handle = &q_u->handle;
6126 uint32 jobid = q_u->jobid;
6127 uint32 command = q_u->command;
6129 struct current_user user;
6130 int snum;
6131 WERROR errcode = WERR_BADFUNC;
6133 if (!get_printer_snum(p, handle, &snum)) {
6134 return WERR_BADFID;
6137 if (!print_job_exists(snum, jobid)) {
6138 return WERR_INVALID_PRINTER_NAME;
6141 get_current_user(&user, p);
6143 switch (command) {
6144 case JOB_CONTROL_CANCEL:
6145 case JOB_CONTROL_DELETE:
6146 if (print_job_delete(&user, snum, jobid, &errcode)) {
6147 errcode = WERR_OK;
6149 break;
6150 case JOB_CONTROL_PAUSE:
6151 if (print_job_pause(&user, snum, jobid, &errcode)) {
6152 errcode = WERR_OK;
6154 break;
6155 case JOB_CONTROL_RESTART:
6156 case JOB_CONTROL_RESUME:
6157 if (print_job_resume(&user, snum, jobid, &errcode)) {
6158 errcode = WERR_OK;
6160 break;
6161 default:
6162 return WERR_UNKNOWN_LEVEL;
6165 return errcode;
6168 /****************************************************************************
6169 Enumerates all printer drivers at level 1.
6170 ****************************************************************************/
6172 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6174 int i;
6175 int ndrivers;
6176 uint32 version;
6177 fstring *list = NULL;
6179 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6180 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6182 *returned=0;
6184 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6185 list=NULL;
6186 ndrivers=get_ntdrivers(&list, architecture, version);
6187 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6189 if(ndrivers == -1)
6190 return WERR_NOMEM;
6192 if(ndrivers != 0) {
6193 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6194 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6195 SAFE_FREE(driver_info_1);
6196 SAFE_FREE(list);
6197 return WERR_NOMEM;
6199 else driver_info_1 = tdi1;
6202 for (i=0; i<ndrivers; i++) {
6203 WERROR status;
6204 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6205 ZERO_STRUCT(driver);
6206 status = get_a_printer_driver(&driver, 3, list[i],
6207 architecture, version);
6208 if (!W_ERROR_IS_OK(status)) {
6209 SAFE_FREE(list);
6210 return status;
6212 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6213 free_a_printer_driver(driver, 3);
6216 *returned+=ndrivers;
6217 SAFE_FREE(list);
6220 /* check the required size. */
6221 for (i=0; i<*returned; i++) {
6222 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6223 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6226 if (!alloc_buffer_size(buffer, *needed)) {
6227 SAFE_FREE(driver_info_1);
6228 return WERR_INSUFFICIENT_BUFFER;
6231 /* fill the buffer with the driver structures */
6232 for (i=0; i<*returned; i++) {
6233 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6234 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6237 SAFE_FREE(driver_info_1);
6239 if (*needed > offered) {
6240 *returned=0;
6241 return WERR_INSUFFICIENT_BUFFER;
6244 return WERR_OK;
6247 /****************************************************************************
6248 Enumerates all printer drivers at level 2.
6249 ****************************************************************************/
6251 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6253 int i;
6254 int ndrivers;
6255 uint32 version;
6256 fstring *list = NULL;
6258 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6259 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6261 *returned=0;
6263 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6264 list=NULL;
6265 ndrivers=get_ntdrivers(&list, architecture, version);
6266 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6268 if(ndrivers == -1)
6269 return WERR_NOMEM;
6271 if(ndrivers != 0) {
6272 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6273 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6274 SAFE_FREE(driver_info_2);
6275 SAFE_FREE(list);
6276 return WERR_NOMEM;
6278 else driver_info_2 = tdi2;
6281 for (i=0; i<ndrivers; i++) {
6282 WERROR status;
6284 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6285 ZERO_STRUCT(driver);
6286 status = get_a_printer_driver(&driver, 3, list[i],
6287 architecture, version);
6288 if (!W_ERROR_IS_OK(status)) {
6289 SAFE_FREE(list);
6290 return status;
6292 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6293 free_a_printer_driver(driver, 3);
6296 *returned+=ndrivers;
6297 SAFE_FREE(list);
6300 /* check the required size. */
6301 for (i=0; i<*returned; i++) {
6302 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6303 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6306 if (!alloc_buffer_size(buffer, *needed)) {
6307 SAFE_FREE(driver_info_2);
6308 return WERR_INSUFFICIENT_BUFFER;
6311 /* fill the buffer with the form structures */
6312 for (i=0; i<*returned; i++) {
6313 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6314 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6317 SAFE_FREE(driver_info_2);
6319 if (*needed > offered) {
6320 *returned=0;
6321 return WERR_INSUFFICIENT_BUFFER;
6324 return WERR_OK;
6327 /****************************************************************************
6328 Enumerates all printer drivers at level 3.
6329 ****************************************************************************/
6331 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6333 int i;
6334 int ndrivers;
6335 uint32 version;
6336 fstring *list = NULL;
6338 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6339 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6341 *returned=0;
6343 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6344 list=NULL;
6345 ndrivers=get_ntdrivers(&list, architecture, version);
6346 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6348 if(ndrivers == -1)
6349 return WERR_NOMEM;
6351 if(ndrivers != 0) {
6352 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6353 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6354 SAFE_FREE(driver_info_3);
6355 SAFE_FREE(list);
6356 return WERR_NOMEM;
6358 else driver_info_3 = tdi3;
6361 for (i=0; i<ndrivers; i++) {
6362 WERROR status;
6364 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6365 ZERO_STRUCT(driver);
6366 status = get_a_printer_driver(&driver, 3, list[i],
6367 architecture, version);
6368 if (!W_ERROR_IS_OK(status)) {
6369 SAFE_FREE(list);
6370 return status;
6372 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6373 free_a_printer_driver(driver, 3);
6376 *returned+=ndrivers;
6377 SAFE_FREE(list);
6380 /* check the required size. */
6381 for (i=0; i<*returned; i++) {
6382 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6383 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6386 if (!alloc_buffer_size(buffer, *needed)) {
6387 SAFE_FREE(driver_info_3);
6388 return WERR_INSUFFICIENT_BUFFER;
6391 /* fill the buffer with the driver structures */
6392 for (i=0; i<*returned; i++) {
6393 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6394 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6397 for (i=0; i<*returned; i++)
6398 SAFE_FREE(driver_info_3[i].dependentfiles);
6400 SAFE_FREE(driver_info_3);
6402 if (*needed > offered) {
6403 *returned=0;
6404 return WERR_INSUFFICIENT_BUFFER;
6407 return WERR_OK;
6410 /****************************************************************************
6411 Enumerates all printer drivers.
6412 ****************************************************************************/
6414 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6416 UNISTR2 *environment = &q_u->environment;
6417 uint32 level = q_u->level;
6418 NEW_BUFFER *buffer = NULL;
6419 uint32 offered = q_u->offered;
6420 uint32 *needed = &r_u->needed;
6421 uint32 *returned = &r_u->returned;
6423 fstring *list = NULL;
6424 fstring servername;
6425 fstring architecture;
6427 /* that's an [in out] buffer */
6428 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6429 buffer = r_u->buffer;
6431 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6432 fstrcpy(servername, get_called_name());
6433 *needed=0;
6434 *returned=0;
6436 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6438 switch (level) {
6439 case 1:
6440 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6441 case 2:
6442 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6443 case 3:
6444 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6445 default:
6446 *returned=0;
6447 SAFE_FREE(list);
6448 return WERR_UNKNOWN_LEVEL;
6452 /****************************************************************************
6453 ****************************************************************************/
6455 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6457 form->flag=list->flag;
6458 init_unistr(&form->name, list->name);
6459 form->width=list->width;
6460 form->length=list->length;
6461 form->left=list->left;
6462 form->top=list->top;
6463 form->right=list->right;
6464 form->bottom=list->bottom;
6467 /****************************************************************************
6468 ****************************************************************************/
6470 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6472 uint32 level = q_u->level;
6473 NEW_BUFFER *buffer = NULL;
6474 uint32 offered = q_u->offered;
6475 uint32 *needed = &r_u->needed;
6476 uint32 *numofforms = &r_u->numofforms;
6477 uint32 numbuiltinforms;
6479 nt_forms_struct *list=NULL;
6480 nt_forms_struct *builtinlist=NULL;
6481 FORM_1 *forms_1;
6482 int buffer_size=0;
6483 int i;
6485 /* that's an [in out] buffer */
6486 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6487 buffer = r_u->buffer;
6489 DEBUG(4,("_spoolss_enumforms\n"));
6490 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6491 DEBUGADD(5,("Info level [%d]\n", level));
6493 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6494 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6495 *numofforms = get_ntforms(&list);
6496 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6497 *numofforms += numbuiltinforms;
6499 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6501 switch (level) {
6502 case 1:
6503 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6504 *numofforms=0;
6505 return WERR_NOMEM;
6508 /* construct the list of form structures */
6509 for (i=0; i<numbuiltinforms; i++) {
6510 DEBUGADD(6,("Filling form number [%d]\n",i));
6511 fill_form_1(&forms_1[i], &builtinlist[i]);
6514 SAFE_FREE(builtinlist);
6516 for (; i<*numofforms; i++) {
6517 DEBUGADD(6,("Filling form number [%d]\n",i));
6518 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6521 SAFE_FREE(list);
6523 /* check the required size. */
6524 for (i=0; i<numbuiltinforms; i++) {
6525 DEBUGADD(6,("adding form [%d]'s size\n",i));
6526 buffer_size += spoolss_size_form_1(&forms_1[i]);
6528 for (; i<*numofforms; i++) {
6529 DEBUGADD(6,("adding form [%d]'s size\n",i));
6530 buffer_size += spoolss_size_form_1(&forms_1[i]);
6533 *needed=buffer_size;
6535 if (!alloc_buffer_size(buffer, buffer_size)){
6536 SAFE_FREE(forms_1);
6537 return WERR_INSUFFICIENT_BUFFER;
6540 /* fill the buffer with the form structures */
6541 for (i=0; i<numbuiltinforms; i++) {
6542 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6543 smb_io_form_1("", buffer, &forms_1[i], 0);
6545 for (; i<*numofforms; i++) {
6546 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6547 smb_io_form_1("", buffer, &forms_1[i], 0);
6550 SAFE_FREE(forms_1);
6552 if (*needed > offered) {
6553 *numofforms=0;
6554 return WERR_INSUFFICIENT_BUFFER;
6556 else
6557 return WERR_OK;
6559 default:
6560 SAFE_FREE(list);
6561 SAFE_FREE(builtinlist);
6562 return WERR_UNKNOWN_LEVEL;
6567 /****************************************************************************
6568 ****************************************************************************/
6570 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6572 uint32 level = q_u->level;
6573 UNISTR2 *uni_formname = &q_u->formname;
6574 NEW_BUFFER *buffer = NULL;
6575 uint32 offered = q_u->offered;
6576 uint32 *needed = &r_u->needed;
6578 nt_forms_struct *list=NULL;
6579 nt_forms_struct builtin_form;
6580 BOOL foundBuiltin;
6581 FORM_1 form_1;
6582 fstring form_name;
6583 int buffer_size=0;
6584 int numofforms=0, i=0;
6586 /* that's an [in out] buffer */
6587 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6588 buffer = r_u->buffer;
6590 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6592 DEBUG(4,("_spoolss_getform\n"));
6593 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6594 DEBUGADD(5,("Info level [%d]\n", level));
6596 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6597 if (!foundBuiltin) {
6598 numofforms = get_ntforms(&list);
6599 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6601 if (numofforms == 0)
6602 return WERR_BADFID;
6605 switch (level) {
6606 case 1:
6607 if (foundBuiltin) {
6608 fill_form_1(&form_1, &builtin_form);
6609 } else {
6611 /* Check if the requested name is in the list of form structures */
6612 for (i=0; i<numofforms; i++) {
6614 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6616 if (strequal(form_name, list[i].name)) {
6617 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6618 fill_form_1(&form_1, &list[i]);
6619 break;
6623 SAFE_FREE(list);
6624 if (i == numofforms) {
6625 return WERR_BADFID;
6628 /* check the required size. */
6630 *needed=spoolss_size_form_1(&form_1);
6632 if (!alloc_buffer_size(buffer, buffer_size)){
6633 return WERR_INSUFFICIENT_BUFFER;
6636 if (*needed > offered) {
6637 return WERR_INSUFFICIENT_BUFFER;
6640 /* fill the buffer with the form structures */
6641 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6642 smb_io_form_1("", buffer, &form_1, 0);
6644 return WERR_OK;
6646 default:
6647 SAFE_FREE(list);
6648 return WERR_UNKNOWN_LEVEL;
6652 /****************************************************************************
6653 ****************************************************************************/
6655 static void fill_port_1(PORT_INFO_1 *port, char *name)
6657 init_unistr(&port->port_name, name);
6660 /****************************************************************************
6661 ****************************************************************************/
6663 static void fill_port_2(PORT_INFO_2 *port, char *name)
6665 init_unistr(&port->port_name, name);
6666 init_unistr(&port->monitor_name, "Local Monitor");
6667 init_unistr(&port->description, "Local Port");
6668 #define PORT_TYPE_WRITE 1
6669 port->port_type=PORT_TYPE_WRITE;
6670 port->reserved=0x0;
6673 /****************************************************************************
6674 enumports level 1.
6675 ****************************************************************************/
6677 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6679 PORT_INFO_1 *ports=NULL;
6680 int i=0;
6682 if (*lp_enumports_cmd()) {
6683 char *cmd = lp_enumports_cmd();
6684 char **qlines;
6685 pstring command;
6686 int numlines;
6687 int ret;
6688 int fd;
6690 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6692 DEBUG(10,("Running [%s]\n", command));
6693 ret = smbrun(command, &fd);
6694 DEBUG(10,("Returned [%d]\n", ret));
6695 if (ret != 0) {
6696 if (fd != -1)
6697 close(fd);
6698 /* Is this the best error to return here? */
6699 return WERR_ACCESS_DENIED;
6702 numlines = 0;
6703 qlines = fd_lines_load(fd, &numlines);
6704 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6705 close(fd);
6707 if(numlines) {
6708 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6709 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6710 dos_errstr(WERR_NOMEM)));
6711 file_lines_free(qlines);
6712 return WERR_NOMEM;
6715 for (i=0; i<numlines; i++) {
6716 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6717 fill_port_1(&ports[i], qlines[i]);
6720 file_lines_free(qlines);
6723 *returned = numlines;
6725 } else {
6726 *returned = 1; /* Sole Samba port returned. */
6728 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6729 return WERR_NOMEM;
6731 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6733 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6736 /* check the required size. */
6737 for (i=0; i<*returned; i++) {
6738 DEBUGADD(6,("adding port [%d]'s size\n", i));
6739 *needed += spoolss_size_port_info_1(&ports[i]);
6742 if (!alloc_buffer_size(buffer, *needed)) {
6743 SAFE_FREE(ports);
6744 return WERR_INSUFFICIENT_BUFFER;
6747 /* fill the buffer with the ports structures */
6748 for (i=0; i<*returned; i++) {
6749 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6750 smb_io_port_1("", buffer, &ports[i], 0);
6753 SAFE_FREE(ports);
6755 if (*needed > offered) {
6756 *returned=0;
6757 return WERR_INSUFFICIENT_BUFFER;
6760 return WERR_OK;
6763 /****************************************************************************
6764 enumports level 2.
6765 ****************************************************************************/
6767 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6769 PORT_INFO_2 *ports=NULL;
6770 int i=0;
6772 if (*lp_enumports_cmd()) {
6773 char *cmd = lp_enumports_cmd();
6774 char *path;
6775 char **qlines;
6776 pstring tmp_file;
6777 pstring command;
6778 int numlines;
6779 int ret;
6780 int fd;
6782 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6783 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6784 else
6785 path = lp_lockdir();
6787 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6788 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6790 unlink(tmp_file);
6791 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6792 ret = smbrun(command, &fd);
6793 DEBUGADD(10,("returned [%d]\n", ret));
6794 if (ret != 0) {
6795 if (fd != -1)
6796 close(fd);
6797 /* Is this the best error to return here? */
6798 return WERR_ACCESS_DENIED;
6801 numlines = 0;
6802 qlines = fd_lines_load(fd, &numlines);
6803 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6804 close(fd);
6806 if(numlines) {
6807 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6808 file_lines_free(qlines);
6809 return WERR_NOMEM;
6812 for (i=0; i<numlines; i++) {
6813 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6814 fill_port_2(&(ports[i]), qlines[i]);
6817 file_lines_free(qlines);
6820 *returned = numlines;
6822 } else {
6824 *returned = 1;
6826 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6827 return WERR_NOMEM;
6829 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6831 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6834 /* check the required size. */
6835 for (i=0; i<*returned; i++) {
6836 DEBUGADD(6,("adding port [%d]'s size\n", i));
6837 *needed += spoolss_size_port_info_2(&ports[i]);
6840 if (!alloc_buffer_size(buffer, *needed)) {
6841 SAFE_FREE(ports);
6842 return WERR_INSUFFICIENT_BUFFER;
6845 /* fill the buffer with the ports structures */
6846 for (i=0; i<*returned; i++) {
6847 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6848 smb_io_port_2("", buffer, &ports[i], 0);
6851 SAFE_FREE(ports);
6853 if (*needed > offered) {
6854 *returned=0;
6855 return WERR_INSUFFICIENT_BUFFER;
6858 return WERR_OK;
6861 /****************************************************************************
6862 enumports.
6863 ****************************************************************************/
6865 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6867 uint32 level = q_u->level;
6868 NEW_BUFFER *buffer = NULL;
6869 uint32 offered = q_u->offered;
6870 uint32 *needed = &r_u->needed;
6871 uint32 *returned = &r_u->returned;
6873 /* that's an [in out] buffer */
6874 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6875 buffer = r_u->buffer;
6877 DEBUG(4,("_spoolss_enumports\n"));
6879 *returned=0;
6880 *needed=0;
6882 switch (level) {
6883 case 1:
6884 return enumports_level_1(buffer, offered, needed, returned);
6885 case 2:
6886 return enumports_level_2(buffer, offered, needed, returned);
6887 default:
6888 return WERR_UNKNOWN_LEVEL;
6892 /****************************************************************************
6893 ****************************************************************************/
6895 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6896 const SPOOL_PRINTER_INFO_LEVEL *info,
6897 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6898 uint32 user_switch, const SPOOL_USER_CTR *user,
6899 POLICY_HND *handle)
6901 NT_PRINTER_INFO_LEVEL *printer = NULL;
6902 fstring name;
6903 int snum;
6904 WERROR err = WERR_OK;
6906 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6907 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6908 return WERR_NOMEM;
6911 ZERO_STRUCTP(printer);
6913 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6914 if (!convert_printer_info(info, printer, 2)) {
6915 free_a_printer(&printer, 2);
6916 return WERR_NOMEM;
6919 /* check to see if the printer already exists */
6921 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6922 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6923 printer->info_2->sharename));
6924 free_a_printer(&printer, 2);
6925 return WERR_PRINTER_ALREADY_EXISTS;
6928 if (*lp_addprinter_cmd() ) {
6929 if ( !add_printer_hook(printer) ) {
6930 free_a_printer(&printer,2);
6931 return WERR_ACCESS_DENIED;
6935 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6936 printer->info_2->sharename);
6939 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6940 free_a_printer(&printer,2);
6941 return WERR_ACCESS_DENIED;
6944 /* you must be a printer admin to add a new printer */
6945 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6946 free_a_printer(&printer,2);
6947 return WERR_ACCESS_DENIED;
6951 * Do sanity check on the requested changes for Samba.
6954 if (!check_printer_ok(printer->info_2, snum)) {
6955 free_a_printer(&printer,2);
6956 return WERR_INVALID_PARAM;
6960 * When a printer is created, the drivername bound to the printer is used
6961 * to lookup previously saved driver initialization info, which is then
6962 * bound to the new printer, simulating what happens in the Windows arch.
6965 if (!devmode)
6967 set_driver_init(printer, 2);
6969 else
6971 /* A valid devmode was included, convert and link it
6973 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6975 if (!convert_devicemode(printer->info_2->printername, devmode,
6976 &printer->info_2->devmode))
6977 return WERR_NOMEM;
6980 /* write the ASCII on disk */
6981 err = mod_a_printer(*printer, 2);
6982 if (!W_ERROR_IS_OK(err)) {
6983 free_a_printer(&printer,2);
6984 return err;
6987 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6988 /* Handle open failed - remove addition. */
6989 del_a_printer(printer->info_2->sharename);
6990 free_a_printer(&printer,2);
6991 return WERR_ACCESS_DENIED;
6994 update_c_setprinter(False);
6995 free_a_printer(&printer,2);
6997 return WERR_OK;
7000 /****************************************************************************
7001 ****************************************************************************/
7003 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7005 UNISTR2 *uni_srv_name = &q_u->server_name;
7006 uint32 level = q_u->level;
7007 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7008 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7009 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7010 uint32 user_switch = q_u->user_switch;
7011 SPOOL_USER_CTR *user = &q_u->user_ctr;
7012 POLICY_HND *handle = &r_u->handle;
7014 switch (level) {
7015 case 1:
7016 /* we don't handle yet */
7017 /* but I know what to do ... */
7018 return WERR_UNKNOWN_LEVEL;
7019 case 2:
7020 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7021 devmode, sdb,
7022 user_switch, user, handle);
7023 default:
7024 return WERR_UNKNOWN_LEVEL;
7028 /****************************************************************************
7029 ****************************************************************************/
7031 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7033 uint32 level = q_u->level;
7034 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7035 WERROR err = WERR_OK;
7036 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7037 struct current_user user;
7038 fstring driver_name;
7039 uint32 version;
7041 ZERO_STRUCT(driver);
7043 get_current_user(&user, p);
7045 if (!convert_printer_driver_info(info, &driver, level)) {
7046 err = WERR_NOMEM;
7047 goto done;
7050 DEBUG(5,("Cleaning driver's information\n"));
7051 err = clean_up_driver_struct(driver, level, &user);
7052 if (!W_ERROR_IS_OK(err))
7053 goto done;
7055 DEBUG(5,("Moving driver to final destination\n"));
7056 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7057 if (W_ERROR_IS_OK(err))
7058 err = WERR_ACCESS_DENIED;
7059 goto done;
7062 if (add_a_printer_driver(driver, level)!=0) {
7063 err = WERR_ACCESS_DENIED;
7064 goto done;
7067 /* BEGIN_ADMIN_LOG */
7068 switch(level) {
7069 case 3:
7070 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7071 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7072 fstrcpy(driver_name, driver.info_3->name);
7073 break;
7074 case 6:
7075 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7076 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7077 fstrcpy(driver_name, driver.info_6->name);
7078 break;
7080 /* END_ADMIN_LOG */
7083 * I think this is where he DrvUpgradePrinter() hook would be
7084 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7085 * server. Right now, we just need to send ourselves a message
7086 * to update each printer bound to this driver. --jerry
7089 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7090 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7091 driver_name));
7095 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7096 * decide if the driver init data should be deleted. The rules are:
7097 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7098 * 2) delete init data only if there is no 2k/Xp driver
7099 * 3) always delete init data
7100 * The generalized rule is always use init data from the highest order driver.
7101 * It is necessary to follow the driver install by an initialization step to
7102 * finish off this process.
7104 if (level == 3)
7105 version = driver.info_3->cversion;
7106 else if (level == 6)
7107 version = driver.info_6->version;
7108 else
7109 version = -1;
7110 switch (version) {
7112 * 9x printer driver - never delete init data
7114 case 0:
7115 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7116 driver_name));
7117 break;
7120 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7121 * there is no 2k/Xp driver init data for this driver name.
7123 case 2:
7125 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7127 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7129 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7131 if (!del_driver_init(driver_name))
7132 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7133 } else {
7135 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7137 free_a_printer_driver(driver1,3);
7138 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7139 driver_name));
7142 break;
7145 * 2k or Xp printer driver - always delete init data
7147 case 3:
7148 if (!del_driver_init(driver_name))
7149 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7150 break;
7152 default:
7153 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7154 break;
7158 done:
7159 free_a_printer_driver(driver, level);
7160 return err;
7163 /********************************************************************
7164 * spoolss_addprinterdriverex
7165 ********************************************************************/
7167 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7169 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7170 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7173 * we only support the semantics of AddPrinterDriver()
7174 * i.e. only copy files that are newer than existing ones
7177 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7178 return WERR_ACCESS_DENIED;
7180 ZERO_STRUCT(q_u_local);
7181 ZERO_STRUCT(r_u_local);
7183 /* just pass the information off to _spoolss_addprinterdriver() */
7184 q_u_local.server_name_ptr = q_u->server_name_ptr;
7185 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7186 q_u_local.level = q_u->level;
7187 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7189 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7192 /****************************************************************************
7193 ****************************************************************************/
7195 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7197 init_unistr(&info->name, name);
7200 /****************************************************************************
7201 ****************************************************************************/
7203 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7205 pstring path;
7206 pstring long_archi;
7207 pstring short_archi;
7208 DRIVER_DIRECTORY_1 *info=NULL;
7210 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7212 if (get_short_archi(short_archi, long_archi)==False)
7213 return WERR_INVALID_ENVIRONMENT;
7215 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7216 return WERR_NOMEM;
7218 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7220 DEBUG(4,("printer driver directory: [%s]\n", path));
7222 fill_driverdir_1(info, path);
7224 *needed += spoolss_size_driverdir_info_1(info);
7226 if (!alloc_buffer_size(buffer, *needed)) {
7227 SAFE_FREE(info);
7228 return WERR_INSUFFICIENT_BUFFER;
7231 smb_io_driverdir_1("", buffer, info, 0);
7233 SAFE_FREE(info);
7235 if (*needed > offered)
7236 return WERR_INSUFFICIENT_BUFFER;
7238 return WERR_OK;
7241 /****************************************************************************
7242 ****************************************************************************/
7244 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7246 UNISTR2 *name = &q_u->name;
7247 UNISTR2 *uni_environment = &q_u->environment;
7248 uint32 level = q_u->level;
7249 NEW_BUFFER *buffer = NULL;
7250 uint32 offered = q_u->offered;
7251 uint32 *needed = &r_u->needed;
7253 /* that's an [in out] buffer */
7254 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7255 buffer = r_u->buffer;
7257 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7259 *needed=0;
7261 switch(level) {
7262 case 1:
7263 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7264 default:
7265 return WERR_UNKNOWN_LEVEL;
7269 /****************************************************************************
7270 ****************************************************************************/
7272 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7274 POLICY_HND *handle = &q_u->handle;
7275 uint32 idx = q_u->index;
7276 uint32 in_value_len = q_u->valuesize;
7277 uint32 in_data_len = q_u->datasize;
7278 uint32 *out_max_value_len = &r_u->valuesize;
7279 uint16 **out_value = &r_u->value;
7280 uint32 *out_value_len = &r_u->realvaluesize;
7281 uint32 *out_type = &r_u->type;
7282 uint32 *out_max_data_len = &r_u->datasize;
7283 uint8 **data_out = &r_u->data;
7284 uint32 *out_data_len = &r_u->realdatasize;
7286 NT_PRINTER_INFO_LEVEL *printer = NULL;
7288 uint32 param_index;
7289 uint32 biggest_valuesize;
7290 uint32 biggest_datasize;
7291 uint32 data_len;
7292 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7293 int snum;
7294 WERROR result;
7295 REGISTRY_VALUE *val;
7296 NT_PRINTER_DATA *p_data;
7297 int i, key_index, num_values;
7298 int name_length;
7300 ZERO_STRUCT( printer );
7302 *out_type = 0;
7304 *out_max_data_len = 0;
7305 *data_out = NULL;
7306 *out_data_len = 0;
7308 DEBUG(5,("spoolss_enumprinterdata\n"));
7310 if (!Printer) {
7311 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7312 return WERR_BADFID;
7315 if (!get_printer_snum(p,handle, &snum))
7316 return WERR_BADFID;
7318 result = get_a_printer(&printer, 2, lp_servicename(snum));
7319 if (!W_ERROR_IS_OK(result))
7320 return result;
7322 p_data = &printer->info_2->data;
7323 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7325 result = WERR_OK;
7328 * The NT machine wants to know the biggest size of value and data
7330 * cf: MSDN EnumPrinterData remark section
7333 if ( !in_value_len && !in_data_len )
7335 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7337 param_index = 0;
7338 biggest_valuesize = 0;
7339 biggest_datasize = 0;
7341 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7343 for ( i=0; i<num_values; i++ )
7345 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7347 name_length = strlen(val->valuename);
7348 if ( strlen(val->valuename) > biggest_valuesize )
7349 biggest_valuesize = name_length;
7351 if ( val->size > biggest_datasize )
7352 biggest_datasize = val->size;
7354 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7355 biggest_datasize));
7358 /* the value is an UNICODE string but real_value_size is the length
7359 in bytes including the trailing 0 */
7361 *out_value_len = 2 * (1+biggest_valuesize);
7362 *out_data_len = biggest_datasize;
7364 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7366 goto done;
7370 * the value len is wrong in NT sp3
7371 * that's the number of bytes not the number of unicode chars
7374 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7376 if ( !val )
7379 /* out_value should default to "" or else NT4 has
7380 problems unmarshalling the response */
7382 *out_max_value_len = (in_value_len/sizeof(uint16));
7384 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7386 result = WERR_NOMEM;
7387 goto done;
7390 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7392 /* the data is counted in bytes */
7394 *out_max_data_len = in_data_len;
7395 *out_data_len = in_data_len;
7397 /* only allocate when given a non-zero data_len */
7399 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7401 result = WERR_NOMEM;
7402 goto done;
7405 result = WERR_NO_MORE_ITEMS;
7407 else
7410 * the value is:
7411 * - counted in bytes in the request
7412 * - counted in UNICODE chars in the max reply
7413 * - counted in bytes in the real size
7415 * take a pause *before* coding not *during* coding
7418 /* name */
7419 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7420 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7422 result = WERR_NOMEM;
7423 goto done;
7426 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7428 /* type */
7430 *out_type = regval_type( val );
7432 /* data - counted in bytes */
7434 *out_max_data_len = in_data_len;
7435 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7437 result = WERR_NOMEM;
7438 goto done;
7440 data_len = (size_t)regval_size(val);
7441 memcpy( *data_out, regval_data_p(val), data_len );
7442 *out_data_len = data_len;
7445 done:
7446 free_a_printer(&printer, 2);
7447 return result;
7450 /****************************************************************************
7451 ****************************************************************************/
7453 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7455 POLICY_HND *handle = &q_u->handle;
7456 UNISTR2 *value = &q_u->value;
7457 uint32 type = q_u->type;
7458 uint8 *data = q_u->data;
7459 uint32 real_len = q_u->real_len;
7461 NT_PRINTER_INFO_LEVEL *printer = NULL;
7462 int snum=0;
7463 WERROR status = WERR_OK;
7464 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7465 fstring valuename;
7467 DEBUG(5,("spoolss_setprinterdata\n"));
7469 if (!Printer) {
7470 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7471 return WERR_BADFID;
7474 if (!get_printer_snum(p,handle, &snum))
7475 return WERR_BADFID;
7478 * Access check : NT returns "access denied" if you make a
7479 * SetPrinterData call without the necessary privildge.
7480 * we were originally returning OK if nothing changed
7481 * which made Win2k issue **a lot** of SetPrinterData
7482 * when connecting to a printer --jerry
7485 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7487 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7488 status = WERR_ACCESS_DENIED;
7489 goto done;
7492 status = get_a_printer(&printer, 2, lp_servicename(snum));
7493 if (!W_ERROR_IS_OK(status))
7494 return status;
7496 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7499 * When client side code sets a magic printer data key, detect it and save
7500 * the current printer data and the magic key's data (its the DEVMODE) for
7501 * future printer/driver initializations.
7503 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7505 /* Set devmode and printer initialization info */
7506 status = save_driver_init( printer, 2, data, real_len );
7508 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7510 else
7512 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7513 type, data, real_len );
7514 if ( W_ERROR_IS_OK(status) )
7515 status = mod_a_printer(*printer, 2);
7518 done:
7519 free_a_printer(&printer, 2);
7521 return status;
7524 /****************************************************************************
7525 ****************************************************************************/
7527 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7529 POLICY_HND *handle = &q_u->handle;
7530 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7531 int snum;
7533 DEBUG(5,("_spoolss_resetprinter\n"));
7536 * All we do is to check to see if the handle and queue is valid.
7537 * This call really doesn't mean anything to us because we only
7538 * support RAW printing. --jerry
7541 if (!Printer) {
7542 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7543 return WERR_BADFID;
7546 if (!get_printer_snum(p,handle, &snum))
7547 return WERR_BADFID;
7550 /* blindly return success */
7551 return WERR_OK;
7555 /****************************************************************************
7556 ****************************************************************************/
7558 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7560 POLICY_HND *handle = &q_u->handle;
7561 UNISTR2 *value = &q_u->valuename;
7563 NT_PRINTER_INFO_LEVEL *printer = NULL;
7564 int snum=0;
7565 WERROR status = WERR_OK;
7566 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7567 pstring valuename;
7569 DEBUG(5,("spoolss_deleteprinterdata\n"));
7571 if (!Printer) {
7572 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7573 return WERR_BADFID;
7576 if (!get_printer_snum(p, handle, &snum))
7577 return WERR_BADFID;
7579 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7580 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7581 return WERR_ACCESS_DENIED;
7584 status = get_a_printer(&printer, 2, lp_servicename(snum));
7585 if (!W_ERROR_IS_OK(status))
7586 return status;
7588 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7590 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7592 free_a_printer(&printer, 2);
7594 return status;
7597 /****************************************************************************
7598 ****************************************************************************/
7600 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7602 POLICY_HND *handle = &q_u->handle;
7603 FORM *form = &q_u->form;
7604 nt_forms_struct tmpForm;
7605 int snum;
7606 WERROR status = WERR_OK;
7607 NT_PRINTER_INFO_LEVEL *printer = NULL;
7609 int count=0;
7610 nt_forms_struct *list=NULL;
7611 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7613 DEBUG(5,("spoolss_addform\n"));
7615 if (!Printer) {
7616 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7617 return WERR_BADFID;
7621 /* forms can be added on printer of on the print server handle */
7623 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7625 if (!get_printer_snum(p,handle, &snum))
7626 return WERR_BADFID;
7628 status = get_a_printer(&printer, 2, lp_servicename(snum));
7629 if (!W_ERROR_IS_OK(status))
7630 goto done;
7633 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7634 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7635 status = WERR_ACCESS_DENIED;
7636 goto done;
7639 /* can't add if builtin */
7641 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7642 status = WERR_ALREADY_EXISTS;
7643 goto done;
7646 count = get_ntforms(&list);
7648 if(!add_a_form(&list, form, &count)) {
7649 status = WERR_NOMEM;
7650 goto done;
7653 write_ntforms(&list, count);
7656 * ChangeID must always be set if this is a printer
7659 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7660 status = mod_a_printer(*printer, 2);
7662 done:
7663 if ( printer )
7664 free_a_printer(&printer, 2);
7665 SAFE_FREE(list);
7667 return status;
7670 /****************************************************************************
7671 ****************************************************************************/
7673 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7675 POLICY_HND *handle = &q_u->handle;
7676 UNISTR2 *form_name = &q_u->name;
7677 nt_forms_struct tmpForm;
7678 int count=0;
7679 nt_forms_struct *list=NULL;
7680 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7681 int snum;
7682 WERROR status = WERR_OK;
7683 NT_PRINTER_INFO_LEVEL *printer = NULL;
7685 DEBUG(5,("spoolss_deleteform\n"));
7687 if (!Printer) {
7688 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7689 return WERR_BADFID;
7692 /* forms can be deleted on printer of on the print server handle */
7694 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7696 if (!get_printer_snum(p,handle, &snum))
7697 return WERR_BADFID;
7699 status = get_a_printer(&printer, 2, lp_servicename(snum));
7700 if (!W_ERROR_IS_OK(status))
7701 goto done;
7704 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7705 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7706 status = WERR_ACCESS_DENIED;
7707 goto done;
7710 /* can't delete if builtin */
7712 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7713 status = WERR_INVALID_PARAM;
7714 goto done;
7717 count = get_ntforms(&list);
7719 if ( !delete_a_form(&list, form_name, &count, &status ))
7720 goto done;
7723 * ChangeID must always be set if this is a printer
7726 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7727 status = mod_a_printer(*printer, 2);
7729 done:
7730 if ( printer )
7731 free_a_printer(&printer, 2);
7732 SAFE_FREE(list);
7734 return status;
7737 /****************************************************************************
7738 ****************************************************************************/
7740 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7742 POLICY_HND *handle = &q_u->handle;
7743 FORM *form = &q_u->form;
7744 nt_forms_struct tmpForm;
7745 int snum;
7746 WERROR status = WERR_OK;
7747 NT_PRINTER_INFO_LEVEL *printer = NULL;
7749 int count=0;
7750 nt_forms_struct *list=NULL;
7751 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7753 DEBUG(5,("spoolss_setform\n"));
7755 if (!Printer) {
7756 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7757 return WERR_BADFID;
7760 /* forms can be modified on printer of on the print server handle */
7762 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7764 if (!get_printer_snum(p,handle, &snum))
7765 return WERR_BADFID;
7767 status = get_a_printer(&printer, 2, lp_servicename(snum));
7768 if (!W_ERROR_IS_OK(status))
7769 goto done;
7772 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7773 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7774 status = WERR_ACCESS_DENIED;
7775 goto done;
7778 /* can't set if builtin */
7779 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7780 status = WERR_INVALID_PARAM;
7781 goto done;
7784 count = get_ntforms(&list);
7785 update_a_form(&list, form, count);
7786 write_ntforms(&list, count);
7789 * ChangeID must always be set if this is a printer
7792 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7793 status = mod_a_printer(*printer, 2);
7796 done:
7797 if ( printer )
7798 free_a_printer(&printer, 2);
7799 SAFE_FREE(list);
7801 return status;
7804 /****************************************************************************
7805 enumprintprocessors level 1.
7806 ****************************************************************************/
7808 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7810 PRINTPROCESSOR_1 *info_1=NULL;
7812 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7813 return WERR_NOMEM;
7815 (*returned) = 0x1;
7817 init_unistr(&info_1->name, "winprint");
7819 *needed += spoolss_size_printprocessor_info_1(info_1);
7821 if (!alloc_buffer_size(buffer, *needed))
7822 return WERR_INSUFFICIENT_BUFFER;
7824 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7826 SAFE_FREE(info_1);
7828 if (*needed > offered) {
7829 *returned=0;
7830 return WERR_INSUFFICIENT_BUFFER;
7833 return WERR_OK;
7836 /****************************************************************************
7837 ****************************************************************************/
7839 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7841 uint32 level = q_u->level;
7842 NEW_BUFFER *buffer = NULL;
7843 uint32 offered = q_u->offered;
7844 uint32 *needed = &r_u->needed;
7845 uint32 *returned = &r_u->returned;
7847 /* that's an [in out] buffer */
7848 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7849 buffer = r_u->buffer;
7851 DEBUG(5,("spoolss_enumprintprocessors\n"));
7854 * Enumerate the print processors ...
7856 * Just reply with "winprint", to keep NT happy
7857 * and I can use my nice printer checker.
7860 *returned=0;
7861 *needed=0;
7863 switch (level) {
7864 case 1:
7865 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7866 default:
7867 return WERR_UNKNOWN_LEVEL;
7871 /****************************************************************************
7872 enumprintprocdatatypes level 1.
7873 ****************************************************************************/
7875 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7877 PRINTPROCDATATYPE_1 *info_1=NULL;
7879 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7880 return WERR_NOMEM;
7882 (*returned) = 0x1;
7884 init_unistr(&info_1->name, "RAW");
7886 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7888 if (!alloc_buffer_size(buffer, *needed))
7889 return WERR_INSUFFICIENT_BUFFER;
7891 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7893 SAFE_FREE(info_1);
7895 if (*needed > offered) {
7896 *returned=0;
7897 return WERR_INSUFFICIENT_BUFFER;
7900 return WERR_OK;
7903 /****************************************************************************
7904 ****************************************************************************/
7906 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7908 uint32 level = q_u->level;
7909 NEW_BUFFER *buffer = NULL;
7910 uint32 offered = q_u->offered;
7911 uint32 *needed = &r_u->needed;
7912 uint32 *returned = &r_u->returned;
7914 /* that's an [in out] buffer */
7915 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7916 buffer = r_u->buffer;
7918 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7920 *returned=0;
7921 *needed=0;
7923 switch (level) {
7924 case 1:
7925 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7926 default:
7927 return WERR_UNKNOWN_LEVEL;
7931 /****************************************************************************
7932 enumprintmonitors level 1.
7933 ****************************************************************************/
7935 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7937 PRINTMONITOR_1 *info_1=NULL;
7939 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7940 return WERR_NOMEM;
7942 (*returned) = 0x1;
7944 init_unistr(&info_1->name, "Local Port");
7946 *needed += spoolss_size_printmonitor_info_1(info_1);
7948 if (!alloc_buffer_size(buffer, *needed))
7949 return WERR_INSUFFICIENT_BUFFER;
7951 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7953 SAFE_FREE(info_1);
7955 if (*needed > offered) {
7956 *returned=0;
7957 return WERR_INSUFFICIENT_BUFFER;
7960 return WERR_OK;
7963 /****************************************************************************
7964 enumprintmonitors level 2.
7965 ****************************************************************************/
7967 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7969 PRINTMONITOR_2 *info_2=NULL;
7971 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7972 return WERR_NOMEM;
7974 (*returned) = 0x1;
7976 init_unistr(&info_2->name, "Local Port");
7977 init_unistr(&info_2->environment, "Windows NT X86");
7978 init_unistr(&info_2->dll_name, "localmon.dll");
7980 *needed += spoolss_size_printmonitor_info_2(info_2);
7982 if (!alloc_buffer_size(buffer, *needed))
7983 return WERR_INSUFFICIENT_BUFFER;
7985 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7987 SAFE_FREE(info_2);
7989 if (*needed > offered) {
7990 *returned=0;
7991 return WERR_INSUFFICIENT_BUFFER;
7994 return WERR_OK;
7997 /****************************************************************************
7998 ****************************************************************************/
8000 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8002 uint32 level = q_u->level;
8003 NEW_BUFFER *buffer = NULL;
8004 uint32 offered = q_u->offered;
8005 uint32 *needed = &r_u->needed;
8006 uint32 *returned = &r_u->returned;
8008 /* that's an [in out] buffer */
8009 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8010 buffer = r_u->buffer;
8012 DEBUG(5,("spoolss_enumprintmonitors\n"));
8015 * Enumerate the print monitors ...
8017 * Just reply with "Local Port", to keep NT happy
8018 * and I can use my nice printer checker.
8021 *returned=0;
8022 *needed=0;
8024 switch (level) {
8025 case 1:
8026 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8027 case 2:
8028 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8029 default:
8030 return WERR_UNKNOWN_LEVEL;
8034 /****************************************************************************
8035 ****************************************************************************/
8037 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8039 int i=0;
8040 BOOL found=False;
8041 JOB_INFO_1 *info_1=NULL;
8043 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8045 if (info_1 == NULL) {
8046 SAFE_FREE(queue);
8047 return WERR_NOMEM;
8050 for (i=0; i<count && found==False; i++) {
8051 if (queue[i].job==(int)jobid)
8052 found=True;
8055 if (found==False) {
8056 SAFE_FREE(queue);
8057 SAFE_FREE(info_1);
8058 /* NT treats not found as bad param... yet another bad choice */
8059 return WERR_INVALID_PARAM;
8062 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8064 *needed += spoolss_size_job_info_1(info_1);
8066 if (!alloc_buffer_size(buffer, *needed)) {
8067 SAFE_FREE(info_1);
8068 return WERR_INSUFFICIENT_BUFFER;
8071 smb_io_job_info_1("", buffer, info_1, 0);
8073 SAFE_FREE(info_1);
8075 if (*needed > offered)
8076 return WERR_INSUFFICIENT_BUFFER;
8078 return WERR_OK;
8081 /****************************************************************************
8082 ****************************************************************************/
8084 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8086 int i = 0;
8087 BOOL found = False;
8088 JOB_INFO_2 *info_2;
8089 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8090 WERROR ret;
8091 DEVICEMODE *devmode = NULL;
8092 NT_DEVICEMODE *nt_devmode = NULL;
8094 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8096 ZERO_STRUCTP(info_2);
8098 if (info_2 == NULL) {
8099 ret = WERR_NOMEM;
8100 goto done;
8103 for ( i=0; i<count && found==False; i++ )
8105 if (queue[i].job == (int)jobid)
8106 found = True;
8109 if ( !found )
8111 /* NT treats not found as bad param... yet another bad
8112 choice */
8113 ret = WERR_INVALID_PARAM;
8114 goto done;
8117 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8118 if (!W_ERROR_IS_OK(ret))
8119 goto done;
8122 * if the print job does not have a DEVMODE associated with it,
8123 * just use the one for the printer. A NULL devicemode is not
8124 * a failure condition
8127 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8128 devmode = construct_dev_mode(snum);
8129 else {
8130 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8131 ZERO_STRUCTP( devmode );
8132 convert_nt_devicemode( devmode, nt_devmode );
8136 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8138 *needed += spoolss_size_job_info_2(info_2);
8140 if (!alloc_buffer_size(buffer, *needed)) {
8141 ret = WERR_INSUFFICIENT_BUFFER;
8142 goto done;
8145 smb_io_job_info_2("", buffer, info_2, 0);
8147 if (*needed > offered) {
8148 ret = WERR_INSUFFICIENT_BUFFER;
8149 goto done;
8152 ret = WERR_OK;
8154 done:
8155 /* Cleanup allocated memory */
8157 free_job_info_2(info_2); /* Also frees devmode */
8158 SAFE_FREE(info_2);
8159 free_a_printer(&ntprinter, 2);
8161 return ret;
8164 /****************************************************************************
8165 ****************************************************************************/
8167 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8169 POLICY_HND *handle = &q_u->handle;
8170 uint32 jobid = q_u->jobid;
8171 uint32 level = q_u->level;
8172 NEW_BUFFER *buffer = NULL;
8173 uint32 offered = q_u->offered;
8174 uint32 *needed = &r_u->needed;
8175 WERROR wstatus = WERR_OK;
8177 int snum;
8178 int count;
8179 print_queue_struct *queue = NULL;
8180 print_status_struct prt_status;
8182 /* that's an [in out] buffer */
8183 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8184 buffer = r_u->buffer;
8186 DEBUG(5,("spoolss_getjob\n"));
8188 *needed = 0;
8190 if (!get_printer_snum(p, handle, &snum))
8191 return WERR_BADFID;
8193 count = print_queue_status(snum, &queue, &prt_status);
8195 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8196 count, prt_status.status, prt_status.message));
8198 switch ( level ) {
8199 case 1:
8200 wstatus = getjob_level_1(queue, count, snum, jobid,
8201 buffer, offered, needed);
8202 break;
8203 case 2:
8204 wstatus = getjob_level_2(queue, count, snum, jobid,
8205 buffer, offered, needed);
8206 break;
8207 default:
8208 wstatus = WERR_UNKNOWN_LEVEL;
8209 break;
8212 SAFE_FREE(queue);
8213 return wstatus;
8216 /********************************************************************
8217 spoolss_getprinterdataex
8219 From MSDN documentation of GetPrinterDataEx: pass request
8220 to GetPrinterData if key is "PrinterDriverData".
8221 ********************************************************************/
8223 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8225 POLICY_HND *handle = &q_u->handle;
8226 uint32 in_size = q_u->size;
8227 uint32 *type = &r_u->type;
8228 uint32 *out_size = &r_u->size;
8229 uint8 **data = &r_u->data;
8230 uint32 *needed = &r_u->needed;
8231 fstring keyname, valuename;
8233 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8235 NT_PRINTER_INFO_LEVEL *printer = NULL;
8236 int snum = 0;
8237 WERROR status = WERR_OK;
8239 DEBUG(4,("_spoolss_getprinterdataex\n"));
8241 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8242 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8244 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8245 keyname, valuename));
8247 /* in case of problem, return some default values */
8249 *needed = 0;
8250 *type = 0;
8251 *out_size = in_size;
8253 if (!Printer) {
8254 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8255 status = WERR_BADFID;
8256 goto done;
8259 /* Is the handle to a printer or to the server? */
8261 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8262 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8263 status = WERR_INVALID_PARAM;
8264 goto done;
8267 if ( !get_printer_snum(p,handle, &snum) )
8268 return WERR_BADFID;
8270 status = get_a_printer(&printer, 2, lp_servicename(snum));
8271 if ( !W_ERROR_IS_OK(status) )
8272 goto done;
8274 /* check to see if the keyname is valid */
8275 if ( !strlen(keyname) ) {
8276 status = WERR_INVALID_PARAM;
8277 goto done;
8280 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8281 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8282 free_a_printer( &printer, 2 );
8283 status = WERR_BADFILE;
8284 goto done;
8287 /* When given a new keyname, we should just create it */
8289 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8291 if (*needed > *out_size)
8292 status = WERR_MORE_DATA;
8294 done:
8295 if ( !W_ERROR_IS_OK(status) )
8297 DEBUG(5, ("error: allocating %d\n", *out_size));
8299 /* reply this param doesn't exist */
8301 if ( *out_size )
8303 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8304 status = WERR_NOMEM;
8305 goto done;
8308 else {
8309 *data = NULL;
8313 if ( printer )
8314 free_a_printer( &printer, 2 );
8316 return status;
8319 /********************************************************************
8320 * spoolss_setprinterdataex
8321 ********************************************************************/
8323 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8325 POLICY_HND *handle = &q_u->handle;
8326 uint32 type = q_u->type;
8327 uint8 *data = q_u->data;
8328 uint32 real_len = q_u->real_len;
8330 NT_PRINTER_INFO_LEVEL *printer = NULL;
8331 int snum = 0;
8332 WERROR status = WERR_OK;
8333 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8334 fstring valuename;
8335 fstring keyname;
8336 char *oid_string;
8338 DEBUG(4,("_spoolss_setprinterdataex\n"));
8340 /* From MSDN documentation of SetPrinterDataEx: pass request to
8341 SetPrinterData if key is "PrinterDriverData" */
8343 if (!Printer) {
8344 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8345 return WERR_BADFID;
8348 if ( !get_printer_snum(p,handle, &snum) )
8349 return WERR_BADFID;
8352 * Access check : NT returns "access denied" if you make a
8353 * SetPrinterData call without the necessary privildge.
8354 * we were originally returning OK if nothing changed
8355 * which made Win2k issue **a lot** of SetPrinterData
8356 * when connecting to a printer --jerry
8359 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8361 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8362 return WERR_ACCESS_DENIED;
8365 status = get_a_printer(&printer, 2, lp_servicename(snum));
8366 if (!W_ERROR_IS_OK(status))
8367 return status;
8369 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8370 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8372 /* check for OID in valuename */
8374 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8376 *oid_string = '\0';
8377 oid_string++;
8380 /* save the registry data */
8382 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8384 /* save the OID if one was specified and the previous set call succeeded */
8386 if ( W_ERROR_IS_OK(status) && oid_string )
8389 fstrcat( keyname, "\\" );
8390 fstrcat( keyname, SPOOL_OID_KEY );
8393 * I'm not checking the status here on purpose. Don't know
8394 * if this is right, but I'm returning the status from the
8395 * previous set_printer_dataex() call. I have no idea if
8396 * this is right. --jerry
8399 set_printer_dataex( printer, keyname, valuename,
8400 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8403 free_a_printer(&printer, 2);
8405 return status;
8409 /********************************************************************
8410 * spoolss_deleteprinterdataex
8411 ********************************************************************/
8413 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8415 POLICY_HND *handle = &q_u->handle;
8416 UNISTR2 *value = &q_u->valuename;
8417 UNISTR2 *key = &q_u->keyname;
8419 NT_PRINTER_INFO_LEVEL *printer = NULL;
8420 int snum=0;
8421 WERROR status = WERR_OK;
8422 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8423 pstring valuename, keyname;
8425 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8427 if (!Printer) {
8428 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8429 return WERR_BADFID;
8432 if (!get_printer_snum(p, handle, &snum))
8433 return WERR_BADFID;
8435 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8436 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8437 return WERR_ACCESS_DENIED;
8440 status = get_a_printer(&printer, 2, lp_servicename(snum));
8441 if (!W_ERROR_IS_OK(status))
8442 return status;
8444 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8445 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8447 status = delete_printer_dataex( printer, keyname, valuename );
8449 free_a_printer(&printer, 2);
8451 return status;
8454 /********************************************************************
8455 * spoolss_enumprinterkey
8456 ********************************************************************/
8459 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8461 fstring key;
8462 fstring *keynames = NULL;
8463 uint16 *enumkeys = NULL;
8464 int num_keys;
8465 int printerkey_len;
8466 POLICY_HND *handle = &q_u->handle;
8467 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8468 NT_PRINTER_DATA *data;
8469 NT_PRINTER_INFO_LEVEL *printer = NULL;
8470 int snum = 0;
8471 WERROR status = WERR_BADFILE;
8474 DEBUG(4,("_spoolss_enumprinterkey\n"));
8476 if (!Printer) {
8477 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8478 return WERR_BADFID;
8481 if ( !get_printer_snum(p,handle, &snum) )
8482 return WERR_BADFID;
8484 status = get_a_printer(&printer, 2, lp_servicename(snum));
8485 if (!W_ERROR_IS_OK(status))
8486 return status;
8488 /* get the list of subkey names */
8490 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8491 data = &printer->info_2->data;
8493 num_keys = get_printer_subkeys( data, key, &keynames );
8495 if ( num_keys == -1 ) {
8496 status = WERR_BADFILE;
8497 goto done;
8500 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8502 r_u->needed = printerkey_len*2;
8504 if ( q_u->size < r_u->needed ) {
8505 status = WERR_MORE_DATA;
8506 goto done;
8509 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8510 status = WERR_NOMEM;
8511 goto done;
8514 status = WERR_OK;
8516 if ( q_u->size < r_u->needed )
8517 status = WERR_MORE_DATA;
8519 done:
8520 free_a_printer( &printer, 2 );
8521 SAFE_FREE( keynames );
8523 return status;
8526 /********************************************************************
8527 * spoolss_deleteprinterkey
8528 ********************************************************************/
8530 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8532 POLICY_HND *handle = &q_u->handle;
8533 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8534 fstring key;
8535 NT_PRINTER_INFO_LEVEL *printer = NULL;
8536 int snum=0;
8537 WERROR status;
8539 DEBUG(5,("spoolss_deleteprinterkey\n"));
8541 if (!Printer) {
8542 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8543 return WERR_BADFID;
8546 /* if keyname == NULL, return error */
8548 if ( !q_u->keyname.buffer )
8549 return WERR_INVALID_PARAM;
8551 if (!get_printer_snum(p, handle, &snum))
8552 return WERR_BADFID;
8554 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8555 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8556 return WERR_ACCESS_DENIED;
8559 status = get_a_printer(&printer, 2, lp_servicename(snum));
8560 if (!W_ERROR_IS_OK(status))
8561 return status;
8563 /* delete the key and all subneys */
8565 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8567 status = delete_all_printer_data( printer->info_2, key );
8569 if ( W_ERROR_IS_OK(status) )
8570 status = mod_a_printer(*printer, 2);
8572 free_a_printer( &printer, 2 );
8574 return status;
8578 /********************************************************************
8579 * spoolss_enumprinterdataex
8580 ********************************************************************/
8582 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8584 POLICY_HND *handle = &q_u->handle;
8585 uint32 in_size = q_u->size;
8586 uint32 num_entries,
8587 needed;
8588 NT_PRINTER_INFO_LEVEL *printer = NULL;
8589 PRINTER_ENUM_VALUES *enum_values = NULL;
8590 NT_PRINTER_DATA *p_data;
8591 fstring key;
8592 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8593 int snum;
8594 WERROR result;
8595 int key_index;
8596 int i;
8597 REGISTRY_VALUE *val;
8598 char *value_name;
8599 int data_len;
8602 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8604 if (!Printer) {
8605 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8606 return WERR_BADFID;
8609 /* first get the printer off of disk */
8611 if (!get_printer_snum(p,handle, &snum))
8612 return WERR_BADFID;
8614 ZERO_STRUCT(printer);
8615 result = get_a_printer(&printer, 2, lp_servicename(snum));
8616 if (!W_ERROR_IS_OK(result))
8617 return result;
8619 /* now look for a match on the key name */
8621 p_data = &printer->info_2->data;
8623 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8624 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8626 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8627 result = WERR_INVALID_PARAM;
8628 goto done;
8631 result = WERR_OK;
8632 needed = 0;
8634 /* allocate the memory for the array of pointers -- if necessary */
8636 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8637 if ( num_entries )
8639 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8641 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8642 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8643 result = WERR_NOMEM;
8644 goto done;
8647 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8651 * loop through all params and build the array to pass
8652 * back to the client
8655 for ( i=0; i<num_entries; i++ )
8657 /* lookup the registry value */
8659 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8660 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8662 /* copy the data */
8664 value_name = regval_name( val );
8665 init_unistr( &enum_values[i].valuename, value_name );
8666 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8667 enum_values[i].type = regval_type( val );
8669 data_len = regval_size( val );
8670 if ( data_len ) {
8671 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8673 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8674 data_len ));
8675 result = WERR_NOMEM;
8676 goto done;
8679 enum_values[i].data_len = data_len;
8681 /* keep track of the size of the array in bytes */
8683 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8686 /* housekeeping information in the reply */
8688 r_u->needed = needed;
8689 r_u->returned = num_entries;
8691 if (needed > in_size) {
8692 result = WERR_MORE_DATA;
8693 goto done;
8696 /* copy data into the reply */
8698 r_u->ctr.size = r_u->needed;
8699 r_u->ctr.size_of_array = r_u->returned;
8700 r_u->ctr.values = enum_values;
8704 done:
8705 free_a_printer(&printer, 2);
8707 return result;
8710 /****************************************************************************
8711 ****************************************************************************/
8713 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8715 init_unistr(&info->name, name);
8718 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8719 UNISTR2 *environment,
8720 NEW_BUFFER *buffer,
8721 uint32 offered,
8722 uint32 *needed)
8724 pstring path;
8725 pstring long_archi;
8726 pstring short_archi;
8727 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8729 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8731 if (get_short_archi(short_archi, long_archi)==False)
8732 return WERR_INVALID_ENVIRONMENT;
8734 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8735 return WERR_NOMEM;
8737 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8739 fill_printprocessordirectory_1(info, path);
8741 *needed += spoolss_size_printprocessordirectory_info_1(info);
8743 if (!alloc_buffer_size(buffer, *needed)) {
8744 safe_free(info);
8745 return WERR_INSUFFICIENT_BUFFER;
8748 smb_io_printprocessordirectory_1("", buffer, info, 0);
8750 safe_free(info);
8752 if (*needed > offered)
8753 return WERR_INSUFFICIENT_BUFFER;
8754 else
8755 return WERR_OK;
8758 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8760 uint32 level = q_u->level;
8761 NEW_BUFFER *buffer = NULL;
8762 uint32 offered = q_u->offered;
8763 uint32 *needed = &r_u->needed;
8764 WERROR result;
8766 /* that's an [in out] buffer */
8767 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8768 buffer = r_u->buffer;
8770 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8772 *needed=0;
8774 switch(level) {
8775 case 1:
8776 result = getprintprocessordirectory_level_1
8777 (&q_u->name, &q_u->environment, buffer, offered, needed);
8778 break;
8779 default:
8780 result = WERR_UNKNOWN_LEVEL;
8783 return result;
8786 #if 0
8788 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8789 SPOOL_R_REPLYOPENPRINTER *r_u)
8791 DEBUG(5,("_spoolss_replyopenprinter\n"));
8793 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8795 return WERR_OK;
8798 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8799 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8801 DEBUG(5,("_spoolss_replycloseprinter\n"));
8802 return WERR_OK;
8805 #endif