r9752: figured out why talloc_steal() is a bad idea for SEC_DESC*
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
bloba622bfb5bd98e7aed4972e2a00351c1f0c20f36f
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-2004,
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 extern userdom_struct current_user_info;
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
38 #endif
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
45 /* to OS */
46 static const 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 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
56 return "";
57 return drv_ver_to_os[ver];
60 struct table_node {
61 const char *long_archi;
62 const char *short_archi;
63 int version;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
72 int snum;
73 uint32 counter;
74 } counter_printer_0;
76 static counter_printer_0 *counter_list;
78 static struct cli_state notify_cli; /* print notify back-channel */
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
92 switch (v) {
93 case LPQ_QUEUED:
94 return 0;
95 case LPQ_PAUSED:
96 return JOB_STATUS_PAUSED;
97 case LPQ_SPOOLING:
98 return JOB_STATUS_SPOOLING;
99 case LPQ_PRINTING:
100 return JOB_STATUS_PRINTING;
101 case LPQ_ERROR:
102 return JOB_STATUS_ERROR;
103 case LPQ_DELETING:
104 return JOB_STATUS_DELETING;
105 case LPQ_OFFLINE:
106 return JOB_STATUS_OFFLINE;
107 case LPQ_PAPEROUT:
108 return JOB_STATUS_PAPEROUT;
109 case LPQ_PRINTED:
110 return JOB_STATUS_PRINTED;
111 case LPQ_DELETED:
112 return JOB_STATUS_DELETED;
113 case LPQ_BLOCKED:
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
118 return 0;
121 static int nt_printq_status(int v)
123 switch (v) {
124 case LPQ_PAUSED:
125 return PRINTER_STATUS_PAUSED;
126 case LPQ_QUEUED:
127 case LPQ_SPOOLING:
128 case LPQ_PRINTING:
129 return 0;
131 return 0;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
140 if (*pp == NULL)
141 return;
143 SAFE_FREE((*pp)->ctr.type);
144 SAFE_FREE(*pp);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
153 WERROR result;
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 return;
169 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
177 cli_nt_session_close(&notify_cli);
178 cli_ulogoff(&notify_cli);
179 cli_shutdown(&notify_cli);
180 message_deregister(MSG_PRINTER_NOTIFY2);
182 /* Tell the connections db we're no longer interested in
183 * printer notify messages. */
185 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
188 smb_connections--;
191 /****************************************************************************
192 Functions to free a printer entry datastruct.
193 ****************************************************************************/
195 static void free_printer_entry(void *ptr)
197 Printer_entry *Printer = (Printer_entry *)ptr;
199 if (Printer->notify.client_connected==True) {
200 int snum = -1;
202 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
203 snum = -1;
204 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
205 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
206 snum = print_queue_snum(Printer->sharename);
207 if (snum != -1)
208 srv_spoolss_replycloseprinter(snum,
209 &Printer->notify.client_hnd);
213 Printer->notify.flags=0;
214 Printer->notify.options=0;
215 Printer->notify.localmachine[0]='\0';
216 Printer->notify.printerlocal=0;
217 free_spool_notify_option(&Printer->notify.option);
218 Printer->notify.option=NULL;
219 Printer->notify.client_connected=False;
221 free_nt_devicemode( &Printer->nt_devmode );
222 free_a_printer( &Printer->printer_info, 2 );
224 talloc_destroy( Printer->ctx );
226 /* Remove from the internal list. */
227 DLIST_REMOVE(printers_list, Printer);
229 SAFE_FREE(Printer);
232 /****************************************************************************
233 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
234 ****************************************************************************/
236 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
238 SPOOL_NOTIFY_OPTION *new_sp = NULL;
240 if (!sp)
241 return NULL;
243 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
244 if (!new_sp)
245 return NULL;
247 *new_sp = *sp;
249 if (sp->ctr.count) {
250 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
252 if (!new_sp->ctr.type) {
253 SAFE_FREE(new_sp);
254 return NULL;
258 return new_sp;
261 /****************************************************************************
262 find printer index by handle
263 ****************************************************************************/
265 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
267 Printer_entry *find_printer = NULL;
269 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
270 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
271 return NULL;
274 return find_printer;
277 /****************************************************************************
278 Close printer index by handle.
279 ****************************************************************************/
281 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
283 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
285 if (!Printer) {
286 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
287 return False;
290 close_policy_hnd(p, hnd);
292 return True;
295 /****************************************************************************
296 Delete a printer given a handle.
297 ****************************************************************************/
298 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
300 char *cmd = lp_deleteprinter_cmd();
301 pstring command;
302 int ret;
303 SE_PRIV se_printop = SE_PRINT_OPERATOR;
304 BOOL is_print_op = False;
306 /* can't fail if we don't try */
308 if ( !*cmd )
309 return WERR_OK;
311 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
313 if ( token )
314 is_print_op = user_has_privileges( token, &se_printop );
316 DEBUG(10,("Running [%s]\n", command));
318 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
320 if ( is_print_op )
321 become_root();
323 if ( (ret = smbrun(command, NULL)) == 0 ) {
324 /* Tell everyone we updated smb.conf. */
325 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
328 if ( is_print_op )
329 unbecome_root();
331 /********** END SePrintOperatorPrivlege BLOCK **********/
333 DEBUGADD(10,("returned [%d]\n", ret));
335 if (ret != 0)
336 return WERR_BADFID; /* What to return here? */
338 /* go ahead and re-read the services immediately */
339 reload_services( False );
341 if ( lp_servicenumber( sharename ) < 0 )
342 return WERR_ACCESS_DENIED;
344 return WERR_OK;
347 /****************************************************************************
348 Delete a printer given a handle.
349 ****************************************************************************/
351 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
353 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355 if (!Printer) {
356 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
357 return WERR_BADFID;
361 * It turns out that Windows allows delete printer on a handle
362 * opened by an admin user, then used on a pipe handle created
363 * by an anonymous user..... but they're working on security.... riiight !
364 * JRA.
367 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
368 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
369 return WERR_ACCESS_DENIED;
372 /* this does not need a become root since the access check has been
373 done on the handle already */
375 if (del_a_printer( Printer->sharename ) != 0) {
376 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
377 return WERR_BADFID;
380 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
383 /****************************************************************************
384 Return the snum of a printer corresponding to an handle.
385 ****************************************************************************/
387 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
389 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
391 if (!Printer) {
392 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
393 return False;
396 switch (Printer->printer_type) {
397 case PRINTER_HANDLE_IS_PRINTER:
398 DEBUG(4,("short name:%s\n", Printer->sharename));
399 *number = print_queue_snum(Printer->sharename);
400 return (*number != -1);
401 case PRINTER_HANDLE_IS_PRINTSERVER:
402 return False;
403 default:
404 return False;
408 /****************************************************************************
409 Set printer handle type.
410 Check if it's \\server or \\server\printer
411 ****************************************************************************/
413 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
415 DEBUG(3,("Setting printer type=%s\n", handlename));
417 if ( strlen(handlename) < 3 ) {
418 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
419 return False;
422 /* it's a print server */
423 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
424 DEBUGADD(4,("Printer is a print server\n"));
425 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
427 /* it's a printer */
428 else {
429 DEBUGADD(4,("Printer is a printer\n"));
430 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
433 return True;
436 /****************************************************************************
437 Set printer handle name.
438 ****************************************************************************/
440 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
442 int snum;
443 int n_services=lp_numservices();
444 char *aprinter, *printername;
445 const char *servername;
446 fstring sname;
447 BOOL found=False;
448 NT_PRINTER_INFO_LEVEL *printer;
449 WERROR result;
451 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
453 aprinter = handlename;
454 if ( *handlename == '\\' ) {
455 servername = handlename + 2;
456 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
457 *aprinter = '\0';
458 aprinter++;
461 else {
462 servername = "";
465 /* save the servername to fill in replies on this handle */
467 if ( !is_myname_or_ipaddr( servername ) )
468 return False;
470 fstrcpy( Printer->servername, servername );
472 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
473 return True;
475 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
476 return False;
478 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
480 /* Search all sharenames first as this is easier than pulling
481 the printer_info_2 off of disk */
483 snum = find_service(aprinter);
485 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
486 found = True;
487 fstrcpy( sname, aprinter );
490 /* do another loop to look for printernames */
492 for (snum=0; !found && snum<n_services; snum++) {
494 /* no point in checking if this is not a printer or
495 we aren't allowing printername != sharename */
497 if ( !(lp_snum_ok(snum)
498 && lp_print_ok(snum)
499 && !lp_force_printername(snum)) )
501 continue;
504 fstrcpy(sname, lp_servicename(snum));
506 printer = NULL;
507 result = get_a_printer( NULL, &printer, 2, sname );
508 if ( !W_ERROR_IS_OK(result) ) {
509 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
510 sname, dos_errstr(result)));
511 continue;
514 /* printername is always returned as \\server\printername */
515 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
516 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
517 printer->info_2->printername));
518 free_a_printer( &printer, 2);
519 continue;
522 printername++;
524 if ( strequal(printername, aprinter) ) {
525 found = True;
528 DEBUGADD(10, ("printername: %s\n", printername));
530 free_a_printer( &printer, 2);
533 if ( !found ) {
534 DEBUGADD(4,("Printer not found\n"));
535 return False;
538 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
540 fstrcpy(Printer->sharename, sname);
542 return True;
545 /****************************************************************************
546 Find first available printer slot. creates a printer handle for you.
547 ****************************************************************************/
549 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
551 Printer_entry *new_printer;
553 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
555 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
556 return False;
558 ZERO_STRUCTP(new_printer);
560 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
561 SAFE_FREE(new_printer);
562 return False;
565 /* Add to the internal list. */
566 DLIST_ADD(printers_list, new_printer);
568 new_printer->notify.option=NULL;
570 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
571 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
572 close_printer_handle(p, hnd);
573 return False;
576 if (!set_printer_hnd_printertype(new_printer, name)) {
577 close_printer_handle(p, hnd);
578 return False;
581 if (!set_printer_hnd_name(new_printer, name)) {
582 close_printer_handle(p, hnd);
583 return False;
586 new_printer->access_granted = access_granted;
588 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
590 return True;
593 /***************************************************************************
594 check to see if the client motify handle is monitoring the notification
595 given by (notify_type, notify_field).
596 **************************************************************************/
598 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
599 uint16 notify_field)
601 return True;
604 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
605 uint16 notify_field)
607 SPOOL_NOTIFY_OPTION *option = p->notify.option;
608 uint32 i, j;
611 * Flags should always be zero when the change notify
612 * is registered by the client's spooler. A user Win32 app
613 * might use the flags though instead of the NOTIFY_OPTION_INFO
614 * --jerry
617 if (!option) {
618 return False;
621 if (p->notify.flags)
622 return is_monitoring_event_flags(
623 p->notify.flags, notify_type, notify_field);
625 for (i = 0; i < option->count; i++) {
627 /* Check match for notify_type */
629 if (option->ctr.type[i].type != notify_type)
630 continue;
632 /* Check match for field */
634 for (j = 0; j < option->ctr.type[i].count; j++) {
635 if (option->ctr.type[i].fields[j] == notify_field) {
636 return True;
641 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
642 p->servername, p->sharename, notify_type, notify_field));
644 return False;
647 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
649 static void notify_one_value(struct spoolss_notify_msg *msg,
650 SPOOL_NOTIFY_INFO_DATA *data,
651 TALLOC_CTX *mem_ctx)
653 data->notify_data.value[0] = msg->notify.value[0];
654 data->notify_data.value[1] = 0;
657 static void notify_string(struct spoolss_notify_msg *msg,
658 SPOOL_NOTIFY_INFO_DATA *data,
659 TALLOC_CTX *mem_ctx)
661 UNISTR2 unistr;
663 /* The length of the message includes the trailing \0 */
665 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
667 data->notify_data.data.length = msg->len * 2;
668 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
670 if (!data->notify_data.data.string) {
671 data->notify_data.data.length = 0;
672 return;
675 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
678 static void notify_system_time(struct spoolss_notify_msg *msg,
679 SPOOL_NOTIFY_INFO_DATA *data,
680 TALLOC_CTX *mem_ctx)
682 SYSTEMTIME systime;
683 prs_struct ps;
685 if (msg->len != sizeof(time_t)) {
686 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
687 msg->len));
688 return;
691 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
692 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
693 return;
696 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
697 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
698 return;
701 if (!spoolss_io_system_time("", &ps, 0, &systime))
702 return;
704 data->notify_data.data.length = prs_offset(&ps);
705 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
707 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
709 prs_mem_free(&ps);
712 struct notify2_message_table {
713 const char *name;
714 void (*fn)(struct spoolss_notify_msg *msg,
715 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
718 static struct notify2_message_table printer_notify_table[] = {
719 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
720 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
721 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
722 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
723 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
724 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
725 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
726 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
727 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
728 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
729 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
730 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
731 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
732 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
733 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
734 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
735 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
736 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
737 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
740 static struct notify2_message_table job_notify_table[] = {
741 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
742 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
743 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
744 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
745 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
746 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
747 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
748 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
749 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
750 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
751 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
752 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
753 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
754 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
755 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
756 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
757 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
758 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
759 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
760 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
761 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
762 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
763 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
764 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
768 /***********************************************************************
769 Allocate talloc context for container object
770 **********************************************************************/
772 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
774 if ( !ctr )
775 return;
777 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
779 return;
782 /***********************************************************************
783 release all allocated memory and zero out structure
784 **********************************************************************/
786 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
788 if ( !ctr )
789 return;
791 if ( ctr->ctx )
792 talloc_destroy(ctr->ctx);
794 ZERO_STRUCTP(ctr);
796 return;
799 /***********************************************************************
800 **********************************************************************/
802 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
804 if ( !ctr )
805 return NULL;
807 return ctr->ctx;
810 /***********************************************************************
811 **********************************************************************/
813 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
815 if ( !ctr || !ctr->msg_groups )
816 return NULL;
818 if ( idx >= ctr->num_groups )
819 return NULL;
821 return &ctr->msg_groups[idx];
825 /***********************************************************************
826 How many groups of change messages do we have ?
827 **********************************************************************/
829 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
831 if ( !ctr )
832 return 0;
834 return ctr->num_groups;
837 /***********************************************************************
838 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
839 **********************************************************************/
841 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
843 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
844 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
845 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
846 int i, new_slot;
848 if ( !ctr || !msg )
849 return 0;
851 /* loop over all groups looking for a matching printer name */
853 for ( i=0; i<ctr->num_groups; i++ ) {
854 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
855 break;
858 /* add a new group? */
860 if ( i == ctr->num_groups ) {
861 ctr->num_groups++;
863 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
864 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
865 return 0;
867 ctr->msg_groups = groups;
869 /* clear the new entry and set the printer name */
871 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
872 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
875 /* add the change messages; 'i' is the correct index now regardless */
877 msg_grp = &ctr->msg_groups[i];
879 msg_grp->num_msgs++;
881 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
882 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
883 return 0;
885 msg_grp->msgs = msg_list;
887 new_slot = msg_grp->num_msgs-1;
888 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
890 /* need to allocate own copy of data */
892 if ( msg->len != 0 )
893 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
895 return ctr->num_groups;
898 /***********************************************************************
899 Send a change notication message on all handles which have a call
900 back registered
901 **********************************************************************/
903 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
905 Printer_entry *p;
906 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
907 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
908 SPOOLSS_NOTIFY_MSG *messages;
909 int sending_msg_count;
911 if ( !msg_group ) {
912 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
913 return;
916 messages = msg_group->msgs;
918 if ( !messages ) {
919 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
920 return;
923 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
925 /* loop over all printers */
927 for (p = printers_list; p; p = p->next) {
928 SPOOL_NOTIFY_INFO_DATA *data;
929 uint32 data_len = 0;
930 uint32 id;
931 int i;
933 /* Is there notification on this handle? */
935 if ( !p->notify.client_connected )
936 continue;
938 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
940 /* For this printer? Print servers always receive
941 notifications. */
943 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
944 ( !strequal(msg_group->printername, p->sharename) ) )
945 continue;
947 DEBUG(10,("Our printer\n"));
949 /* allocate the max entries possible */
951 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
952 ZERO_STRUCTP(data);
954 /* build the array of change notifications */
956 sending_msg_count = 0;
958 for ( i=0; i<msg_group->num_msgs; i++ ) {
959 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
961 /* Are we monitoring this event? */
963 if (!is_monitoring_event(p, msg->type, msg->field))
964 continue;
966 sending_msg_count++;
969 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
970 msg->type, msg->field, p->sharename));
973 * if the is a printer notification handle and not a job notification
974 * type, then set the id to 0. Other wise just use what was specified
975 * in the message.
977 * When registering change notification on a print server handle
978 * we always need to send back the id (snum) matching the printer
979 * for which the change took place. For change notify registered
980 * on a printer handle, this does not matter and the id should be 0.
982 * --jerry
985 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
986 id = 0;
987 else
988 id = msg->id;
991 /* Convert unix jobid to smb jobid */
993 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
994 id = sysjob_to_jobid(msg->id);
996 if (id == -1) {
997 DEBUG(3, ("no such unix jobid %d\n", msg->id));
998 goto done;
1002 construct_info_data( &data[data_len], msg->type, msg->field, id );
1004 switch(msg->type) {
1005 case PRINTER_NOTIFY_TYPE:
1006 if ( printer_notify_table[msg->field].fn )
1007 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1008 break;
1010 case JOB_NOTIFY_TYPE:
1011 if ( job_notify_table[msg->field].fn )
1012 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1013 break;
1015 default:
1016 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1017 goto done;
1020 data_len++;
1023 if ( sending_msg_count ) {
1024 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1025 data_len, data, p->notify.change, 0 );
1029 done:
1030 DEBUG(8,("send_notify2_changes: Exit...\n"));
1031 return;
1034 /***********************************************************************
1035 **********************************************************************/
1037 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1040 uint32 tv_sec, tv_usec;
1041 size_t offset = 0;
1043 /* Unpack message */
1045 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1046 msg->printer);
1048 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1049 &tv_sec, &tv_usec,
1050 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1052 if (msg->len == 0)
1053 tdb_unpack((char *)buf + offset, len - offset, "dd",
1054 &msg->notify.value[0], &msg->notify.value[1]);
1055 else
1056 tdb_unpack((char *)buf + offset, len - offset, "B",
1057 &msg->len, &msg->notify.data);
1059 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1060 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1062 tv->tv_sec = tv_sec;
1063 tv->tv_usec = tv_usec;
1065 if (msg->len == 0)
1066 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1067 msg->notify.value[1]));
1068 else
1069 dump_data(3, msg->notify.data, msg->len);
1071 return True;
1074 /********************************************************************
1075 Receive a notify2 message list
1076 ********************************************************************/
1078 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1080 size_t msg_count, i;
1081 char *buf = (char *)msg;
1082 char *msg_ptr;
1083 size_t msg_len;
1084 SPOOLSS_NOTIFY_MSG notify;
1085 SPOOLSS_NOTIFY_MSG_CTR messages;
1086 int num_groups;
1088 if (len < 4) {
1089 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1090 return;
1093 msg_count = IVAL(buf, 0);
1094 msg_ptr = buf + 4;
1096 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1098 if (msg_count == 0) {
1099 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1100 return;
1103 /* initialize the container */
1105 ZERO_STRUCT( messages );
1106 notify_msg_ctr_init( &messages );
1109 * build message groups for each printer identified
1110 * in a change_notify msg. Remember that a PCN message
1111 * includes the handle returned for the srv_spoolss_replyopenprinter()
1112 * call. Therefore messages are grouped according to printer handle.
1115 for ( i=0; i<msg_count; i++ ) {
1116 struct timeval msg_tv;
1118 if (msg_ptr + 4 - buf > len) {
1119 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1120 return;
1123 msg_len = IVAL(msg_ptr,0);
1124 msg_ptr += 4;
1126 if (msg_ptr + msg_len - buf > len) {
1127 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1128 return;
1131 /* unpack messages */
1133 ZERO_STRUCT( notify );
1134 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1135 msg_ptr += msg_len;
1137 /* add to correct list in container */
1139 notify_msg_ctr_addmsg( &messages, &notify );
1141 /* free memory that might have been allocated by notify2_unpack_msg() */
1143 if ( notify.len != 0 )
1144 SAFE_FREE( notify.notify.data );
1147 /* process each group of messages */
1149 num_groups = notify_msg_ctr_numgroups( &messages );
1150 for ( i=0; i<num_groups; i++ )
1151 send_notify2_changes( &messages, i );
1154 /* cleanup */
1156 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1158 notify_msg_ctr_destroy( &messages );
1160 return;
1163 /********************************************************************
1164 Send a message to ourself about new driver being installed
1165 so we can upgrade the information for each printer bound to this
1166 driver
1167 ********************************************************************/
1169 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1171 int len = strlen(drivername);
1173 if (!len)
1174 return False;
1176 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1177 drivername));
1179 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1181 return True;
1184 /**********************************************************************
1185 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1186 over all printers, upgrading ones as necessary
1187 **********************************************************************/
1189 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1191 fstring drivername;
1192 int snum;
1193 int n_services = lp_numservices();
1195 len = MIN(len,sizeof(drivername)-1);
1196 strncpy(drivername, buf, len);
1198 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1200 /* Iterate the printer list */
1202 for (snum=0; snum<n_services; snum++)
1204 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1206 WERROR result;
1207 NT_PRINTER_INFO_LEVEL *printer = NULL;
1209 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1210 if (!W_ERROR_IS_OK(result))
1211 continue;
1213 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1215 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1217 /* all we care about currently is the change_id */
1219 result = mod_a_printer(printer, 2);
1220 if (!W_ERROR_IS_OK(result)) {
1221 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1222 dos_errstr(result)));
1226 free_a_printer(&printer, 2);
1230 /* all done */
1233 /********************************************************************
1234 Update the cache for all printq's with a registered client
1235 connection
1236 ********************************************************************/
1238 void update_monitored_printq_cache( void )
1240 Printer_entry *printer = printers_list;
1241 int snum;
1243 /* loop through all printers and update the cache where
1244 client_connected == True */
1245 while ( printer )
1247 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1248 && printer->notify.client_connected )
1250 snum = print_queue_snum(printer->sharename);
1251 print_queue_status( snum, NULL, NULL );
1254 printer = printer->next;
1257 return;
1259 /********************************************************************
1260 Send a message to ourself about new driver being installed
1261 so we can upgrade the information for each printer bound to this
1262 driver
1263 ********************************************************************/
1265 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1267 int len = strlen(drivername);
1269 if (!len)
1270 return False;
1272 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1273 drivername));
1275 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1277 return True;
1280 /**********************************************************************
1281 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1282 over all printers, resetting printer data as neessary
1283 **********************************************************************/
1285 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1287 fstring drivername;
1288 int snum;
1289 int n_services = lp_numservices();
1291 len = MIN( len, sizeof(drivername)-1 );
1292 strncpy( drivername, buf, len );
1294 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1296 /* Iterate the printer list */
1298 for ( snum=0; snum<n_services; snum++ )
1300 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1302 WERROR result;
1303 NT_PRINTER_INFO_LEVEL *printer = NULL;
1305 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1306 if ( !W_ERROR_IS_OK(result) )
1307 continue;
1310 * if the printer is bound to the driver,
1311 * then reset to the new driver initdata
1314 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1316 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1318 if ( !set_driver_init(printer, 2) ) {
1319 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1320 printer->info_2->printername, printer->info_2->drivername));
1323 result = mod_a_printer( printer, 2 );
1324 if ( !W_ERROR_IS_OK(result) ) {
1325 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1326 get_dos_error_msg(result)));
1330 free_a_printer( &printer, 2 );
1334 /* all done */
1336 return;
1339 /********************************************************************
1340 Copy routines used by convert_to_openprinterex()
1341 *******************************************************************/
1343 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1345 DEVICEMODE *d;
1346 int len;
1348 if (!devmode)
1349 return NULL;
1351 DEBUG (8,("dup_devmode\n"));
1353 /* bulk copy first */
1355 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1356 if (!d)
1357 return NULL;
1359 /* dup the pointer members separately */
1361 len = unistrlen(devmode->devicename.buffer);
1362 if (len != -1) {
1363 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1364 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1365 return NULL;
1369 len = unistrlen(devmode->formname.buffer);
1370 if (len != -1) {
1371 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1372 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1373 return NULL;
1376 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1378 return d;
1381 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1383 if (!new_ctr || !ctr)
1384 return;
1386 DEBUG(8,("copy_devmode_ctr\n"));
1388 new_ctr->size = ctr->size;
1389 new_ctr->devmode_ptr = ctr->devmode_ptr;
1391 if(ctr->devmode_ptr)
1392 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1395 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1397 if (!new_def || !def)
1398 return;
1400 DEBUG(8,("copy_printer_defaults\n"));
1402 new_def->datatype_ptr = def->datatype_ptr;
1404 if (def->datatype_ptr)
1405 copy_unistr2(&new_def->datatype, &def->datatype);
1407 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1409 new_def->access_required = def->access_required;
1412 /********************************************************************
1413 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1414 * SPOOL_Q_OPEN_PRINTER_EX structure
1415 ********************************************************************/
1417 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1419 if (!q_u_ex || !q_u)
1420 return WERR_OK;
1422 DEBUG(8,("convert_to_openprinterex\n"));
1424 if ( q_u->printername ) {
1425 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1426 if (q_u_ex->printername == NULL)
1427 return WERR_NOMEM;
1428 copy_unistr2(q_u_ex->printername, q_u->printername);
1431 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1433 return WERR_OK;
1436 /********************************************************************
1437 * spoolss_open_printer
1439 * called from the spoolss dispatcher
1440 ********************************************************************/
1442 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1444 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1445 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1447 if (!q_u || !r_u)
1448 return WERR_NOMEM;
1450 ZERO_STRUCT(q_u_ex);
1451 ZERO_STRUCT(r_u_ex);
1453 /* convert the OpenPrinter() call to OpenPrinterEx() */
1455 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1456 if (!W_ERROR_IS_OK(r_u_ex.status))
1457 return r_u_ex.status;
1459 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1461 /* convert back to OpenPrinter() */
1463 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1465 return r_u->status;
1468 /********************************************************************
1469 * spoolss_open_printer
1471 * If the openprinterex rpc call contains a devmode,
1472 * it's a per-user one. This per-user devmode is derivated
1473 * from the global devmode. Openprinterex() contains a per-user
1474 * devmode for when you do EMF printing and spooling.
1475 * In the EMF case, the NT workstation is only doing half the job
1476 * of rendering the page. The other half is done by running the printer
1477 * driver on the server.
1478 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1479 * The EMF file only contains what is to be printed on the page.
1480 * So in order for the server to know how to print, the NT client sends
1481 * a devicemode attached to the openprinterex call.
1482 * But this devicemode is short lived, it's only valid for the current print job.
1484 * If Samba would have supported EMF spooling, this devicemode would
1485 * have been attached to the handle, to sent it to the driver to correctly
1486 * rasterize the EMF file.
1488 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1489 * we just act as a pass-thru between windows and the printer.
1491 * In order to know that Samba supports only RAW spooling, NT has to call
1492 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1493 * and until NT sends a RAW job, we refuse it.
1495 * But to call getprinter() or startdoc(), you first need a valid handle,
1496 * and to get an handle you have to call openprintex(). Hence why you have
1497 * a devicemode in the openprinterex() call.
1500 * Differences between NT4 and NT 2000.
1501 * NT4:
1502 * ---
1503 * On NT4, you only have a global devicemode. This global devicemode can be changed
1504 * by the administrator (or by a user with enough privs). Everytime a user
1505 * wants to print, the devicemode is resetted to the default. In Word, everytime
1506 * you print, the printer's characteristics are always reset to the global devicemode.
1508 * NT 2000:
1509 * -------
1510 * In W2K, there is the notion of per-user devicemode. The first time you use
1511 * a printer, a per-user devicemode is build from the global devicemode.
1512 * If you change your per-user devicemode, it is saved in the registry, under the
1513 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1514 * printer preferences available.
1516 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1517 * on the General Tab of the printer properties windows.
1519 * To change the global devicemode: it's the "Printing Defaults..." button
1520 * on the Advanced Tab of the printer properties window.
1522 * JFM.
1523 ********************************************************************/
1525 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1527 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1528 POLICY_HND *handle = &r_u->handle;
1530 fstring name;
1531 int snum;
1532 struct current_user user;
1533 Printer_entry *Printer=NULL;
1535 if ( !q_u->printername )
1536 return WERR_INVALID_PRINTER_NAME;
1538 /* some sanity check because you can open a printer or a print server */
1539 /* aka: \\server\printer or \\server */
1541 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1543 DEBUGADD(3,("checking name: %s\n",name));
1545 if (!open_printer_hnd(p, handle, name, 0))
1546 return WERR_INVALID_PRINTER_NAME;
1548 Printer=find_printer_index_by_hnd(p, handle);
1549 if ( !Printer ) {
1550 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1551 "handle we created for printer %s\n", name ));
1552 close_printer_handle(p,handle);
1553 return WERR_INVALID_PRINTER_NAME;
1556 get_current_user(&user, p);
1559 * First case: the user is opening the print server:
1561 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1562 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1564 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1565 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1566 * or if the user is listed in the smb.conf printer admin parameter.
1568 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1569 * client view printer folder, but does not show the MSAPW.
1571 * Note: this test needs code to check access rights here too. Jeremy
1572 * could you look at this?
1574 * Second case: the user is opening a printer:
1575 * NT doesn't let us connect to a printer if the connecting user
1576 * doesn't have print permission.
1579 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1581 /* Printserver handles use global struct... */
1583 snum = -1;
1585 /* Map standard access rights to object specific access rights */
1587 se_map_standard(&printer_default->access_required,
1588 &printserver_std_mapping);
1590 /* Deny any object specific bits that don't apply to print
1591 servers (i.e printer and job specific bits) */
1593 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1595 if (printer_default->access_required &
1596 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1597 DEBUG(3, ("access DENIED for non-printserver bits"));
1598 close_printer_handle(p, handle);
1599 return WERR_ACCESS_DENIED;
1602 /* Allow admin access */
1604 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1606 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1608 if (!lp_ms_add_printer_wizard()) {
1609 close_printer_handle(p, handle);
1610 return WERR_ACCESS_DENIED;
1613 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1614 and not a printer admin, then fail */
1616 if ( user.uid != 0
1617 && !user_has_privileges( user.nt_user_token, &se_printop )
1618 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1620 close_printer_handle(p, handle);
1621 return WERR_ACCESS_DENIED;
1624 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1626 else
1628 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1631 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1632 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1634 /* We fall through to return WERR_OK */
1637 else
1639 /* NT doesn't let us connect to a printer if the connecting user
1640 doesn't have print permission. */
1642 if (!get_printer_snum(p, handle, &snum)) {
1643 close_printer_handle(p, handle);
1644 return WERR_BADFID;
1647 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1649 /* map an empty access mask to the minimum access mask */
1650 if (printer_default->access_required == 0x0)
1651 printer_default->access_required = PRINTER_ACCESS_USE;
1654 * If we are not serving the printer driver for this printer,
1655 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1656 * will keep NT clients happy --jerry
1659 if (lp_use_client_driver(snum)
1660 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1662 printer_default->access_required = PRINTER_ACCESS_USE;
1665 /* check smb.conf parameters and the the sec_desc */
1667 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1668 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1669 return WERR_ACCESS_DENIED;
1672 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1673 DEBUG(3, ("access DENIED for printer open\n"));
1674 close_printer_handle(p, handle);
1675 return WERR_ACCESS_DENIED;
1678 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1679 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1680 close_printer_handle(p, handle);
1681 return WERR_ACCESS_DENIED;
1684 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1685 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1686 else
1687 printer_default->access_required = PRINTER_ACCESS_USE;
1689 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1690 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1694 Printer->access_granted = printer_default->access_required;
1697 * If the client sent a devmode in the OpenPrinter() call, then
1698 * save it here in case we get a job submission on this handle
1701 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1702 && q_u->printer_default.devmode_cont.devmode_ptr )
1704 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1705 &Printer->nt_devmode );
1708 #if 0 /* JERRY -- I'm doubtful this is really effective */
1709 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1710 optimization in Windows 2000 clients --jerry */
1712 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1713 && (RA_WIN2K == get_remote_arch()) )
1715 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1716 sys_usleep( 500000 );
1718 #endif
1720 return WERR_OK;
1723 /****************************************************************************
1724 ****************************************************************************/
1726 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1727 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1729 BOOL ret = True;
1731 switch (level) {
1732 case 2:
1733 /* printer->info_2 is already a valid printer */
1734 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1735 printer->info_2->setuptime = time(NULL);
1737 break;
1738 default:
1739 break;
1742 return ret;
1745 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1746 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1748 BOOL result = True;
1750 switch (level) {
1751 case 3:
1752 printer->info_3=NULL;
1753 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1754 result = False;
1755 break;
1756 case 6:
1757 printer->info_6=NULL;
1758 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1759 result = False;
1760 break;
1761 default:
1762 break;
1765 return result;
1768 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1769 NT_DEVICEMODE **pp_nt_devmode)
1771 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1774 * Ensure nt_devmode is a valid pointer
1775 * as we will be overwriting it.
1778 if (nt_devmode == NULL) {
1779 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1780 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1781 return False;
1784 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1785 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1787 nt_devmode->specversion=devmode->specversion;
1788 nt_devmode->driverversion=devmode->driverversion;
1789 nt_devmode->size=devmode->size;
1790 nt_devmode->fields=devmode->fields;
1791 nt_devmode->orientation=devmode->orientation;
1792 nt_devmode->papersize=devmode->papersize;
1793 nt_devmode->paperlength=devmode->paperlength;
1794 nt_devmode->paperwidth=devmode->paperwidth;
1795 nt_devmode->scale=devmode->scale;
1796 nt_devmode->copies=devmode->copies;
1797 nt_devmode->defaultsource=devmode->defaultsource;
1798 nt_devmode->printquality=devmode->printquality;
1799 nt_devmode->color=devmode->color;
1800 nt_devmode->duplex=devmode->duplex;
1801 nt_devmode->yresolution=devmode->yresolution;
1802 nt_devmode->ttoption=devmode->ttoption;
1803 nt_devmode->collate=devmode->collate;
1805 nt_devmode->logpixels=devmode->logpixels;
1806 nt_devmode->bitsperpel=devmode->bitsperpel;
1807 nt_devmode->pelswidth=devmode->pelswidth;
1808 nt_devmode->pelsheight=devmode->pelsheight;
1809 nt_devmode->displayflags=devmode->displayflags;
1810 nt_devmode->displayfrequency=devmode->displayfrequency;
1811 nt_devmode->icmmethod=devmode->icmmethod;
1812 nt_devmode->icmintent=devmode->icmintent;
1813 nt_devmode->mediatype=devmode->mediatype;
1814 nt_devmode->dithertype=devmode->dithertype;
1815 nt_devmode->reserved1=devmode->reserved1;
1816 nt_devmode->reserved2=devmode->reserved2;
1817 nt_devmode->panningwidth=devmode->panningwidth;
1818 nt_devmode->panningheight=devmode->panningheight;
1821 * Only change private and driverextra if the incoming devmode
1822 * has a new one. JRA.
1825 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1826 SAFE_FREE(nt_devmode->nt_dev_private);
1827 nt_devmode->driverextra=devmode->driverextra;
1828 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1829 return False;
1830 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1833 *pp_nt_devmode = nt_devmode;
1835 return True;
1838 /********************************************************************
1839 * _spoolss_enddocprinter_internal.
1840 ********************************************************************/
1842 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1844 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1845 int snum;
1847 if (!Printer) {
1848 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1849 return WERR_BADFID;
1852 if (!get_printer_snum(p, handle, &snum))
1853 return WERR_BADFID;
1855 Printer->document_started=False;
1856 print_job_end(snum, Printer->jobid,True);
1857 /* error codes unhandled so far ... */
1859 return WERR_OK;
1862 /********************************************************************
1863 * api_spoolss_closeprinter
1864 ********************************************************************/
1866 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1868 POLICY_HND *handle = &q_u->handle;
1870 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1872 if (Printer && Printer->document_started)
1873 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1875 if (!close_printer_handle(p, handle))
1876 return WERR_BADFID;
1878 /* clear the returned printer handle. Observed behavior
1879 from Win2k server. Don't think this really matters.
1880 Previous code just copied the value of the closed
1881 handle. --jerry */
1883 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1885 return WERR_OK;
1888 /********************************************************************
1889 * api_spoolss_deleteprinter
1891 ********************************************************************/
1893 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1895 POLICY_HND *handle = &q_u->handle;
1896 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1897 WERROR result;
1899 if (Printer && Printer->document_started)
1900 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1902 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1904 result = delete_printer_handle(p, handle);
1906 update_c_setprinter(False);
1908 return result;
1911 /*******************************************************************
1912 * static function to lookup the version id corresponding to an
1913 * long architecture string
1914 ******************************************************************/
1916 static int get_version_id (char * arch)
1918 int i;
1919 struct table_node archi_table[]= {
1921 {"Windows 4.0", "WIN40", 0 },
1922 {"Windows NT x86", "W32X86", 2 },
1923 {"Windows NT R4000", "W32MIPS", 2 },
1924 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1925 {"Windows NT PowerPC", "W32PPC", 2 },
1926 {"Windows IA64", "IA64", 3 },
1927 {"Windows x64", "x64", 3 },
1928 {NULL, "", -1 }
1931 for (i=0; archi_table[i].long_archi != NULL; i++)
1933 if (strcmp(arch, archi_table[i].long_archi) == 0)
1934 return (archi_table[i].version);
1937 return -1;
1940 /********************************************************************
1941 * _spoolss_deleteprinterdriver
1942 ********************************************************************/
1944 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1946 fstring driver;
1947 fstring arch;
1948 NT_PRINTER_DRIVER_INFO_LEVEL info;
1949 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1950 int version;
1951 struct current_user user;
1952 WERROR status;
1953 WERROR status_win2k = WERR_ACCESS_DENIED;
1955 get_current_user(&user, p);
1957 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1958 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1960 /* check that we have a valid driver name first */
1962 if ((version=get_version_id(arch)) == -1)
1963 return WERR_INVALID_ENVIRONMENT;
1965 ZERO_STRUCT(info);
1966 ZERO_STRUCT(info_win2k);
1968 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1970 /* try for Win2k driver if "Windows NT x86" */
1972 if ( version == 2 ) {
1973 version = 3;
1974 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1975 status = WERR_UNKNOWN_PRINTER_DRIVER;
1976 goto done;
1979 /* otherwise it was a failure */
1980 else {
1981 status = WERR_UNKNOWN_PRINTER_DRIVER;
1982 goto done;
1987 if (printer_driver_in_use(info.info_3)) {
1988 status = WERR_PRINTER_DRIVER_IN_USE;
1989 goto done;
1992 if ( version == 2 )
1994 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1996 /* if we get to here, we now have 2 driver info structures to remove */
1997 /* remove the Win2k driver first*/
1999 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2000 free_a_printer_driver( info_win2k, 3 );
2002 /* this should not have failed---if it did, report to client */
2003 if ( !W_ERROR_IS_OK(status_win2k) )
2004 goto done;
2008 status = delete_printer_driver(info.info_3, &user, version, False);
2010 /* if at least one of the deletes succeeded return OK */
2012 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2013 status = WERR_OK;
2015 done:
2016 free_a_printer_driver( info, 3 );
2018 return status;
2021 /********************************************************************
2022 * spoolss_deleteprinterdriverex
2023 ********************************************************************/
2025 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2027 fstring driver;
2028 fstring arch;
2029 NT_PRINTER_DRIVER_INFO_LEVEL info;
2030 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2031 int version;
2032 uint32 flags = q_u->delete_flags;
2033 BOOL delete_files;
2034 struct current_user user;
2035 WERROR status;
2036 WERROR status_win2k = WERR_ACCESS_DENIED;
2038 get_current_user(&user, p);
2040 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2041 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2043 /* check that we have a valid driver name first */
2044 if ((version=get_version_id(arch)) == -1) {
2045 /* this is what NT returns */
2046 return WERR_INVALID_ENVIRONMENT;
2049 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2050 version = q_u->version;
2052 ZERO_STRUCT(info);
2053 ZERO_STRUCT(info_win2k);
2055 status = get_a_printer_driver(&info, 3, driver, arch, version);
2057 if ( !W_ERROR_IS_OK(status) )
2060 * if the client asked for a specific version,
2061 * or this is something other than Windows NT x86,
2062 * then we've failed
2065 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2066 goto done;
2068 /* try for Win2k driver if "Windows NT x86" */
2070 version = 3;
2071 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2072 status = WERR_UNKNOWN_PRINTER_DRIVER;
2073 goto done;
2077 if ( printer_driver_in_use(info.info_3) ) {
2078 status = WERR_PRINTER_DRIVER_IN_USE;
2079 goto done;
2083 * we have a couple of cases to consider.
2084 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2085 * then the delete should fail if **any** files overlap with
2086 * other drivers
2087 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2088 * non-overlapping files
2089 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2090 * is set, the do not delete any files
2091 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2094 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2096 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2098 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2099 /* no idea of the correct error here */
2100 status = WERR_ACCESS_DENIED;
2101 goto done;
2105 /* also check for W32X86/3 if necessary; maybe we already have? */
2107 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2108 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2111 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2112 /* no idea of the correct error here */
2113 free_a_printer_driver( info_win2k, 3 );
2114 status = WERR_ACCESS_DENIED;
2115 goto done;
2118 /* if we get to here, we now have 2 driver info structures to remove */
2119 /* remove the Win2k driver first*/
2121 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2122 free_a_printer_driver( info_win2k, 3 );
2124 /* this should not have failed---if it did, report to client */
2126 if ( !W_ERROR_IS_OK(status_win2k) )
2127 goto done;
2131 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2133 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2134 status = WERR_OK;
2135 done:
2136 free_a_printer_driver( info, 3 );
2138 return status;
2142 /****************************************************************************
2143 Internal routine for retreiving printerdata
2144 ***************************************************************************/
2146 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2147 const char *key, const char *value, uint32 *type, uint8 **data,
2148 uint32 *needed, uint32 in_size )
2150 REGISTRY_VALUE *val;
2151 uint32 size;
2152 int data_len;
2154 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2155 return WERR_BADFILE;
2157 *type = regval_type( val );
2159 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2161 size = regval_size( val );
2163 /* copy the min(in_size, len) */
2165 if ( in_size ) {
2166 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2168 /* special case for 0 length values */
2169 if ( data_len ) {
2170 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2171 return WERR_NOMEM;
2173 else {
2174 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2175 return WERR_NOMEM;
2178 else
2179 *data = NULL;
2181 *needed = size;
2183 DEBUG(5,("get_printer_dataex: copy done\n"));
2185 return WERR_OK;
2188 /****************************************************************************
2189 Internal routine for removing printerdata
2190 ***************************************************************************/
2192 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2194 return delete_printer_data( printer->info_2, key, value );
2197 /****************************************************************************
2198 Internal routine for storing printerdata
2199 ***************************************************************************/
2201 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2202 uint32 type, uint8 *data, int real_len )
2204 /* the registry objects enforce uniqueness based on value name */
2206 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2209 /********************************************************************
2210 GetPrinterData on a printer server Handle.
2211 ********************************************************************/
2213 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2215 int i;
2217 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2219 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2220 *type = REG_DWORD;
2221 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2222 return WERR_NOMEM;
2223 *needed = 0x4;
2224 return WERR_OK;
2227 if (!StrCaseCmp(value, "BeepEnabled")) {
2228 *type = REG_DWORD;
2229 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2230 return WERR_NOMEM;
2231 SIVAL(*data, 0, 0x00);
2232 *needed = 0x4;
2233 return WERR_OK;
2236 if (!StrCaseCmp(value, "EventLog")) {
2237 *type = REG_DWORD;
2238 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2239 return WERR_NOMEM;
2240 /* formally was 0x1b */
2241 SIVAL(*data, 0, 0x0);
2242 *needed = 0x4;
2243 return WERR_OK;
2246 if (!StrCaseCmp(value, "NetPopup")) {
2247 *type = REG_DWORD;
2248 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2249 return WERR_NOMEM;
2250 SIVAL(*data, 0, 0x00);
2251 *needed = 0x4;
2252 return WERR_OK;
2255 if (!StrCaseCmp(value, "MajorVersion")) {
2256 *type = REG_DWORD;
2257 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2258 return WERR_NOMEM;
2260 /* Windows NT 4.0 seems to not allow uploading of drivers
2261 to a server that reports 0x3 as the MajorVersion.
2262 need to investigate more how Win2k gets around this .
2263 -- jerry */
2265 if ( RA_WINNT == get_remote_arch() )
2266 SIVAL(*data, 0, 2);
2267 else
2268 SIVAL(*data, 0, 3);
2270 *needed = 0x4;
2271 return WERR_OK;
2274 if (!StrCaseCmp(value, "MinorVersion")) {
2275 *type = REG_DWORD;
2276 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2277 return WERR_NOMEM;
2278 SIVAL(*data, 0, 0);
2279 *needed = 0x4;
2280 return WERR_OK;
2283 /* REG_BINARY
2284 * uint32 size = 0x114
2285 * uint32 major = 5
2286 * uint32 minor = [0|1]
2287 * uint32 build = [2195|2600]
2288 * extra unicode string = e.g. "Service Pack 3"
2290 if (!StrCaseCmp(value, "OSVersion")) {
2291 *type = REG_BINARY;
2292 *needed = 0x114;
2294 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2295 return WERR_NOMEM;
2297 SIVAL(*data, 0, *needed); /* size */
2298 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2299 SIVAL(*data, 8, 0);
2300 SIVAL(*data, 12, 2195); /* build */
2302 /* leave extra string empty */
2304 return WERR_OK;
2308 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2309 const char *string="C:\\PRINTERS";
2310 *type = REG_SZ;
2311 *needed = 2*(strlen(string)+1);
2312 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2313 return WERR_NOMEM;
2314 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2316 /* it's done by hand ready to go on the wire */
2317 for (i=0; i<strlen(string); i++) {
2318 (*data)[2*i]=string[i];
2319 (*data)[2*i+1]='\0';
2321 return WERR_OK;
2324 if (!StrCaseCmp(value, "Architecture")) {
2325 const char *string="Windows NT x86";
2326 *type = REG_SZ;
2327 *needed = 2*(strlen(string)+1);
2328 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2329 return WERR_NOMEM;
2330 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2331 for (i=0; i<strlen(string); i++) {
2332 (*data)[2*i]=string[i];
2333 (*data)[2*i+1]='\0';
2335 return WERR_OK;
2338 if (!StrCaseCmp(value, "DsPresent")) {
2339 *type = REG_DWORD;
2340 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2341 return WERR_NOMEM;
2343 /* only show the publish check box if we are a
2344 memeber of a AD domain */
2346 if ( lp_security() == SEC_ADS )
2347 SIVAL(*data, 0, 0x01);
2348 else
2349 SIVAL(*data, 0, 0x00);
2351 *needed = 0x4;
2352 return WERR_OK;
2355 if (!StrCaseCmp(value, "DNSMachineName")) {
2356 pstring hostname;
2358 if (!get_mydnsfullname(hostname))
2359 return WERR_BADFILE;
2360 *type = REG_SZ;
2361 *needed = 2*(strlen(hostname)+1);
2362 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2363 return WERR_NOMEM;
2364 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2365 for (i=0; i<strlen(hostname); i++) {
2366 (*data)[2*i]=hostname[i];
2367 (*data)[2*i+1]='\0';
2369 return WERR_OK;
2373 return WERR_BADFILE;
2376 /********************************************************************
2377 * spoolss_getprinterdata
2378 ********************************************************************/
2380 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2382 POLICY_HND *handle = &q_u->handle;
2383 UNISTR2 *valuename = &q_u->valuename;
2384 uint32 in_size = q_u->size;
2385 uint32 *type = &r_u->type;
2386 uint32 *out_size = &r_u->size;
2387 uint8 **data = &r_u->data;
2388 uint32 *needed = &r_u->needed;
2389 WERROR status;
2390 fstring value;
2391 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2392 NT_PRINTER_INFO_LEVEL *printer = NULL;
2393 int snum = 0;
2396 * Reminder: when it's a string, the length is in BYTES
2397 * even if UNICODE is negociated.
2399 * JFM, 4/19/1999
2402 *out_size = in_size;
2404 /* in case of problem, return some default values */
2406 *needed = 0;
2407 *type = 0;
2409 DEBUG(4,("_spoolss_getprinterdata\n"));
2411 if ( !Printer ) {
2412 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2413 status = WERR_BADFID;
2414 goto done;
2417 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2419 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2420 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2421 else
2423 if ( !get_printer_snum(p,handle, &snum) ) {
2424 status = WERR_BADFID;
2425 goto done;
2428 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2429 if ( !W_ERROR_IS_OK(status) )
2430 goto done;
2432 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2434 if ( strequal(value, "ChangeId") ) {
2435 *type = REG_DWORD;
2436 *needed = sizeof(uint32);
2437 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2438 status = WERR_NOMEM;
2439 goto done;
2441 SIVAL( *data, 0, printer->info_2->changeid );
2442 status = WERR_OK;
2444 else
2445 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2448 if (*needed > *out_size)
2449 status = WERR_MORE_DATA;
2451 done:
2452 if ( !W_ERROR_IS_OK(status) )
2454 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2456 /* reply this param doesn't exist */
2458 if ( *out_size ) {
2459 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2460 if ( printer )
2461 free_a_printer( &printer, 2 );
2462 return WERR_NOMEM;
2465 else {
2466 *data = NULL;
2470 /* cleanup & exit */
2472 if ( printer )
2473 free_a_printer( &printer, 2 );
2475 return status;
2478 /*********************************************************
2479 Connect to the client machine.
2480 **********************************************************/
2482 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2483 struct in_addr *client_ip, const char *remote_machine)
2485 ZERO_STRUCTP(the_cli);
2487 if(cli_initialise(the_cli) == NULL) {
2488 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2489 return False;
2492 if ( is_zero_ip(*client_ip) ) {
2493 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2494 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2495 cli_shutdown(the_cli);
2496 return False;
2499 if (ismyip(the_cli->dest_ip)) {
2500 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2501 cli_shutdown(the_cli);
2502 return False;
2505 else {
2506 the_cli->dest_ip.s_addr = client_ip->s_addr;
2507 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2508 inet_ntoa(*client_ip) ));
2511 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2512 DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2513 cli_shutdown(the_cli);
2514 return False;
2517 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2518 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2519 remote_machine));
2520 cli_shutdown(the_cli);
2521 return False;
2524 the_cli->protocol = PROTOCOL_NT1;
2525 cli_setup_signing_state(the_cli, lp_client_signing());
2527 if (!cli_negprot(the_cli)) {
2528 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2529 cli_shutdown(the_cli);
2530 return False;
2533 if (the_cli->protocol != PROTOCOL_NT1) {
2534 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2535 cli_shutdown(the_cli);
2536 return False;
2540 * Do an anonymous session setup.
2543 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2544 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2545 cli_shutdown(the_cli);
2546 return False;
2549 if (!(the_cli->sec_mode & 1)) {
2550 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2551 cli_shutdown(the_cli);
2552 return False;
2555 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2556 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2557 cli_shutdown(the_cli);
2558 return False;
2562 * Ok - we have an anonymous connection to the IPC$ share.
2563 * Now start the NT Domain stuff :-).
2566 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2567 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2568 cli_nt_session_close(the_cli);
2569 cli_ulogoff(the_cli);
2570 cli_shutdown(the_cli);
2571 return False;
2574 return True;
2577 /***************************************************************************
2578 Connect to the client.
2579 ****************************************************************************/
2581 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2582 uint32 localprinter, uint32 type,
2583 POLICY_HND *handle, struct in_addr *client_ip)
2585 WERROR result;
2588 * If it's the first connection, contact the client
2589 * and connect to the IPC$ share anonymously
2591 if (smb_connections==0) {
2592 fstring unix_printer;
2594 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2596 ZERO_STRUCT(notify_cli);
2598 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2599 return False;
2601 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2602 /* Tell the connections db we're now interested in printer
2603 * notify messages. */
2604 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2608 * Tell the specific printing tdb we want messages for this printer
2609 * by registering our PID.
2612 if (!print_notify_register_pid(snum))
2613 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2615 smb_connections++;
2617 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2618 type, handle);
2620 if (!W_ERROR_IS_OK(result))
2621 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2622 dos_errstr(result)));
2624 return (W_ERROR_IS_OK(result));
2627 /********************************************************************
2628 * _spoolss_rffpcnex
2629 * ReplyFindFirstPrinterChangeNotifyEx
2631 * before replying OK: status=0 a rpc call is made to the workstation
2632 * asking ReplyOpenPrinter
2634 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2635 * called from api_spoolss_rffpcnex
2636 ********************************************************************/
2638 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2640 POLICY_HND *handle = &q_u->handle;
2641 uint32 flags = q_u->flags;
2642 uint32 options = q_u->options;
2643 UNISTR2 *localmachine = &q_u->localmachine;
2644 uint32 printerlocal = q_u->printerlocal;
2645 int snum = -1;
2646 SPOOL_NOTIFY_OPTION *option = q_u->option;
2647 struct in_addr client_ip;
2649 /* store the notify value in the printer struct */
2651 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2653 if (!Printer) {
2654 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2655 return WERR_BADFID;
2658 Printer->notify.flags=flags;
2659 Printer->notify.options=options;
2660 Printer->notify.printerlocal=printerlocal;
2662 if (Printer->notify.option)
2663 free_spool_notify_option(&Printer->notify.option);
2665 Printer->notify.option=dup_spool_notify_option(option);
2667 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2668 sizeof(Printer->notify.localmachine)-1);
2670 /* Connect to the client machine and send a ReplyOpenPrinter */
2672 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2673 snum = -1;
2674 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2675 !get_printer_snum(p, handle, &snum) )
2676 return WERR_BADFID;
2678 client_ip.s_addr = inet_addr(p->conn->client_address);
2680 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2681 Printer->notify.printerlocal, 1,
2682 &Printer->notify.client_hnd, &client_ip))
2683 return WERR_SERVER_UNAVAILABLE;
2685 Printer->notify.client_connected=True;
2687 return WERR_OK;
2690 /*******************************************************************
2691 * fill a notify_info_data with the servername
2692 ********************************************************************/
2694 void spoolss_notify_server_name(int snum,
2695 SPOOL_NOTIFY_INFO_DATA *data,
2696 print_queue_struct *queue,
2697 NT_PRINTER_INFO_LEVEL *printer,
2698 TALLOC_CTX *mem_ctx)
2700 pstring temp;
2701 uint32 len;
2703 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2705 data->notify_data.data.length = len;
2706 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2708 if (!data->notify_data.data.string) {
2709 data->notify_data.data.length = 0;
2710 return;
2713 memcpy(data->notify_data.data.string, temp, len);
2716 /*******************************************************************
2717 * fill a notify_info_data with the printername (not including the servername).
2718 ********************************************************************/
2720 void spoolss_notify_printer_name(int snum,
2721 SPOOL_NOTIFY_INFO_DATA *data,
2722 print_queue_struct *queue,
2723 NT_PRINTER_INFO_LEVEL *printer,
2724 TALLOC_CTX *mem_ctx)
2726 pstring temp;
2727 uint32 len;
2729 /* the notify name should not contain the \\server\ part */
2730 char *p = strrchr(printer->info_2->printername, '\\');
2732 if (!p) {
2733 p = printer->info_2->printername;
2734 } else {
2735 p++;
2738 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2740 data->notify_data.data.length = len;
2741 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2743 if (!data->notify_data.data.string) {
2744 data->notify_data.data.length = 0;
2745 return;
2748 memcpy(data->notify_data.data.string, temp, len);
2751 /*******************************************************************
2752 * fill a notify_info_data with the servicename
2753 ********************************************************************/
2755 void spoolss_notify_share_name(int snum,
2756 SPOOL_NOTIFY_INFO_DATA *data,
2757 print_queue_struct *queue,
2758 NT_PRINTER_INFO_LEVEL *printer,
2759 TALLOC_CTX *mem_ctx)
2761 pstring temp;
2762 uint32 len;
2764 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2766 data->notify_data.data.length = len;
2767 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2769 if (!data->notify_data.data.string) {
2770 data->notify_data.data.length = 0;
2771 return;
2774 memcpy(data->notify_data.data.string, temp, len);
2777 /*******************************************************************
2778 * fill a notify_info_data with the port name
2779 ********************************************************************/
2781 void spoolss_notify_port_name(int snum,
2782 SPOOL_NOTIFY_INFO_DATA *data,
2783 print_queue_struct *queue,
2784 NT_PRINTER_INFO_LEVEL *printer,
2785 TALLOC_CTX *mem_ctx)
2787 pstring temp;
2788 uint32 len;
2790 /* even if it's strange, that's consistant in all the code */
2792 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2794 data->notify_data.data.length = len;
2795 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2797 if (!data->notify_data.data.string) {
2798 data->notify_data.data.length = 0;
2799 return;
2802 memcpy(data->notify_data.data.string, temp, len);
2805 /*******************************************************************
2806 * fill a notify_info_data with the printername
2807 * but it doesn't exist, have to see what to do
2808 ********************************************************************/
2810 void spoolss_notify_driver_name(int snum,
2811 SPOOL_NOTIFY_INFO_DATA *data,
2812 print_queue_struct *queue,
2813 NT_PRINTER_INFO_LEVEL *printer,
2814 TALLOC_CTX *mem_ctx)
2816 pstring temp;
2817 uint32 len;
2819 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2821 data->notify_data.data.length = len;
2822 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2824 if (!data->notify_data.data.string) {
2825 data->notify_data.data.length = 0;
2826 return;
2829 memcpy(data->notify_data.data.string, temp, len);
2832 /*******************************************************************
2833 * fill a notify_info_data with the comment
2834 ********************************************************************/
2836 void spoolss_notify_comment(int snum,
2837 SPOOL_NOTIFY_INFO_DATA *data,
2838 print_queue_struct *queue,
2839 NT_PRINTER_INFO_LEVEL *printer,
2840 TALLOC_CTX *mem_ctx)
2842 pstring temp;
2843 uint32 len;
2845 if (*printer->info_2->comment == '\0')
2846 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2847 else
2848 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2850 data->notify_data.data.length = len;
2851 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2853 if (!data->notify_data.data.string) {
2854 data->notify_data.data.length = 0;
2855 return;
2858 memcpy(data->notify_data.data.string, temp, len);
2861 /*******************************************************************
2862 * fill a notify_info_data with the comment
2863 * location = "Room 1, floor 2, building 3"
2864 ********************************************************************/
2866 void spoolss_notify_location(int snum,
2867 SPOOL_NOTIFY_INFO_DATA *data,
2868 print_queue_struct *queue,
2869 NT_PRINTER_INFO_LEVEL *printer,
2870 TALLOC_CTX *mem_ctx)
2872 pstring temp;
2873 uint32 len;
2875 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2877 data->notify_data.data.length = len;
2878 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2880 if (!data->notify_data.data.string) {
2881 data->notify_data.data.length = 0;
2882 return;
2885 memcpy(data->notify_data.data.string, temp, len);
2888 /*******************************************************************
2889 * fill a notify_info_data with the device mode
2890 * jfm:xxxx don't to it for know but that's a real problem !!!
2891 ********************************************************************/
2893 static void spoolss_notify_devmode(int snum,
2894 SPOOL_NOTIFY_INFO_DATA *data,
2895 print_queue_struct *queue,
2896 NT_PRINTER_INFO_LEVEL *printer,
2897 TALLOC_CTX *mem_ctx)
2901 /*******************************************************************
2902 * fill a notify_info_data with the separator file name
2903 ********************************************************************/
2905 void spoolss_notify_sepfile(int snum,
2906 SPOOL_NOTIFY_INFO_DATA *data,
2907 print_queue_struct *queue,
2908 NT_PRINTER_INFO_LEVEL *printer,
2909 TALLOC_CTX *mem_ctx)
2911 pstring temp;
2912 uint32 len;
2914 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2916 data->notify_data.data.length = len;
2917 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2919 if (!data->notify_data.data.string) {
2920 data->notify_data.data.length = 0;
2921 return;
2924 memcpy(data->notify_data.data.string, temp, len);
2927 /*******************************************************************
2928 * fill a notify_info_data with the print processor
2929 * jfm:xxxx return always winprint to indicate we don't do anything to it
2930 ********************************************************************/
2932 void spoolss_notify_print_processor(int snum,
2933 SPOOL_NOTIFY_INFO_DATA *data,
2934 print_queue_struct *queue,
2935 NT_PRINTER_INFO_LEVEL *printer,
2936 TALLOC_CTX *mem_ctx)
2938 pstring temp;
2939 uint32 len;
2941 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2943 data->notify_data.data.length = len;
2944 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2946 if (!data->notify_data.data.string) {
2947 data->notify_data.data.length = 0;
2948 return;
2951 memcpy(data->notify_data.data.string, temp, len);
2954 /*******************************************************************
2955 * fill a notify_info_data with the print processor options
2956 * jfm:xxxx send an empty string
2957 ********************************************************************/
2959 void spoolss_notify_parameters(int snum,
2960 SPOOL_NOTIFY_INFO_DATA *data,
2961 print_queue_struct *queue,
2962 NT_PRINTER_INFO_LEVEL *printer,
2963 TALLOC_CTX *mem_ctx)
2965 pstring temp;
2966 uint32 len;
2968 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2970 data->notify_data.data.length = len;
2971 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2973 if (!data->notify_data.data.string) {
2974 data->notify_data.data.length = 0;
2975 return;
2978 memcpy(data->notify_data.data.string, temp, len);
2981 /*******************************************************************
2982 * fill a notify_info_data with the data type
2983 * jfm:xxxx always send RAW as data type
2984 ********************************************************************/
2986 void spoolss_notify_datatype(int snum,
2987 SPOOL_NOTIFY_INFO_DATA *data,
2988 print_queue_struct *queue,
2989 NT_PRINTER_INFO_LEVEL *printer,
2990 TALLOC_CTX *mem_ctx)
2992 pstring temp;
2993 uint32 len;
2995 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2997 data->notify_data.data.length = len;
2998 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3000 if (!data->notify_data.data.string) {
3001 data->notify_data.data.length = 0;
3002 return;
3005 memcpy(data->notify_data.data.string, temp, len);
3008 /*******************************************************************
3009 * fill a notify_info_data with the security descriptor
3010 * jfm:xxxx send an null pointer to say no security desc
3011 * have to implement security before !
3012 ********************************************************************/
3014 static void spoolss_notify_security_desc(int snum,
3015 SPOOL_NOTIFY_INFO_DATA *data,
3016 print_queue_struct *queue,
3017 NT_PRINTER_INFO_LEVEL *printer,
3018 TALLOC_CTX *mem_ctx)
3020 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3021 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3024 /*******************************************************************
3025 * fill a notify_info_data with the attributes
3026 * jfm:xxxx a samba printer is always shared
3027 ********************************************************************/
3029 void spoolss_notify_attributes(int snum,
3030 SPOOL_NOTIFY_INFO_DATA *data,
3031 print_queue_struct *queue,
3032 NT_PRINTER_INFO_LEVEL *printer,
3033 TALLOC_CTX *mem_ctx)
3035 data->notify_data.value[0] = printer->info_2->attributes;
3036 data->notify_data.value[1] = 0;
3039 /*******************************************************************
3040 * fill a notify_info_data with the priority
3041 ********************************************************************/
3043 static void spoolss_notify_priority(int snum,
3044 SPOOL_NOTIFY_INFO_DATA *data,
3045 print_queue_struct *queue,
3046 NT_PRINTER_INFO_LEVEL *printer,
3047 TALLOC_CTX *mem_ctx)
3049 data->notify_data.value[0] = printer->info_2->priority;
3050 data->notify_data.value[1] = 0;
3053 /*******************************************************************
3054 * fill a notify_info_data with the default priority
3055 ********************************************************************/
3057 static void spoolss_notify_default_priority(int snum,
3058 SPOOL_NOTIFY_INFO_DATA *data,
3059 print_queue_struct *queue,
3060 NT_PRINTER_INFO_LEVEL *printer,
3061 TALLOC_CTX *mem_ctx)
3063 data->notify_data.value[0] = printer->info_2->default_priority;
3064 data->notify_data.value[1] = 0;
3067 /*******************************************************************
3068 * fill a notify_info_data with the start time
3069 ********************************************************************/
3071 static void spoolss_notify_start_time(int snum,
3072 SPOOL_NOTIFY_INFO_DATA *data,
3073 print_queue_struct *queue,
3074 NT_PRINTER_INFO_LEVEL *printer,
3075 TALLOC_CTX *mem_ctx)
3077 data->notify_data.value[0] = printer->info_2->starttime;
3078 data->notify_data.value[1] = 0;
3081 /*******************************************************************
3082 * fill a notify_info_data with the until time
3083 ********************************************************************/
3085 static void spoolss_notify_until_time(int snum,
3086 SPOOL_NOTIFY_INFO_DATA *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3091 data->notify_data.value[0] = printer->info_2->untiltime;
3092 data->notify_data.value[1] = 0;
3095 /*******************************************************************
3096 * fill a notify_info_data with the status
3097 ********************************************************************/
3099 static void spoolss_notify_status(int snum,
3100 SPOOL_NOTIFY_INFO_DATA *data,
3101 print_queue_struct *queue,
3102 NT_PRINTER_INFO_LEVEL *printer,
3103 TALLOC_CTX *mem_ctx)
3105 print_status_struct status;
3107 print_queue_length(snum, &status);
3108 data->notify_data.value[0]=(uint32) status.status;
3109 data->notify_data.value[1] = 0;
3112 /*******************************************************************
3113 * fill a notify_info_data with the number of jobs queued
3114 ********************************************************************/
3116 void spoolss_notify_cjobs(int snum,
3117 SPOOL_NOTIFY_INFO_DATA *data,
3118 print_queue_struct *queue,
3119 NT_PRINTER_INFO_LEVEL *printer,
3120 TALLOC_CTX *mem_ctx)
3122 data->notify_data.value[0] = print_queue_length(snum, NULL);
3123 data->notify_data.value[1] = 0;
3126 /*******************************************************************
3127 * fill a notify_info_data with the average ppm
3128 ********************************************************************/
3130 static void spoolss_notify_average_ppm(int snum,
3131 SPOOL_NOTIFY_INFO_DATA *data,
3132 print_queue_struct *queue,
3133 NT_PRINTER_INFO_LEVEL *printer,
3134 TALLOC_CTX *mem_ctx)
3136 /* always respond 8 pages per minutes */
3137 /* a little hard ! */
3138 data->notify_data.value[0] = printer->info_2->averageppm;
3139 data->notify_data.value[1] = 0;
3142 /*******************************************************************
3143 * fill a notify_info_data with username
3144 ********************************************************************/
3146 static void spoolss_notify_username(int snum,
3147 SPOOL_NOTIFY_INFO_DATA *data,
3148 print_queue_struct *queue,
3149 NT_PRINTER_INFO_LEVEL *printer,
3150 TALLOC_CTX *mem_ctx)
3152 pstring temp;
3153 uint32 len;
3155 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3157 data->notify_data.data.length = len;
3158 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3160 if (!data->notify_data.data.string) {
3161 data->notify_data.data.length = 0;
3162 return;
3165 memcpy(data->notify_data.data.string, temp, len);
3168 /*******************************************************************
3169 * fill a notify_info_data with job status
3170 ********************************************************************/
3172 static void spoolss_notify_job_status(int snum,
3173 SPOOL_NOTIFY_INFO_DATA *data,
3174 print_queue_struct *queue,
3175 NT_PRINTER_INFO_LEVEL *printer,
3176 TALLOC_CTX *mem_ctx)
3178 data->notify_data.value[0]=nt_printj_status(queue->status);
3179 data->notify_data.value[1] = 0;
3182 /*******************************************************************
3183 * fill a notify_info_data with job name
3184 ********************************************************************/
3186 static void spoolss_notify_job_name(int snum,
3187 SPOOL_NOTIFY_INFO_DATA *data,
3188 print_queue_struct *queue,
3189 NT_PRINTER_INFO_LEVEL *printer,
3190 TALLOC_CTX *mem_ctx)
3192 pstring temp;
3193 uint32 len;
3195 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3197 data->notify_data.data.length = len;
3198 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3200 if (!data->notify_data.data.string) {
3201 data->notify_data.data.length = 0;
3202 return;
3205 memcpy(data->notify_data.data.string, temp, len);
3208 /*******************************************************************
3209 * fill a notify_info_data with job status
3210 ********************************************************************/
3212 static void spoolss_notify_job_status_string(int snum,
3213 SPOOL_NOTIFY_INFO_DATA *data,
3214 print_queue_struct *queue,
3215 NT_PRINTER_INFO_LEVEL *printer,
3216 TALLOC_CTX *mem_ctx)
3219 * Now we're returning job status codes we just return a "" here. JRA.
3222 const char *p = "";
3223 pstring temp;
3224 uint32 len;
3226 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3227 p = "unknown";
3229 switch (queue->status) {
3230 case LPQ_QUEUED:
3231 p = "Queued";
3232 break;
3233 case LPQ_PAUSED:
3234 p = ""; /* NT provides the paused string */
3235 break;
3236 case LPQ_SPOOLING:
3237 p = "Spooling";
3238 break;
3239 case LPQ_PRINTING:
3240 p = "Printing";
3241 break;
3243 #endif /* NO LONGER NEEDED. */
3245 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3247 data->notify_data.data.length = len;
3248 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3250 if (!data->notify_data.data.string) {
3251 data->notify_data.data.length = 0;
3252 return;
3255 memcpy(data->notify_data.data.string, temp, len);
3258 /*******************************************************************
3259 * fill a notify_info_data with job time
3260 ********************************************************************/
3262 static void spoolss_notify_job_time(int snum,
3263 SPOOL_NOTIFY_INFO_DATA *data,
3264 print_queue_struct *queue,
3265 NT_PRINTER_INFO_LEVEL *printer,
3266 TALLOC_CTX *mem_ctx)
3268 data->notify_data.value[0]=0x0;
3269 data->notify_data.value[1]=0;
3272 /*******************************************************************
3273 * fill a notify_info_data with job size
3274 ********************************************************************/
3276 static void spoolss_notify_job_size(int snum,
3277 SPOOL_NOTIFY_INFO_DATA *data,
3278 print_queue_struct *queue,
3279 NT_PRINTER_INFO_LEVEL *printer,
3280 TALLOC_CTX *mem_ctx)
3282 data->notify_data.value[0]=queue->size;
3283 data->notify_data.value[1]=0;
3286 /*******************************************************************
3287 * fill a notify_info_data with page info
3288 ********************************************************************/
3289 static void spoolss_notify_total_pages(int snum,
3290 SPOOL_NOTIFY_INFO_DATA *data,
3291 print_queue_struct *queue,
3292 NT_PRINTER_INFO_LEVEL *printer,
3293 TALLOC_CTX *mem_ctx)
3295 data->notify_data.value[0]=queue->page_count;
3296 data->notify_data.value[1]=0;
3299 /*******************************************************************
3300 * fill a notify_info_data with pages printed info.
3301 ********************************************************************/
3302 static void spoolss_notify_pages_printed(int snum,
3303 SPOOL_NOTIFY_INFO_DATA *data,
3304 print_queue_struct *queue,
3305 NT_PRINTER_INFO_LEVEL *printer,
3306 TALLOC_CTX *mem_ctx)
3308 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3309 data->notify_data.value[1]=0;
3312 /*******************************************************************
3313 Fill a notify_info_data with job position.
3314 ********************************************************************/
3316 static void spoolss_notify_job_position(int snum,
3317 SPOOL_NOTIFY_INFO_DATA *data,
3318 print_queue_struct *queue,
3319 NT_PRINTER_INFO_LEVEL *printer,
3320 TALLOC_CTX *mem_ctx)
3322 data->notify_data.value[0]=queue->job;
3323 data->notify_data.value[1]=0;
3326 /*******************************************************************
3327 Fill a notify_info_data with submitted time.
3328 ********************************************************************/
3330 static void spoolss_notify_submitted_time(int snum,
3331 SPOOL_NOTIFY_INFO_DATA *data,
3332 print_queue_struct *queue,
3333 NT_PRINTER_INFO_LEVEL *printer,
3334 TALLOC_CTX *mem_ctx)
3336 struct tm *t;
3337 uint32 len;
3338 SYSTEMTIME st;
3339 char *p;
3341 t=gmtime(&queue->time);
3343 len = sizeof(SYSTEMTIME);
3345 data->notify_data.data.length = len;
3346 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3348 if (!data->notify_data.data.string) {
3349 data->notify_data.data.length = 0;
3350 return;
3353 make_systemtime(&st, t);
3356 * Systemtime must be linearized as a set of UINT16's.
3357 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3360 p = (char *)data->notify_data.data.string;
3361 SSVAL(p, 0, st.year);
3362 SSVAL(p, 2, st.month);
3363 SSVAL(p, 4, st.dayofweek);
3364 SSVAL(p, 6, st.day);
3365 SSVAL(p, 8, st.hour);
3366 SSVAL(p, 10, st.minute);
3367 SSVAL(p, 12, st.second);
3368 SSVAL(p, 14, st.milliseconds);
3371 struct s_notify_info_data_table
3373 uint16 type;
3374 uint16 field;
3375 const char *name;
3376 uint32 size;
3377 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3378 print_queue_struct *queue,
3379 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3382 /* A table describing the various print notification constants and
3383 whether the notification data is a pointer to a variable sized
3384 buffer, a one value uint32 or a two value uint32. */
3386 static const struct s_notify_info_data_table notify_info_data_table[] =
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3437 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3440 /*******************************************************************
3441 Return the size of info_data structure.
3442 ********************************************************************/
3444 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3446 int i=0;
3448 for (i = 0; i < sizeof(notify_info_data_table); i++)
3450 if ( (notify_info_data_table[i].type == type)
3451 && (notify_info_data_table[i].field == field) )
3453 switch(notify_info_data_table[i].size)
3455 case NOTIFY_ONE_VALUE:
3456 case NOTIFY_TWO_VALUE:
3457 return 1;
3458 case NOTIFY_STRING:
3459 return 2;
3461 /* The only pointer notify data I have seen on
3462 the wire is the submitted time and this has
3463 the notify size set to 4. -tpot */
3465 case NOTIFY_POINTER:
3466 return 4;
3468 case NOTIFY_SECDESC:
3469 return 5;
3474 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3476 return 0;
3479 /*******************************************************************
3480 Return the type of notify_info_data.
3481 ********************************************************************/
3483 static int type_of_notify_info_data(uint16 type, uint16 field)
3485 int i=0;
3487 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3488 if (notify_info_data_table[i].type == type &&
3489 notify_info_data_table[i].field == field)
3490 return notify_info_data_table[i].size;
3493 return False;
3496 /****************************************************************************
3497 ****************************************************************************/
3499 static int search_notify(uint16 type, uint16 field, int *value)
3501 int i;
3503 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3504 if (notify_info_data_table[i].type == type &&
3505 notify_info_data_table[i].field == field &&
3506 notify_info_data_table[i].fn != NULL) {
3507 *value = i;
3508 return True;
3512 return False;
3515 /****************************************************************************
3516 ****************************************************************************/
3518 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3520 info_data->type = type;
3521 info_data->field = field;
3522 info_data->reserved = 0;
3524 info_data->size = size_of_notify_info_data(type, field);
3525 info_data->enc_type = type_of_notify_info_data(type, field);
3527 info_data->id = id;
3532 /*******************************************************************
3534 * fill a notify_info struct with info asked
3536 ********************************************************************/
3538 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3539 snum, SPOOL_NOTIFY_OPTION_TYPE
3540 *option_type, uint32 id,
3541 TALLOC_CTX *mem_ctx)
3543 int field_num,j;
3544 uint16 type;
3545 uint16 field;
3547 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3548 NT_PRINTER_INFO_LEVEL *printer = NULL;
3549 print_queue_struct *queue=NULL;
3551 type=option_type->type;
3553 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3554 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3555 option_type->count, lp_servicename(snum)));
3557 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3558 return False;
3560 for(field_num=0; field_num<option_type->count; field_num++) {
3561 field = option_type->fields[field_num];
3563 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3565 if (!search_notify(type, field, &j) )
3566 continue;
3568 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3569 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3570 return False;
3571 } else
3572 info->data = tid;
3574 current_data = &info->data[info->count];
3576 construct_info_data(current_data, type, field, id);
3578 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3579 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3581 notify_info_data_table[j].fn(snum, current_data, queue,
3582 printer, mem_ctx);
3584 info->count++;
3587 free_a_printer(&printer, 2);
3588 return True;
3591 /*******************************************************************
3593 * fill a notify_info struct with info asked
3595 ********************************************************************/
3597 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3598 SPOOL_NOTIFY_INFO *info,
3599 NT_PRINTER_INFO_LEVEL *printer,
3600 int snum, SPOOL_NOTIFY_OPTION_TYPE
3601 *option_type, uint32 id,
3602 TALLOC_CTX *mem_ctx)
3604 int field_num,j;
3605 uint16 type;
3606 uint16 field;
3608 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3610 DEBUG(4,("construct_notify_jobs_info\n"));
3612 type = option_type->type;
3614 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3615 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3616 option_type->count));
3618 for(field_num=0; field_num<option_type->count; field_num++) {
3619 field = option_type->fields[field_num];
3621 if (!search_notify(type, field, &j) )
3622 continue;
3624 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3625 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3626 return False;
3628 else info->data = tid;
3630 current_data=&(info->data[info->count]);
3632 construct_info_data(current_data, type, field, id);
3633 notify_info_data_table[j].fn(snum, current_data, queue,
3634 printer, mem_ctx);
3635 info->count++;
3638 return True;
3642 * JFM: The enumeration is not that simple, it's even non obvious.
3644 * let's take an example: I want to monitor the PRINTER SERVER for
3645 * the printer's name and the number of jobs currently queued.
3646 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3647 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3649 * I have 3 printers on the back of my server.
3651 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3652 * structures.
3653 * Number Data Id
3654 * 1 printer 1 name 1
3655 * 2 printer 1 cjob 1
3656 * 3 printer 2 name 2
3657 * 4 printer 2 cjob 2
3658 * 5 printer 3 name 3
3659 * 6 printer 3 name 3
3661 * that's the print server case, the printer case is even worse.
3664 /*******************************************************************
3666 * enumerate all printers on the printserver
3667 * fill a notify_info struct with info asked
3669 ********************************************************************/
3671 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3672 SPOOL_NOTIFY_INFO *info,
3673 TALLOC_CTX *mem_ctx)
3675 int snum;
3676 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3677 int n_services=lp_numservices();
3678 int i;
3679 SPOOL_NOTIFY_OPTION *option;
3680 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3682 DEBUG(4,("printserver_notify_info\n"));
3684 if (!Printer)
3685 return WERR_BADFID;
3687 option=Printer->notify.option;
3688 info->version=2;
3689 info->data=NULL;
3690 info->count=0;
3692 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3693 sending a ffpcn() request first */
3695 if ( !option )
3696 return WERR_BADFID;
3698 for (i=0; i<option->count; i++) {
3699 option_type=&(option->ctr.type[i]);
3701 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3702 continue;
3704 for (snum=0; snum<n_services; snum++)
3706 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3707 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3711 #if 0
3713 * Debugging information, don't delete.
3716 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3717 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3718 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3720 for (i=0; i<info->count; i++) {
3721 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3722 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3723 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3725 #endif
3727 return WERR_OK;
3730 /*******************************************************************
3732 * fill a notify_info struct with info asked
3734 ********************************************************************/
3736 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3737 TALLOC_CTX *mem_ctx)
3739 int snum;
3740 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3741 int i;
3742 uint32 id;
3743 SPOOL_NOTIFY_OPTION *option;
3744 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3745 int count,j;
3746 print_queue_struct *queue=NULL;
3747 print_status_struct status;
3749 DEBUG(4,("printer_notify_info\n"));
3751 if (!Printer)
3752 return WERR_BADFID;
3754 option=Printer->notify.option;
3755 id = 0x0;
3756 info->version=2;
3757 info->data=NULL;
3758 info->count=0;
3760 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3761 sending a ffpcn() request first */
3763 if ( !option )
3764 return WERR_BADFID;
3766 get_printer_snum(p, hnd, &snum);
3768 for (i=0; i<option->count; i++) {
3769 option_type=&option->ctr.type[i];
3771 switch ( option_type->type ) {
3772 case PRINTER_NOTIFY_TYPE:
3773 if(construct_notify_printer_info(Printer, info, snum,
3774 option_type, id,
3775 mem_ctx))
3776 id--;
3777 break;
3779 case JOB_NOTIFY_TYPE: {
3780 NT_PRINTER_INFO_LEVEL *printer = NULL;
3782 count = print_queue_status(snum, &queue, &status);
3784 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3785 goto done;
3787 for (j=0; j<count; j++) {
3788 construct_notify_jobs_info(&queue[j], info,
3789 printer, snum,
3790 option_type,
3791 queue[j].job,
3792 mem_ctx);
3795 free_a_printer(&printer, 2);
3797 done:
3798 SAFE_FREE(queue);
3799 break;
3805 * Debugging information, don't delete.
3808 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3809 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3810 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3812 for (i=0; i<info->count; i++) {
3813 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3814 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3815 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3818 return WERR_OK;
3821 /********************************************************************
3822 * spoolss_rfnpcnex
3823 ********************************************************************/
3825 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3827 POLICY_HND *handle = &q_u->handle;
3828 SPOOL_NOTIFY_INFO *info = &r_u->info;
3830 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3831 WERROR result = WERR_BADFID;
3833 /* we always have a NOTIFY_INFO struct */
3834 r_u->info_ptr=0x1;
3836 if (!Printer) {
3837 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3838 OUR_HANDLE(handle)));
3839 goto done;
3842 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3845 * We are now using the change value, and
3846 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3847 * I don't have a global notification system, I'm sending back all the
3848 * informations even when _NOTHING_ has changed.
3851 /* We need to keep track of the change value to send back in
3852 RRPCN replies otherwise our updates are ignored. */
3854 Printer->notify.fnpcn = True;
3856 if (Printer->notify.client_connected) {
3857 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3858 Printer->notify.change = q_u->change;
3861 /* just ignore the SPOOL_NOTIFY_OPTION */
3863 switch (Printer->printer_type) {
3864 case PRINTER_HANDLE_IS_PRINTSERVER:
3865 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3866 break;
3868 case PRINTER_HANDLE_IS_PRINTER:
3869 result = printer_notify_info(p, handle, info, p->mem_ctx);
3870 break;
3873 Printer->notify.fnpcn = False;
3875 done:
3876 return result;
3879 /********************************************************************
3880 * construct_printer_info_0
3881 * fill a printer_info_0 struct
3882 ********************************************************************/
3884 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3886 pstring chaine;
3887 int count;
3888 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3889 counter_printer_0 *session_counter;
3890 uint32 global_counter;
3891 struct tm *t;
3892 time_t setuptime;
3893 print_status_struct status;
3895 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3896 return False;
3898 count = print_queue_length(snum, &status);
3900 /* check if we already have a counter for this printer */
3901 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3902 if (session_counter->snum == snum)
3903 break;
3906 /* it's the first time, add it to the list */
3907 if (session_counter==NULL) {
3908 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3909 free_a_printer(&ntprinter, 2);
3910 return False;
3912 ZERO_STRUCTP(session_counter);
3913 session_counter->snum=snum;
3914 session_counter->counter=0;
3915 DLIST_ADD(counter_list, session_counter);
3918 /* increment it */
3919 session_counter->counter++;
3921 /* JFM:
3922 * the global_counter should be stored in a TDB as it's common to all the clients
3923 * and should be zeroed on samba startup
3925 global_counter=session_counter->counter;
3927 pstrcpy(chaine,ntprinter->info_2->printername);
3929 init_unistr(&printer->printername, chaine);
3931 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3932 init_unistr(&printer->servername, chaine);
3934 printer->cjobs = count;
3935 printer->total_jobs = 0;
3936 printer->total_bytes = 0;
3938 setuptime = (time_t)ntprinter->info_2->setuptime;
3939 t=gmtime(&setuptime);
3941 printer->year = t->tm_year+1900;
3942 printer->month = t->tm_mon+1;
3943 printer->dayofweek = t->tm_wday;
3944 printer->day = t->tm_mday;
3945 printer->hour = t->tm_hour;
3946 printer->minute = t->tm_min;
3947 printer->second = t->tm_sec;
3948 printer->milliseconds = 0;
3950 printer->global_counter = global_counter;
3951 printer->total_pages = 0;
3953 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3954 printer->major_version = 0x0005; /* NT 5 */
3955 printer->build_version = 0x0893; /* build 2195 */
3957 printer->unknown7 = 0x1;
3958 printer->unknown8 = 0x0;
3959 printer->unknown9 = 0x0;
3960 printer->session_counter = session_counter->counter;
3961 printer->unknown11 = 0x0;
3962 printer->printer_errors = 0x0; /* number of print failure */
3963 printer->unknown13 = 0x0;
3964 printer->unknown14 = 0x1;
3965 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3966 printer->unknown16 = 0x0;
3967 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3968 printer->unknown18 = 0x0;
3969 printer->status = nt_printq_status(status.status);
3970 printer->unknown20 = 0x0;
3971 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3972 printer->unknown22 = 0x0;
3973 printer->unknown23 = 0x6; /* 6 ???*/
3974 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3975 printer->unknown25 = 0;
3976 printer->unknown26 = 0;
3977 printer->unknown27 = 0;
3978 printer->unknown28 = 0;
3979 printer->unknown29 = 0;
3981 free_a_printer(&ntprinter,2);
3982 return (True);
3985 /********************************************************************
3986 * construct_printer_info_1
3987 * fill a printer_info_1 struct
3988 ********************************************************************/
3989 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3991 pstring chaine;
3992 pstring chaine2;
3993 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3995 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3996 return False;
3998 printer->flags=flags;
4000 if (*ntprinter->info_2->comment == '\0') {
4001 init_unistr(&printer->comment, lp_comment(snum));
4002 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4003 ntprinter->info_2->drivername, lp_comment(snum));
4005 else {
4006 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4007 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4008 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4011 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4013 init_unistr(&printer->description, chaine);
4014 init_unistr(&printer->name, chaine2);
4016 free_a_printer(&ntprinter,2);
4018 return True;
4021 /****************************************************************************
4022 Free a DEVMODE struct.
4023 ****************************************************************************/
4025 static void free_dev_mode(DEVICEMODE *dev)
4027 if (dev == NULL)
4028 return;
4030 SAFE_FREE(dev->dev_private);
4031 SAFE_FREE(dev);
4035 /****************************************************************************
4036 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4037 should be valid upon entry
4038 ****************************************************************************/
4040 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4042 if ( !devmode || !ntdevmode )
4043 return False;
4045 init_unistr(&devmode->devicename, ntdevmode->devicename);
4047 init_unistr(&devmode->formname, ntdevmode->formname);
4049 devmode->specversion = ntdevmode->specversion;
4050 devmode->driverversion = ntdevmode->driverversion;
4051 devmode->size = ntdevmode->size;
4052 devmode->driverextra = ntdevmode->driverextra;
4053 devmode->fields = ntdevmode->fields;
4055 devmode->orientation = ntdevmode->orientation;
4056 devmode->papersize = ntdevmode->papersize;
4057 devmode->paperlength = ntdevmode->paperlength;
4058 devmode->paperwidth = ntdevmode->paperwidth;
4059 devmode->scale = ntdevmode->scale;
4060 devmode->copies = ntdevmode->copies;
4061 devmode->defaultsource = ntdevmode->defaultsource;
4062 devmode->printquality = ntdevmode->printquality;
4063 devmode->color = ntdevmode->color;
4064 devmode->duplex = ntdevmode->duplex;
4065 devmode->yresolution = ntdevmode->yresolution;
4066 devmode->ttoption = ntdevmode->ttoption;
4067 devmode->collate = ntdevmode->collate;
4068 devmode->icmmethod = ntdevmode->icmmethod;
4069 devmode->icmintent = ntdevmode->icmintent;
4070 devmode->mediatype = ntdevmode->mediatype;
4071 devmode->dithertype = ntdevmode->dithertype;
4073 if (ntdevmode->nt_dev_private != NULL) {
4074 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4075 return False;
4078 return True;
4081 /****************************************************************************
4082 Create a DEVMODE struct. Returns malloced memory.
4083 ****************************************************************************/
4085 DEVICEMODE *construct_dev_mode(int snum)
4087 NT_PRINTER_INFO_LEVEL *printer = NULL;
4088 DEVICEMODE *devmode = NULL;
4090 DEBUG(7,("construct_dev_mode\n"));
4092 DEBUGADD(8,("getting printer characteristics\n"));
4094 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4095 return NULL;
4097 if ( !printer->info_2->devmode ) {
4098 DEBUG(5, ("BONG! There was no device mode!\n"));
4099 goto done;
4102 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4103 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4104 goto done;
4107 ZERO_STRUCTP(devmode);
4109 DEBUGADD(8,("loading DEVICEMODE\n"));
4111 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4112 free_dev_mode( devmode );
4113 devmode = NULL;
4116 done:
4117 free_a_printer(&printer,2);
4119 return devmode;
4122 /********************************************************************
4123 * construct_printer_info_2
4124 * fill a printer_info_2 struct
4125 ********************************************************************/
4127 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4129 int count;
4130 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4132 print_status_struct status;
4134 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4135 return False;
4137 count = print_queue_length(snum, &status);
4139 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4140 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4141 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4142 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4143 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4145 if (*ntprinter->info_2->comment == '\0')
4146 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4147 else
4148 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4150 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4151 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4152 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4153 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4154 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4156 printer->attributes = ntprinter->info_2->attributes;
4158 printer->priority = ntprinter->info_2->priority; /* priority */
4159 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4160 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4161 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4162 printer->status = nt_printq_status(status.status); /* status */
4163 printer->cjobs = count; /* jobs */
4164 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4166 if ( !(printer->devmode = construct_dev_mode(snum)) )
4167 DEBUG(8, ("Returning NULL Devicemode!\n"));
4169 printer->secdesc = NULL;
4171 if ( ntprinter->info_2->secdesc_buf
4172 && ntprinter->info_2->secdesc_buf->len != 0 )
4174 /* don't use talloc_steal() here unless you do a deep steal of all
4175 the SEC_DESC members */
4177 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4178 ntprinter->info_2->secdesc_buf->sec );
4181 free_a_printer(&ntprinter, 2);
4183 return True;
4186 /********************************************************************
4187 * construct_printer_info_3
4188 * fill a printer_info_3 struct
4189 ********************************************************************/
4191 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4193 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4194 PRINTER_INFO_3 *printer = NULL;
4196 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4197 return False;
4199 *pp_printer = NULL;
4200 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4201 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4202 return False;
4205 ZERO_STRUCTP(printer);
4207 /* These are the components of the SD we are returning. */
4209 printer->flags = 0x4;
4211 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4212 /* don't use talloc_steal() here unless you do a deep steal of all
4213 the SEC_DESC members */
4215 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4216 ntprinter->info_2->secdesc_buf->sec );
4219 free_a_printer(&ntprinter, 2);
4221 *pp_printer = printer;
4222 return True;
4225 /********************************************************************
4226 * construct_printer_info_4
4227 * fill a printer_info_4 struct
4228 ********************************************************************/
4230 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4232 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4234 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4235 return False;
4237 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4238 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4239 printer->attributes = ntprinter->info_2->attributes;
4241 free_a_printer(&ntprinter, 2);
4242 return True;
4245 /********************************************************************
4246 * construct_printer_info_5
4247 * fill a printer_info_5 struct
4248 ********************************************************************/
4250 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4252 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4254 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4255 return False;
4257 init_unistr(&printer->printername, ntprinter->info_2->printername);
4258 init_unistr(&printer->portname, ntprinter->info_2->portname);
4259 printer->attributes = ntprinter->info_2->attributes;
4261 /* these two are not used by NT+ according to MSDN */
4263 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4264 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4266 free_a_printer(&ntprinter, 2);
4268 return True;
4271 /********************************************************************
4272 * construct_printer_info_7
4273 * fill a printer_info_7 struct
4274 ********************************************************************/
4276 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4278 char *guid_str = NULL;
4279 struct uuid guid;
4281 if (is_printer_published(print_hnd, snum, &guid)) {
4282 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4283 strupper_m(guid_str);
4284 init_unistr(&printer->guid, guid_str);
4285 printer->action = SPOOL_DS_PUBLISH;
4286 } else {
4287 init_unistr(&printer->guid, "");
4288 printer->action = SPOOL_DS_UNPUBLISH;
4291 return True;
4294 /********************************************************************
4295 Spoolss_enumprinters.
4296 ********************************************************************/
4298 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4300 int snum;
4301 int i;
4302 int n_services=lp_numservices();
4303 PRINTER_INFO_1 *tp, *printers=NULL;
4304 PRINTER_INFO_1 current_prt;
4305 WERROR result = WERR_OK;
4307 DEBUG(4,("enum_all_printers_info_1\n"));
4309 for (snum=0; snum<n_services; snum++) {
4310 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4311 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4313 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4314 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4315 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4316 SAFE_FREE(printers);
4317 *returned=0;
4318 return WERR_NOMEM;
4320 else printers = tp;
4321 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4323 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4324 (*returned)++;
4329 /* check the required size. */
4330 for (i=0; i<*returned; i++)
4331 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4333 if (*needed > offered) {
4334 result = WERR_INSUFFICIENT_BUFFER;
4335 goto out;
4338 if (!rpcbuf_alloc_size(buffer, *needed)) {
4339 result = WERR_NOMEM;
4340 goto out;
4343 /* fill the buffer with the structures */
4344 for (i=0; i<*returned; i++)
4345 smb_io_printer_info_1("", buffer, &printers[i], 0);
4347 out:
4348 /* clear memory */
4350 SAFE_FREE(printers);
4352 if ( !W_ERROR_IS_OK(result) )
4353 *returned = 0;
4355 return result;
4358 /********************************************************************
4359 enum_all_printers_info_1_local.
4360 *********************************************************************/
4362 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4364 DEBUG(4,("enum_all_printers_info_1_local\n"));
4366 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4369 /********************************************************************
4370 enum_all_printers_info_1_name.
4371 *********************************************************************/
4373 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4375 char *s = name;
4377 DEBUG(4,("enum_all_printers_info_1_name\n"));
4379 if ((name[0] == '\\') && (name[1] == '\\'))
4380 s = name + 2;
4382 if (is_myname_or_ipaddr(s)) {
4383 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4385 else
4386 return WERR_INVALID_NAME;
4389 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4390 /********************************************************************
4391 enum_all_printers_info_1_remote.
4392 *********************************************************************/
4394 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4396 PRINTER_INFO_1 *printer;
4397 fstring printername;
4398 fstring desc;
4399 fstring comment;
4400 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4401 WERROR result = WERR_OK;
4403 /* JFM: currently it's more a place holder than anything else.
4404 * In the spooler world there is a notion of server registration.
4405 * the print servers are registered on the PDC (in the same domain)
4407 * We should have a TDB here. The registration is done thru an
4408 * undocumented RPC call.
4411 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4412 return WERR_NOMEM;
4414 *returned=1;
4416 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4417 slprintf(desc, sizeof(desc)-1,"%s", name);
4418 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4420 init_unistr(&printer->description, desc);
4421 init_unistr(&printer->name, printername);
4422 init_unistr(&printer->comment, comment);
4423 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4425 /* check the required size. */
4426 *needed += spoolss_size_printer_info_1(printer);
4428 if (*needed > offered) {
4429 result = WERR_INSUFFICIENT_BUFFER;
4430 goto out;
4433 if (!rpcbuf_alloc_size(buffer, *needed)) {
4434 result = WERR_NOMEM;
4435 goto out;
4438 /* fill the buffer with the structures */
4439 smb_io_printer_info_1("", buffer, printer, 0);
4441 out:
4442 /* clear memory */
4443 SAFE_FREE(printer);
4445 if ( !W_ERROR_IS_OK(result) )
4446 *returned = 0;
4448 return result;
4451 #endif
4453 /********************************************************************
4454 enum_all_printers_info_1_network.
4455 *********************************************************************/
4457 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4459 char *s = name;
4461 DEBUG(4,("enum_all_printers_info_1_network\n"));
4463 /* If we respond to a enum_printers level 1 on our name with flags
4464 set to PRINTER_ENUM_REMOTE with a list of printers then these
4465 printers incorrectly appear in the APW browse list.
4466 Specifically the printers for the server appear at the workgroup
4467 level where all the other servers in the domain are
4468 listed. Windows responds to this call with a
4469 WERR_CAN_NOT_COMPLETE so we should do the same. */
4471 if (name[0] == '\\' && name[1] == '\\')
4472 s = name + 2;
4474 if (is_myname_or_ipaddr(s))
4475 return WERR_CAN_NOT_COMPLETE;
4477 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4480 /********************************************************************
4481 * api_spoolss_enumprinters
4483 * called from api_spoolss_enumprinters (see this to understand)
4484 ********************************************************************/
4486 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4488 int snum;
4489 int i;
4490 int n_services=lp_numservices();
4491 PRINTER_INFO_2 *tp, *printers=NULL;
4492 PRINTER_INFO_2 current_prt;
4493 WERROR result = WERR_OK;
4495 for (snum=0; snum<n_services; snum++) {
4496 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4497 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4499 if (construct_printer_info_2(NULL, &current_prt, snum))
4501 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4502 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4503 SAFE_FREE(printers);
4504 *returned = 0;
4505 return WERR_NOMEM;
4508 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4510 printers = tp;
4511 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4513 (*returned)++;
4518 /* check the required size. */
4519 for (i=0; i<*returned; i++)
4520 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4522 if (*needed > offered) {
4523 result = WERR_INSUFFICIENT_BUFFER;
4524 goto out;
4527 if (!rpcbuf_alloc_size(buffer, *needed)) {
4528 result = WERR_NOMEM;
4529 goto out;
4532 /* fill the buffer with the structures */
4533 for (i=0; i<*returned; i++)
4534 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4536 out:
4537 /* clear memory */
4539 for (i=0; i<*returned; i++)
4540 free_devmode(printers[i].devmode);
4542 SAFE_FREE(printers);
4544 if ( !W_ERROR_IS_OK(result) )
4545 *returned = 0;
4547 return result;
4550 /********************************************************************
4551 * handle enumeration of printers at level 1
4552 ********************************************************************/
4554 static WERROR enumprinters_level1( uint32 flags, fstring name,
4555 RPC_BUFFER *buffer, uint32 offered,
4556 uint32 *needed, uint32 *returned)
4558 /* Not all the flags are equals */
4560 if (flags & PRINTER_ENUM_LOCAL)
4561 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4563 if (flags & PRINTER_ENUM_NAME)
4564 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4566 #if 0 /* JERRY - disabled for now */
4567 if (flags & PRINTER_ENUM_REMOTE)
4568 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4569 #endif
4571 if (flags & PRINTER_ENUM_NETWORK)
4572 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4574 return WERR_OK; /* NT4sp5 does that */
4577 /********************************************************************
4578 * handle enumeration of printers at level 2
4579 ********************************************************************/
4581 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4582 RPC_BUFFER *buffer, uint32 offered,
4583 uint32 *needed, uint32 *returned)
4585 char *s = servername;
4587 if (flags & PRINTER_ENUM_LOCAL) {
4588 return enum_all_printers_info_2(buffer, offered, needed, returned);
4591 if (flags & PRINTER_ENUM_NAME) {
4592 if ((servername[0] == '\\') && (servername[1] == '\\'))
4593 s = servername + 2;
4594 if (is_myname_or_ipaddr(s))
4595 return enum_all_printers_info_2(buffer, offered, needed, returned);
4596 else
4597 return WERR_INVALID_NAME;
4600 if (flags & PRINTER_ENUM_REMOTE)
4601 return WERR_UNKNOWN_LEVEL;
4603 return WERR_OK;
4606 /********************************************************************
4607 * handle enumeration of printers at level 5
4608 ********************************************************************/
4610 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4611 RPC_BUFFER *buffer, uint32 offered,
4612 uint32 *needed, uint32 *returned)
4614 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4615 return WERR_OK;
4618 /********************************************************************
4619 * api_spoolss_enumprinters
4621 * called from api_spoolss_enumprinters (see this to understand)
4622 ********************************************************************/
4624 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4626 uint32 flags = q_u->flags;
4627 UNISTR2 *servername = &q_u->servername;
4628 uint32 level = q_u->level;
4629 RPC_BUFFER *buffer = NULL;
4630 uint32 offered = q_u->offered;
4631 uint32 *needed = &r_u->needed;
4632 uint32 *returned = &r_u->returned;
4634 fstring name;
4636 /* that's an [in out] buffer */
4638 if ( q_u->buffer ) {
4639 rpcbuf_move(q_u->buffer, &r_u->buffer);
4640 buffer = r_u->buffer;
4643 DEBUG(4,("_spoolss_enumprinters\n"));
4645 *needed=0;
4646 *returned=0;
4649 * Level 1:
4650 * flags==PRINTER_ENUM_NAME
4651 * if name=="" then enumerates all printers
4652 * if name!="" then enumerate the printer
4653 * flags==PRINTER_ENUM_REMOTE
4654 * name is NULL, enumerate printers
4655 * Level 2: name!="" enumerates printers, name can't be NULL
4656 * Level 3: doesn't exist
4657 * Level 4: does a local registry lookup
4658 * Level 5: same as Level 2
4661 unistr2_to_ascii(name, servername, sizeof(name)-1);
4662 strupper_m(name);
4664 switch (level) {
4665 case 1:
4666 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4667 case 2:
4668 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4669 case 5:
4670 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4671 case 3:
4672 case 4:
4673 break;
4675 return WERR_UNKNOWN_LEVEL;
4678 /****************************************************************************
4679 ****************************************************************************/
4681 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4683 PRINTER_INFO_0 *printer=NULL;
4684 WERROR result = WERR_OK;
4686 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4687 return WERR_NOMEM;
4689 construct_printer_info_0(print_hnd, printer, snum);
4691 /* check the required size. */
4692 *needed += spoolss_size_printer_info_0(printer);
4694 if (*needed > offered) {
4695 result = WERR_INSUFFICIENT_BUFFER;
4696 goto out;
4699 if (!rpcbuf_alloc_size(buffer, *needed)) {
4700 result = WERR_NOMEM;
4701 goto out;
4704 /* fill the buffer with the structures */
4705 smb_io_printer_info_0("", buffer, printer, 0);
4707 out:
4708 /* clear memory */
4710 SAFE_FREE(printer);
4712 return result;
4715 /****************************************************************************
4716 ****************************************************************************/
4718 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4720 PRINTER_INFO_1 *printer=NULL;
4721 WERROR result = WERR_OK;
4723 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4724 return WERR_NOMEM;
4726 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4728 /* check the required size. */
4729 *needed += spoolss_size_printer_info_1(printer);
4731 if (*needed > offered) {
4732 result = WERR_INSUFFICIENT_BUFFER;
4733 goto out;
4736 if (!rpcbuf_alloc_size(buffer, *needed)) {
4737 result = WERR_NOMEM;
4738 goto out;
4741 /* fill the buffer with the structures */
4742 smb_io_printer_info_1("", buffer, printer, 0);
4744 out:
4745 /* clear memory */
4746 SAFE_FREE(printer);
4748 return result;
4751 /****************************************************************************
4752 ****************************************************************************/
4754 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4756 PRINTER_INFO_2 *printer=NULL;
4757 WERROR result = WERR_OK;
4759 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4760 return WERR_NOMEM;
4762 construct_printer_info_2(print_hnd, printer, snum);
4764 /* check the required size. */
4765 *needed += spoolss_size_printer_info_2(printer);
4767 if (*needed > offered) {
4768 result = WERR_INSUFFICIENT_BUFFER;
4769 goto out;
4772 if (!rpcbuf_alloc_size(buffer, *needed)) {
4773 result = WERR_NOMEM;
4774 goto out;
4777 /* fill the buffer with the structures */
4778 if (!smb_io_printer_info_2("", buffer, printer, 0))
4779 result = WERR_NOMEM;
4781 out:
4782 /* clear memory */
4783 free_printer_info_2(printer);
4785 return result;
4788 /****************************************************************************
4789 ****************************************************************************/
4791 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4793 PRINTER_INFO_3 *printer=NULL;
4794 WERROR result = WERR_OK;
4796 if (!construct_printer_info_3(print_hnd, &printer, snum))
4797 return WERR_NOMEM;
4799 /* check the required size. */
4800 *needed += spoolss_size_printer_info_3(printer);
4802 if (*needed > offered) {
4803 result = WERR_INSUFFICIENT_BUFFER;
4804 goto out;
4807 if (!rpcbuf_alloc_size(buffer, *needed)) {
4808 result = WERR_NOMEM;
4809 goto out;
4812 /* fill the buffer with the structures */
4813 smb_io_printer_info_3("", buffer, printer, 0);
4815 out:
4816 /* clear memory */
4817 free_printer_info_3(printer);
4819 return result;
4822 /****************************************************************************
4823 ****************************************************************************/
4825 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4827 PRINTER_INFO_4 *printer=NULL;
4828 WERROR result = WERR_OK;
4830 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4831 return WERR_NOMEM;
4833 if (!construct_printer_info_4(print_hnd, printer, snum))
4834 return WERR_NOMEM;
4836 /* check the required size. */
4837 *needed += spoolss_size_printer_info_4(printer);
4839 if (*needed > offered) {
4840 result = WERR_INSUFFICIENT_BUFFER;
4841 goto out;
4844 if (!rpcbuf_alloc_size(buffer, *needed)) {
4845 result = WERR_NOMEM;
4846 goto out;
4849 /* fill the buffer with the structures */
4850 smb_io_printer_info_4("", buffer, printer, 0);
4852 out:
4853 /* clear memory */
4854 free_printer_info_4(printer);
4856 return result;
4859 /****************************************************************************
4860 ****************************************************************************/
4862 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4864 PRINTER_INFO_5 *printer=NULL;
4865 WERROR result = WERR_OK;
4867 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4868 return WERR_NOMEM;
4870 if (!construct_printer_info_5(print_hnd, printer, snum))
4871 return WERR_NOMEM;
4873 /* check the required size. */
4874 *needed += spoolss_size_printer_info_5(printer);
4876 if (*needed > offered) {
4877 result = WERR_INSUFFICIENT_BUFFER;
4878 goto out;
4881 if (!rpcbuf_alloc_size(buffer, *needed)) {
4882 result = WERR_NOMEM;
4883 goto out;
4886 /* fill the buffer with the structures */
4887 smb_io_printer_info_5("", buffer, printer, 0);
4889 out:
4890 /* clear memory */
4891 free_printer_info_5(printer);
4893 return result;
4896 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4898 PRINTER_INFO_7 *printer=NULL;
4899 WERROR result = WERR_OK;
4901 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4902 return WERR_NOMEM;
4904 if (!construct_printer_info_7(print_hnd, printer, snum))
4905 return WERR_NOMEM;
4907 /* check the required size. */
4908 *needed += spoolss_size_printer_info_7(printer);
4910 if (*needed > offered) {
4911 result = WERR_INSUFFICIENT_BUFFER;
4912 goto out;
4915 if (!rpcbuf_alloc_size(buffer, *needed)) {
4916 result = WERR_NOMEM;
4917 goto out;
4921 /* fill the buffer with the structures */
4922 smb_io_printer_info_7("", buffer, printer, 0);
4924 out:
4925 /* clear memory */
4926 free_printer_info_7(printer);
4928 return result;
4931 /****************************************************************************
4932 ****************************************************************************/
4934 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4936 POLICY_HND *handle = &q_u->handle;
4937 uint32 level = q_u->level;
4938 RPC_BUFFER *buffer = NULL;
4939 uint32 offered = q_u->offered;
4940 uint32 *needed = &r_u->needed;
4941 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4943 int snum;
4945 /* that's an [in out] buffer */
4947 if ( q_u->buffer ) {
4948 rpcbuf_move(q_u->buffer, &r_u->buffer);
4949 buffer = r_u->buffer;
4952 *needed=0;
4954 if (!get_printer_snum(p, handle, &snum))
4955 return WERR_BADFID;
4957 switch (level) {
4958 case 0:
4959 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4960 case 1:
4961 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4962 case 2:
4963 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4964 case 3:
4965 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4966 case 4:
4967 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4968 case 5:
4969 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4970 case 7:
4971 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4973 return WERR_UNKNOWN_LEVEL;
4976 /********************************************************************
4977 * fill a DRIVER_INFO_1 struct
4978 ********************************************************************/
4980 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4982 init_unistr( &info->name, driver.info_3->name);
4985 /********************************************************************
4986 * construct_printer_driver_info_1
4987 ********************************************************************/
4989 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4991 NT_PRINTER_INFO_LEVEL *printer = NULL;
4992 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4994 ZERO_STRUCT(driver);
4996 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4997 return WERR_INVALID_PRINTER_NAME;
4999 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5000 return WERR_UNKNOWN_PRINTER_DRIVER;
5002 fill_printer_driver_info_1(info, driver, servername, architecture);
5004 free_a_printer(&printer,2);
5006 return WERR_OK;
5009 /********************************************************************
5010 * construct_printer_driver_info_2
5011 * fill a printer_info_2 struct
5012 ********************************************************************/
5014 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5016 pstring temp;
5018 info->version=driver.info_3->cversion;
5020 init_unistr( &info->name, driver.info_3->name );
5021 init_unistr( &info->architecture, driver.info_3->environment );
5024 if (strlen(driver.info_3->driverpath)) {
5025 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5026 init_unistr( &info->driverpath, temp );
5027 } else
5028 init_unistr( &info->driverpath, "" );
5030 if (strlen(driver.info_3->datafile)) {
5031 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5032 init_unistr( &info->datafile, temp );
5033 } else
5034 init_unistr( &info->datafile, "" );
5036 if (strlen(driver.info_3->configfile)) {
5037 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5038 init_unistr( &info->configfile, temp );
5039 } else
5040 init_unistr( &info->configfile, "" );
5043 /********************************************************************
5044 * construct_printer_driver_info_2
5045 * fill a printer_info_2 struct
5046 ********************************************************************/
5048 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5050 NT_PRINTER_INFO_LEVEL *printer = NULL;
5051 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5053 ZERO_STRUCT(printer);
5054 ZERO_STRUCT(driver);
5056 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5057 return WERR_INVALID_PRINTER_NAME;
5059 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5060 return WERR_UNKNOWN_PRINTER_DRIVER;
5062 fill_printer_driver_info_2(info, driver, servername);
5064 free_a_printer(&printer,2);
5066 return WERR_OK;
5069 /********************************************************************
5070 * copy a strings array and convert to UNICODE
5072 * convert an array of ascii string to a UNICODE string
5073 ********************************************************************/
5075 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5077 int i=0;
5078 int j=0;
5079 const char *v;
5080 pstring line;
5081 uint16 *tuary;
5083 DEBUG(6,("init_unistr_array\n"));
5084 *uni_array=NULL;
5086 while (True)
5088 if ( !char_array )
5089 v = "";
5090 else
5092 v = char_array[i];
5093 if (!v)
5094 v = ""; /* hack to handle null lists */
5097 /* hack to allow this to be used in places other than when generating
5098 the list of dependent files */
5100 if ( servername )
5101 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5102 else
5103 pstrcpy( line, v );
5105 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5107 /* add one extra unit16 for the second terminating NULL */
5109 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5110 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5111 return 0;
5112 } else
5113 *uni_array = tuary;
5115 if ( !strlen(v) )
5116 break;
5118 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5119 i++;
5122 if (*uni_array) {
5123 /* special case for ""; we need to add both NULL's here */
5124 if (!j)
5125 (*uni_array)[j++]=0x0000;
5126 (*uni_array)[j]=0x0000;
5129 DEBUGADD(6,("last one:done\n"));
5131 /* return size of array in uint16's */
5133 return j+1;
5136 /********************************************************************
5137 * construct_printer_info_3
5138 * fill a printer_info_3 struct
5139 ********************************************************************/
5141 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5143 pstring temp;
5145 ZERO_STRUCTP(info);
5147 info->version=driver.info_3->cversion;
5149 init_unistr( &info->name, driver.info_3->name );
5150 init_unistr( &info->architecture, driver.info_3->environment );
5152 if (strlen(driver.info_3->driverpath)) {
5153 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5154 init_unistr( &info->driverpath, temp );
5155 } else
5156 init_unistr( &info->driverpath, "" );
5158 if (strlen(driver.info_3->datafile)) {
5159 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5160 init_unistr( &info->datafile, temp );
5161 } else
5162 init_unistr( &info->datafile, "" );
5164 if (strlen(driver.info_3->configfile)) {
5165 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5166 init_unistr( &info->configfile, temp );
5167 } else
5168 init_unistr( &info->configfile, "" );
5170 if (strlen(driver.info_3->helpfile)) {
5171 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5172 init_unistr( &info->helpfile, temp );
5173 } else
5174 init_unistr( &info->helpfile, "" );
5176 init_unistr( &info->monitorname, driver.info_3->monitorname );
5177 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5179 info->dependentfiles=NULL;
5180 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5183 /********************************************************************
5184 * construct_printer_info_3
5185 * fill a printer_info_3 struct
5186 ********************************************************************/
5188 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5190 NT_PRINTER_INFO_LEVEL *printer = NULL;
5191 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5192 WERROR status;
5193 ZERO_STRUCT(driver);
5195 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5196 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5197 if (!W_ERROR_IS_OK(status))
5198 return WERR_INVALID_PRINTER_NAME;
5200 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5201 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5203 #if 0 /* JERRY */
5206 * I put this code in during testing. Helpful when commenting out the
5207 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5208 * as win2k always queries the driver using an infor level of 6.
5209 * I've left it in (but ifdef'd out) because I'll probably
5210 * use it in experimentation again in the future. --jerry 22/01/2002
5213 if (!W_ERROR_IS_OK(status)) {
5215 * Is this a W2k client ?
5217 if (version == 3) {
5218 /* Yes - try again with a WinNT driver. */
5219 version = 2;
5220 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5221 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5223 #endif
5225 if (!W_ERROR_IS_OK(status)) {
5226 free_a_printer(&printer,2);
5227 return WERR_UNKNOWN_PRINTER_DRIVER;
5230 #if 0 /* JERRY */
5232 #endif
5235 fill_printer_driver_info_3(info, driver, servername);
5237 free_a_printer(&printer,2);
5239 return WERR_OK;
5242 /********************************************************************
5243 * construct_printer_info_6
5244 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5245 ********************************************************************/
5247 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5249 pstring temp;
5250 fstring nullstr;
5252 ZERO_STRUCTP(info);
5253 memset(&nullstr, '\0', sizeof(fstring));
5255 info->version=driver.info_3->cversion;
5257 init_unistr( &info->name, driver.info_3->name );
5258 init_unistr( &info->architecture, driver.info_3->environment );
5260 if (strlen(driver.info_3->driverpath)) {
5261 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5262 init_unistr( &info->driverpath, temp );
5263 } else
5264 init_unistr( &info->driverpath, "" );
5266 if (strlen(driver.info_3->datafile)) {
5267 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5268 init_unistr( &info->datafile, temp );
5269 } else
5270 init_unistr( &info->datafile, "" );
5272 if (strlen(driver.info_3->configfile)) {
5273 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5274 init_unistr( &info->configfile, temp );
5275 } else
5276 init_unistr( &info->configfile, "" );
5278 if (strlen(driver.info_3->helpfile)) {
5279 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5280 init_unistr( &info->helpfile, temp );
5281 } else
5282 init_unistr( &info->helpfile, "" );
5284 init_unistr( &info->monitorname, driver.info_3->monitorname );
5285 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5287 info->dependentfiles = NULL;
5288 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5290 info->previousdrivernames=NULL;
5291 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5293 info->driver_date.low=0;
5294 info->driver_date.high=0;
5296 info->padding=0;
5297 info->driver_version_low=0;
5298 info->driver_version_high=0;
5300 init_unistr( &info->mfgname, "");
5301 init_unistr( &info->oem_url, "");
5302 init_unistr( &info->hardware_id, "");
5303 init_unistr( &info->provider, "");
5306 /********************************************************************
5307 * construct_printer_info_6
5308 * fill a printer_info_6 struct
5309 ********************************************************************/
5311 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5312 fstring servername, fstring architecture, uint32 version)
5314 NT_PRINTER_INFO_LEVEL *printer = NULL;
5315 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5316 WERROR status;
5318 ZERO_STRUCT(driver);
5320 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5322 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5324 if (!W_ERROR_IS_OK(status))
5325 return WERR_INVALID_PRINTER_NAME;
5327 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5329 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5331 if (!W_ERROR_IS_OK(status))
5334 * Is this a W2k client ?
5337 if (version < 3) {
5338 free_a_printer(&printer,2);
5339 return WERR_UNKNOWN_PRINTER_DRIVER;
5342 /* Yes - try again with a WinNT driver. */
5343 version = 2;
5344 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5345 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5346 if (!W_ERROR_IS_OK(status)) {
5347 free_a_printer(&printer,2);
5348 return WERR_UNKNOWN_PRINTER_DRIVER;
5352 fill_printer_driver_info_6(info, driver, servername);
5354 free_a_printer(&printer,2);
5355 free_a_printer_driver(driver, 3);
5357 return WERR_OK;
5360 /****************************************************************************
5361 ****************************************************************************/
5363 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5365 SAFE_FREE(info->dependentfiles);
5368 /****************************************************************************
5369 ****************************************************************************/
5371 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5373 SAFE_FREE(info->dependentfiles);
5376 /****************************************************************************
5377 ****************************************************************************/
5379 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5381 DRIVER_INFO_1 *info=NULL;
5382 WERROR result;
5384 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5385 return WERR_NOMEM;
5387 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5388 if (!W_ERROR_IS_OK(result))
5389 goto out;
5391 /* check the required size. */
5392 *needed += spoolss_size_printer_driver_info_1(info);
5394 if (*needed > offered) {
5395 result = WERR_INSUFFICIENT_BUFFER;
5396 goto out;
5399 if (!rpcbuf_alloc_size(buffer, *needed)) {
5400 result = WERR_NOMEM;
5401 goto out;
5404 /* fill the buffer with the structures */
5405 smb_io_printer_driver_info_1("", buffer, info, 0);
5407 out:
5408 /* clear memory */
5409 SAFE_FREE(info);
5411 return result;
5414 /****************************************************************************
5415 ****************************************************************************/
5417 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5419 DRIVER_INFO_2 *info=NULL;
5420 WERROR result;
5422 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5423 return WERR_NOMEM;
5425 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5426 if (!W_ERROR_IS_OK(result))
5427 goto out;
5429 /* check the required size. */
5430 *needed += spoolss_size_printer_driver_info_2(info);
5432 if (*needed > offered) {
5433 result = WERR_INSUFFICIENT_BUFFER;
5434 goto out;
5437 if (!rpcbuf_alloc_size(buffer, *needed)) {
5438 result = WERR_NOMEM;
5439 goto out;
5442 /* fill the buffer with the structures */
5443 smb_io_printer_driver_info_2("", buffer, info, 0);
5445 out:
5446 /* clear memory */
5447 SAFE_FREE(info);
5449 return result;
5452 /****************************************************************************
5453 ****************************************************************************/
5455 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5457 DRIVER_INFO_3 info;
5458 WERROR result;
5460 ZERO_STRUCT(info);
5462 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5463 if (!W_ERROR_IS_OK(result))
5464 goto out;
5466 /* check the required size. */
5467 *needed += spoolss_size_printer_driver_info_3(&info);
5469 if (*needed > offered) {
5470 result = WERR_INSUFFICIENT_BUFFER;
5471 goto out;
5474 if (!rpcbuf_alloc_size(buffer, *needed)) {
5475 result = WERR_NOMEM;
5476 goto out;
5479 /* fill the buffer with the structures */
5480 smb_io_printer_driver_info_3("", buffer, &info, 0);
5482 out:
5483 free_printer_driver_info_3(&info);
5485 return result;
5488 /****************************************************************************
5489 ****************************************************************************/
5491 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5493 DRIVER_INFO_6 info;
5494 WERROR result;
5496 ZERO_STRUCT(info);
5498 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5499 if (!W_ERROR_IS_OK(result))
5500 goto out;
5502 /* check the required size. */
5503 *needed += spoolss_size_printer_driver_info_6(&info);
5505 if (*needed > offered) {
5506 result = WERR_INSUFFICIENT_BUFFER;
5507 goto out;
5510 if (!rpcbuf_alloc_size(buffer, *needed)) {
5511 result = WERR_NOMEM;
5512 goto out;
5515 /* fill the buffer with the structures */
5516 smb_io_printer_driver_info_6("", buffer, &info, 0);
5518 out:
5519 free_printer_driver_info_6(&info);
5521 return result;
5524 /****************************************************************************
5525 ****************************************************************************/
5527 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5529 POLICY_HND *handle = &q_u->handle;
5530 UNISTR2 *uni_arch = &q_u->architecture;
5531 uint32 level = q_u->level;
5532 uint32 clientmajorversion = q_u->clientmajorversion;
5533 RPC_BUFFER *buffer = NULL;
5534 uint32 offered = q_u->offered;
5535 uint32 *needed = &r_u->needed;
5536 uint32 *servermajorversion = &r_u->servermajorversion;
5537 uint32 *serverminorversion = &r_u->serverminorversion;
5538 Printer_entry *printer;
5540 fstring servername;
5541 fstring architecture;
5542 int snum;
5544 /* that's an [in out] buffer */
5546 if ( q_u->buffer ) {
5547 rpcbuf_move(q_u->buffer, &r_u->buffer);
5548 buffer = r_u->buffer;
5551 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5553 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5554 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5555 return WERR_INVALID_PRINTER_NAME;
5558 *needed = 0;
5559 *servermajorversion = 0;
5560 *serverminorversion = 0;
5562 fstrcpy(servername, get_server_name( printer ));
5563 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5565 if (!get_printer_snum(p, handle, &snum))
5566 return WERR_BADFID;
5568 switch (level) {
5569 case 1:
5570 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5571 case 2:
5572 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5573 case 3:
5574 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5575 case 6:
5576 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5577 #if 0 /* JERRY */
5578 case 101:
5579 /* apparently this call is the equivalent of
5580 EnumPrinterDataEx() for the DsDriver key */
5581 break;
5582 #endif
5585 return WERR_UNKNOWN_LEVEL;
5588 /****************************************************************************
5589 ****************************************************************************/
5591 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5593 POLICY_HND *handle = &q_u->handle;
5595 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5597 if (!Printer) {
5598 DEBUG(3,("Error in startpageprinter printer handle\n"));
5599 return WERR_BADFID;
5602 Printer->page_started=True;
5603 return WERR_OK;
5606 /****************************************************************************
5607 ****************************************************************************/
5609 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5611 POLICY_HND *handle = &q_u->handle;
5612 int snum;
5614 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5616 if (!Printer) {
5617 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5618 return WERR_BADFID;
5621 if (!get_printer_snum(p, handle, &snum))
5622 return WERR_BADFID;
5624 Printer->page_started=False;
5625 print_job_endpage(snum, Printer->jobid);
5627 return WERR_OK;
5630 /********************************************************************
5631 * api_spoolss_getprinter
5632 * called from the spoolss dispatcher
5634 ********************************************************************/
5636 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5638 POLICY_HND *handle = &q_u->handle;
5639 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5640 uint32 *jobid = &r_u->jobid;
5642 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5643 int snum;
5644 pstring jobname;
5645 fstring datatype;
5646 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5647 struct current_user user;
5649 if (!Printer) {
5650 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5651 return WERR_BADFID;
5654 get_current_user(&user, p);
5657 * a nice thing with NT is it doesn't listen to what you tell it.
5658 * when asked to send _only_ RAW datas, it tries to send datas
5659 * in EMF format.
5661 * So I add checks like in NT Server ...
5664 if (info_1->p_datatype != 0) {
5665 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5666 if (strcmp(datatype, "RAW") != 0) {
5667 (*jobid)=0;
5668 return WERR_INVALID_DATATYPE;
5672 /* get the share number of the printer */
5673 if (!get_printer_snum(p, handle, &snum)) {
5674 return WERR_BADFID;
5677 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5679 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5681 /* An error occured in print_job_start() so return an appropriate
5682 NT error code. */
5684 if (Printer->jobid == -1) {
5685 return map_werror_from_unix(errno);
5688 Printer->document_started=True;
5689 (*jobid) = Printer->jobid;
5691 return WERR_OK;
5694 /********************************************************************
5695 * api_spoolss_getprinter
5696 * called from the spoolss dispatcher
5698 ********************************************************************/
5700 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5702 POLICY_HND *handle = &q_u->handle;
5704 return _spoolss_enddocprinter_internal(p, handle);
5707 /****************************************************************************
5708 ****************************************************************************/
5710 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5712 POLICY_HND *handle = &q_u->handle;
5713 uint32 buffer_size = q_u->buffer_size;
5714 uint8 *buffer = q_u->buffer;
5715 uint32 *buffer_written = &q_u->buffer_size2;
5716 int snum;
5717 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5719 if (!Printer) {
5720 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5721 r_u->buffer_written = q_u->buffer_size2;
5722 return WERR_BADFID;
5725 if (!get_printer_snum(p, handle, &snum))
5726 return WERR_BADFID;
5728 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5729 (SMB_OFF_T)-1, (size_t)buffer_size);
5730 if (*buffer_written == (uint32)-1) {
5731 r_u->buffer_written = 0;
5732 if (errno == ENOSPC)
5733 return WERR_NO_SPOOL_SPACE;
5734 else
5735 return WERR_ACCESS_DENIED;
5738 r_u->buffer_written = q_u->buffer_size2;
5740 return WERR_OK;
5743 /********************************************************************
5744 * api_spoolss_getprinter
5745 * called from the spoolss dispatcher
5747 ********************************************************************/
5749 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5750 pipes_struct *p)
5752 struct current_user user;
5753 int snum;
5754 WERROR errcode = WERR_BADFUNC;
5755 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5757 get_current_user(&user, p);
5759 if (!Printer) {
5760 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5761 return WERR_BADFID;
5764 if (!get_printer_snum(p, handle, &snum))
5765 return WERR_BADFID;
5767 switch (command) {
5768 case PRINTER_CONTROL_PAUSE:
5769 if (print_queue_pause(&user, snum, &errcode)) {
5770 errcode = WERR_OK;
5772 break;
5773 case PRINTER_CONTROL_RESUME:
5774 case PRINTER_CONTROL_UNPAUSE:
5775 if (print_queue_resume(&user, snum, &errcode)) {
5776 errcode = WERR_OK;
5778 break;
5779 case PRINTER_CONTROL_PURGE:
5780 if (print_queue_purge(&user, snum, &errcode)) {
5781 errcode = WERR_OK;
5783 break;
5784 default:
5785 return WERR_UNKNOWN_LEVEL;
5788 return errcode;
5791 /********************************************************************
5792 * api_spoolss_abortprinter
5793 * From MSDN: "Deletes printer's spool file if printer is configured
5794 * for spooling"
5795 ********************************************************************/
5797 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5799 POLICY_HND *handle = &q_u->handle;
5800 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5801 int snum;
5802 struct current_user user;
5803 WERROR errcode = WERR_OK;
5805 if (!Printer) {
5806 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5807 return WERR_BADFID;
5810 if (!get_printer_snum(p, handle, &snum))
5811 return WERR_BADFID;
5813 get_current_user( &user, p );
5815 print_job_delete( &user, snum, Printer->jobid, &errcode );
5817 return errcode;
5820 /********************************************************************
5821 * called by spoolss_api_setprinter
5822 * when updating a printer description
5823 ********************************************************************/
5825 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5826 const SPOOL_PRINTER_INFO_LEVEL *info,
5827 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5829 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5830 WERROR result;
5831 int snum;
5833 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5835 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5836 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5837 OUR_HANDLE(handle)));
5839 result = WERR_BADFID;
5840 goto done;
5843 /* Check the user has permissions to change the security
5844 descriptor. By experimentation with two NT machines, the user
5845 requires Full Access to the printer to change security
5846 information. */
5848 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5849 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5850 result = WERR_ACCESS_DENIED;
5851 goto done;
5854 /* NT seems to like setting the security descriptor even though
5855 nothing may have actually changed. */
5857 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5859 if (DEBUGLEVEL >= 10) {
5860 SEC_ACL *the_acl;
5861 int i;
5863 the_acl = old_secdesc_ctr->sec->dacl;
5864 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5865 PRINTERNAME(snum), the_acl->num_aces));
5867 for (i = 0; i < the_acl->num_aces; i++) {
5868 fstring sid_str;
5870 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5872 DEBUG(10, ("%s 0x%08x\n", sid_str,
5873 the_acl->ace[i].info.mask));
5876 the_acl = secdesc_ctr->sec->dacl;
5878 if (the_acl) {
5879 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5880 PRINTERNAME(snum), the_acl->num_aces));
5882 for (i = 0; i < the_acl->num_aces; i++) {
5883 fstring sid_str;
5885 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5887 DEBUG(10, ("%s 0x%08x\n", sid_str,
5888 the_acl->ace[i].info.mask));
5890 } else {
5891 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5895 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5897 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5898 result = WERR_OK;
5899 goto done;
5902 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5904 done:
5906 return result;
5909 /********************************************************************
5910 Canonicalize printer info from a client
5912 ATTN: It does not matter what we set the servername to hear
5913 since we do the necessary work in get_a_printer() to set it to
5914 the correct value based on what the client sent in the
5915 _spoolss_open_printer_ex().
5916 ********************************************************************/
5918 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5920 fstring printername;
5921 const char *p;
5923 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5924 "portname=%s drivername=%s comment=%s location=%s\n",
5925 info->servername, info->printername, info->sharename,
5926 info->portname, info->drivername, info->comment, info->location));
5928 /* we force some elements to "correct" values */
5929 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5930 fstrcpy(info->sharename, lp_servicename(snum));
5932 /* check to see if we allow printername != sharename */
5934 if ( lp_force_printername(snum) ) {
5935 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5936 global_myname(), info->sharename );
5937 } else {
5939 /* make sure printername is in \\server\printername format */
5941 fstrcpy( printername, info->printername );
5942 p = printername;
5943 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5944 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5945 p++;
5948 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5949 global_myname(), p );
5952 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5953 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5957 return True;
5960 /****************************************************************************
5961 ****************************************************************************/
5963 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5965 char *cmd = lp_addprinter_cmd();
5966 char **qlines;
5967 pstring command;
5968 int numlines;
5969 int ret;
5970 int fd;
5971 fstring remote_machine = "%m";
5972 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5973 BOOL is_print_op = False;
5975 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5977 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5978 cmd, printer->info_2->printername, printer->info_2->sharename,
5979 printer->info_2->portname, printer->info_2->drivername,
5980 printer->info_2->location, printer->info_2->comment, remote_machine);
5982 if ( token )
5983 is_print_op = user_has_privileges( token, &se_printop );
5985 DEBUG(10,("Running [%s]\n", command));
5987 /********* BEGIN SePrintOperatorPrivilege **********/
5989 if ( is_print_op )
5990 become_root();
5992 if ( (ret = smbrun(command, &fd)) == 0 ) {
5993 /* Tell everyone we updated smb.conf. */
5994 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
5997 if ( is_print_op )
5998 unbecome_root();
6000 /********* END SePrintOperatorPrivilege **********/
6002 DEBUGADD(10,("returned [%d]\n", ret));
6004 if ( ret != 0 ) {
6005 if (fd != -1)
6006 close(fd);
6007 return False;
6010 /* reload our services immediately */
6011 reload_services( False );
6013 numlines = 0;
6014 /* Get lines and convert them back to dos-codepage */
6015 qlines = fd_lines_load(fd, &numlines);
6016 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6017 close(fd);
6019 /* Set the portname to what the script says the portname should be. */
6020 /* but don't require anything to be return from the script exit a good error code */
6022 if (numlines) {
6023 /* Set the portname to what the script says the portname should be. */
6024 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6025 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6028 file_lines_free(qlines);
6029 return True;
6032 /********************************************************************
6033 * Called by spoolss_api_setprinter
6034 * when updating a printer description.
6035 ********************************************************************/
6037 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6038 const SPOOL_PRINTER_INFO_LEVEL *info,
6039 DEVICEMODE *devmode)
6041 int snum;
6042 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6043 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6044 WERROR result;
6045 UNISTR2 buffer;
6046 fstring asc_buffer;
6048 DEBUG(8,("update_printer\n"));
6050 result = WERR_OK;
6052 if (!Printer) {
6053 result = WERR_BADFID;
6054 goto done;
6057 if (!get_printer_snum(p, handle, &snum)) {
6058 result = WERR_BADFID;
6059 goto done;
6062 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6063 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6064 result = WERR_BADFID;
6065 goto done;
6068 DEBUGADD(8,("Converting info_2 struct\n"));
6071 * convert_printer_info converts the incoming
6072 * info from the client and overwrites the info
6073 * just read from the tdb in the pointer 'printer'.
6076 if (!convert_printer_info(info, printer, level)) {
6077 result = WERR_NOMEM;
6078 goto done;
6081 if (devmode) {
6082 /* we have a valid devmode
6083 convert it and link it*/
6085 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6086 if (!convert_devicemode(printer->info_2->printername, devmode,
6087 &printer->info_2->devmode)) {
6088 result = WERR_NOMEM;
6089 goto done;
6093 /* Do sanity check on the requested changes for Samba */
6095 if (!check_printer_ok(printer->info_2, snum)) {
6096 result = WERR_INVALID_PARAM;
6097 goto done;
6100 /* FIXME!!! If the driver has changed we really should verify that
6101 it is installed before doing much else --jerry */
6103 /* Check calling user has permission to update printer description */
6105 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6106 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6107 result = WERR_ACCESS_DENIED;
6108 goto done;
6111 /* Call addprinter hook */
6112 /* Check changes to see if this is really needed */
6114 if ( *lp_addprinter_cmd()
6115 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6116 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6117 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6118 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6120 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6121 result = WERR_ACCESS_DENIED;
6122 goto done;
6126 * make sure we actually reload the services after
6127 * this as smb.conf could have a new section in it
6128 * .... shouldn't .... but could
6130 reload_services(False);
6134 * When a *new* driver is bound to a printer, the drivername is used to
6135 * lookup previously saved driver initialization info, which is then
6136 * bound to the printer, simulating what happens in the Windows arch.
6138 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6140 if (!set_driver_init(printer, 2))
6142 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6143 printer->info_2->drivername));
6146 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6147 printer->info_2->drivername));
6149 notify_printer_driver(snum, printer->info_2->drivername);
6153 * flag which changes actually occured. This is a small subset of
6154 * all the possible changes. We also have to update things in the
6155 * DsSpooler key.
6158 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6159 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6160 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6161 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6163 notify_printer_comment(snum, printer->info_2->comment);
6166 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6167 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6168 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6169 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6171 notify_printer_sharename(snum, printer->info_2->sharename);
6174 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6175 char *pname;
6177 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6178 pname++;
6179 else
6180 pname = printer->info_2->printername;
6183 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6184 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6185 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6187 notify_printer_printername( snum, pname );
6190 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6191 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6192 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6193 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6195 notify_printer_port(snum, printer->info_2->portname);
6198 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6199 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6200 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6201 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6203 notify_printer_location(snum, printer->info_2->location);
6206 /* here we need to update some more DsSpooler keys */
6207 /* uNCName, serverName, shortServerName */
6209 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6210 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6211 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6212 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6213 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6215 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6216 global_myname(), printer->info_2->sharename );
6217 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6218 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6219 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6221 /* Update printer info */
6222 result = mod_a_printer(printer, 2);
6224 done:
6225 free_a_printer(&printer, 2);
6226 free_a_printer(&old_printer, 2);
6229 return result;
6232 /****************************************************************************
6233 ****************************************************************************/
6234 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6235 const SPOOL_PRINTER_INFO_LEVEL *info)
6237 #ifdef HAVE_ADS
6238 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6239 int snum;
6240 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6242 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6244 if (!Printer)
6245 return WERR_BADFID;
6247 if (!get_printer_snum(p, handle, &snum))
6248 return WERR_BADFID;
6250 nt_printer_publish(Printer, snum, info7->action);
6252 return WERR_OK;
6253 #else
6254 return WERR_UNKNOWN_LEVEL;
6255 #endif
6257 /****************************************************************************
6258 ****************************************************************************/
6260 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6262 POLICY_HND *handle = &q_u->handle;
6263 uint32 level = q_u->level;
6264 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6265 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6266 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6267 uint32 command = q_u->command;
6268 WERROR result;
6270 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6272 if (!Printer) {
6273 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6274 return WERR_BADFID;
6277 /* check the level */
6278 switch (level) {
6279 case 0:
6280 return control_printer(handle, command, p);
6281 case 2:
6282 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6283 if (!W_ERROR_IS_OK(result))
6284 return result;
6285 if (secdesc_ctr)
6286 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6287 return result;
6288 case 3:
6289 return update_printer_sec(handle, level, info, p,
6290 secdesc_ctr);
6291 case 7:
6292 return publish_or_unpublish_printer(p, handle, info);
6293 default:
6294 return WERR_UNKNOWN_LEVEL;
6298 /****************************************************************************
6299 ****************************************************************************/
6301 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6303 POLICY_HND *handle = &q_u->handle;
6304 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6306 if (!Printer) {
6307 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6308 return WERR_BADFID;
6311 if (Printer->notify.client_connected==True) {
6312 int snum = -1;
6314 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6315 snum = -1;
6316 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6317 !get_printer_snum(p, handle, &snum) )
6318 return WERR_BADFID;
6320 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6323 Printer->notify.flags=0;
6324 Printer->notify.options=0;
6325 Printer->notify.localmachine[0]='\0';
6326 Printer->notify.printerlocal=0;
6327 if (Printer->notify.option)
6328 free_spool_notify_option(&Printer->notify.option);
6329 Printer->notify.client_connected=False;
6331 return WERR_OK;
6334 /****************************************************************************
6335 ****************************************************************************/
6337 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6339 /* that's an [in out] buffer */
6341 if ( q_u->buffer )
6342 rpcbuf_move(q_u->buffer, &r_u->buffer);
6344 r_u->needed = 0;
6345 return WERR_INVALID_PARAM; /* this is what a NT server
6346 returns for AddJob. AddJob
6347 must fail on non-local
6348 printers */
6351 /****************************************************************************
6352 ****************************************************************************/
6354 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6355 int position, int snum,
6356 NT_PRINTER_INFO_LEVEL *ntprinter)
6358 struct tm *t;
6360 t=gmtime(&queue->time);
6362 job_info->jobid=queue->job;
6363 init_unistr(&job_info->printername, lp_servicename(snum));
6364 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6365 init_unistr(&job_info->username, queue->fs_user);
6366 init_unistr(&job_info->document, queue->fs_file);
6367 init_unistr(&job_info->datatype, "RAW");
6368 init_unistr(&job_info->text_status, "");
6369 job_info->status=nt_printj_status(queue->status);
6370 job_info->priority=queue->priority;
6371 job_info->position=position;
6372 job_info->totalpages=queue->page_count;
6373 job_info->pagesprinted=0;
6375 make_systemtime(&job_info->submitted, t);
6378 /****************************************************************************
6379 ****************************************************************************/
6381 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6382 int position, int snum,
6383 NT_PRINTER_INFO_LEVEL *ntprinter,
6384 DEVICEMODE *devmode)
6386 struct tm *t;
6388 t=gmtime(&queue->time);
6390 job_info->jobid=queue->job;
6392 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6394 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6395 init_unistr(&job_info->username, queue->fs_user);
6396 init_unistr(&job_info->document, queue->fs_file);
6397 init_unistr(&job_info->notifyname, queue->fs_user);
6398 init_unistr(&job_info->datatype, "RAW");
6399 init_unistr(&job_info->printprocessor, "winprint");
6400 init_unistr(&job_info->parameters, "");
6401 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6402 init_unistr(&job_info->text_status, "");
6404 /* and here the security descriptor */
6406 job_info->status=nt_printj_status(queue->status);
6407 job_info->priority=queue->priority;
6408 job_info->position=position;
6409 job_info->starttime=0;
6410 job_info->untiltime=0;
6411 job_info->totalpages=queue->page_count;
6412 job_info->size=queue->size;
6413 make_systemtime(&(job_info->submitted), t);
6414 job_info->timeelapsed=0;
6415 job_info->pagesprinted=0;
6417 job_info->devmode = devmode;
6419 return (True);
6422 /****************************************************************************
6423 Enumjobs at level 1.
6424 ****************************************************************************/
6426 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6427 NT_PRINTER_INFO_LEVEL *ntprinter,
6428 RPC_BUFFER *buffer, uint32 offered,
6429 uint32 *needed, uint32 *returned)
6431 JOB_INFO_1 *info;
6432 int i;
6433 WERROR result = WERR_OK;
6435 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6436 if (info==NULL) {
6437 SAFE_FREE(queue);
6438 *returned=0;
6439 return WERR_NOMEM;
6442 for (i=0; i<*returned; i++)
6443 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6445 SAFE_FREE(queue);
6447 /* check the required size. */
6448 for (i=0; i<*returned; i++)
6449 (*needed) += spoolss_size_job_info_1(&info[i]);
6451 if (*needed > offered) {
6452 result = WERR_INSUFFICIENT_BUFFER;
6453 goto out;
6456 if (!rpcbuf_alloc_size(buffer, *needed)) {
6457 result = WERR_NOMEM;
6458 goto out;
6461 /* fill the buffer with the structures */
6462 for (i=0; i<*returned; i++)
6463 smb_io_job_info_1("", buffer, &info[i], 0);
6465 out:
6466 /* clear memory */
6467 SAFE_FREE(info);
6469 if ( !W_ERROR_IS_OK(result) )
6470 *returned = 0;
6472 return result;
6475 /****************************************************************************
6476 Enumjobs at level 2.
6477 ****************************************************************************/
6479 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6480 NT_PRINTER_INFO_LEVEL *ntprinter,
6481 RPC_BUFFER *buffer, uint32 offered,
6482 uint32 *needed, uint32 *returned)
6484 JOB_INFO_2 *info = NULL;
6485 int i;
6486 WERROR result = WERR_OK;
6487 DEVICEMODE *devmode = NULL;
6489 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6490 *returned=0;
6491 return WERR_NOMEM;
6494 /* this should not be a failure condition if the devmode is NULL */
6496 devmode = construct_dev_mode(snum);
6498 for (i=0; i<*returned; i++)
6499 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6501 free_a_printer(&ntprinter, 2);
6502 SAFE_FREE(queue);
6504 /* check the required size. */
6505 for (i=0; i<*returned; i++)
6506 (*needed) += spoolss_size_job_info_2(&info[i]);
6508 if (*needed > offered) {
6509 result = WERR_INSUFFICIENT_BUFFER;
6510 goto out;
6513 if (!rpcbuf_alloc_size(buffer, *needed)) {
6514 result = WERR_NOMEM;
6515 goto out;
6518 /* fill the buffer with the structures */
6519 for (i=0; i<*returned; i++)
6520 smb_io_job_info_2("", buffer, &info[i], 0);
6522 out:
6523 free_devmode(devmode);
6524 SAFE_FREE(info);
6526 if ( !W_ERROR_IS_OK(result) )
6527 *returned = 0;
6529 return result;
6533 /****************************************************************************
6534 Enumjobs.
6535 ****************************************************************************/
6537 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6539 POLICY_HND *handle = &q_u->handle;
6540 uint32 level = q_u->level;
6541 RPC_BUFFER *buffer = NULL;
6542 uint32 offered = q_u->offered;
6543 uint32 *needed = &r_u->needed;
6544 uint32 *returned = &r_u->returned;
6545 WERROR wret;
6546 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6547 int snum;
6548 print_status_struct prt_status;
6549 print_queue_struct *queue=NULL;
6551 /* that's an [in out] buffer */
6553 if ( q_u->buffer ) {
6554 rpcbuf_move(q_u->buffer, &r_u->buffer);
6555 buffer = r_u->buffer;
6558 DEBUG(4,("_spoolss_enumjobs\n"));
6560 *needed=0;
6561 *returned=0;
6563 /* lookup the printer snum and tdb entry */
6565 if (!get_printer_snum(p, handle, &snum))
6566 return WERR_BADFID;
6568 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6569 if ( !W_ERROR_IS_OK(wret) )
6570 return wret;
6572 *returned = print_queue_status(snum, &queue, &prt_status);
6573 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6575 if (*returned == 0) {
6576 SAFE_FREE(queue);
6577 return WERR_OK;
6580 switch (level) {
6581 case 1:
6582 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6583 return wret;
6584 case 2:
6585 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6586 return wret;
6587 default:
6588 SAFE_FREE(queue);
6589 *returned=0;
6590 wret = WERR_UNKNOWN_LEVEL;
6593 free_a_printer( &ntprinter, 2 );
6594 return wret;
6597 /****************************************************************************
6598 ****************************************************************************/
6600 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6602 return WERR_OK;
6605 /****************************************************************************
6606 ****************************************************************************/
6608 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6610 POLICY_HND *handle = &q_u->handle;
6611 uint32 jobid = q_u->jobid;
6612 uint32 command = q_u->command;
6614 struct current_user user;
6615 int snum;
6616 WERROR errcode = WERR_BADFUNC;
6618 if (!get_printer_snum(p, handle, &snum)) {
6619 return WERR_BADFID;
6622 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6623 return WERR_INVALID_PRINTER_NAME;
6626 get_current_user(&user, p);
6628 switch (command) {
6629 case JOB_CONTROL_CANCEL:
6630 case JOB_CONTROL_DELETE:
6631 if (print_job_delete(&user, snum, jobid, &errcode)) {
6632 errcode = WERR_OK;
6634 break;
6635 case JOB_CONTROL_PAUSE:
6636 if (print_job_pause(&user, snum, jobid, &errcode)) {
6637 errcode = WERR_OK;
6639 break;
6640 case JOB_CONTROL_RESTART:
6641 case JOB_CONTROL_RESUME:
6642 if (print_job_resume(&user, snum, jobid, &errcode)) {
6643 errcode = WERR_OK;
6645 break;
6646 default:
6647 return WERR_UNKNOWN_LEVEL;
6650 return errcode;
6653 /****************************************************************************
6654 Enumerates all printer drivers at level 1.
6655 ****************************************************************************/
6657 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6659 int i;
6660 int ndrivers;
6661 uint32 version;
6662 fstring *list = NULL;
6663 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6664 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6665 WERROR result = WERR_OK;
6667 *returned=0;
6669 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6670 list=NULL;
6671 ndrivers=get_ntdrivers(&list, architecture, version);
6672 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6674 if(ndrivers == -1)
6675 return WERR_NOMEM;
6677 if(ndrivers != 0) {
6678 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6679 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6680 SAFE_FREE(driver_info_1);
6681 SAFE_FREE(list);
6682 return WERR_NOMEM;
6684 else driver_info_1 = tdi1;
6687 for (i=0; i<ndrivers; i++) {
6688 WERROR status;
6689 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6690 ZERO_STRUCT(driver);
6691 status = get_a_printer_driver(&driver, 3, list[i],
6692 architecture, version);
6693 if (!W_ERROR_IS_OK(status)) {
6694 SAFE_FREE(list);
6695 return status;
6697 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6698 free_a_printer_driver(driver, 3);
6701 *returned+=ndrivers;
6702 SAFE_FREE(list);
6705 /* check the required size. */
6706 for (i=0; i<*returned; i++) {
6707 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6708 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6711 if (*needed > offered) {
6712 result = WERR_INSUFFICIENT_BUFFER;
6713 goto out;
6716 if (!rpcbuf_alloc_size(buffer, *needed)) {
6717 result = WERR_NOMEM;
6718 goto out;
6721 /* fill the buffer with the driver structures */
6722 for (i=0; i<*returned; i++) {
6723 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6724 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6727 out:
6728 SAFE_FREE(driver_info_1);
6730 if ( !W_ERROR_IS_OK(result) )
6731 *returned = 0;
6733 return result;
6736 /****************************************************************************
6737 Enumerates all printer drivers at level 2.
6738 ****************************************************************************/
6740 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6742 int i;
6743 int ndrivers;
6744 uint32 version;
6745 fstring *list = NULL;
6746 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6747 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6748 WERROR result = WERR_OK;
6750 *returned=0;
6752 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6753 list=NULL;
6754 ndrivers=get_ntdrivers(&list, architecture, version);
6755 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6757 if(ndrivers == -1)
6758 return WERR_NOMEM;
6760 if(ndrivers != 0) {
6761 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6762 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6763 SAFE_FREE(driver_info_2);
6764 SAFE_FREE(list);
6765 return WERR_NOMEM;
6767 else driver_info_2 = tdi2;
6770 for (i=0; i<ndrivers; i++) {
6771 WERROR status;
6773 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6774 ZERO_STRUCT(driver);
6775 status = get_a_printer_driver(&driver, 3, list[i],
6776 architecture, version);
6777 if (!W_ERROR_IS_OK(status)) {
6778 SAFE_FREE(list);
6779 return status;
6781 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6782 free_a_printer_driver(driver, 3);
6785 *returned+=ndrivers;
6786 SAFE_FREE(list);
6789 /* check the required size. */
6790 for (i=0; i<*returned; i++) {
6791 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6792 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6795 if (*needed > offered) {
6796 result = WERR_INSUFFICIENT_BUFFER;
6797 goto out;
6800 if (!rpcbuf_alloc_size(buffer, *needed)) {
6801 result = WERR_NOMEM;
6802 goto out;
6805 /* fill the buffer with the form structures */
6806 for (i=0; i<*returned; i++) {
6807 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6808 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6811 out:
6812 SAFE_FREE(driver_info_2);
6814 if ( !W_ERROR_IS_OK(result) )
6815 *returned = 0;
6817 return result;
6820 /****************************************************************************
6821 Enumerates all printer drivers at level 3.
6822 ****************************************************************************/
6824 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6826 int i;
6827 int ndrivers;
6828 uint32 version;
6829 fstring *list = NULL;
6830 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6831 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6832 WERROR result = WERR_OK;
6834 *returned=0;
6836 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6837 list=NULL;
6838 ndrivers=get_ntdrivers(&list, architecture, version);
6839 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6841 if(ndrivers == -1)
6842 return WERR_NOMEM;
6844 if(ndrivers != 0) {
6845 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6846 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6847 SAFE_FREE(driver_info_3);
6848 SAFE_FREE(list);
6849 return WERR_NOMEM;
6851 else driver_info_3 = tdi3;
6854 for (i=0; i<ndrivers; i++) {
6855 WERROR status;
6857 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6858 ZERO_STRUCT(driver);
6859 status = get_a_printer_driver(&driver, 3, list[i],
6860 architecture, version);
6861 if (!W_ERROR_IS_OK(status)) {
6862 SAFE_FREE(list);
6863 return status;
6865 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6866 free_a_printer_driver(driver, 3);
6869 *returned+=ndrivers;
6870 SAFE_FREE(list);
6873 /* check the required size. */
6874 for (i=0; i<*returned; i++) {
6875 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6876 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6879 if (*needed > offered) {
6880 result = WERR_INSUFFICIENT_BUFFER;
6881 goto out;
6884 if (!rpcbuf_alloc_size(buffer, *needed)) {
6885 result = WERR_NOMEM;
6886 goto out;
6889 /* fill the buffer with the driver structures */
6890 for (i=0; i<*returned; i++) {
6891 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6892 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6895 out:
6896 for (i=0; i<*returned; i++)
6897 SAFE_FREE(driver_info_3[i].dependentfiles);
6899 SAFE_FREE(driver_info_3);
6901 if ( !W_ERROR_IS_OK(result) )
6902 *returned = 0;
6904 return result;
6907 /****************************************************************************
6908 Enumerates all printer drivers.
6909 ****************************************************************************/
6911 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6913 uint32 level = q_u->level;
6914 RPC_BUFFER *buffer = NULL;
6915 uint32 offered = q_u->offered;
6916 uint32 *needed = &r_u->needed;
6917 uint32 *returned = &r_u->returned;
6919 fstring servername;
6920 fstring architecture;
6922 /* that's an [in out] buffer */
6924 if ( q_u->buffer ) {
6925 rpcbuf_move(q_u->buffer, &r_u->buffer);
6926 buffer = r_u->buffer;
6929 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6931 *needed = 0;
6932 *returned = 0;
6934 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6935 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6937 if ( !is_myname_or_ipaddr( servername ) )
6938 return WERR_UNKNOWN_PRINTER_DRIVER;
6940 switch (level) {
6941 case 1:
6942 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6943 case 2:
6944 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6945 case 3:
6946 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6947 default:
6948 return WERR_UNKNOWN_LEVEL;
6952 /****************************************************************************
6953 ****************************************************************************/
6955 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6957 form->flag=list->flag;
6958 init_unistr(&form->name, list->name);
6959 form->width=list->width;
6960 form->length=list->length;
6961 form->left=list->left;
6962 form->top=list->top;
6963 form->right=list->right;
6964 form->bottom=list->bottom;
6967 /****************************************************************************
6968 ****************************************************************************/
6970 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6972 uint32 level = q_u->level;
6973 RPC_BUFFER *buffer = NULL;
6974 uint32 offered = q_u->offered;
6975 uint32 *needed = &r_u->needed;
6976 uint32 *numofforms = &r_u->numofforms;
6977 uint32 numbuiltinforms;
6979 nt_forms_struct *list=NULL;
6980 nt_forms_struct *builtinlist=NULL;
6981 FORM_1 *forms_1;
6982 int buffer_size=0;
6983 int i;
6985 /* that's an [in out] buffer */
6987 if ( q_u->buffer ) {
6988 rpcbuf_move(q_u->buffer, &r_u->buffer);
6989 buffer = r_u->buffer;
6992 DEBUG(4,("_spoolss_enumforms\n"));
6993 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6994 DEBUGADD(5,("Info level [%d]\n", level));
6996 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6997 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6998 *numofforms = get_ntforms(&list);
6999 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7000 *numofforms += numbuiltinforms;
7002 if (*numofforms == 0)
7003 return WERR_NO_MORE_ITEMS;
7005 switch (level) {
7006 case 1:
7007 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7008 *numofforms=0;
7009 return WERR_NOMEM;
7012 /* construct the list of form structures */
7013 for (i=0; i<numbuiltinforms; i++) {
7014 DEBUGADD(6,("Filling form number [%d]\n",i));
7015 fill_form_1(&forms_1[i], &builtinlist[i]);
7018 SAFE_FREE(builtinlist);
7020 for (; i<*numofforms; i++) {
7021 DEBUGADD(6,("Filling form number [%d]\n",i));
7022 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7025 SAFE_FREE(list);
7027 /* check the required size. */
7028 for (i=0; i<numbuiltinforms; i++) {
7029 DEBUGADD(6,("adding form [%d]'s size\n",i));
7030 buffer_size += spoolss_size_form_1(&forms_1[i]);
7032 for (; i<*numofforms; i++) {
7033 DEBUGADD(6,("adding form [%d]'s size\n",i));
7034 buffer_size += spoolss_size_form_1(&forms_1[i]);
7037 *needed=buffer_size;
7039 if (*needed > offered) {
7040 SAFE_FREE(forms_1);
7041 *numofforms=0;
7042 return WERR_INSUFFICIENT_BUFFER;
7045 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7046 SAFE_FREE(forms_1);
7047 *numofforms=0;
7048 return WERR_NOMEM;
7051 /* fill the buffer with the form structures */
7052 for (i=0; i<numbuiltinforms; i++) {
7053 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7054 smb_io_form_1("", buffer, &forms_1[i], 0);
7056 for (; i<*numofforms; i++) {
7057 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7058 smb_io_form_1("", buffer, &forms_1[i], 0);
7061 SAFE_FREE(forms_1);
7063 return WERR_OK;
7065 default:
7066 SAFE_FREE(list);
7067 SAFE_FREE(builtinlist);
7068 return WERR_UNKNOWN_LEVEL;
7073 /****************************************************************************
7074 ****************************************************************************/
7076 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7078 uint32 level = q_u->level;
7079 UNISTR2 *uni_formname = &q_u->formname;
7080 RPC_BUFFER *buffer = NULL;
7081 uint32 offered = q_u->offered;
7082 uint32 *needed = &r_u->needed;
7084 nt_forms_struct *list=NULL;
7085 nt_forms_struct builtin_form;
7086 BOOL foundBuiltin;
7087 FORM_1 form_1;
7088 fstring form_name;
7089 int buffer_size=0;
7090 int numofforms=0, i=0;
7092 /* that's an [in out] buffer */
7094 if ( q_u->buffer ) {
7095 rpcbuf_move(q_u->buffer, &r_u->buffer);
7096 buffer = r_u->buffer;
7099 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7101 DEBUG(4,("_spoolss_getform\n"));
7102 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7103 DEBUGADD(5,("Info level [%d]\n", level));
7105 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7106 if (!foundBuiltin) {
7107 numofforms = get_ntforms(&list);
7108 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7110 if (numofforms == 0)
7111 return WERR_BADFID;
7114 switch (level) {
7115 case 1:
7116 if (foundBuiltin) {
7117 fill_form_1(&form_1, &builtin_form);
7118 } else {
7120 /* Check if the requested name is in the list of form structures */
7121 for (i=0; i<numofforms; i++) {
7123 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7125 if (strequal(form_name, list[i].name)) {
7126 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7127 fill_form_1(&form_1, &list[i]);
7128 break;
7132 SAFE_FREE(list);
7133 if (i == numofforms) {
7134 return WERR_BADFID;
7137 /* check the required size. */
7139 *needed=spoolss_size_form_1(&form_1);
7141 if (*needed > offered)
7142 return WERR_INSUFFICIENT_BUFFER;
7144 if (!rpcbuf_alloc_size(buffer, buffer_size))
7145 return WERR_NOMEM;
7147 /* fill the buffer with the form structures */
7148 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7149 smb_io_form_1("", buffer, &form_1, 0);
7151 return WERR_OK;
7153 default:
7154 SAFE_FREE(list);
7155 return WERR_UNKNOWN_LEVEL;
7159 /****************************************************************************
7160 ****************************************************************************/
7162 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7164 init_unistr(&port->port_name, name);
7167 /****************************************************************************
7168 ****************************************************************************/
7170 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7172 init_unistr(&port->port_name, name);
7173 init_unistr(&port->monitor_name, "Local Monitor");
7174 init_unistr(&port->description, "Local Port");
7175 port->port_type=PORT_TYPE_WRITE;
7176 port->reserved=0x0;
7180 /****************************************************************************
7181 wrapper around the enumer ports command
7182 ****************************************************************************/
7184 WERROR enumports_hook( int *count, char ***lines )
7186 char *cmd = lp_enumports_cmd();
7187 char **qlines;
7188 pstring command;
7189 int numlines;
7190 int ret;
7191 int fd;
7194 /* if no hook then just fill in the default port */
7196 if ( !*cmd ) {
7197 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7198 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7199 qlines[1] = NULL;
7200 numlines = 1;
7202 else {
7203 /* we have a valid enumport command */
7205 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7207 DEBUG(10,("Running [%s]\n", command));
7208 ret = smbrun(command, &fd);
7209 DEBUG(10,("Returned [%d]\n", ret));
7210 if (ret != 0) {
7211 if (fd != -1)
7212 close(fd);
7214 return WERR_ACCESS_DENIED;
7217 numlines = 0;
7218 qlines = fd_lines_load(fd, &numlines);
7219 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7220 close(fd);
7223 *count = numlines;
7224 *lines = qlines;
7226 return WERR_OK;
7229 /****************************************************************************
7230 enumports level 1.
7231 ****************************************************************************/
7233 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7235 PORT_INFO_1 *ports=NULL;
7236 int i=0;
7237 WERROR result = WERR_OK;
7238 char **qlines;
7239 int numlines;
7241 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7242 return result;
7244 if(numlines) {
7245 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7246 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7247 dos_errstr(WERR_NOMEM)));
7248 file_lines_free(qlines);
7249 return WERR_NOMEM;
7252 for (i=0; i<numlines; i++) {
7253 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7254 fill_port_1(&ports[i], qlines[i]);
7257 file_lines_free(qlines);
7260 *returned = numlines;
7262 /* check the required size. */
7263 for (i=0; i<*returned; i++) {
7264 DEBUGADD(6,("adding port [%d]'s size\n", i));
7265 *needed += spoolss_size_port_info_1(&ports[i]);
7268 if (*needed > offered) {
7269 result = WERR_INSUFFICIENT_BUFFER;
7270 goto out;
7273 if (!rpcbuf_alloc_size(buffer, *needed)) {
7274 result = WERR_NOMEM;
7275 goto out;
7278 /* fill the buffer with the ports structures */
7279 for (i=0; i<*returned; i++) {
7280 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7281 smb_io_port_1("", buffer, &ports[i], 0);
7284 out:
7285 SAFE_FREE(ports);
7287 if ( !W_ERROR_IS_OK(result) )
7288 *returned = 0;
7290 return result;
7293 /****************************************************************************
7294 enumports level 2.
7295 ****************************************************************************/
7297 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7299 PORT_INFO_2 *ports=NULL;
7300 int i=0;
7301 WERROR result = WERR_OK;
7302 char **qlines;
7303 int numlines;
7305 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7306 return result;
7309 if(numlines) {
7310 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7311 file_lines_free(qlines);
7312 return WERR_NOMEM;
7315 for (i=0; i<numlines; i++) {
7316 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7317 fill_port_2(&(ports[i]), qlines[i]);
7320 file_lines_free(qlines);
7323 *returned = numlines;
7325 /* check the required size. */
7326 for (i=0; i<*returned; i++) {
7327 DEBUGADD(6,("adding port [%d]'s size\n", i));
7328 *needed += spoolss_size_port_info_2(&ports[i]);
7331 if (*needed > offered) {
7332 result = WERR_INSUFFICIENT_BUFFER;
7333 goto out;
7336 if (!rpcbuf_alloc_size(buffer, *needed)) {
7337 result = WERR_NOMEM;
7338 goto out;
7341 /* fill the buffer with the ports structures */
7342 for (i=0; i<*returned; i++) {
7343 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7344 smb_io_port_2("", buffer, &ports[i], 0);
7347 out:
7348 SAFE_FREE(ports);
7350 if ( !W_ERROR_IS_OK(result) )
7351 *returned = 0;
7353 return result;
7356 /****************************************************************************
7357 enumports.
7358 ****************************************************************************/
7360 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7362 uint32 level = q_u->level;
7363 RPC_BUFFER *buffer = NULL;
7364 uint32 offered = q_u->offered;
7365 uint32 *needed = &r_u->needed;
7366 uint32 *returned = &r_u->returned;
7368 /* that's an [in out] buffer */
7370 if ( q_u->buffer ) {
7371 rpcbuf_move(q_u->buffer, &r_u->buffer);
7372 buffer = r_u->buffer;
7375 DEBUG(4,("_spoolss_enumports\n"));
7377 *returned=0;
7378 *needed=0;
7380 switch (level) {
7381 case 1:
7382 return enumports_level_1(buffer, offered, needed, returned);
7383 case 2:
7384 return enumports_level_2(buffer, offered, needed, returned);
7385 default:
7386 return WERR_UNKNOWN_LEVEL;
7390 /****************************************************************************
7391 ****************************************************************************/
7393 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7394 const SPOOL_PRINTER_INFO_LEVEL *info,
7395 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7396 uint32 user_switch, const SPOOL_USER_CTR *user,
7397 POLICY_HND *handle)
7399 NT_PRINTER_INFO_LEVEL *printer = NULL;
7400 fstring name;
7401 int snum;
7402 WERROR err = WERR_OK;
7404 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7405 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7406 return WERR_NOMEM;
7409 ZERO_STRUCTP(printer);
7411 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7412 if (!convert_printer_info(info, printer, 2)) {
7413 free_a_printer(&printer, 2);
7414 return WERR_NOMEM;
7417 /* check to see if the printer already exists */
7419 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7420 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7421 printer->info_2->sharename));
7422 free_a_printer(&printer, 2);
7423 return WERR_PRINTER_ALREADY_EXISTS;
7426 /* FIXME!!! smbd should check to see if the driver is installed before
7427 trying to add a printer like this --jerry */
7429 if (*lp_addprinter_cmd() ) {
7430 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7431 free_a_printer(&printer,2);
7432 return WERR_ACCESS_DENIED;
7434 } else {
7435 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7436 "smb.conf parameter \"addprinter command\" is defined. This"
7437 "parameter must exist for this call to succeed\n",
7438 printer->info_2->sharename ));
7441 /* use our primary netbios name since get_a_printer() will convert
7442 it to what the client expects on a case by case basis */
7444 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7445 printer->info_2->sharename);
7448 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7449 free_a_printer(&printer,2);
7450 return WERR_ACCESS_DENIED;
7453 /* you must be a printer admin to add a new printer */
7454 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7455 free_a_printer(&printer,2);
7456 return WERR_ACCESS_DENIED;
7460 * Do sanity check on the requested changes for Samba.
7463 if (!check_printer_ok(printer->info_2, snum)) {
7464 free_a_printer(&printer,2);
7465 return WERR_INVALID_PARAM;
7469 * When a printer is created, the drivername bound to the printer is used
7470 * to lookup previously saved driver initialization info, which is then
7471 * bound to the new printer, simulating what happens in the Windows arch.
7474 if (!devmode)
7476 set_driver_init(printer, 2);
7478 else
7480 /* A valid devmode was included, convert and link it
7482 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7484 if (!convert_devicemode(printer->info_2->printername, devmode,
7485 &printer->info_2->devmode))
7486 return WERR_NOMEM;
7489 /* write the ASCII on disk */
7490 err = mod_a_printer(printer, 2);
7491 if (!W_ERROR_IS_OK(err)) {
7492 free_a_printer(&printer,2);
7493 return err;
7496 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7497 /* Handle open failed - remove addition. */
7498 del_a_printer(printer->info_2->sharename);
7499 free_a_printer(&printer,2);
7500 return WERR_ACCESS_DENIED;
7503 update_c_setprinter(False);
7504 free_a_printer(&printer,2);
7506 return WERR_OK;
7509 /****************************************************************************
7510 ****************************************************************************/
7512 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7514 UNISTR2 *uni_srv_name = q_u->server_name;
7515 uint32 level = q_u->level;
7516 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7517 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7518 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7519 uint32 user_switch = q_u->user_switch;
7520 SPOOL_USER_CTR *user = &q_u->user_ctr;
7521 POLICY_HND *handle = &r_u->handle;
7523 switch (level) {
7524 case 1:
7525 /* we don't handle yet */
7526 /* but I know what to do ... */
7527 return WERR_UNKNOWN_LEVEL;
7528 case 2:
7529 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7530 devmode, sdb,
7531 user_switch, user, handle);
7532 default:
7533 return WERR_UNKNOWN_LEVEL;
7537 /****************************************************************************
7538 ****************************************************************************/
7540 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7542 uint32 level = q_u->level;
7543 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7544 WERROR err = WERR_OK;
7545 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7546 struct current_user user;
7547 fstring driver_name;
7548 uint32 version;
7550 ZERO_STRUCT(driver);
7552 get_current_user(&user, p);
7554 if (!convert_printer_driver_info(info, &driver, level)) {
7555 err = WERR_NOMEM;
7556 goto done;
7559 DEBUG(5,("Cleaning driver's information\n"));
7560 err = clean_up_driver_struct(driver, level, &user);
7561 if (!W_ERROR_IS_OK(err))
7562 goto done;
7564 DEBUG(5,("Moving driver to final destination\n"));
7565 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7566 goto done;
7569 if (add_a_printer_driver(driver, level)!=0) {
7570 err = WERR_ACCESS_DENIED;
7571 goto done;
7574 /* BEGIN_ADMIN_LOG */
7575 switch(level) {
7576 case 3:
7577 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7578 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7579 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7580 break;
7581 case 6:
7582 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7583 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7584 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7585 break;
7587 /* END_ADMIN_LOG */
7590 * I think this is where he DrvUpgradePrinter() hook would be
7591 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7592 * server. Right now, we just need to send ourselves a message
7593 * to update each printer bound to this driver. --jerry
7596 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7597 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7598 driver_name));
7602 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7603 * decide if the driver init data should be deleted. The rules are:
7604 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7605 * 2) delete init data only if there is no 2k/Xp driver
7606 * 3) always delete init data
7607 * The generalized rule is always use init data from the highest order driver.
7608 * It is necessary to follow the driver install by an initialization step to
7609 * finish off this process.
7611 if (level == 3)
7612 version = driver.info_3->cversion;
7613 else if (level == 6)
7614 version = driver.info_6->version;
7615 else
7616 version = -1;
7617 switch (version) {
7619 * 9x printer driver - never delete init data
7621 case 0:
7622 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7623 driver_name));
7624 break;
7627 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7628 * there is no 2k/Xp driver init data for this driver name.
7630 case 2:
7632 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7634 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7636 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7638 if (!del_driver_init(driver_name))
7639 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7640 } else {
7642 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7644 free_a_printer_driver(driver1,3);
7645 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7646 driver_name));
7649 break;
7652 * 2k or Xp printer driver - always delete init data
7654 case 3:
7655 if (!del_driver_init(driver_name))
7656 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7657 break;
7659 default:
7660 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7661 break;
7665 done:
7666 free_a_printer_driver(driver, level);
7667 return err;
7670 /********************************************************************
7671 * spoolss_addprinterdriverex
7672 ********************************************************************/
7674 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7676 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7677 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7680 * we only support the semantics of AddPrinterDriver()
7681 * i.e. only copy files that are newer than existing ones
7684 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7685 return WERR_ACCESS_DENIED;
7687 ZERO_STRUCT(q_u_local);
7688 ZERO_STRUCT(r_u_local);
7690 /* just pass the information off to _spoolss_addprinterdriver() */
7691 q_u_local.server_name_ptr = q_u->server_name_ptr;
7692 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7693 q_u_local.level = q_u->level;
7694 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7696 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7699 /****************************************************************************
7700 ****************************************************************************/
7702 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7704 init_unistr(&info->name, name);
7707 /****************************************************************************
7708 ****************************************************************************/
7710 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7712 pstring path;
7713 pstring long_archi;
7714 fstring servername;
7715 char *pservername;
7716 const char *short_archi;
7717 DRIVER_DIRECTORY_1 *info=NULL;
7718 WERROR result = WERR_OK;
7720 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7721 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7723 /* check for beginning double '\'s and that the server
7724 long enough */
7726 pservername = servername;
7727 if ( *pservername == '\\' && strlen(servername)>2 ) {
7728 pservername += 2;
7731 if ( !is_myname_or_ipaddr( pservername ) )
7732 return WERR_INVALID_PARAM;
7734 if (!(short_archi = get_short_archi(long_archi)))
7735 return WERR_INVALID_ENVIRONMENT;
7737 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7738 return WERR_NOMEM;
7740 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7742 DEBUG(4,("printer driver directory: [%s]\n", path));
7744 fill_driverdir_1(info, path);
7746 *needed += spoolss_size_driverdir_info_1(info);
7748 if (*needed > offered) {
7749 result = WERR_INSUFFICIENT_BUFFER;
7750 goto out;
7753 if (!rpcbuf_alloc_size(buffer, *needed)) {
7754 result = WERR_NOMEM;
7755 goto out;
7758 smb_io_driverdir_1("", buffer, info, 0);
7760 out:
7761 SAFE_FREE(info);
7763 return result;
7766 /****************************************************************************
7767 ****************************************************************************/
7769 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7771 UNISTR2 *name = &q_u->name;
7772 UNISTR2 *uni_environment = &q_u->environment;
7773 uint32 level = q_u->level;
7774 RPC_BUFFER *buffer = NULL;
7775 uint32 offered = q_u->offered;
7776 uint32 *needed = &r_u->needed;
7778 /* that's an [in out] buffer */
7780 if ( q_u->buffer ) {
7781 rpcbuf_move(q_u->buffer, &r_u->buffer);
7782 buffer = r_u->buffer;
7785 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7787 *needed=0;
7789 switch(level) {
7790 case 1:
7791 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7792 default:
7793 return WERR_UNKNOWN_LEVEL;
7797 /****************************************************************************
7798 ****************************************************************************/
7800 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7802 POLICY_HND *handle = &q_u->handle;
7803 uint32 idx = q_u->index;
7804 uint32 in_value_len = q_u->valuesize;
7805 uint32 in_data_len = q_u->datasize;
7806 uint32 *out_max_value_len = &r_u->valuesize;
7807 uint16 **out_value = &r_u->value;
7808 uint32 *out_value_len = &r_u->realvaluesize;
7809 uint32 *out_type = &r_u->type;
7810 uint32 *out_max_data_len = &r_u->datasize;
7811 uint8 **data_out = &r_u->data;
7812 uint32 *out_data_len = &r_u->realdatasize;
7814 NT_PRINTER_INFO_LEVEL *printer = NULL;
7816 uint32 biggest_valuesize;
7817 uint32 biggest_datasize;
7818 uint32 data_len;
7819 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7820 int snum;
7821 WERROR result;
7822 REGISTRY_VALUE *val = NULL;
7823 NT_PRINTER_DATA *p_data;
7824 int i, key_index, num_values;
7825 int name_length;
7827 *out_type = 0;
7829 *out_max_data_len = 0;
7830 *data_out = NULL;
7831 *out_data_len = 0;
7833 DEBUG(5,("spoolss_enumprinterdata\n"));
7835 if (!Printer) {
7836 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7837 return WERR_BADFID;
7840 if (!get_printer_snum(p,handle, &snum))
7841 return WERR_BADFID;
7843 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7844 if (!W_ERROR_IS_OK(result))
7845 return result;
7847 p_data = printer->info_2->data;
7848 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7850 result = WERR_OK;
7853 * The NT machine wants to know the biggest size of value and data
7855 * cf: MSDN EnumPrinterData remark section
7858 if ( !in_value_len && !in_data_len && (key_index != -1) )
7860 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7862 biggest_valuesize = 0;
7863 biggest_datasize = 0;
7865 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7867 for ( i=0; i<num_values; i++ )
7869 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7871 name_length = strlen(val->valuename);
7872 if ( strlen(val->valuename) > biggest_valuesize )
7873 biggest_valuesize = name_length;
7875 if ( val->size > biggest_datasize )
7876 biggest_datasize = val->size;
7878 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7879 biggest_datasize));
7882 /* the value is an UNICODE string but real_value_size is the length
7883 in bytes including the trailing 0 */
7885 *out_value_len = 2 * (1+biggest_valuesize);
7886 *out_data_len = biggest_datasize;
7888 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7890 goto done;
7894 * the value len is wrong in NT sp3
7895 * that's the number of bytes not the number of unicode chars
7898 if ( key_index != -1 )
7899 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7901 if ( !val )
7904 /* out_value should default to "" or else NT4 has
7905 problems unmarshalling the response */
7907 *out_max_value_len=(in_value_len/sizeof(uint16));
7909 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7911 result = WERR_NOMEM;
7912 goto done;
7915 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7917 /* the data is counted in bytes */
7919 *out_max_data_len = in_data_len;
7920 *out_data_len = in_data_len;
7922 /* only allocate when given a non-zero data_len */
7924 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7926 result = WERR_NOMEM;
7927 goto done;
7930 result = WERR_NO_MORE_ITEMS;
7932 else
7935 * the value is:
7936 * - counted in bytes in the request
7937 * - counted in UNICODE chars in the max reply
7938 * - counted in bytes in the real size
7940 * take a pause *before* coding not *during* coding
7943 /* name */
7944 *out_max_value_len=(in_value_len/sizeof(uint16));
7945 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7947 result = WERR_NOMEM;
7948 goto done;
7951 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7953 /* type */
7955 *out_type = regval_type( val );
7957 /* data - counted in bytes */
7959 *out_max_data_len = in_data_len;
7960 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7962 result = WERR_NOMEM;
7963 goto done;
7965 data_len = regval_size(val);
7966 if ( *data_out )
7967 memcpy( *data_out, regval_data_p(val), data_len );
7968 *out_data_len = data_len;
7971 done:
7972 free_a_printer(&printer, 2);
7973 return result;
7976 /****************************************************************************
7977 ****************************************************************************/
7979 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7981 POLICY_HND *handle = &q_u->handle;
7982 UNISTR2 *value = &q_u->value;
7983 uint32 type = q_u->type;
7984 uint8 *data = q_u->data;
7985 uint32 real_len = q_u->real_len;
7987 NT_PRINTER_INFO_LEVEL *printer = NULL;
7988 int snum=0;
7989 WERROR status = WERR_OK;
7990 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7991 fstring valuename;
7993 DEBUG(5,("spoolss_setprinterdata\n"));
7995 if (!Printer) {
7996 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7997 return WERR_BADFID;
8000 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8001 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8002 return WERR_INVALID_PARAM;
8005 if (!get_printer_snum(p,handle, &snum))
8006 return WERR_BADFID;
8009 * Access check : NT returns "access denied" if you make a
8010 * SetPrinterData call without the necessary privildge.
8011 * we were originally returning OK if nothing changed
8012 * which made Win2k issue **a lot** of SetPrinterData
8013 * when connecting to a printer --jerry
8016 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8018 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8019 status = WERR_ACCESS_DENIED;
8020 goto done;
8023 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8024 if (!W_ERROR_IS_OK(status))
8025 return status;
8027 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8030 * When client side code sets a magic printer data key, detect it and save
8031 * the current printer data and the magic key's data (its the DEVMODE) for
8032 * future printer/driver initializations.
8034 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8036 /* Set devmode and printer initialization info */
8037 status = save_driver_init( printer, 2, data, real_len );
8039 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8041 else
8043 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8044 type, data, real_len );
8045 if ( W_ERROR_IS_OK(status) )
8046 status = mod_a_printer(printer, 2);
8049 done:
8050 free_a_printer(&printer, 2);
8052 return status;
8055 /****************************************************************************
8056 ****************************************************************************/
8058 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8060 POLICY_HND *handle = &q_u->handle;
8061 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8062 int snum;
8064 DEBUG(5,("_spoolss_resetprinter\n"));
8067 * All we do is to check to see if the handle and queue is valid.
8068 * This call really doesn't mean anything to us because we only
8069 * support RAW printing. --jerry
8072 if (!Printer) {
8073 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8074 return WERR_BADFID;
8077 if (!get_printer_snum(p,handle, &snum))
8078 return WERR_BADFID;
8081 /* blindly return success */
8082 return WERR_OK;
8086 /****************************************************************************
8087 ****************************************************************************/
8089 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8091 POLICY_HND *handle = &q_u->handle;
8092 UNISTR2 *value = &q_u->valuename;
8094 NT_PRINTER_INFO_LEVEL *printer = NULL;
8095 int snum=0;
8096 WERROR status = WERR_OK;
8097 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8098 pstring valuename;
8100 DEBUG(5,("spoolss_deleteprinterdata\n"));
8102 if (!Printer) {
8103 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8104 return WERR_BADFID;
8107 if (!get_printer_snum(p, handle, &snum))
8108 return WERR_BADFID;
8110 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8111 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8112 return WERR_ACCESS_DENIED;
8115 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8116 if (!W_ERROR_IS_OK(status))
8117 return status;
8119 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8121 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8123 if ( W_ERROR_IS_OK(status) )
8124 mod_a_printer( printer, 2 );
8126 free_a_printer(&printer, 2);
8128 return status;
8131 /****************************************************************************
8132 ****************************************************************************/
8134 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8136 POLICY_HND *handle = &q_u->handle;
8137 FORM *form = &q_u->form;
8138 nt_forms_struct tmpForm;
8139 int snum;
8140 WERROR status = WERR_OK;
8141 NT_PRINTER_INFO_LEVEL *printer = NULL;
8143 int count=0;
8144 nt_forms_struct *list=NULL;
8145 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8147 DEBUG(5,("spoolss_addform\n"));
8149 if (!Printer) {
8150 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8151 return WERR_BADFID;
8155 /* forms can be added on printer of on the print server handle */
8157 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8159 if (!get_printer_snum(p,handle, &snum))
8160 return WERR_BADFID;
8162 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8163 if (!W_ERROR_IS_OK(status))
8164 goto done;
8167 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8168 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8169 status = WERR_ACCESS_DENIED;
8170 goto done;
8173 /* can't add if builtin */
8175 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8176 status = WERR_ALREADY_EXISTS;
8177 goto done;
8180 count = get_ntforms(&list);
8182 if(!add_a_form(&list, form, &count)) {
8183 status = WERR_NOMEM;
8184 goto done;
8187 write_ntforms(&list, count);
8190 * ChangeID must always be set if this is a printer
8193 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8194 status = mod_a_printer(printer, 2);
8196 done:
8197 if ( printer )
8198 free_a_printer(&printer, 2);
8199 SAFE_FREE(list);
8201 return status;
8204 /****************************************************************************
8205 ****************************************************************************/
8207 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8209 POLICY_HND *handle = &q_u->handle;
8210 UNISTR2 *form_name = &q_u->name;
8211 nt_forms_struct tmpForm;
8212 int count=0;
8213 nt_forms_struct *list=NULL;
8214 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8215 int snum;
8216 WERROR status = WERR_OK;
8217 NT_PRINTER_INFO_LEVEL *printer = NULL;
8219 DEBUG(5,("spoolss_deleteform\n"));
8221 if (!Printer) {
8222 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8223 return WERR_BADFID;
8226 /* forms can be deleted on printer of on the print server handle */
8228 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8230 if (!get_printer_snum(p,handle, &snum))
8231 return WERR_BADFID;
8233 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8234 if (!W_ERROR_IS_OK(status))
8235 goto done;
8238 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8239 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8240 status = WERR_ACCESS_DENIED;
8241 goto done;
8244 /* can't delete if builtin */
8246 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8247 status = WERR_INVALID_PARAM;
8248 goto done;
8251 count = get_ntforms(&list);
8253 if ( !delete_a_form(&list, form_name, &count, &status ))
8254 goto done;
8257 * ChangeID must always be set if this is a printer
8260 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8261 status = mod_a_printer(printer, 2);
8263 done:
8264 if ( printer )
8265 free_a_printer(&printer, 2);
8266 SAFE_FREE(list);
8268 return status;
8271 /****************************************************************************
8272 ****************************************************************************/
8274 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8276 POLICY_HND *handle = &q_u->handle;
8277 FORM *form = &q_u->form;
8278 nt_forms_struct tmpForm;
8279 int snum;
8280 WERROR status = WERR_OK;
8281 NT_PRINTER_INFO_LEVEL *printer = NULL;
8283 int count=0;
8284 nt_forms_struct *list=NULL;
8285 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8287 DEBUG(5,("spoolss_setform\n"));
8289 if (!Printer) {
8290 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8291 return WERR_BADFID;
8294 /* forms can be modified on printer of on the print server handle */
8296 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8298 if (!get_printer_snum(p,handle, &snum))
8299 return WERR_BADFID;
8301 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8302 if (!W_ERROR_IS_OK(status))
8303 goto done;
8306 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8307 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8308 status = WERR_ACCESS_DENIED;
8309 goto done;
8312 /* can't set if builtin */
8313 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8314 status = WERR_INVALID_PARAM;
8315 goto done;
8318 count = get_ntforms(&list);
8319 update_a_form(&list, form, count);
8320 write_ntforms(&list, count);
8323 * ChangeID must always be set if this is a printer
8326 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8327 status = mod_a_printer(printer, 2);
8330 done:
8331 if ( printer )
8332 free_a_printer(&printer, 2);
8333 SAFE_FREE(list);
8335 return status;
8338 /****************************************************************************
8339 enumprintprocessors level 1.
8340 ****************************************************************************/
8342 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8344 PRINTPROCESSOR_1 *info_1=NULL;
8345 WERROR result = WERR_OK;
8347 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8348 return WERR_NOMEM;
8350 (*returned) = 0x1;
8352 init_unistr(&info_1->name, "winprint");
8354 *needed += spoolss_size_printprocessor_info_1(info_1);
8356 if (*needed > offered) {
8357 result = WERR_INSUFFICIENT_BUFFER;
8358 goto out;
8361 if (!rpcbuf_alloc_size(buffer, *needed)) {
8362 result = WERR_NOMEM;
8363 goto out;
8366 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8368 out:
8369 SAFE_FREE(info_1);
8371 if ( !W_ERROR_IS_OK(result) )
8372 *returned = 0;
8374 return result;
8377 /****************************************************************************
8378 ****************************************************************************/
8380 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8382 uint32 level = q_u->level;
8383 RPC_BUFFER *buffer = NULL;
8384 uint32 offered = q_u->offered;
8385 uint32 *needed = &r_u->needed;
8386 uint32 *returned = &r_u->returned;
8388 /* that's an [in out] buffer */
8390 if ( q_u->buffer ) {
8391 rpcbuf_move(q_u->buffer, &r_u->buffer);
8392 buffer = r_u->buffer;
8395 DEBUG(5,("spoolss_enumprintprocessors\n"));
8398 * Enumerate the print processors ...
8400 * Just reply with "winprint", to keep NT happy
8401 * and I can use my nice printer checker.
8404 *returned=0;
8405 *needed=0;
8407 switch (level) {
8408 case 1:
8409 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8410 default:
8411 return WERR_UNKNOWN_LEVEL;
8415 /****************************************************************************
8416 enumprintprocdatatypes level 1.
8417 ****************************************************************************/
8419 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8421 PRINTPROCDATATYPE_1 *info_1=NULL;
8422 WERROR result = WERR_NOMEM;
8424 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8425 return WERR_NOMEM;
8427 (*returned) = 0x1;
8429 init_unistr(&info_1->name, "RAW");
8431 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8433 if (*needed > offered) {
8434 result = WERR_INSUFFICIENT_BUFFER;
8435 goto out;
8438 if (!rpcbuf_alloc_size(buffer, *needed)) {
8439 result = WERR_NOMEM;
8440 goto out;
8443 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8445 out:
8446 SAFE_FREE(info_1);
8448 if ( !W_ERROR_IS_OK(result) )
8449 *returned = 0;
8451 return result;
8454 /****************************************************************************
8455 ****************************************************************************/
8457 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8459 uint32 level = q_u->level;
8460 RPC_BUFFER *buffer = NULL;
8461 uint32 offered = q_u->offered;
8462 uint32 *needed = &r_u->needed;
8463 uint32 *returned = &r_u->returned;
8465 /* that's an [in out] buffer */
8467 if ( q_u->buffer ) {
8468 rpcbuf_move(q_u->buffer, &r_u->buffer);
8469 buffer = r_u->buffer;
8472 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8474 *returned=0;
8475 *needed=0;
8477 switch (level) {
8478 case 1:
8479 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8480 default:
8481 return WERR_UNKNOWN_LEVEL;
8485 /****************************************************************************
8486 enumprintmonitors level 1.
8487 ****************************************************************************/
8489 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8491 PRINTMONITOR_1 *info_1=NULL;
8492 WERROR result = WERR_OK;
8494 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8495 return WERR_NOMEM;
8497 (*returned) = 0x1;
8499 init_unistr(&info_1->name, "Local Port");
8501 *needed += spoolss_size_printmonitor_info_1(info_1);
8503 if (*needed > offered) {
8504 result = WERR_INSUFFICIENT_BUFFER;
8505 goto out;
8508 if (!rpcbuf_alloc_size(buffer, *needed)) {
8509 result = WERR_NOMEM;
8510 goto out;
8513 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8515 out:
8516 SAFE_FREE(info_1);
8518 if ( !W_ERROR_IS_OK(result) )
8519 *returned = 0;
8521 return result;
8524 /****************************************************************************
8525 enumprintmonitors level 2.
8526 ****************************************************************************/
8528 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8530 PRINTMONITOR_2 *info_2=NULL;
8531 WERROR result = WERR_OK;
8533 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8534 return WERR_NOMEM;
8536 (*returned) = 0x1;
8538 init_unistr(&info_2->name, "Local Port");
8539 init_unistr(&info_2->environment, "Windows NT X86");
8540 init_unistr(&info_2->dll_name, "localmon.dll");
8542 *needed += spoolss_size_printmonitor_info_2(info_2);
8544 if (*needed > offered) {
8545 result = WERR_INSUFFICIENT_BUFFER;
8546 goto out;
8549 if (!rpcbuf_alloc_size(buffer, *needed)) {
8550 result = WERR_NOMEM;
8551 goto out;
8554 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8556 out:
8557 SAFE_FREE(info_2);
8559 if ( !W_ERROR_IS_OK(result) )
8560 *returned = 0;
8562 return result;
8565 /****************************************************************************
8566 ****************************************************************************/
8568 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8570 uint32 level = q_u->level;
8571 RPC_BUFFER *buffer = NULL;
8572 uint32 offered = q_u->offered;
8573 uint32 *needed = &r_u->needed;
8574 uint32 *returned = &r_u->returned;
8576 /* that's an [in out] buffer */
8578 if ( q_u->buffer ) {
8579 rpcbuf_move(q_u->buffer, &r_u->buffer);
8580 buffer = r_u->buffer;
8583 DEBUG(5,("spoolss_enumprintmonitors\n"));
8586 * Enumerate the print monitors ...
8588 * Just reply with "Local Port", to keep NT happy
8589 * and I can use my nice printer checker.
8592 *returned=0;
8593 *needed=0;
8595 switch (level) {
8596 case 1:
8597 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8598 case 2:
8599 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8600 default:
8601 return WERR_UNKNOWN_LEVEL;
8605 /****************************************************************************
8606 ****************************************************************************/
8608 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8609 NT_PRINTER_INFO_LEVEL *ntprinter,
8610 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8611 uint32 *needed)
8613 int i=0;
8614 BOOL found=False;
8615 JOB_INFO_1 *info_1=NULL;
8616 WERROR result = WERR_OK;
8618 info_1=SMB_MALLOC_P(JOB_INFO_1);
8620 if (info_1 == NULL) {
8621 return WERR_NOMEM;
8624 for (i=0; i<count && found==False; i++) {
8625 if ((*queue)[i].job==(int)jobid)
8626 found=True;
8629 if (found==False) {
8630 SAFE_FREE(info_1);
8631 /* NT treats not found as bad param... yet another bad choice */
8632 return WERR_INVALID_PARAM;
8635 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8637 *needed += spoolss_size_job_info_1(info_1);
8639 if (*needed > offered) {
8640 result = WERR_INSUFFICIENT_BUFFER;
8641 goto out;
8644 if (!rpcbuf_alloc_size(buffer, *needed)) {
8645 result = WERR_NOMEM;
8646 goto out;
8649 smb_io_job_info_1("", buffer, info_1, 0);
8651 out:
8652 SAFE_FREE(info_1);
8654 return result;
8657 /****************************************************************************
8658 ****************************************************************************/
8660 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8661 NT_PRINTER_INFO_LEVEL *ntprinter,
8662 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8663 uint32 *needed)
8665 int i = 0;
8666 BOOL found = False;
8667 JOB_INFO_2 *info_2;
8668 WERROR result;
8669 DEVICEMODE *devmode = NULL;
8670 NT_DEVICEMODE *nt_devmode = NULL;
8672 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8673 return WERR_NOMEM;
8675 ZERO_STRUCTP(info_2);
8677 for ( i=0; i<count && found==False; i++ )
8679 if ((*queue)[i].job == (int)jobid)
8680 found = True;
8683 if ( !found ) {
8684 /* NT treats not found as bad param... yet another bad
8685 choice */
8686 result = WERR_INVALID_PARAM;
8687 goto done;
8691 * if the print job does not have a DEVMODE associated with it,
8692 * just use the one for the printer. A NULL devicemode is not
8693 * a failure condition
8696 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8697 devmode = construct_dev_mode(snum);
8698 else {
8699 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8700 ZERO_STRUCTP( devmode );
8701 convert_nt_devicemode( devmode, nt_devmode );
8705 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8707 *needed += spoolss_size_job_info_2(info_2);
8709 if (*needed > offered) {
8710 result = WERR_INSUFFICIENT_BUFFER;
8711 goto done;
8714 if (!rpcbuf_alloc_size(buffer, *needed)) {
8715 result = WERR_NOMEM;
8716 goto done;
8719 smb_io_job_info_2("", buffer, info_2, 0);
8721 result = WERR_OK;
8723 done:
8724 /* Cleanup allocated memory */
8726 free_job_info_2(info_2); /* Also frees devmode */
8727 SAFE_FREE(info_2);
8729 return result;
8732 /****************************************************************************
8733 ****************************************************************************/
8735 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8737 POLICY_HND *handle = &q_u->handle;
8738 uint32 jobid = q_u->jobid;
8739 uint32 level = q_u->level;
8740 RPC_BUFFER *buffer = NULL;
8741 uint32 offered = q_u->offered;
8742 uint32 *needed = &r_u->needed;
8743 WERROR wstatus = WERR_OK;
8744 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8745 int snum;
8746 int count;
8747 print_queue_struct *queue = NULL;
8748 print_status_struct prt_status;
8750 /* that's an [in out] buffer */
8752 if ( q_u->buffer ) {
8753 rpcbuf_move(q_u->buffer, &r_u->buffer);
8754 buffer = r_u->buffer;
8757 DEBUG(5,("spoolss_getjob\n"));
8759 *needed = 0;
8761 if (!get_printer_snum(p, handle, &snum))
8762 return WERR_BADFID;
8764 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8765 if ( !W_ERROR_IS_OK(wstatus) )
8766 return wstatus;
8768 count = print_queue_status(snum, &queue, &prt_status);
8770 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8771 count, prt_status.status, prt_status.message));
8773 switch ( level ) {
8774 case 1:
8775 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8776 buffer, offered, needed);
8777 break;
8778 case 2:
8779 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8780 buffer, offered, needed);
8781 break;
8782 default:
8783 wstatus = WERR_UNKNOWN_LEVEL;
8784 break;
8787 SAFE_FREE(queue);
8788 free_a_printer( &ntprinter, 2 );
8790 return wstatus;
8793 /********************************************************************
8794 spoolss_getprinterdataex
8796 From MSDN documentation of GetPrinterDataEx: pass request
8797 to GetPrinterData if key is "PrinterDriverData".
8798 ********************************************************************/
8800 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8802 POLICY_HND *handle = &q_u->handle;
8803 uint32 in_size = q_u->size;
8804 uint32 *type = &r_u->type;
8805 uint32 *out_size = &r_u->size;
8806 uint8 **data = &r_u->data;
8807 uint32 *needed = &r_u->needed;
8808 fstring keyname, valuename;
8810 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8812 NT_PRINTER_INFO_LEVEL *printer = NULL;
8813 int snum = 0;
8814 WERROR status = WERR_OK;
8816 DEBUG(4,("_spoolss_getprinterdataex\n"));
8818 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8819 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8821 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8822 keyname, valuename));
8824 /* in case of problem, return some default values */
8826 *needed = 0;
8827 *type = 0;
8828 *out_size = in_size;
8830 if (!Printer) {
8831 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8832 status = WERR_BADFID;
8833 goto done;
8836 /* Is the handle to a printer or to the server? */
8838 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8839 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8840 status = WERR_INVALID_PARAM;
8841 goto done;
8844 if ( !get_printer_snum(p,handle, &snum) )
8845 return WERR_BADFID;
8847 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8848 if ( !W_ERROR_IS_OK(status) )
8849 goto done;
8851 /* check to see if the keyname is valid */
8852 if ( !strlen(keyname) ) {
8853 status = WERR_INVALID_PARAM;
8854 goto done;
8857 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8858 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8859 free_a_printer( &printer, 2 );
8860 status = WERR_BADFILE;
8861 goto done;
8864 /* When given a new keyname, we should just create it */
8866 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8868 if (*needed > *out_size)
8869 status = WERR_MORE_DATA;
8871 done:
8872 if ( !W_ERROR_IS_OK(status) )
8874 DEBUG(5, ("error: allocating %d\n", *out_size));
8876 /* reply this param doesn't exist */
8878 if ( *out_size )
8880 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8881 status = WERR_NOMEM;
8882 goto done;
8885 else {
8886 *data = NULL;
8890 if ( printer )
8891 free_a_printer( &printer, 2 );
8893 return status;
8896 /********************************************************************
8897 * spoolss_setprinterdataex
8898 ********************************************************************/
8900 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8902 POLICY_HND *handle = &q_u->handle;
8903 uint32 type = q_u->type;
8904 uint8 *data = q_u->data;
8905 uint32 real_len = q_u->real_len;
8907 NT_PRINTER_INFO_LEVEL *printer = NULL;
8908 int snum = 0;
8909 WERROR status = WERR_OK;
8910 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8911 fstring valuename;
8912 fstring keyname;
8913 char *oid_string;
8915 DEBUG(4,("_spoolss_setprinterdataex\n"));
8917 /* From MSDN documentation of SetPrinterDataEx: pass request to
8918 SetPrinterData if key is "PrinterDriverData" */
8920 if (!Printer) {
8921 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8922 return WERR_BADFID;
8925 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8926 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8927 return WERR_INVALID_PARAM;
8930 if ( !get_printer_snum(p,handle, &snum) )
8931 return WERR_BADFID;
8934 * Access check : NT returns "access denied" if you make a
8935 * SetPrinterData call without the necessary privildge.
8936 * we were originally returning OK if nothing changed
8937 * which made Win2k issue **a lot** of SetPrinterData
8938 * when connecting to a printer --jerry
8941 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8943 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8944 return WERR_ACCESS_DENIED;
8947 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8948 if (!W_ERROR_IS_OK(status))
8949 return status;
8951 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8952 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8954 /* check for OID in valuename */
8956 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8958 *oid_string = '\0';
8959 oid_string++;
8962 /* save the registry data */
8964 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8966 if ( W_ERROR_IS_OK(status) )
8968 /* save the OID if one was specified */
8969 if ( oid_string ) {
8970 fstrcat( keyname, "\\" );
8971 fstrcat( keyname, SPOOL_OID_KEY );
8974 * I'm not checking the status here on purpose. Don't know
8975 * if this is right, but I'm returning the status from the
8976 * previous set_printer_dataex() call. I have no idea if
8977 * this is right. --jerry
8980 set_printer_dataex( printer, keyname, valuename,
8981 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8984 status = mod_a_printer(printer, 2);
8987 free_a_printer(&printer, 2);
8989 return status;
8993 /********************************************************************
8994 * spoolss_deleteprinterdataex
8995 ********************************************************************/
8997 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8999 POLICY_HND *handle = &q_u->handle;
9000 UNISTR2 *value = &q_u->valuename;
9001 UNISTR2 *key = &q_u->keyname;
9003 NT_PRINTER_INFO_LEVEL *printer = NULL;
9004 int snum=0;
9005 WERROR status = WERR_OK;
9006 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9007 pstring valuename, keyname;
9009 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9011 if (!Printer) {
9012 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9013 return WERR_BADFID;
9016 if (!get_printer_snum(p, handle, &snum))
9017 return WERR_BADFID;
9019 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9020 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9021 return WERR_ACCESS_DENIED;
9024 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9025 if (!W_ERROR_IS_OK(status))
9026 return status;
9028 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9029 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9031 status = delete_printer_dataex( printer, keyname, valuename );
9033 if ( W_ERROR_IS_OK(status) )
9034 mod_a_printer( printer, 2 );
9036 free_a_printer(&printer, 2);
9038 return status;
9041 /********************************************************************
9042 * spoolss_enumprinterkey
9043 ********************************************************************/
9046 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9048 fstring key;
9049 fstring *keynames = NULL;
9050 uint16 *enumkeys = NULL;
9051 int num_keys;
9052 int printerkey_len;
9053 POLICY_HND *handle = &q_u->handle;
9054 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9055 NT_PRINTER_DATA *data;
9056 NT_PRINTER_INFO_LEVEL *printer = NULL;
9057 int snum = 0;
9058 WERROR status = WERR_BADFILE;
9061 DEBUG(4,("_spoolss_enumprinterkey\n"));
9063 if (!Printer) {
9064 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9065 return WERR_BADFID;
9068 if ( !get_printer_snum(p,handle, &snum) )
9069 return WERR_BADFID;
9071 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9072 if (!W_ERROR_IS_OK(status))
9073 return status;
9075 /* get the list of subkey names */
9077 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9078 data = printer->info_2->data;
9080 num_keys = get_printer_subkeys( data, key, &keynames );
9082 if ( num_keys == -1 ) {
9083 status = WERR_BADFILE;
9084 goto done;
9087 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9089 r_u->needed = printerkey_len*2;
9091 if ( q_u->size < r_u->needed ) {
9092 status = WERR_MORE_DATA;
9093 goto done;
9096 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9097 status = WERR_NOMEM;
9098 goto done;
9101 status = WERR_OK;
9103 if ( q_u->size < r_u->needed )
9104 status = WERR_MORE_DATA;
9106 done:
9107 free_a_printer( &printer, 2 );
9108 SAFE_FREE( keynames );
9110 return status;
9113 /********************************************************************
9114 * spoolss_deleteprinterkey
9115 ********************************************************************/
9117 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9119 POLICY_HND *handle = &q_u->handle;
9120 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9121 fstring key;
9122 NT_PRINTER_INFO_LEVEL *printer = NULL;
9123 int snum=0;
9124 WERROR status;
9126 DEBUG(5,("spoolss_deleteprinterkey\n"));
9128 if (!Printer) {
9129 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9130 return WERR_BADFID;
9133 /* if keyname == NULL, return error */
9135 if ( !q_u->keyname.buffer )
9136 return WERR_INVALID_PARAM;
9138 if (!get_printer_snum(p, handle, &snum))
9139 return WERR_BADFID;
9141 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9142 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9143 return WERR_ACCESS_DENIED;
9146 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9147 if (!W_ERROR_IS_OK(status))
9148 return status;
9150 /* delete the key and all subneys */
9152 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9154 status = delete_all_printer_data( printer->info_2, key );
9156 if ( W_ERROR_IS_OK(status) )
9157 status = mod_a_printer(printer, 2);
9159 free_a_printer( &printer, 2 );
9161 return status;
9165 /********************************************************************
9166 * spoolss_enumprinterdataex
9167 ********************************************************************/
9169 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9171 POLICY_HND *handle = &q_u->handle;
9172 uint32 in_size = q_u->size;
9173 uint32 num_entries,
9174 needed;
9175 NT_PRINTER_INFO_LEVEL *printer = NULL;
9176 PRINTER_ENUM_VALUES *enum_values = NULL;
9177 NT_PRINTER_DATA *p_data;
9178 fstring key;
9179 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9180 int snum;
9181 WERROR result;
9182 int key_index;
9183 int i;
9184 REGISTRY_VALUE *val;
9185 char *value_name;
9186 uint32 data_len;
9189 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9191 if (!Printer) {
9192 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9193 return WERR_BADFID;
9197 * first check for a keyname of NULL or "". Win2k seems to send
9198 * this a lot and we should send back WERR_INVALID_PARAM
9199 * no need to spend time looking up the printer in this case.
9200 * --jerry
9203 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9204 if ( !strlen(key) ) {
9205 result = WERR_INVALID_PARAM;
9206 goto done;
9209 /* get the printer off of disk */
9211 if (!get_printer_snum(p,handle, &snum))
9212 return WERR_BADFID;
9214 ZERO_STRUCT(printer);
9215 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9216 if (!W_ERROR_IS_OK(result))
9217 return result;
9219 /* now look for a match on the key name */
9221 p_data = printer->info_2->data;
9223 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9224 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9226 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9227 result = WERR_INVALID_PARAM;
9228 goto done;
9231 result = WERR_OK;
9232 needed = 0;
9234 /* allocate the memory for the array of pointers -- if necessary */
9236 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9237 if ( num_entries )
9239 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9241 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9242 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9243 result = WERR_NOMEM;
9244 goto done;
9247 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9251 * loop through all params and build the array to pass
9252 * back to the client
9255 for ( i=0; i<num_entries; i++ )
9257 /* lookup the registry value */
9259 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9260 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9262 /* copy the data */
9264 value_name = regval_name( val );
9265 init_unistr( &enum_values[i].valuename, value_name );
9266 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9267 enum_values[i].type = regval_type( val );
9269 data_len = regval_size( val );
9270 if ( data_len ) {
9271 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9273 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9274 data_len ));
9275 result = WERR_NOMEM;
9276 goto done;
9279 enum_values[i].data_len = data_len;
9281 /* keep track of the size of the array in bytes */
9283 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9286 /* housekeeping information in the reply */
9288 r_u->needed = needed;
9289 r_u->returned = num_entries;
9291 if (needed > in_size) {
9292 result = WERR_MORE_DATA;
9293 goto done;
9296 /* copy data into the reply */
9298 r_u->ctr.size = r_u->needed;
9299 r_u->ctr.size_of_array = r_u->returned;
9300 r_u->ctr.values = enum_values;
9304 done:
9305 if ( printer )
9306 free_a_printer(&printer, 2);
9308 return result;
9311 /****************************************************************************
9312 ****************************************************************************/
9314 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9316 init_unistr(&info->name, name);
9319 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9320 UNISTR2 *environment,
9321 RPC_BUFFER *buffer,
9322 uint32 offered,
9323 uint32 *needed)
9325 pstring path;
9326 pstring long_archi;
9327 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9328 WERROR result = WERR_OK;
9330 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9332 if (!get_short_archi(long_archi))
9333 return WERR_INVALID_ENVIRONMENT;
9335 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9336 return WERR_NOMEM;
9338 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9340 fill_printprocessordirectory_1(info, path);
9342 *needed += spoolss_size_printprocessordirectory_info_1(info);
9344 if (*needed > offered) {
9345 result = WERR_INSUFFICIENT_BUFFER;
9346 goto out;
9349 if (!rpcbuf_alloc_size(buffer, *needed)) {
9350 result = WERR_INSUFFICIENT_BUFFER;
9351 goto out;
9354 smb_io_printprocessordirectory_1("", buffer, info, 0);
9356 out:
9357 SAFE_FREE(info);
9359 return result;
9362 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9364 uint32 level = q_u->level;
9365 RPC_BUFFER *buffer = NULL;
9366 uint32 offered = q_u->offered;
9367 uint32 *needed = &r_u->needed;
9368 WERROR result;
9370 /* that's an [in out] buffer */
9372 if ( q_u->buffer ) {
9373 rpcbuf_move(q_u->buffer, &r_u->buffer);
9374 buffer = r_u->buffer;
9377 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9379 *needed=0;
9381 switch(level) {
9382 case 1:
9383 result = getprintprocessordirectory_level_1
9384 (&q_u->name, &q_u->environment, buffer, offered, needed);
9385 break;
9386 default:
9387 result = WERR_UNKNOWN_LEVEL;
9390 return result;
9393 #if 0
9395 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9396 SPOOL_R_REPLYOPENPRINTER *r_u)
9398 DEBUG(5,("_spoolss_replyopenprinter\n"));
9400 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9402 return WERR_OK;
9405 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9406 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9408 DEBUG(5,("_spoolss_replycloseprinter\n"));
9409 return WERR_OK;
9412 #endif