r9742: merging reg_objects and NT_PRINTER_DATA changes from SAMBA_3_0
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob66b4bb5f25be52c3af63622afc2751af41a69bab
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 printer->secdesc = dup_sec_desc( get_talloc_ctx(), ntprinter->info_2->secdesc_buf->sec );
4177 free_a_printer(&ntprinter, 2);
4179 return True;
4182 /********************************************************************
4183 * construct_printer_info_3
4184 * fill a printer_info_3 struct
4185 ********************************************************************/
4187 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4189 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4190 PRINTER_INFO_3 *printer = NULL;
4192 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4193 return False;
4195 *pp_printer = NULL;
4196 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4197 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4198 return False;
4201 ZERO_STRUCTP(printer);
4203 /* These are the components of the SD we are returning. */
4205 printer->flags = 0x4;
4207 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4208 printer->secdesc = dup_sec_desc( get_talloc_ctx(), ntprinter->info_2->secdesc_buf->sec );
4211 free_a_printer(&ntprinter, 2);
4213 *pp_printer = printer;
4214 return True;
4217 /********************************************************************
4218 * construct_printer_info_4
4219 * fill a printer_info_4 struct
4220 ********************************************************************/
4222 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4224 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4226 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4227 return False;
4229 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4230 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4231 printer->attributes = ntprinter->info_2->attributes;
4233 free_a_printer(&ntprinter, 2);
4234 return True;
4237 /********************************************************************
4238 * construct_printer_info_5
4239 * fill a printer_info_5 struct
4240 ********************************************************************/
4242 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4244 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4246 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4247 return False;
4249 init_unistr(&printer->printername, ntprinter->info_2->printername);
4250 init_unistr(&printer->portname, ntprinter->info_2->portname);
4251 printer->attributes = ntprinter->info_2->attributes;
4253 /* these two are not used by NT+ according to MSDN */
4255 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4256 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4258 free_a_printer(&ntprinter, 2);
4260 return True;
4263 /********************************************************************
4264 * construct_printer_info_7
4265 * fill a printer_info_7 struct
4266 ********************************************************************/
4268 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4270 char *guid_str = NULL;
4271 struct uuid guid;
4273 if (is_printer_published(print_hnd, snum, &guid)) {
4274 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4275 strupper_m(guid_str);
4276 init_unistr(&printer->guid, guid_str);
4277 printer->action = SPOOL_DS_PUBLISH;
4278 } else {
4279 init_unistr(&printer->guid, "");
4280 printer->action = SPOOL_DS_UNPUBLISH;
4283 return True;
4286 /********************************************************************
4287 Spoolss_enumprinters.
4288 ********************************************************************/
4290 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4292 int snum;
4293 int i;
4294 int n_services=lp_numservices();
4295 PRINTER_INFO_1 *tp, *printers=NULL;
4296 PRINTER_INFO_1 current_prt;
4297 WERROR result = WERR_OK;
4299 DEBUG(4,("enum_all_printers_info_1\n"));
4301 for (snum=0; snum<n_services; snum++) {
4302 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4303 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4305 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4306 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4307 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4308 SAFE_FREE(printers);
4309 *returned=0;
4310 return WERR_NOMEM;
4312 else printers = tp;
4313 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4315 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4316 (*returned)++;
4321 /* check the required size. */
4322 for (i=0; i<*returned; i++)
4323 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4325 if (*needed > offered) {
4326 result = WERR_INSUFFICIENT_BUFFER;
4327 goto out;
4330 if (!rpcbuf_alloc_size(buffer, *needed)) {
4331 result = WERR_NOMEM;
4332 goto out;
4335 /* fill the buffer with the structures */
4336 for (i=0; i<*returned; i++)
4337 smb_io_printer_info_1("", buffer, &printers[i], 0);
4339 out:
4340 /* clear memory */
4342 SAFE_FREE(printers);
4344 if ( !W_ERROR_IS_OK(result) )
4345 *returned = 0;
4347 return result;
4350 /********************************************************************
4351 enum_all_printers_info_1_local.
4352 *********************************************************************/
4354 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4356 DEBUG(4,("enum_all_printers_info_1_local\n"));
4358 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4361 /********************************************************************
4362 enum_all_printers_info_1_name.
4363 *********************************************************************/
4365 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4367 char *s = name;
4369 DEBUG(4,("enum_all_printers_info_1_name\n"));
4371 if ((name[0] == '\\') && (name[1] == '\\'))
4372 s = name + 2;
4374 if (is_myname_or_ipaddr(s)) {
4375 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4377 else
4378 return WERR_INVALID_NAME;
4381 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4382 /********************************************************************
4383 enum_all_printers_info_1_remote.
4384 *********************************************************************/
4386 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4388 PRINTER_INFO_1 *printer;
4389 fstring printername;
4390 fstring desc;
4391 fstring comment;
4392 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4393 WERROR result = WERR_OK;
4395 /* JFM: currently it's more a place holder than anything else.
4396 * In the spooler world there is a notion of server registration.
4397 * the print servers are registered on the PDC (in the same domain)
4399 * We should have a TDB here. The registration is done thru an
4400 * undocumented RPC call.
4403 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4404 return WERR_NOMEM;
4406 *returned=1;
4408 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4409 slprintf(desc, sizeof(desc)-1,"%s", name);
4410 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4412 init_unistr(&printer->description, desc);
4413 init_unistr(&printer->name, printername);
4414 init_unistr(&printer->comment, comment);
4415 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4417 /* check the required size. */
4418 *needed += spoolss_size_printer_info_1(printer);
4420 if (*needed > offered) {
4421 result = WERR_INSUFFICIENT_BUFFER;
4422 goto out;
4425 if (!rpcbuf_alloc_size(buffer, *needed)) {
4426 result = WERR_NOMEM;
4427 goto out;
4430 /* fill the buffer with the structures */
4431 smb_io_printer_info_1("", buffer, printer, 0);
4433 out:
4434 /* clear memory */
4435 SAFE_FREE(printer);
4437 if ( !W_ERROR_IS_OK(result) )
4438 *returned = 0;
4440 return result;
4443 #endif
4445 /********************************************************************
4446 enum_all_printers_info_1_network.
4447 *********************************************************************/
4449 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4451 char *s = name;
4453 DEBUG(4,("enum_all_printers_info_1_network\n"));
4455 /* If we respond to a enum_printers level 1 on our name with flags
4456 set to PRINTER_ENUM_REMOTE with a list of printers then these
4457 printers incorrectly appear in the APW browse list.
4458 Specifically the printers for the server appear at the workgroup
4459 level where all the other servers in the domain are
4460 listed. Windows responds to this call with a
4461 WERR_CAN_NOT_COMPLETE so we should do the same. */
4463 if (name[0] == '\\' && name[1] == '\\')
4464 s = name + 2;
4466 if (is_myname_or_ipaddr(s))
4467 return WERR_CAN_NOT_COMPLETE;
4469 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4472 /********************************************************************
4473 * api_spoolss_enumprinters
4475 * called from api_spoolss_enumprinters (see this to understand)
4476 ********************************************************************/
4478 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4480 int snum;
4481 int i;
4482 int n_services=lp_numservices();
4483 PRINTER_INFO_2 *tp, *printers=NULL;
4484 PRINTER_INFO_2 current_prt;
4485 WERROR result = WERR_OK;
4487 for (snum=0; snum<n_services; snum++) {
4488 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4489 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4491 if (construct_printer_info_2(NULL, &current_prt, snum))
4493 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4494 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4495 SAFE_FREE(printers);
4496 *returned = 0;
4497 return WERR_NOMEM;
4500 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4502 printers = tp;
4503 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4505 (*returned)++;
4510 /* check the required size. */
4511 for (i=0; i<*returned; i++)
4512 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4514 if (*needed > offered) {
4515 result = WERR_INSUFFICIENT_BUFFER;
4516 goto out;
4519 if (!rpcbuf_alloc_size(buffer, *needed)) {
4520 result = WERR_NOMEM;
4521 goto out;
4524 /* fill the buffer with the structures */
4525 for (i=0; i<*returned; i++)
4526 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4528 out:
4529 /* clear memory */
4531 for (i=0; i<*returned; i++)
4532 free_devmode(printers[i].devmode);
4534 SAFE_FREE(printers);
4536 if ( !W_ERROR_IS_OK(result) )
4537 *returned = 0;
4539 return result;
4542 /********************************************************************
4543 * handle enumeration of printers at level 1
4544 ********************************************************************/
4546 static WERROR enumprinters_level1( uint32 flags, fstring name,
4547 RPC_BUFFER *buffer, uint32 offered,
4548 uint32 *needed, uint32 *returned)
4550 /* Not all the flags are equals */
4552 if (flags & PRINTER_ENUM_LOCAL)
4553 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4555 if (flags & PRINTER_ENUM_NAME)
4556 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4558 #if 0 /* JERRY - disabled for now */
4559 if (flags & PRINTER_ENUM_REMOTE)
4560 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4561 #endif
4563 if (flags & PRINTER_ENUM_NETWORK)
4564 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4566 return WERR_OK; /* NT4sp5 does that */
4569 /********************************************************************
4570 * handle enumeration of printers at level 2
4571 ********************************************************************/
4573 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4574 RPC_BUFFER *buffer, uint32 offered,
4575 uint32 *needed, uint32 *returned)
4577 char *s = servername;
4579 if (flags & PRINTER_ENUM_LOCAL) {
4580 return enum_all_printers_info_2(buffer, offered, needed, returned);
4583 if (flags & PRINTER_ENUM_NAME) {
4584 if ((servername[0] == '\\') && (servername[1] == '\\'))
4585 s = servername + 2;
4586 if (is_myname_or_ipaddr(s))
4587 return enum_all_printers_info_2(buffer, offered, needed, returned);
4588 else
4589 return WERR_INVALID_NAME;
4592 if (flags & PRINTER_ENUM_REMOTE)
4593 return WERR_UNKNOWN_LEVEL;
4595 return WERR_OK;
4598 /********************************************************************
4599 * handle enumeration of printers at level 5
4600 ********************************************************************/
4602 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4603 RPC_BUFFER *buffer, uint32 offered,
4604 uint32 *needed, uint32 *returned)
4606 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4607 return WERR_OK;
4610 /********************************************************************
4611 * api_spoolss_enumprinters
4613 * called from api_spoolss_enumprinters (see this to understand)
4614 ********************************************************************/
4616 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4618 uint32 flags = q_u->flags;
4619 UNISTR2 *servername = &q_u->servername;
4620 uint32 level = q_u->level;
4621 RPC_BUFFER *buffer = NULL;
4622 uint32 offered = q_u->offered;
4623 uint32 *needed = &r_u->needed;
4624 uint32 *returned = &r_u->returned;
4626 fstring name;
4628 /* that's an [in out] buffer */
4630 if ( q_u->buffer ) {
4631 rpcbuf_move(q_u->buffer, &r_u->buffer);
4632 buffer = r_u->buffer;
4635 DEBUG(4,("_spoolss_enumprinters\n"));
4637 *needed=0;
4638 *returned=0;
4641 * Level 1:
4642 * flags==PRINTER_ENUM_NAME
4643 * if name=="" then enumerates all printers
4644 * if name!="" then enumerate the printer
4645 * flags==PRINTER_ENUM_REMOTE
4646 * name is NULL, enumerate printers
4647 * Level 2: name!="" enumerates printers, name can't be NULL
4648 * Level 3: doesn't exist
4649 * Level 4: does a local registry lookup
4650 * Level 5: same as Level 2
4653 unistr2_to_ascii(name, servername, sizeof(name)-1);
4654 strupper_m(name);
4656 switch (level) {
4657 case 1:
4658 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4659 case 2:
4660 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4661 case 5:
4662 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4663 case 3:
4664 case 4:
4665 break;
4667 return WERR_UNKNOWN_LEVEL;
4670 /****************************************************************************
4671 ****************************************************************************/
4673 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4675 PRINTER_INFO_0 *printer=NULL;
4676 WERROR result = WERR_OK;
4678 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4679 return WERR_NOMEM;
4681 construct_printer_info_0(print_hnd, printer, snum);
4683 /* check the required size. */
4684 *needed += spoolss_size_printer_info_0(printer);
4686 if (*needed > offered) {
4687 result = WERR_INSUFFICIENT_BUFFER;
4688 goto out;
4691 if (!rpcbuf_alloc_size(buffer, *needed)) {
4692 result = WERR_NOMEM;
4693 goto out;
4696 /* fill the buffer with the structures */
4697 smb_io_printer_info_0("", buffer, printer, 0);
4699 out:
4700 /* clear memory */
4702 SAFE_FREE(printer);
4704 return result;
4707 /****************************************************************************
4708 ****************************************************************************/
4710 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4712 PRINTER_INFO_1 *printer=NULL;
4713 WERROR result = WERR_OK;
4715 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4716 return WERR_NOMEM;
4718 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4720 /* check the required size. */
4721 *needed += spoolss_size_printer_info_1(printer);
4723 if (*needed > offered) {
4724 result = WERR_INSUFFICIENT_BUFFER;
4725 goto out;
4728 if (!rpcbuf_alloc_size(buffer, *needed)) {
4729 result = WERR_NOMEM;
4730 goto out;
4733 /* fill the buffer with the structures */
4734 smb_io_printer_info_1("", buffer, printer, 0);
4736 out:
4737 /* clear memory */
4738 SAFE_FREE(printer);
4740 return result;
4743 /****************************************************************************
4744 ****************************************************************************/
4746 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4748 PRINTER_INFO_2 *printer=NULL;
4749 WERROR result = WERR_OK;
4751 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4752 return WERR_NOMEM;
4754 construct_printer_info_2(print_hnd, printer, snum);
4756 /* check the required size. */
4757 *needed += spoolss_size_printer_info_2(printer);
4759 if (*needed > offered) {
4760 result = WERR_INSUFFICIENT_BUFFER;
4761 goto out;
4764 if (!rpcbuf_alloc_size(buffer, *needed)) {
4765 result = WERR_NOMEM;
4766 goto out;
4769 /* fill the buffer with the structures */
4770 if (!smb_io_printer_info_2("", buffer, printer, 0))
4771 result = WERR_NOMEM;
4773 out:
4774 /* clear memory */
4775 free_printer_info_2(printer);
4777 return result;
4780 /****************************************************************************
4781 ****************************************************************************/
4783 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4785 PRINTER_INFO_3 *printer=NULL;
4786 WERROR result = WERR_OK;
4788 if (!construct_printer_info_3(print_hnd, &printer, snum))
4789 return WERR_NOMEM;
4791 /* check the required size. */
4792 *needed += spoolss_size_printer_info_3(printer);
4794 if (*needed > offered) {
4795 result = WERR_INSUFFICIENT_BUFFER;
4796 goto out;
4799 if (!rpcbuf_alloc_size(buffer, *needed)) {
4800 result = WERR_NOMEM;
4801 goto out;
4804 /* fill the buffer with the structures */
4805 smb_io_printer_info_3("", buffer, printer, 0);
4807 out:
4808 /* clear memory */
4809 free_printer_info_3(printer);
4811 return result;
4814 /****************************************************************************
4815 ****************************************************************************/
4817 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4819 PRINTER_INFO_4 *printer=NULL;
4820 WERROR result = WERR_OK;
4822 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4823 return WERR_NOMEM;
4825 if (!construct_printer_info_4(print_hnd, printer, snum))
4826 return WERR_NOMEM;
4828 /* check the required size. */
4829 *needed += spoolss_size_printer_info_4(printer);
4831 if (*needed > offered) {
4832 result = WERR_INSUFFICIENT_BUFFER;
4833 goto out;
4836 if (!rpcbuf_alloc_size(buffer, *needed)) {
4837 result = WERR_NOMEM;
4838 goto out;
4841 /* fill the buffer with the structures */
4842 smb_io_printer_info_4("", buffer, printer, 0);
4844 out:
4845 /* clear memory */
4846 free_printer_info_4(printer);
4848 return result;
4851 /****************************************************************************
4852 ****************************************************************************/
4854 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4856 PRINTER_INFO_5 *printer=NULL;
4857 WERROR result = WERR_OK;
4859 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4860 return WERR_NOMEM;
4862 if (!construct_printer_info_5(print_hnd, printer, snum))
4863 return WERR_NOMEM;
4865 /* check the required size. */
4866 *needed += spoolss_size_printer_info_5(printer);
4868 if (*needed > offered) {
4869 result = WERR_INSUFFICIENT_BUFFER;
4870 goto out;
4873 if (!rpcbuf_alloc_size(buffer, *needed)) {
4874 result = WERR_NOMEM;
4875 goto out;
4878 /* fill the buffer with the structures */
4879 smb_io_printer_info_5("", buffer, printer, 0);
4881 out:
4882 /* clear memory */
4883 free_printer_info_5(printer);
4885 return result;
4888 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4890 PRINTER_INFO_7 *printer=NULL;
4891 WERROR result = WERR_OK;
4893 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4894 return WERR_NOMEM;
4896 if (!construct_printer_info_7(print_hnd, printer, snum))
4897 return WERR_NOMEM;
4899 /* check the required size. */
4900 *needed += spoolss_size_printer_info_7(printer);
4902 if (*needed > offered) {
4903 result = WERR_INSUFFICIENT_BUFFER;
4904 goto out;
4907 if (!rpcbuf_alloc_size(buffer, *needed)) {
4908 result = WERR_NOMEM;
4909 goto out;
4913 /* fill the buffer with the structures */
4914 smb_io_printer_info_7("", buffer, printer, 0);
4916 out:
4917 /* clear memory */
4918 free_printer_info_7(printer);
4920 return result;
4923 /****************************************************************************
4924 ****************************************************************************/
4926 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4928 POLICY_HND *handle = &q_u->handle;
4929 uint32 level = q_u->level;
4930 RPC_BUFFER *buffer = NULL;
4931 uint32 offered = q_u->offered;
4932 uint32 *needed = &r_u->needed;
4933 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4935 int snum;
4937 /* that's an [in out] buffer */
4939 if ( q_u->buffer ) {
4940 rpcbuf_move(q_u->buffer, &r_u->buffer);
4941 buffer = r_u->buffer;
4944 *needed=0;
4946 if (!get_printer_snum(p, handle, &snum))
4947 return WERR_BADFID;
4949 switch (level) {
4950 case 0:
4951 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4952 case 1:
4953 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4954 case 2:
4955 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4956 case 3:
4957 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4958 case 4:
4959 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4960 case 5:
4961 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4962 case 7:
4963 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4965 return WERR_UNKNOWN_LEVEL;
4968 /********************************************************************
4969 * fill a DRIVER_INFO_1 struct
4970 ********************************************************************/
4972 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4974 init_unistr( &info->name, driver.info_3->name);
4977 /********************************************************************
4978 * construct_printer_driver_info_1
4979 ********************************************************************/
4981 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4983 NT_PRINTER_INFO_LEVEL *printer = NULL;
4984 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4986 ZERO_STRUCT(driver);
4988 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4989 return WERR_INVALID_PRINTER_NAME;
4991 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4992 return WERR_UNKNOWN_PRINTER_DRIVER;
4994 fill_printer_driver_info_1(info, driver, servername, architecture);
4996 free_a_printer(&printer,2);
4998 return WERR_OK;
5001 /********************************************************************
5002 * construct_printer_driver_info_2
5003 * fill a printer_info_2 struct
5004 ********************************************************************/
5006 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5008 pstring temp;
5010 info->version=driver.info_3->cversion;
5012 init_unistr( &info->name, driver.info_3->name );
5013 init_unistr( &info->architecture, driver.info_3->environment );
5016 if (strlen(driver.info_3->driverpath)) {
5017 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5018 init_unistr( &info->driverpath, temp );
5019 } else
5020 init_unistr( &info->driverpath, "" );
5022 if (strlen(driver.info_3->datafile)) {
5023 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5024 init_unistr( &info->datafile, temp );
5025 } else
5026 init_unistr( &info->datafile, "" );
5028 if (strlen(driver.info_3->configfile)) {
5029 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5030 init_unistr( &info->configfile, temp );
5031 } else
5032 init_unistr( &info->configfile, "" );
5035 /********************************************************************
5036 * construct_printer_driver_info_2
5037 * fill a printer_info_2 struct
5038 ********************************************************************/
5040 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5042 NT_PRINTER_INFO_LEVEL *printer = NULL;
5043 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5045 ZERO_STRUCT(printer);
5046 ZERO_STRUCT(driver);
5048 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5049 return WERR_INVALID_PRINTER_NAME;
5051 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5052 return WERR_UNKNOWN_PRINTER_DRIVER;
5054 fill_printer_driver_info_2(info, driver, servername);
5056 free_a_printer(&printer,2);
5058 return WERR_OK;
5061 /********************************************************************
5062 * copy a strings array and convert to UNICODE
5064 * convert an array of ascii string to a UNICODE string
5065 ********************************************************************/
5067 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5069 int i=0;
5070 int j=0;
5071 const char *v;
5072 pstring line;
5073 uint16 *tuary;
5075 DEBUG(6,("init_unistr_array\n"));
5076 *uni_array=NULL;
5078 while (True)
5080 if ( !char_array )
5081 v = "";
5082 else
5084 v = char_array[i];
5085 if (!v)
5086 v = ""; /* hack to handle null lists */
5089 /* hack to allow this to be used in places other than when generating
5090 the list of dependent files */
5092 if ( servername )
5093 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5094 else
5095 pstrcpy( line, v );
5097 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5099 /* add one extra unit16 for the second terminating NULL */
5101 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5102 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5103 return 0;
5104 } else
5105 *uni_array = tuary;
5107 if ( !strlen(v) )
5108 break;
5110 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5111 i++;
5114 if (*uni_array) {
5115 /* special case for ""; we need to add both NULL's here */
5116 if (!j)
5117 (*uni_array)[j++]=0x0000;
5118 (*uni_array)[j]=0x0000;
5121 DEBUGADD(6,("last one:done\n"));
5123 /* return size of array in uint16's */
5125 return j+1;
5128 /********************************************************************
5129 * construct_printer_info_3
5130 * fill a printer_info_3 struct
5131 ********************************************************************/
5133 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5135 pstring temp;
5137 ZERO_STRUCTP(info);
5139 info->version=driver.info_3->cversion;
5141 init_unistr( &info->name, driver.info_3->name );
5142 init_unistr( &info->architecture, driver.info_3->environment );
5144 if (strlen(driver.info_3->driverpath)) {
5145 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5146 init_unistr( &info->driverpath, temp );
5147 } else
5148 init_unistr( &info->driverpath, "" );
5150 if (strlen(driver.info_3->datafile)) {
5151 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5152 init_unistr( &info->datafile, temp );
5153 } else
5154 init_unistr( &info->datafile, "" );
5156 if (strlen(driver.info_3->configfile)) {
5157 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5158 init_unistr( &info->configfile, temp );
5159 } else
5160 init_unistr( &info->configfile, "" );
5162 if (strlen(driver.info_3->helpfile)) {
5163 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5164 init_unistr( &info->helpfile, temp );
5165 } else
5166 init_unistr( &info->helpfile, "" );
5168 init_unistr( &info->monitorname, driver.info_3->monitorname );
5169 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5171 info->dependentfiles=NULL;
5172 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5175 /********************************************************************
5176 * construct_printer_info_3
5177 * fill a printer_info_3 struct
5178 ********************************************************************/
5180 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5182 NT_PRINTER_INFO_LEVEL *printer = NULL;
5183 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5184 WERROR status;
5185 ZERO_STRUCT(driver);
5187 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5188 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5189 if (!W_ERROR_IS_OK(status))
5190 return WERR_INVALID_PRINTER_NAME;
5192 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5193 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5195 #if 0 /* JERRY */
5198 * I put this code in during testing. Helpful when commenting out the
5199 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5200 * as win2k always queries the driver using an infor level of 6.
5201 * I've left it in (but ifdef'd out) because I'll probably
5202 * use it in experimentation again in the future. --jerry 22/01/2002
5205 if (!W_ERROR_IS_OK(status)) {
5207 * Is this a W2k client ?
5209 if (version == 3) {
5210 /* Yes - try again with a WinNT driver. */
5211 version = 2;
5212 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5213 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5215 #endif
5217 if (!W_ERROR_IS_OK(status)) {
5218 free_a_printer(&printer,2);
5219 return WERR_UNKNOWN_PRINTER_DRIVER;
5222 #if 0 /* JERRY */
5224 #endif
5227 fill_printer_driver_info_3(info, driver, servername);
5229 free_a_printer(&printer,2);
5231 return WERR_OK;
5234 /********************************************************************
5235 * construct_printer_info_6
5236 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5237 ********************************************************************/
5239 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5241 pstring temp;
5242 fstring nullstr;
5244 ZERO_STRUCTP(info);
5245 memset(&nullstr, '\0', sizeof(fstring));
5247 info->version=driver.info_3->cversion;
5249 init_unistr( &info->name, driver.info_3->name );
5250 init_unistr( &info->architecture, driver.info_3->environment );
5252 if (strlen(driver.info_3->driverpath)) {
5253 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5254 init_unistr( &info->driverpath, temp );
5255 } else
5256 init_unistr( &info->driverpath, "" );
5258 if (strlen(driver.info_3->datafile)) {
5259 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5260 init_unistr( &info->datafile, temp );
5261 } else
5262 init_unistr( &info->datafile, "" );
5264 if (strlen(driver.info_3->configfile)) {
5265 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5266 init_unistr( &info->configfile, temp );
5267 } else
5268 init_unistr( &info->configfile, "" );
5270 if (strlen(driver.info_3->helpfile)) {
5271 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5272 init_unistr( &info->helpfile, temp );
5273 } else
5274 init_unistr( &info->helpfile, "" );
5276 init_unistr( &info->monitorname, driver.info_3->monitorname );
5277 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5279 info->dependentfiles = NULL;
5280 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5282 info->previousdrivernames=NULL;
5283 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5285 info->driver_date.low=0;
5286 info->driver_date.high=0;
5288 info->padding=0;
5289 info->driver_version_low=0;
5290 info->driver_version_high=0;
5292 init_unistr( &info->mfgname, "");
5293 init_unistr( &info->oem_url, "");
5294 init_unistr( &info->hardware_id, "");
5295 init_unistr( &info->provider, "");
5298 /********************************************************************
5299 * construct_printer_info_6
5300 * fill a printer_info_6 struct
5301 ********************************************************************/
5303 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5304 fstring servername, fstring architecture, uint32 version)
5306 NT_PRINTER_INFO_LEVEL *printer = NULL;
5307 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5308 WERROR status;
5310 ZERO_STRUCT(driver);
5312 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5314 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5316 if (!W_ERROR_IS_OK(status))
5317 return WERR_INVALID_PRINTER_NAME;
5319 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5321 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5323 if (!W_ERROR_IS_OK(status))
5326 * Is this a W2k client ?
5329 if (version < 3) {
5330 free_a_printer(&printer,2);
5331 return WERR_UNKNOWN_PRINTER_DRIVER;
5334 /* Yes - try again with a WinNT driver. */
5335 version = 2;
5336 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5337 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5338 if (!W_ERROR_IS_OK(status)) {
5339 free_a_printer(&printer,2);
5340 return WERR_UNKNOWN_PRINTER_DRIVER;
5344 fill_printer_driver_info_6(info, driver, servername);
5346 free_a_printer(&printer,2);
5347 free_a_printer_driver(driver, 3);
5349 return WERR_OK;
5352 /****************************************************************************
5353 ****************************************************************************/
5355 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5357 SAFE_FREE(info->dependentfiles);
5360 /****************************************************************************
5361 ****************************************************************************/
5363 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5365 SAFE_FREE(info->dependentfiles);
5368 /****************************************************************************
5369 ****************************************************************************/
5371 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5373 DRIVER_INFO_1 *info=NULL;
5374 WERROR result;
5376 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5377 return WERR_NOMEM;
5379 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5380 if (!W_ERROR_IS_OK(result))
5381 goto out;
5383 /* check the required size. */
5384 *needed += spoolss_size_printer_driver_info_1(info);
5386 if (*needed > offered) {
5387 result = WERR_INSUFFICIENT_BUFFER;
5388 goto out;
5391 if (!rpcbuf_alloc_size(buffer, *needed)) {
5392 result = WERR_NOMEM;
5393 goto out;
5396 /* fill the buffer with the structures */
5397 smb_io_printer_driver_info_1("", buffer, info, 0);
5399 out:
5400 /* clear memory */
5401 SAFE_FREE(info);
5403 return result;
5406 /****************************************************************************
5407 ****************************************************************************/
5409 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5411 DRIVER_INFO_2 *info=NULL;
5412 WERROR result;
5414 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5415 return WERR_NOMEM;
5417 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5418 if (!W_ERROR_IS_OK(result))
5419 goto out;
5421 /* check the required size. */
5422 *needed += spoolss_size_printer_driver_info_2(info);
5424 if (*needed > offered) {
5425 result = WERR_INSUFFICIENT_BUFFER;
5426 goto out;
5429 if (!rpcbuf_alloc_size(buffer, *needed)) {
5430 result = WERR_NOMEM;
5431 goto out;
5434 /* fill the buffer with the structures */
5435 smb_io_printer_driver_info_2("", buffer, info, 0);
5437 out:
5438 /* clear memory */
5439 SAFE_FREE(info);
5441 return result;
5444 /****************************************************************************
5445 ****************************************************************************/
5447 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5449 DRIVER_INFO_3 info;
5450 WERROR result;
5452 ZERO_STRUCT(info);
5454 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5455 if (!W_ERROR_IS_OK(result))
5456 goto out;
5458 /* check the required size. */
5459 *needed += spoolss_size_printer_driver_info_3(&info);
5461 if (*needed > offered) {
5462 result = WERR_INSUFFICIENT_BUFFER;
5463 goto out;
5466 if (!rpcbuf_alloc_size(buffer, *needed)) {
5467 result = WERR_NOMEM;
5468 goto out;
5471 /* fill the buffer with the structures */
5472 smb_io_printer_driver_info_3("", buffer, &info, 0);
5474 out:
5475 free_printer_driver_info_3(&info);
5477 return result;
5480 /****************************************************************************
5481 ****************************************************************************/
5483 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5485 DRIVER_INFO_6 info;
5486 WERROR result;
5488 ZERO_STRUCT(info);
5490 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5491 if (!W_ERROR_IS_OK(result))
5492 goto out;
5494 /* check the required size. */
5495 *needed += spoolss_size_printer_driver_info_6(&info);
5497 if (*needed > offered) {
5498 result = WERR_INSUFFICIENT_BUFFER;
5499 goto out;
5502 if (!rpcbuf_alloc_size(buffer, *needed)) {
5503 result = WERR_NOMEM;
5504 goto out;
5507 /* fill the buffer with the structures */
5508 smb_io_printer_driver_info_6("", buffer, &info, 0);
5510 out:
5511 free_printer_driver_info_6(&info);
5513 return result;
5516 /****************************************************************************
5517 ****************************************************************************/
5519 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5521 POLICY_HND *handle = &q_u->handle;
5522 UNISTR2 *uni_arch = &q_u->architecture;
5523 uint32 level = q_u->level;
5524 uint32 clientmajorversion = q_u->clientmajorversion;
5525 RPC_BUFFER *buffer = NULL;
5526 uint32 offered = q_u->offered;
5527 uint32 *needed = &r_u->needed;
5528 uint32 *servermajorversion = &r_u->servermajorversion;
5529 uint32 *serverminorversion = &r_u->serverminorversion;
5530 Printer_entry *printer;
5532 fstring servername;
5533 fstring architecture;
5534 int snum;
5536 /* that's an [in out] buffer */
5538 if ( q_u->buffer ) {
5539 rpcbuf_move(q_u->buffer, &r_u->buffer);
5540 buffer = r_u->buffer;
5543 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5545 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5546 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5547 return WERR_INVALID_PRINTER_NAME;
5550 *needed = 0;
5551 *servermajorversion = 0;
5552 *serverminorversion = 0;
5554 fstrcpy(servername, get_server_name( printer ));
5555 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5557 if (!get_printer_snum(p, handle, &snum))
5558 return WERR_BADFID;
5560 switch (level) {
5561 case 1:
5562 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5563 case 2:
5564 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5565 case 3:
5566 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5567 case 6:
5568 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5569 #if 0 /* JERRY */
5570 case 101:
5571 /* apparently this call is the equivalent of
5572 EnumPrinterDataEx() for the DsDriver key */
5573 break;
5574 #endif
5577 return WERR_UNKNOWN_LEVEL;
5580 /****************************************************************************
5581 ****************************************************************************/
5583 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5585 POLICY_HND *handle = &q_u->handle;
5587 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5589 if (!Printer) {
5590 DEBUG(3,("Error in startpageprinter printer handle\n"));
5591 return WERR_BADFID;
5594 Printer->page_started=True;
5595 return WERR_OK;
5598 /****************************************************************************
5599 ****************************************************************************/
5601 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5603 POLICY_HND *handle = &q_u->handle;
5604 int snum;
5606 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5608 if (!Printer) {
5609 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5610 return WERR_BADFID;
5613 if (!get_printer_snum(p, handle, &snum))
5614 return WERR_BADFID;
5616 Printer->page_started=False;
5617 print_job_endpage(snum, Printer->jobid);
5619 return WERR_OK;
5622 /********************************************************************
5623 * api_spoolss_getprinter
5624 * called from the spoolss dispatcher
5626 ********************************************************************/
5628 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5630 POLICY_HND *handle = &q_u->handle;
5631 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5632 uint32 *jobid = &r_u->jobid;
5634 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5635 int snum;
5636 pstring jobname;
5637 fstring datatype;
5638 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5639 struct current_user user;
5641 if (!Printer) {
5642 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5643 return WERR_BADFID;
5646 get_current_user(&user, p);
5649 * a nice thing with NT is it doesn't listen to what you tell it.
5650 * when asked to send _only_ RAW datas, it tries to send datas
5651 * in EMF format.
5653 * So I add checks like in NT Server ...
5656 if (info_1->p_datatype != 0) {
5657 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5658 if (strcmp(datatype, "RAW") != 0) {
5659 (*jobid)=0;
5660 return WERR_INVALID_DATATYPE;
5664 /* get the share number of the printer */
5665 if (!get_printer_snum(p, handle, &snum)) {
5666 return WERR_BADFID;
5669 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5671 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5673 /* An error occured in print_job_start() so return an appropriate
5674 NT error code. */
5676 if (Printer->jobid == -1) {
5677 return map_werror_from_unix(errno);
5680 Printer->document_started=True;
5681 (*jobid) = Printer->jobid;
5683 return WERR_OK;
5686 /********************************************************************
5687 * api_spoolss_getprinter
5688 * called from the spoolss dispatcher
5690 ********************************************************************/
5692 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5694 POLICY_HND *handle = &q_u->handle;
5696 return _spoolss_enddocprinter_internal(p, handle);
5699 /****************************************************************************
5700 ****************************************************************************/
5702 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5704 POLICY_HND *handle = &q_u->handle;
5705 uint32 buffer_size = q_u->buffer_size;
5706 uint8 *buffer = q_u->buffer;
5707 uint32 *buffer_written = &q_u->buffer_size2;
5708 int snum;
5709 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5711 if (!Printer) {
5712 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5713 r_u->buffer_written = q_u->buffer_size2;
5714 return WERR_BADFID;
5717 if (!get_printer_snum(p, handle, &snum))
5718 return WERR_BADFID;
5720 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5721 (SMB_OFF_T)-1, (size_t)buffer_size);
5722 if (*buffer_written == (uint32)-1) {
5723 r_u->buffer_written = 0;
5724 if (errno == ENOSPC)
5725 return WERR_NO_SPOOL_SPACE;
5726 else
5727 return WERR_ACCESS_DENIED;
5730 r_u->buffer_written = q_u->buffer_size2;
5732 return WERR_OK;
5735 /********************************************************************
5736 * api_spoolss_getprinter
5737 * called from the spoolss dispatcher
5739 ********************************************************************/
5741 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5742 pipes_struct *p)
5744 struct current_user user;
5745 int snum;
5746 WERROR errcode = WERR_BADFUNC;
5747 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5749 get_current_user(&user, p);
5751 if (!Printer) {
5752 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5753 return WERR_BADFID;
5756 if (!get_printer_snum(p, handle, &snum))
5757 return WERR_BADFID;
5759 switch (command) {
5760 case PRINTER_CONTROL_PAUSE:
5761 if (print_queue_pause(&user, snum, &errcode)) {
5762 errcode = WERR_OK;
5764 break;
5765 case PRINTER_CONTROL_RESUME:
5766 case PRINTER_CONTROL_UNPAUSE:
5767 if (print_queue_resume(&user, snum, &errcode)) {
5768 errcode = WERR_OK;
5770 break;
5771 case PRINTER_CONTROL_PURGE:
5772 if (print_queue_purge(&user, snum, &errcode)) {
5773 errcode = WERR_OK;
5775 break;
5776 default:
5777 return WERR_UNKNOWN_LEVEL;
5780 return errcode;
5783 /********************************************************************
5784 * api_spoolss_abortprinter
5785 * From MSDN: "Deletes printer's spool file if printer is configured
5786 * for spooling"
5787 ********************************************************************/
5789 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5791 POLICY_HND *handle = &q_u->handle;
5792 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5793 int snum;
5794 struct current_user user;
5795 WERROR errcode = WERR_OK;
5797 if (!Printer) {
5798 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5799 return WERR_BADFID;
5802 if (!get_printer_snum(p, handle, &snum))
5803 return WERR_BADFID;
5805 get_current_user( &user, p );
5807 print_job_delete( &user, snum, Printer->jobid, &errcode );
5809 return errcode;
5812 /********************************************************************
5813 * called by spoolss_api_setprinter
5814 * when updating a printer description
5815 ********************************************************************/
5817 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5818 const SPOOL_PRINTER_INFO_LEVEL *info,
5819 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5821 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5822 WERROR result;
5823 int snum;
5825 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5827 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5828 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5829 OUR_HANDLE(handle)));
5831 result = WERR_BADFID;
5832 goto done;
5835 /* Check the user has permissions to change the security
5836 descriptor. By experimentation with two NT machines, the user
5837 requires Full Access to the printer to change security
5838 information. */
5840 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5841 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5842 result = WERR_ACCESS_DENIED;
5843 goto done;
5846 /* NT seems to like setting the security descriptor even though
5847 nothing may have actually changed. */
5849 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5851 if (DEBUGLEVEL >= 10) {
5852 SEC_ACL *the_acl;
5853 int i;
5855 the_acl = old_secdesc_ctr->sec->dacl;
5856 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5857 PRINTERNAME(snum), the_acl->num_aces));
5859 for (i = 0; i < the_acl->num_aces; i++) {
5860 fstring sid_str;
5862 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5864 DEBUG(10, ("%s 0x%08x\n", sid_str,
5865 the_acl->ace[i].info.mask));
5868 the_acl = secdesc_ctr->sec->dacl;
5870 if (the_acl) {
5871 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5872 PRINTERNAME(snum), the_acl->num_aces));
5874 for (i = 0; i < the_acl->num_aces; i++) {
5875 fstring sid_str;
5877 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5879 DEBUG(10, ("%s 0x%08x\n", sid_str,
5880 the_acl->ace[i].info.mask));
5882 } else {
5883 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5887 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5889 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5890 result = WERR_OK;
5891 goto done;
5894 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5896 done:
5898 return result;
5901 /********************************************************************
5902 Canonicalize printer info from a client
5904 ATTN: It does not matter what we set the servername to hear
5905 since we do the necessary work in get_a_printer() to set it to
5906 the correct value based on what the client sent in the
5907 _spoolss_open_printer_ex().
5908 ********************************************************************/
5910 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5912 fstring printername;
5913 const char *p;
5915 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5916 "portname=%s drivername=%s comment=%s location=%s\n",
5917 info->servername, info->printername, info->sharename,
5918 info->portname, info->drivername, info->comment, info->location));
5920 /* we force some elements to "correct" values */
5921 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5922 fstrcpy(info->sharename, lp_servicename(snum));
5924 /* check to see if we allow printername != sharename */
5926 if ( lp_force_printername(snum) ) {
5927 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5928 global_myname(), info->sharename );
5929 } else {
5931 /* make sure printername is in \\server\printername format */
5933 fstrcpy( printername, info->printername );
5934 p = printername;
5935 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5936 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5937 p++;
5940 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5941 global_myname(), p );
5944 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5945 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5949 return True;
5952 /****************************************************************************
5953 ****************************************************************************/
5955 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5957 char *cmd = lp_addprinter_cmd();
5958 char **qlines;
5959 pstring command;
5960 int numlines;
5961 int ret;
5962 int fd;
5963 fstring remote_machine = "%m";
5964 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5965 BOOL is_print_op = False;
5967 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5969 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5970 cmd, printer->info_2->printername, printer->info_2->sharename,
5971 printer->info_2->portname, printer->info_2->drivername,
5972 printer->info_2->location, printer->info_2->comment, remote_machine);
5974 if ( token )
5975 is_print_op = user_has_privileges( token, &se_printop );
5977 DEBUG(10,("Running [%s]\n", command));
5979 /********* BEGIN SePrintOperatorPrivilege **********/
5981 if ( is_print_op )
5982 become_root();
5984 if ( (ret = smbrun(command, &fd)) == 0 ) {
5985 /* Tell everyone we updated smb.conf. */
5986 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
5989 if ( is_print_op )
5990 unbecome_root();
5992 /********* END SePrintOperatorPrivilege **********/
5994 DEBUGADD(10,("returned [%d]\n", ret));
5996 if ( ret != 0 ) {
5997 if (fd != -1)
5998 close(fd);
5999 return False;
6002 /* reload our services immediately */
6003 reload_services( False );
6005 numlines = 0;
6006 /* Get lines and convert them back to dos-codepage */
6007 qlines = fd_lines_load(fd, &numlines);
6008 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6009 close(fd);
6011 /* Set the portname to what the script says the portname should be. */
6012 /* but don't require anything to be return from the script exit a good error code */
6014 if (numlines) {
6015 /* Set the portname to what the script says the portname should be. */
6016 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6017 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6020 file_lines_free(qlines);
6021 return True;
6024 /********************************************************************
6025 * Called by spoolss_api_setprinter
6026 * when updating a printer description.
6027 ********************************************************************/
6029 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6030 const SPOOL_PRINTER_INFO_LEVEL *info,
6031 DEVICEMODE *devmode)
6033 int snum;
6034 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6035 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6036 WERROR result;
6037 UNISTR2 buffer;
6038 fstring asc_buffer;
6040 DEBUG(8,("update_printer\n"));
6042 result = WERR_OK;
6044 if (!Printer) {
6045 result = WERR_BADFID;
6046 goto done;
6049 if (!get_printer_snum(p, handle, &snum)) {
6050 result = WERR_BADFID;
6051 goto done;
6054 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6055 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6056 result = WERR_BADFID;
6057 goto done;
6060 DEBUGADD(8,("Converting info_2 struct\n"));
6063 * convert_printer_info converts the incoming
6064 * info from the client and overwrites the info
6065 * just read from the tdb in the pointer 'printer'.
6068 if (!convert_printer_info(info, printer, level)) {
6069 result = WERR_NOMEM;
6070 goto done;
6073 if (devmode) {
6074 /* we have a valid devmode
6075 convert it and link it*/
6077 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6078 if (!convert_devicemode(printer->info_2->printername, devmode,
6079 &printer->info_2->devmode)) {
6080 result = WERR_NOMEM;
6081 goto done;
6085 /* Do sanity check on the requested changes for Samba */
6087 if (!check_printer_ok(printer->info_2, snum)) {
6088 result = WERR_INVALID_PARAM;
6089 goto done;
6092 /* FIXME!!! If the driver has changed we really should verify that
6093 it is installed before doing much else --jerry */
6095 /* Check calling user has permission to update printer description */
6097 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6098 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6099 result = WERR_ACCESS_DENIED;
6100 goto done;
6103 /* Call addprinter hook */
6104 /* Check changes to see if this is really needed */
6106 if ( *lp_addprinter_cmd()
6107 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6108 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6109 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6110 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6112 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6113 result = WERR_ACCESS_DENIED;
6114 goto done;
6118 * make sure we actually reload the services after
6119 * this as smb.conf could have a new section in it
6120 * .... shouldn't .... but could
6122 reload_services(False);
6126 * When a *new* driver is bound to a printer, the drivername is used to
6127 * lookup previously saved driver initialization info, which is then
6128 * bound to the printer, simulating what happens in the Windows arch.
6130 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6132 if (!set_driver_init(printer, 2))
6134 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6135 printer->info_2->drivername));
6138 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6139 printer->info_2->drivername));
6141 notify_printer_driver(snum, printer->info_2->drivername);
6145 * flag which changes actually occured. This is a small subset of
6146 * all the possible changes. We also have to update things in the
6147 * DsSpooler key.
6150 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6151 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6152 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6153 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6155 notify_printer_comment(snum, printer->info_2->comment);
6158 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6159 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6160 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6161 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6163 notify_printer_sharename(snum, printer->info_2->sharename);
6166 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6167 char *pname;
6169 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6170 pname++;
6171 else
6172 pname = printer->info_2->printername;
6175 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6176 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6177 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6179 notify_printer_printername( snum, pname );
6182 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6183 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6184 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6185 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6187 notify_printer_port(snum, printer->info_2->portname);
6190 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6191 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6192 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6193 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6195 notify_printer_location(snum, printer->info_2->location);
6198 /* here we need to update some more DsSpooler keys */
6199 /* uNCName, serverName, shortServerName */
6201 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6202 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6203 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6204 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6205 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6207 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6208 global_myname(), printer->info_2->sharename );
6209 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6210 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6211 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6213 /* Update printer info */
6214 result = mod_a_printer(printer, 2);
6216 done:
6217 free_a_printer(&printer, 2);
6218 free_a_printer(&old_printer, 2);
6221 return result;
6224 /****************************************************************************
6225 ****************************************************************************/
6226 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6227 const SPOOL_PRINTER_INFO_LEVEL *info)
6229 #ifdef HAVE_ADS
6230 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6231 int snum;
6232 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6234 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6236 if (!Printer)
6237 return WERR_BADFID;
6239 if (!get_printer_snum(p, handle, &snum))
6240 return WERR_BADFID;
6242 nt_printer_publish(Printer, snum, info7->action);
6244 return WERR_OK;
6245 #else
6246 return WERR_UNKNOWN_LEVEL;
6247 #endif
6249 /****************************************************************************
6250 ****************************************************************************/
6252 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6254 POLICY_HND *handle = &q_u->handle;
6255 uint32 level = q_u->level;
6256 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6257 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6258 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6259 uint32 command = q_u->command;
6260 WERROR result;
6262 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6264 if (!Printer) {
6265 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6266 return WERR_BADFID;
6269 /* check the level */
6270 switch (level) {
6271 case 0:
6272 return control_printer(handle, command, p);
6273 case 2:
6274 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6275 if (!W_ERROR_IS_OK(result))
6276 return result;
6277 if (secdesc_ctr)
6278 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6279 return result;
6280 case 3:
6281 return update_printer_sec(handle, level, info, p,
6282 secdesc_ctr);
6283 case 7:
6284 return publish_or_unpublish_printer(p, handle, info);
6285 default:
6286 return WERR_UNKNOWN_LEVEL;
6290 /****************************************************************************
6291 ****************************************************************************/
6293 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6295 POLICY_HND *handle = &q_u->handle;
6296 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6298 if (!Printer) {
6299 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6300 return WERR_BADFID;
6303 if (Printer->notify.client_connected==True) {
6304 int snum = -1;
6306 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6307 snum = -1;
6308 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6309 !get_printer_snum(p, handle, &snum) )
6310 return WERR_BADFID;
6312 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6315 Printer->notify.flags=0;
6316 Printer->notify.options=0;
6317 Printer->notify.localmachine[0]='\0';
6318 Printer->notify.printerlocal=0;
6319 if (Printer->notify.option)
6320 free_spool_notify_option(&Printer->notify.option);
6321 Printer->notify.client_connected=False;
6323 return WERR_OK;
6326 /****************************************************************************
6327 ****************************************************************************/
6329 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6331 /* that's an [in out] buffer */
6333 if ( q_u->buffer )
6334 rpcbuf_move(q_u->buffer, &r_u->buffer);
6336 r_u->needed = 0;
6337 return WERR_INVALID_PARAM; /* this is what a NT server
6338 returns for AddJob. AddJob
6339 must fail on non-local
6340 printers */
6343 /****************************************************************************
6344 ****************************************************************************/
6346 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6347 int position, int snum,
6348 NT_PRINTER_INFO_LEVEL *ntprinter)
6350 struct tm *t;
6352 t=gmtime(&queue->time);
6354 job_info->jobid=queue->job;
6355 init_unistr(&job_info->printername, lp_servicename(snum));
6356 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6357 init_unistr(&job_info->username, queue->fs_user);
6358 init_unistr(&job_info->document, queue->fs_file);
6359 init_unistr(&job_info->datatype, "RAW");
6360 init_unistr(&job_info->text_status, "");
6361 job_info->status=nt_printj_status(queue->status);
6362 job_info->priority=queue->priority;
6363 job_info->position=position;
6364 job_info->totalpages=queue->page_count;
6365 job_info->pagesprinted=0;
6367 make_systemtime(&job_info->submitted, t);
6370 /****************************************************************************
6371 ****************************************************************************/
6373 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6374 int position, int snum,
6375 NT_PRINTER_INFO_LEVEL *ntprinter,
6376 DEVICEMODE *devmode)
6378 struct tm *t;
6380 t=gmtime(&queue->time);
6382 job_info->jobid=queue->job;
6384 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6386 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6387 init_unistr(&job_info->username, queue->fs_user);
6388 init_unistr(&job_info->document, queue->fs_file);
6389 init_unistr(&job_info->notifyname, queue->fs_user);
6390 init_unistr(&job_info->datatype, "RAW");
6391 init_unistr(&job_info->printprocessor, "winprint");
6392 init_unistr(&job_info->parameters, "");
6393 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6394 init_unistr(&job_info->text_status, "");
6396 /* and here the security descriptor */
6398 job_info->status=nt_printj_status(queue->status);
6399 job_info->priority=queue->priority;
6400 job_info->position=position;
6401 job_info->starttime=0;
6402 job_info->untiltime=0;
6403 job_info->totalpages=queue->page_count;
6404 job_info->size=queue->size;
6405 make_systemtime(&(job_info->submitted), t);
6406 job_info->timeelapsed=0;
6407 job_info->pagesprinted=0;
6409 job_info->devmode = devmode;
6411 return (True);
6414 /****************************************************************************
6415 Enumjobs at level 1.
6416 ****************************************************************************/
6418 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6419 NT_PRINTER_INFO_LEVEL *ntprinter,
6420 RPC_BUFFER *buffer, uint32 offered,
6421 uint32 *needed, uint32 *returned)
6423 JOB_INFO_1 *info;
6424 int i;
6425 WERROR result = WERR_OK;
6427 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6428 if (info==NULL) {
6429 SAFE_FREE(queue);
6430 *returned=0;
6431 return WERR_NOMEM;
6434 for (i=0; i<*returned; i++)
6435 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6437 SAFE_FREE(queue);
6439 /* check the required size. */
6440 for (i=0; i<*returned; i++)
6441 (*needed) += spoolss_size_job_info_1(&info[i]);
6443 if (*needed > offered) {
6444 result = WERR_INSUFFICIENT_BUFFER;
6445 goto out;
6448 if (!rpcbuf_alloc_size(buffer, *needed)) {
6449 result = WERR_NOMEM;
6450 goto out;
6453 /* fill the buffer with the structures */
6454 for (i=0; i<*returned; i++)
6455 smb_io_job_info_1("", buffer, &info[i], 0);
6457 out:
6458 /* clear memory */
6459 SAFE_FREE(info);
6461 if ( !W_ERROR_IS_OK(result) )
6462 *returned = 0;
6464 return result;
6467 /****************************************************************************
6468 Enumjobs at level 2.
6469 ****************************************************************************/
6471 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6472 NT_PRINTER_INFO_LEVEL *ntprinter,
6473 RPC_BUFFER *buffer, uint32 offered,
6474 uint32 *needed, uint32 *returned)
6476 JOB_INFO_2 *info = NULL;
6477 int i;
6478 WERROR result = WERR_OK;
6479 DEVICEMODE *devmode = NULL;
6481 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6482 *returned=0;
6483 return WERR_NOMEM;
6486 /* this should not be a failure condition if the devmode is NULL */
6488 devmode = construct_dev_mode(snum);
6490 for (i=0; i<*returned; i++)
6491 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6493 free_a_printer(&ntprinter, 2);
6494 SAFE_FREE(queue);
6496 /* check the required size. */
6497 for (i=0; i<*returned; i++)
6498 (*needed) += spoolss_size_job_info_2(&info[i]);
6500 if (*needed > offered) {
6501 result = WERR_INSUFFICIENT_BUFFER;
6502 goto out;
6505 if (!rpcbuf_alloc_size(buffer, *needed)) {
6506 result = WERR_NOMEM;
6507 goto out;
6510 /* fill the buffer with the structures */
6511 for (i=0; i<*returned; i++)
6512 smb_io_job_info_2("", buffer, &info[i], 0);
6514 out:
6515 free_devmode(devmode);
6516 SAFE_FREE(info);
6518 if ( !W_ERROR_IS_OK(result) )
6519 *returned = 0;
6521 return result;
6525 /****************************************************************************
6526 Enumjobs.
6527 ****************************************************************************/
6529 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6531 POLICY_HND *handle = &q_u->handle;
6532 uint32 level = q_u->level;
6533 RPC_BUFFER *buffer = NULL;
6534 uint32 offered = q_u->offered;
6535 uint32 *needed = &r_u->needed;
6536 uint32 *returned = &r_u->returned;
6537 WERROR wret;
6538 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6539 int snum;
6540 print_status_struct prt_status;
6541 print_queue_struct *queue=NULL;
6543 /* that's an [in out] buffer */
6545 if ( q_u->buffer ) {
6546 rpcbuf_move(q_u->buffer, &r_u->buffer);
6547 buffer = r_u->buffer;
6550 DEBUG(4,("_spoolss_enumjobs\n"));
6552 *needed=0;
6553 *returned=0;
6555 /* lookup the printer snum and tdb entry */
6557 if (!get_printer_snum(p, handle, &snum))
6558 return WERR_BADFID;
6560 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6561 if ( !W_ERROR_IS_OK(wret) )
6562 return wret;
6564 *returned = print_queue_status(snum, &queue, &prt_status);
6565 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6567 if (*returned == 0) {
6568 SAFE_FREE(queue);
6569 return WERR_OK;
6572 switch (level) {
6573 case 1:
6574 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6575 return wret;
6576 case 2:
6577 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6578 return wret;
6579 default:
6580 SAFE_FREE(queue);
6581 *returned=0;
6582 wret = WERR_UNKNOWN_LEVEL;
6585 free_a_printer( &ntprinter, 2 );
6586 return wret;
6589 /****************************************************************************
6590 ****************************************************************************/
6592 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6594 return WERR_OK;
6597 /****************************************************************************
6598 ****************************************************************************/
6600 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6602 POLICY_HND *handle = &q_u->handle;
6603 uint32 jobid = q_u->jobid;
6604 uint32 command = q_u->command;
6606 struct current_user user;
6607 int snum;
6608 WERROR errcode = WERR_BADFUNC;
6610 if (!get_printer_snum(p, handle, &snum)) {
6611 return WERR_BADFID;
6614 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6615 return WERR_INVALID_PRINTER_NAME;
6618 get_current_user(&user, p);
6620 switch (command) {
6621 case JOB_CONTROL_CANCEL:
6622 case JOB_CONTROL_DELETE:
6623 if (print_job_delete(&user, snum, jobid, &errcode)) {
6624 errcode = WERR_OK;
6626 break;
6627 case JOB_CONTROL_PAUSE:
6628 if (print_job_pause(&user, snum, jobid, &errcode)) {
6629 errcode = WERR_OK;
6631 break;
6632 case JOB_CONTROL_RESTART:
6633 case JOB_CONTROL_RESUME:
6634 if (print_job_resume(&user, snum, jobid, &errcode)) {
6635 errcode = WERR_OK;
6637 break;
6638 default:
6639 return WERR_UNKNOWN_LEVEL;
6642 return errcode;
6645 /****************************************************************************
6646 Enumerates all printer drivers at level 1.
6647 ****************************************************************************/
6649 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6651 int i;
6652 int ndrivers;
6653 uint32 version;
6654 fstring *list = NULL;
6655 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6656 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6657 WERROR result = WERR_OK;
6659 *returned=0;
6661 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6662 list=NULL;
6663 ndrivers=get_ntdrivers(&list, architecture, version);
6664 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6666 if(ndrivers == -1)
6667 return WERR_NOMEM;
6669 if(ndrivers != 0) {
6670 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6671 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6672 SAFE_FREE(driver_info_1);
6673 SAFE_FREE(list);
6674 return WERR_NOMEM;
6676 else driver_info_1 = tdi1;
6679 for (i=0; i<ndrivers; i++) {
6680 WERROR status;
6681 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6682 ZERO_STRUCT(driver);
6683 status = get_a_printer_driver(&driver, 3, list[i],
6684 architecture, version);
6685 if (!W_ERROR_IS_OK(status)) {
6686 SAFE_FREE(list);
6687 return status;
6689 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6690 free_a_printer_driver(driver, 3);
6693 *returned+=ndrivers;
6694 SAFE_FREE(list);
6697 /* check the required size. */
6698 for (i=0; i<*returned; i++) {
6699 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6700 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6703 if (*needed > offered) {
6704 result = WERR_INSUFFICIENT_BUFFER;
6705 goto out;
6708 if (!rpcbuf_alloc_size(buffer, *needed)) {
6709 result = WERR_NOMEM;
6710 goto out;
6713 /* fill the buffer with the driver structures */
6714 for (i=0; i<*returned; i++) {
6715 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6716 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6719 out:
6720 SAFE_FREE(driver_info_1);
6722 if ( !W_ERROR_IS_OK(result) )
6723 *returned = 0;
6725 return result;
6728 /****************************************************************************
6729 Enumerates all printer drivers at level 2.
6730 ****************************************************************************/
6732 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6734 int i;
6735 int ndrivers;
6736 uint32 version;
6737 fstring *list = NULL;
6738 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6739 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6740 WERROR result = WERR_OK;
6742 *returned=0;
6744 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6745 list=NULL;
6746 ndrivers=get_ntdrivers(&list, architecture, version);
6747 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6749 if(ndrivers == -1)
6750 return WERR_NOMEM;
6752 if(ndrivers != 0) {
6753 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6754 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6755 SAFE_FREE(driver_info_2);
6756 SAFE_FREE(list);
6757 return WERR_NOMEM;
6759 else driver_info_2 = tdi2;
6762 for (i=0; i<ndrivers; i++) {
6763 WERROR status;
6765 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6766 ZERO_STRUCT(driver);
6767 status = get_a_printer_driver(&driver, 3, list[i],
6768 architecture, version);
6769 if (!W_ERROR_IS_OK(status)) {
6770 SAFE_FREE(list);
6771 return status;
6773 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6774 free_a_printer_driver(driver, 3);
6777 *returned+=ndrivers;
6778 SAFE_FREE(list);
6781 /* check the required size. */
6782 for (i=0; i<*returned; i++) {
6783 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6784 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6787 if (*needed > offered) {
6788 result = WERR_INSUFFICIENT_BUFFER;
6789 goto out;
6792 if (!rpcbuf_alloc_size(buffer, *needed)) {
6793 result = WERR_NOMEM;
6794 goto out;
6797 /* fill the buffer with the form structures */
6798 for (i=0; i<*returned; i++) {
6799 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6800 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6803 out:
6804 SAFE_FREE(driver_info_2);
6806 if ( !W_ERROR_IS_OK(result) )
6807 *returned = 0;
6809 return result;
6812 /****************************************************************************
6813 Enumerates all printer drivers at level 3.
6814 ****************************************************************************/
6816 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6818 int i;
6819 int ndrivers;
6820 uint32 version;
6821 fstring *list = NULL;
6822 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6823 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6824 WERROR result = WERR_OK;
6826 *returned=0;
6828 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6829 list=NULL;
6830 ndrivers=get_ntdrivers(&list, architecture, version);
6831 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6833 if(ndrivers == -1)
6834 return WERR_NOMEM;
6836 if(ndrivers != 0) {
6837 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6838 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6839 SAFE_FREE(driver_info_3);
6840 SAFE_FREE(list);
6841 return WERR_NOMEM;
6843 else driver_info_3 = tdi3;
6846 for (i=0; i<ndrivers; i++) {
6847 WERROR status;
6849 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6850 ZERO_STRUCT(driver);
6851 status = get_a_printer_driver(&driver, 3, list[i],
6852 architecture, version);
6853 if (!W_ERROR_IS_OK(status)) {
6854 SAFE_FREE(list);
6855 return status;
6857 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6858 free_a_printer_driver(driver, 3);
6861 *returned+=ndrivers;
6862 SAFE_FREE(list);
6865 /* check the required size. */
6866 for (i=0; i<*returned; i++) {
6867 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6868 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6871 if (*needed > offered) {
6872 result = WERR_INSUFFICIENT_BUFFER;
6873 goto out;
6876 if (!rpcbuf_alloc_size(buffer, *needed)) {
6877 result = WERR_NOMEM;
6878 goto out;
6881 /* fill the buffer with the driver structures */
6882 for (i=0; i<*returned; i++) {
6883 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6884 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6887 out:
6888 for (i=0; i<*returned; i++)
6889 SAFE_FREE(driver_info_3[i].dependentfiles);
6891 SAFE_FREE(driver_info_3);
6893 if ( !W_ERROR_IS_OK(result) )
6894 *returned = 0;
6896 return result;
6899 /****************************************************************************
6900 Enumerates all printer drivers.
6901 ****************************************************************************/
6903 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6905 uint32 level = q_u->level;
6906 RPC_BUFFER *buffer = NULL;
6907 uint32 offered = q_u->offered;
6908 uint32 *needed = &r_u->needed;
6909 uint32 *returned = &r_u->returned;
6911 fstring servername;
6912 fstring architecture;
6914 /* that's an [in out] buffer */
6916 if ( q_u->buffer ) {
6917 rpcbuf_move(q_u->buffer, &r_u->buffer);
6918 buffer = r_u->buffer;
6921 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6923 *needed = 0;
6924 *returned = 0;
6926 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6927 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6929 if ( !is_myname_or_ipaddr( servername ) )
6930 return WERR_UNKNOWN_PRINTER_DRIVER;
6932 switch (level) {
6933 case 1:
6934 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6935 case 2:
6936 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6937 case 3:
6938 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6939 default:
6940 return WERR_UNKNOWN_LEVEL;
6944 /****************************************************************************
6945 ****************************************************************************/
6947 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6949 form->flag=list->flag;
6950 init_unistr(&form->name, list->name);
6951 form->width=list->width;
6952 form->length=list->length;
6953 form->left=list->left;
6954 form->top=list->top;
6955 form->right=list->right;
6956 form->bottom=list->bottom;
6959 /****************************************************************************
6960 ****************************************************************************/
6962 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6964 uint32 level = q_u->level;
6965 RPC_BUFFER *buffer = NULL;
6966 uint32 offered = q_u->offered;
6967 uint32 *needed = &r_u->needed;
6968 uint32 *numofforms = &r_u->numofforms;
6969 uint32 numbuiltinforms;
6971 nt_forms_struct *list=NULL;
6972 nt_forms_struct *builtinlist=NULL;
6973 FORM_1 *forms_1;
6974 int buffer_size=0;
6975 int i;
6977 /* that's an [in out] buffer */
6979 if ( q_u->buffer ) {
6980 rpcbuf_move(q_u->buffer, &r_u->buffer);
6981 buffer = r_u->buffer;
6984 DEBUG(4,("_spoolss_enumforms\n"));
6985 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6986 DEBUGADD(5,("Info level [%d]\n", level));
6988 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6989 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6990 *numofforms = get_ntforms(&list);
6991 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6992 *numofforms += numbuiltinforms;
6994 if (*numofforms == 0)
6995 return WERR_NO_MORE_ITEMS;
6997 switch (level) {
6998 case 1:
6999 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7000 *numofforms=0;
7001 return WERR_NOMEM;
7004 /* construct the list of form structures */
7005 for (i=0; i<numbuiltinforms; i++) {
7006 DEBUGADD(6,("Filling form number [%d]\n",i));
7007 fill_form_1(&forms_1[i], &builtinlist[i]);
7010 SAFE_FREE(builtinlist);
7012 for (; i<*numofforms; i++) {
7013 DEBUGADD(6,("Filling form number [%d]\n",i));
7014 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7017 SAFE_FREE(list);
7019 /* check the required size. */
7020 for (i=0; i<numbuiltinforms; i++) {
7021 DEBUGADD(6,("adding form [%d]'s size\n",i));
7022 buffer_size += spoolss_size_form_1(&forms_1[i]);
7024 for (; i<*numofforms; i++) {
7025 DEBUGADD(6,("adding form [%d]'s size\n",i));
7026 buffer_size += spoolss_size_form_1(&forms_1[i]);
7029 *needed=buffer_size;
7031 if (*needed > offered) {
7032 SAFE_FREE(forms_1);
7033 *numofforms=0;
7034 return WERR_INSUFFICIENT_BUFFER;
7037 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7038 SAFE_FREE(forms_1);
7039 *numofforms=0;
7040 return WERR_NOMEM;
7043 /* fill the buffer with the form structures */
7044 for (i=0; i<numbuiltinforms; i++) {
7045 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7046 smb_io_form_1("", buffer, &forms_1[i], 0);
7048 for (; i<*numofforms; i++) {
7049 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7050 smb_io_form_1("", buffer, &forms_1[i], 0);
7053 SAFE_FREE(forms_1);
7055 return WERR_OK;
7057 default:
7058 SAFE_FREE(list);
7059 SAFE_FREE(builtinlist);
7060 return WERR_UNKNOWN_LEVEL;
7065 /****************************************************************************
7066 ****************************************************************************/
7068 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7070 uint32 level = q_u->level;
7071 UNISTR2 *uni_formname = &q_u->formname;
7072 RPC_BUFFER *buffer = NULL;
7073 uint32 offered = q_u->offered;
7074 uint32 *needed = &r_u->needed;
7076 nt_forms_struct *list=NULL;
7077 nt_forms_struct builtin_form;
7078 BOOL foundBuiltin;
7079 FORM_1 form_1;
7080 fstring form_name;
7081 int buffer_size=0;
7082 int numofforms=0, i=0;
7084 /* that's an [in out] buffer */
7086 if ( q_u->buffer ) {
7087 rpcbuf_move(q_u->buffer, &r_u->buffer);
7088 buffer = r_u->buffer;
7091 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7093 DEBUG(4,("_spoolss_getform\n"));
7094 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7095 DEBUGADD(5,("Info level [%d]\n", level));
7097 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7098 if (!foundBuiltin) {
7099 numofforms = get_ntforms(&list);
7100 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7102 if (numofforms == 0)
7103 return WERR_BADFID;
7106 switch (level) {
7107 case 1:
7108 if (foundBuiltin) {
7109 fill_form_1(&form_1, &builtin_form);
7110 } else {
7112 /* Check if the requested name is in the list of form structures */
7113 for (i=0; i<numofforms; i++) {
7115 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7117 if (strequal(form_name, list[i].name)) {
7118 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7119 fill_form_1(&form_1, &list[i]);
7120 break;
7124 SAFE_FREE(list);
7125 if (i == numofforms) {
7126 return WERR_BADFID;
7129 /* check the required size. */
7131 *needed=spoolss_size_form_1(&form_1);
7133 if (*needed > offered)
7134 return WERR_INSUFFICIENT_BUFFER;
7136 if (!rpcbuf_alloc_size(buffer, buffer_size))
7137 return WERR_NOMEM;
7139 /* fill the buffer with the form structures */
7140 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7141 smb_io_form_1("", buffer, &form_1, 0);
7143 return WERR_OK;
7145 default:
7146 SAFE_FREE(list);
7147 return WERR_UNKNOWN_LEVEL;
7151 /****************************************************************************
7152 ****************************************************************************/
7154 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7156 init_unistr(&port->port_name, name);
7159 /****************************************************************************
7160 ****************************************************************************/
7162 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7164 init_unistr(&port->port_name, name);
7165 init_unistr(&port->monitor_name, "Local Monitor");
7166 init_unistr(&port->description, "Local Port");
7167 port->port_type=PORT_TYPE_WRITE;
7168 port->reserved=0x0;
7172 /****************************************************************************
7173 wrapper around the enumer ports command
7174 ****************************************************************************/
7176 WERROR enumports_hook( int *count, char ***lines )
7178 char *cmd = lp_enumports_cmd();
7179 char **qlines;
7180 pstring command;
7181 int numlines;
7182 int ret;
7183 int fd;
7186 /* if no hook then just fill in the default port */
7188 if ( !*cmd ) {
7189 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7190 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7191 qlines[1] = NULL;
7192 numlines = 1;
7194 else {
7195 /* we have a valid enumport command */
7197 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7199 DEBUG(10,("Running [%s]\n", command));
7200 ret = smbrun(command, &fd);
7201 DEBUG(10,("Returned [%d]\n", ret));
7202 if (ret != 0) {
7203 if (fd != -1)
7204 close(fd);
7206 return WERR_ACCESS_DENIED;
7209 numlines = 0;
7210 qlines = fd_lines_load(fd, &numlines);
7211 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7212 close(fd);
7215 *count = numlines;
7216 *lines = qlines;
7218 return WERR_OK;
7221 /****************************************************************************
7222 enumports level 1.
7223 ****************************************************************************/
7225 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7227 PORT_INFO_1 *ports=NULL;
7228 int i=0;
7229 WERROR result = WERR_OK;
7230 char **qlines;
7231 int numlines;
7233 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7234 return result;
7236 if(numlines) {
7237 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7238 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7239 dos_errstr(WERR_NOMEM)));
7240 file_lines_free(qlines);
7241 return WERR_NOMEM;
7244 for (i=0; i<numlines; i++) {
7245 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7246 fill_port_1(&ports[i], qlines[i]);
7249 file_lines_free(qlines);
7252 *returned = numlines;
7254 /* check the required size. */
7255 for (i=0; i<*returned; i++) {
7256 DEBUGADD(6,("adding port [%d]'s size\n", i));
7257 *needed += spoolss_size_port_info_1(&ports[i]);
7260 if (*needed > offered) {
7261 result = WERR_INSUFFICIENT_BUFFER;
7262 goto out;
7265 if (!rpcbuf_alloc_size(buffer, *needed)) {
7266 result = WERR_NOMEM;
7267 goto out;
7270 /* fill the buffer with the ports structures */
7271 for (i=0; i<*returned; i++) {
7272 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7273 smb_io_port_1("", buffer, &ports[i], 0);
7276 out:
7277 SAFE_FREE(ports);
7279 if ( !W_ERROR_IS_OK(result) )
7280 *returned = 0;
7282 return result;
7285 /****************************************************************************
7286 enumports level 2.
7287 ****************************************************************************/
7289 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7291 PORT_INFO_2 *ports=NULL;
7292 int i=0;
7293 WERROR result = WERR_OK;
7294 char **qlines;
7295 int numlines;
7297 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7298 return result;
7301 if(numlines) {
7302 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7303 file_lines_free(qlines);
7304 return WERR_NOMEM;
7307 for (i=0; i<numlines; i++) {
7308 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7309 fill_port_2(&(ports[i]), qlines[i]);
7312 file_lines_free(qlines);
7315 *returned = numlines;
7317 /* check the required size. */
7318 for (i=0; i<*returned; i++) {
7319 DEBUGADD(6,("adding port [%d]'s size\n", i));
7320 *needed += spoolss_size_port_info_2(&ports[i]);
7323 if (*needed > offered) {
7324 result = WERR_INSUFFICIENT_BUFFER;
7325 goto out;
7328 if (!rpcbuf_alloc_size(buffer, *needed)) {
7329 result = WERR_NOMEM;
7330 goto out;
7333 /* fill the buffer with the ports structures */
7334 for (i=0; i<*returned; i++) {
7335 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7336 smb_io_port_2("", buffer, &ports[i], 0);
7339 out:
7340 SAFE_FREE(ports);
7342 if ( !W_ERROR_IS_OK(result) )
7343 *returned = 0;
7345 return result;
7348 /****************************************************************************
7349 enumports.
7350 ****************************************************************************/
7352 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7354 uint32 level = q_u->level;
7355 RPC_BUFFER *buffer = NULL;
7356 uint32 offered = q_u->offered;
7357 uint32 *needed = &r_u->needed;
7358 uint32 *returned = &r_u->returned;
7360 /* that's an [in out] buffer */
7362 if ( q_u->buffer ) {
7363 rpcbuf_move(q_u->buffer, &r_u->buffer);
7364 buffer = r_u->buffer;
7367 DEBUG(4,("_spoolss_enumports\n"));
7369 *returned=0;
7370 *needed=0;
7372 switch (level) {
7373 case 1:
7374 return enumports_level_1(buffer, offered, needed, returned);
7375 case 2:
7376 return enumports_level_2(buffer, offered, needed, returned);
7377 default:
7378 return WERR_UNKNOWN_LEVEL;
7382 /****************************************************************************
7383 ****************************************************************************/
7385 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7386 const SPOOL_PRINTER_INFO_LEVEL *info,
7387 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7388 uint32 user_switch, const SPOOL_USER_CTR *user,
7389 POLICY_HND *handle)
7391 NT_PRINTER_INFO_LEVEL *printer = NULL;
7392 fstring name;
7393 int snum;
7394 WERROR err = WERR_OK;
7396 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7397 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7398 return WERR_NOMEM;
7401 ZERO_STRUCTP(printer);
7403 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7404 if (!convert_printer_info(info, printer, 2)) {
7405 free_a_printer(&printer, 2);
7406 return WERR_NOMEM;
7409 /* check to see if the printer already exists */
7411 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7412 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7413 printer->info_2->sharename));
7414 free_a_printer(&printer, 2);
7415 return WERR_PRINTER_ALREADY_EXISTS;
7418 /* FIXME!!! smbd should check to see if the driver is installed before
7419 trying to add a printer like this --jerry */
7421 if (*lp_addprinter_cmd() ) {
7422 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7423 free_a_printer(&printer,2);
7424 return WERR_ACCESS_DENIED;
7426 } else {
7427 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7428 "smb.conf parameter \"addprinter command\" is defined. This"
7429 "parameter must exist for this call to succeed\n",
7430 printer->info_2->sharename ));
7433 /* use our primary netbios name since get_a_printer() will convert
7434 it to what the client expects on a case by case basis */
7436 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7437 printer->info_2->sharename);
7440 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7441 free_a_printer(&printer,2);
7442 return WERR_ACCESS_DENIED;
7445 /* you must be a printer admin to add a new printer */
7446 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7447 free_a_printer(&printer,2);
7448 return WERR_ACCESS_DENIED;
7452 * Do sanity check on the requested changes for Samba.
7455 if (!check_printer_ok(printer->info_2, snum)) {
7456 free_a_printer(&printer,2);
7457 return WERR_INVALID_PARAM;
7461 * When a printer is created, the drivername bound to the printer is used
7462 * to lookup previously saved driver initialization info, which is then
7463 * bound to the new printer, simulating what happens in the Windows arch.
7466 if (!devmode)
7468 set_driver_init(printer, 2);
7470 else
7472 /* A valid devmode was included, convert and link it
7474 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7476 if (!convert_devicemode(printer->info_2->printername, devmode,
7477 &printer->info_2->devmode))
7478 return WERR_NOMEM;
7481 /* write the ASCII on disk */
7482 err = mod_a_printer(printer, 2);
7483 if (!W_ERROR_IS_OK(err)) {
7484 free_a_printer(&printer,2);
7485 return err;
7488 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7489 /* Handle open failed - remove addition. */
7490 del_a_printer(printer->info_2->sharename);
7491 free_a_printer(&printer,2);
7492 return WERR_ACCESS_DENIED;
7495 update_c_setprinter(False);
7496 free_a_printer(&printer,2);
7498 return WERR_OK;
7501 /****************************************************************************
7502 ****************************************************************************/
7504 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7506 UNISTR2 *uni_srv_name = q_u->server_name;
7507 uint32 level = q_u->level;
7508 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7509 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7510 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7511 uint32 user_switch = q_u->user_switch;
7512 SPOOL_USER_CTR *user = &q_u->user_ctr;
7513 POLICY_HND *handle = &r_u->handle;
7515 switch (level) {
7516 case 1:
7517 /* we don't handle yet */
7518 /* but I know what to do ... */
7519 return WERR_UNKNOWN_LEVEL;
7520 case 2:
7521 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7522 devmode, sdb,
7523 user_switch, user, handle);
7524 default:
7525 return WERR_UNKNOWN_LEVEL;
7529 /****************************************************************************
7530 ****************************************************************************/
7532 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7534 uint32 level = q_u->level;
7535 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7536 WERROR err = WERR_OK;
7537 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7538 struct current_user user;
7539 fstring driver_name;
7540 uint32 version;
7542 ZERO_STRUCT(driver);
7544 get_current_user(&user, p);
7546 if (!convert_printer_driver_info(info, &driver, level)) {
7547 err = WERR_NOMEM;
7548 goto done;
7551 DEBUG(5,("Cleaning driver's information\n"));
7552 err = clean_up_driver_struct(driver, level, &user);
7553 if (!W_ERROR_IS_OK(err))
7554 goto done;
7556 DEBUG(5,("Moving driver to final destination\n"));
7557 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7558 goto done;
7561 if (add_a_printer_driver(driver, level)!=0) {
7562 err = WERR_ACCESS_DENIED;
7563 goto done;
7566 /* BEGIN_ADMIN_LOG */
7567 switch(level) {
7568 case 3:
7569 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7570 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7571 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7572 break;
7573 case 6:
7574 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7575 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7576 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7577 break;
7579 /* END_ADMIN_LOG */
7582 * I think this is where he DrvUpgradePrinter() hook would be
7583 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7584 * server. Right now, we just need to send ourselves a message
7585 * to update each printer bound to this driver. --jerry
7588 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7589 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7590 driver_name));
7594 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7595 * decide if the driver init data should be deleted. The rules are:
7596 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7597 * 2) delete init data only if there is no 2k/Xp driver
7598 * 3) always delete init data
7599 * The generalized rule is always use init data from the highest order driver.
7600 * It is necessary to follow the driver install by an initialization step to
7601 * finish off this process.
7603 if (level == 3)
7604 version = driver.info_3->cversion;
7605 else if (level == 6)
7606 version = driver.info_6->version;
7607 else
7608 version = -1;
7609 switch (version) {
7611 * 9x printer driver - never delete init data
7613 case 0:
7614 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7615 driver_name));
7616 break;
7619 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7620 * there is no 2k/Xp driver init data for this driver name.
7622 case 2:
7624 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7626 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7628 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7630 if (!del_driver_init(driver_name))
7631 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7632 } else {
7634 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7636 free_a_printer_driver(driver1,3);
7637 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7638 driver_name));
7641 break;
7644 * 2k or Xp printer driver - always delete init data
7646 case 3:
7647 if (!del_driver_init(driver_name))
7648 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7649 break;
7651 default:
7652 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7653 break;
7657 done:
7658 free_a_printer_driver(driver, level);
7659 return err;
7662 /********************************************************************
7663 * spoolss_addprinterdriverex
7664 ********************************************************************/
7666 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7668 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7669 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7672 * we only support the semantics of AddPrinterDriver()
7673 * i.e. only copy files that are newer than existing ones
7676 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7677 return WERR_ACCESS_DENIED;
7679 ZERO_STRUCT(q_u_local);
7680 ZERO_STRUCT(r_u_local);
7682 /* just pass the information off to _spoolss_addprinterdriver() */
7683 q_u_local.server_name_ptr = q_u->server_name_ptr;
7684 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7685 q_u_local.level = q_u->level;
7686 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7688 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7691 /****************************************************************************
7692 ****************************************************************************/
7694 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7696 init_unistr(&info->name, name);
7699 /****************************************************************************
7700 ****************************************************************************/
7702 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7704 pstring path;
7705 pstring long_archi;
7706 fstring servername;
7707 char *pservername;
7708 const char *short_archi;
7709 DRIVER_DIRECTORY_1 *info=NULL;
7710 WERROR result = WERR_OK;
7712 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7713 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7715 /* check for beginning double '\'s and that the server
7716 long enough */
7718 pservername = servername;
7719 if ( *pservername == '\\' && strlen(servername)>2 ) {
7720 pservername += 2;
7723 if ( !is_myname_or_ipaddr( pservername ) )
7724 return WERR_INVALID_PARAM;
7726 if (!(short_archi = get_short_archi(long_archi)))
7727 return WERR_INVALID_ENVIRONMENT;
7729 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7730 return WERR_NOMEM;
7732 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7734 DEBUG(4,("printer driver directory: [%s]\n", path));
7736 fill_driverdir_1(info, path);
7738 *needed += spoolss_size_driverdir_info_1(info);
7740 if (*needed > offered) {
7741 result = WERR_INSUFFICIENT_BUFFER;
7742 goto out;
7745 if (!rpcbuf_alloc_size(buffer, *needed)) {
7746 result = WERR_NOMEM;
7747 goto out;
7750 smb_io_driverdir_1("", buffer, info, 0);
7752 out:
7753 SAFE_FREE(info);
7755 return result;
7758 /****************************************************************************
7759 ****************************************************************************/
7761 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7763 UNISTR2 *name = &q_u->name;
7764 UNISTR2 *uni_environment = &q_u->environment;
7765 uint32 level = q_u->level;
7766 RPC_BUFFER *buffer = NULL;
7767 uint32 offered = q_u->offered;
7768 uint32 *needed = &r_u->needed;
7770 /* that's an [in out] buffer */
7772 if ( q_u->buffer ) {
7773 rpcbuf_move(q_u->buffer, &r_u->buffer);
7774 buffer = r_u->buffer;
7777 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7779 *needed=0;
7781 switch(level) {
7782 case 1:
7783 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7784 default:
7785 return WERR_UNKNOWN_LEVEL;
7789 /****************************************************************************
7790 ****************************************************************************/
7792 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7794 POLICY_HND *handle = &q_u->handle;
7795 uint32 idx = q_u->index;
7796 uint32 in_value_len = q_u->valuesize;
7797 uint32 in_data_len = q_u->datasize;
7798 uint32 *out_max_value_len = &r_u->valuesize;
7799 uint16 **out_value = &r_u->value;
7800 uint32 *out_value_len = &r_u->realvaluesize;
7801 uint32 *out_type = &r_u->type;
7802 uint32 *out_max_data_len = &r_u->datasize;
7803 uint8 **data_out = &r_u->data;
7804 uint32 *out_data_len = &r_u->realdatasize;
7806 NT_PRINTER_INFO_LEVEL *printer = NULL;
7808 uint32 biggest_valuesize;
7809 uint32 biggest_datasize;
7810 uint32 data_len;
7811 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7812 int snum;
7813 WERROR result;
7814 REGISTRY_VALUE *val = NULL;
7815 NT_PRINTER_DATA *p_data;
7816 int i, key_index, num_values;
7817 int name_length;
7819 *out_type = 0;
7821 *out_max_data_len = 0;
7822 *data_out = NULL;
7823 *out_data_len = 0;
7825 DEBUG(5,("spoolss_enumprinterdata\n"));
7827 if (!Printer) {
7828 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7829 return WERR_BADFID;
7832 if (!get_printer_snum(p,handle, &snum))
7833 return WERR_BADFID;
7835 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7836 if (!W_ERROR_IS_OK(result))
7837 return result;
7839 p_data = printer->info_2->data;
7840 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7842 result = WERR_OK;
7845 * The NT machine wants to know the biggest size of value and data
7847 * cf: MSDN EnumPrinterData remark section
7850 if ( !in_value_len && !in_data_len && (key_index != -1) )
7852 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7854 biggest_valuesize = 0;
7855 biggest_datasize = 0;
7857 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7859 for ( i=0; i<num_values; i++ )
7861 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7863 name_length = strlen(val->valuename);
7864 if ( strlen(val->valuename) > biggest_valuesize )
7865 biggest_valuesize = name_length;
7867 if ( val->size > biggest_datasize )
7868 biggest_datasize = val->size;
7870 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7871 biggest_datasize));
7874 /* the value is an UNICODE string but real_value_size is the length
7875 in bytes including the trailing 0 */
7877 *out_value_len = 2 * (1+biggest_valuesize);
7878 *out_data_len = biggest_datasize;
7880 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7882 goto done;
7886 * the value len is wrong in NT sp3
7887 * that's the number of bytes not the number of unicode chars
7890 if ( key_index != -1 )
7891 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7893 if ( !val )
7896 /* out_value should default to "" or else NT4 has
7897 problems unmarshalling the response */
7899 *out_max_value_len=(in_value_len/sizeof(uint16));
7901 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7903 result = WERR_NOMEM;
7904 goto done;
7907 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7909 /* the data is counted in bytes */
7911 *out_max_data_len = in_data_len;
7912 *out_data_len = in_data_len;
7914 /* only allocate when given a non-zero data_len */
7916 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7918 result = WERR_NOMEM;
7919 goto done;
7922 result = WERR_NO_MORE_ITEMS;
7924 else
7927 * the value is:
7928 * - counted in bytes in the request
7929 * - counted in UNICODE chars in the max reply
7930 * - counted in bytes in the real size
7932 * take a pause *before* coding not *during* coding
7935 /* name */
7936 *out_max_value_len=(in_value_len/sizeof(uint16));
7937 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7939 result = WERR_NOMEM;
7940 goto done;
7943 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7945 /* type */
7947 *out_type = regval_type( val );
7949 /* data - counted in bytes */
7951 *out_max_data_len = in_data_len;
7952 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7954 result = WERR_NOMEM;
7955 goto done;
7957 data_len = regval_size(val);
7958 if ( *data_out )
7959 memcpy( *data_out, regval_data_p(val), data_len );
7960 *out_data_len = data_len;
7963 done:
7964 free_a_printer(&printer, 2);
7965 return result;
7968 /****************************************************************************
7969 ****************************************************************************/
7971 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7973 POLICY_HND *handle = &q_u->handle;
7974 UNISTR2 *value = &q_u->value;
7975 uint32 type = q_u->type;
7976 uint8 *data = q_u->data;
7977 uint32 real_len = q_u->real_len;
7979 NT_PRINTER_INFO_LEVEL *printer = NULL;
7980 int snum=0;
7981 WERROR status = WERR_OK;
7982 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7983 fstring valuename;
7985 DEBUG(5,("spoolss_setprinterdata\n"));
7987 if (!Printer) {
7988 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7989 return WERR_BADFID;
7992 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7993 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7994 return WERR_INVALID_PARAM;
7997 if (!get_printer_snum(p,handle, &snum))
7998 return WERR_BADFID;
8001 * Access check : NT returns "access denied" if you make a
8002 * SetPrinterData call without the necessary privildge.
8003 * we were originally returning OK if nothing changed
8004 * which made Win2k issue **a lot** of SetPrinterData
8005 * when connecting to a printer --jerry
8008 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8010 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8011 status = WERR_ACCESS_DENIED;
8012 goto done;
8015 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8016 if (!W_ERROR_IS_OK(status))
8017 return status;
8019 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8022 * When client side code sets a magic printer data key, detect it and save
8023 * the current printer data and the magic key's data (its the DEVMODE) for
8024 * future printer/driver initializations.
8026 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8028 /* Set devmode and printer initialization info */
8029 status = save_driver_init( printer, 2, data, real_len );
8031 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8033 else
8035 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8036 type, data, real_len );
8037 if ( W_ERROR_IS_OK(status) )
8038 status = mod_a_printer(printer, 2);
8041 done:
8042 free_a_printer(&printer, 2);
8044 return status;
8047 /****************************************************************************
8048 ****************************************************************************/
8050 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8052 POLICY_HND *handle = &q_u->handle;
8053 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8054 int snum;
8056 DEBUG(5,("_spoolss_resetprinter\n"));
8059 * All we do is to check to see if the handle and queue is valid.
8060 * This call really doesn't mean anything to us because we only
8061 * support RAW printing. --jerry
8064 if (!Printer) {
8065 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8066 return WERR_BADFID;
8069 if (!get_printer_snum(p,handle, &snum))
8070 return WERR_BADFID;
8073 /* blindly return success */
8074 return WERR_OK;
8078 /****************************************************************************
8079 ****************************************************************************/
8081 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8083 POLICY_HND *handle = &q_u->handle;
8084 UNISTR2 *value = &q_u->valuename;
8086 NT_PRINTER_INFO_LEVEL *printer = NULL;
8087 int snum=0;
8088 WERROR status = WERR_OK;
8089 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8090 pstring valuename;
8092 DEBUG(5,("spoolss_deleteprinterdata\n"));
8094 if (!Printer) {
8095 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8096 return WERR_BADFID;
8099 if (!get_printer_snum(p, handle, &snum))
8100 return WERR_BADFID;
8102 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8103 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8104 return WERR_ACCESS_DENIED;
8107 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8108 if (!W_ERROR_IS_OK(status))
8109 return status;
8111 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8113 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8115 if ( W_ERROR_IS_OK(status) )
8116 mod_a_printer( printer, 2 );
8118 free_a_printer(&printer, 2);
8120 return status;
8123 /****************************************************************************
8124 ****************************************************************************/
8126 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8128 POLICY_HND *handle = &q_u->handle;
8129 FORM *form = &q_u->form;
8130 nt_forms_struct tmpForm;
8131 int snum;
8132 WERROR status = WERR_OK;
8133 NT_PRINTER_INFO_LEVEL *printer = NULL;
8135 int count=0;
8136 nt_forms_struct *list=NULL;
8137 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8139 DEBUG(5,("spoolss_addform\n"));
8141 if (!Printer) {
8142 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8143 return WERR_BADFID;
8147 /* forms can be added on printer of on the print server handle */
8149 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8151 if (!get_printer_snum(p,handle, &snum))
8152 return WERR_BADFID;
8154 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8155 if (!W_ERROR_IS_OK(status))
8156 goto done;
8159 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8160 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8161 status = WERR_ACCESS_DENIED;
8162 goto done;
8165 /* can't add if builtin */
8167 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8168 status = WERR_ALREADY_EXISTS;
8169 goto done;
8172 count = get_ntforms(&list);
8174 if(!add_a_form(&list, form, &count)) {
8175 status = WERR_NOMEM;
8176 goto done;
8179 write_ntforms(&list, count);
8182 * ChangeID must always be set if this is a printer
8185 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8186 status = mod_a_printer(printer, 2);
8188 done:
8189 if ( printer )
8190 free_a_printer(&printer, 2);
8191 SAFE_FREE(list);
8193 return status;
8196 /****************************************************************************
8197 ****************************************************************************/
8199 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8201 POLICY_HND *handle = &q_u->handle;
8202 UNISTR2 *form_name = &q_u->name;
8203 nt_forms_struct tmpForm;
8204 int count=0;
8205 nt_forms_struct *list=NULL;
8206 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8207 int snum;
8208 WERROR status = WERR_OK;
8209 NT_PRINTER_INFO_LEVEL *printer = NULL;
8211 DEBUG(5,("spoolss_deleteform\n"));
8213 if (!Printer) {
8214 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8215 return WERR_BADFID;
8218 /* forms can be deleted on printer of on the print server handle */
8220 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8222 if (!get_printer_snum(p,handle, &snum))
8223 return WERR_BADFID;
8225 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8226 if (!W_ERROR_IS_OK(status))
8227 goto done;
8230 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8231 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8232 status = WERR_ACCESS_DENIED;
8233 goto done;
8236 /* can't delete if builtin */
8238 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8239 status = WERR_INVALID_PARAM;
8240 goto done;
8243 count = get_ntforms(&list);
8245 if ( !delete_a_form(&list, form_name, &count, &status ))
8246 goto done;
8249 * ChangeID must always be set if this is a printer
8252 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8253 status = mod_a_printer(printer, 2);
8255 done:
8256 if ( printer )
8257 free_a_printer(&printer, 2);
8258 SAFE_FREE(list);
8260 return status;
8263 /****************************************************************************
8264 ****************************************************************************/
8266 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8268 POLICY_HND *handle = &q_u->handle;
8269 FORM *form = &q_u->form;
8270 nt_forms_struct tmpForm;
8271 int snum;
8272 WERROR status = WERR_OK;
8273 NT_PRINTER_INFO_LEVEL *printer = NULL;
8275 int count=0;
8276 nt_forms_struct *list=NULL;
8277 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8279 DEBUG(5,("spoolss_setform\n"));
8281 if (!Printer) {
8282 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8283 return WERR_BADFID;
8286 /* forms can be modified on printer of on the print server handle */
8288 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8290 if (!get_printer_snum(p,handle, &snum))
8291 return WERR_BADFID;
8293 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8294 if (!W_ERROR_IS_OK(status))
8295 goto done;
8298 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8299 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8300 status = WERR_ACCESS_DENIED;
8301 goto done;
8304 /* can't set if builtin */
8305 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8306 status = WERR_INVALID_PARAM;
8307 goto done;
8310 count = get_ntforms(&list);
8311 update_a_form(&list, form, count);
8312 write_ntforms(&list, count);
8315 * ChangeID must always be set if this is a printer
8318 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8319 status = mod_a_printer(printer, 2);
8322 done:
8323 if ( printer )
8324 free_a_printer(&printer, 2);
8325 SAFE_FREE(list);
8327 return status;
8330 /****************************************************************************
8331 enumprintprocessors level 1.
8332 ****************************************************************************/
8334 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8336 PRINTPROCESSOR_1 *info_1=NULL;
8337 WERROR result = WERR_OK;
8339 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8340 return WERR_NOMEM;
8342 (*returned) = 0x1;
8344 init_unistr(&info_1->name, "winprint");
8346 *needed += spoolss_size_printprocessor_info_1(info_1);
8348 if (*needed > offered) {
8349 result = WERR_INSUFFICIENT_BUFFER;
8350 goto out;
8353 if (!rpcbuf_alloc_size(buffer, *needed)) {
8354 result = WERR_NOMEM;
8355 goto out;
8358 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8360 out:
8361 SAFE_FREE(info_1);
8363 if ( !W_ERROR_IS_OK(result) )
8364 *returned = 0;
8366 return result;
8369 /****************************************************************************
8370 ****************************************************************************/
8372 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8374 uint32 level = q_u->level;
8375 RPC_BUFFER *buffer = NULL;
8376 uint32 offered = q_u->offered;
8377 uint32 *needed = &r_u->needed;
8378 uint32 *returned = &r_u->returned;
8380 /* that's an [in out] buffer */
8382 if ( q_u->buffer ) {
8383 rpcbuf_move(q_u->buffer, &r_u->buffer);
8384 buffer = r_u->buffer;
8387 DEBUG(5,("spoolss_enumprintprocessors\n"));
8390 * Enumerate the print processors ...
8392 * Just reply with "winprint", to keep NT happy
8393 * and I can use my nice printer checker.
8396 *returned=0;
8397 *needed=0;
8399 switch (level) {
8400 case 1:
8401 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8402 default:
8403 return WERR_UNKNOWN_LEVEL;
8407 /****************************************************************************
8408 enumprintprocdatatypes level 1.
8409 ****************************************************************************/
8411 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8413 PRINTPROCDATATYPE_1 *info_1=NULL;
8414 WERROR result = WERR_NOMEM;
8416 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8417 return WERR_NOMEM;
8419 (*returned) = 0x1;
8421 init_unistr(&info_1->name, "RAW");
8423 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8425 if (*needed > offered) {
8426 result = WERR_INSUFFICIENT_BUFFER;
8427 goto out;
8430 if (!rpcbuf_alloc_size(buffer, *needed)) {
8431 result = WERR_NOMEM;
8432 goto out;
8435 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8437 out:
8438 SAFE_FREE(info_1);
8440 if ( !W_ERROR_IS_OK(result) )
8441 *returned = 0;
8443 return result;
8446 /****************************************************************************
8447 ****************************************************************************/
8449 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8451 uint32 level = q_u->level;
8452 RPC_BUFFER *buffer = NULL;
8453 uint32 offered = q_u->offered;
8454 uint32 *needed = &r_u->needed;
8455 uint32 *returned = &r_u->returned;
8457 /* that's an [in out] buffer */
8459 if ( q_u->buffer ) {
8460 rpcbuf_move(q_u->buffer, &r_u->buffer);
8461 buffer = r_u->buffer;
8464 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8466 *returned=0;
8467 *needed=0;
8469 switch (level) {
8470 case 1:
8471 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8472 default:
8473 return WERR_UNKNOWN_LEVEL;
8477 /****************************************************************************
8478 enumprintmonitors level 1.
8479 ****************************************************************************/
8481 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8483 PRINTMONITOR_1 *info_1=NULL;
8484 WERROR result = WERR_OK;
8486 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8487 return WERR_NOMEM;
8489 (*returned) = 0x1;
8491 init_unistr(&info_1->name, "Local Port");
8493 *needed += spoolss_size_printmonitor_info_1(info_1);
8495 if (*needed > offered) {
8496 result = WERR_INSUFFICIENT_BUFFER;
8497 goto out;
8500 if (!rpcbuf_alloc_size(buffer, *needed)) {
8501 result = WERR_NOMEM;
8502 goto out;
8505 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8507 out:
8508 SAFE_FREE(info_1);
8510 if ( !W_ERROR_IS_OK(result) )
8511 *returned = 0;
8513 return result;
8516 /****************************************************************************
8517 enumprintmonitors level 2.
8518 ****************************************************************************/
8520 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8522 PRINTMONITOR_2 *info_2=NULL;
8523 WERROR result = WERR_OK;
8525 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8526 return WERR_NOMEM;
8528 (*returned) = 0x1;
8530 init_unistr(&info_2->name, "Local Port");
8531 init_unistr(&info_2->environment, "Windows NT X86");
8532 init_unistr(&info_2->dll_name, "localmon.dll");
8534 *needed += spoolss_size_printmonitor_info_2(info_2);
8536 if (*needed > offered) {
8537 result = WERR_INSUFFICIENT_BUFFER;
8538 goto out;
8541 if (!rpcbuf_alloc_size(buffer, *needed)) {
8542 result = WERR_NOMEM;
8543 goto out;
8546 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8548 out:
8549 SAFE_FREE(info_2);
8551 if ( !W_ERROR_IS_OK(result) )
8552 *returned = 0;
8554 return result;
8557 /****************************************************************************
8558 ****************************************************************************/
8560 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8562 uint32 level = q_u->level;
8563 RPC_BUFFER *buffer = NULL;
8564 uint32 offered = q_u->offered;
8565 uint32 *needed = &r_u->needed;
8566 uint32 *returned = &r_u->returned;
8568 /* that's an [in out] buffer */
8570 if ( q_u->buffer ) {
8571 rpcbuf_move(q_u->buffer, &r_u->buffer);
8572 buffer = r_u->buffer;
8575 DEBUG(5,("spoolss_enumprintmonitors\n"));
8578 * Enumerate the print monitors ...
8580 * Just reply with "Local Port", to keep NT happy
8581 * and I can use my nice printer checker.
8584 *returned=0;
8585 *needed=0;
8587 switch (level) {
8588 case 1:
8589 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8590 case 2:
8591 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8592 default:
8593 return WERR_UNKNOWN_LEVEL;
8597 /****************************************************************************
8598 ****************************************************************************/
8600 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8601 NT_PRINTER_INFO_LEVEL *ntprinter,
8602 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8603 uint32 *needed)
8605 int i=0;
8606 BOOL found=False;
8607 JOB_INFO_1 *info_1=NULL;
8608 WERROR result = WERR_OK;
8610 info_1=SMB_MALLOC_P(JOB_INFO_1);
8612 if (info_1 == NULL) {
8613 return WERR_NOMEM;
8616 for (i=0; i<count && found==False; i++) {
8617 if ((*queue)[i].job==(int)jobid)
8618 found=True;
8621 if (found==False) {
8622 SAFE_FREE(info_1);
8623 /* NT treats not found as bad param... yet another bad choice */
8624 return WERR_INVALID_PARAM;
8627 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8629 *needed += spoolss_size_job_info_1(info_1);
8631 if (*needed > offered) {
8632 result = WERR_INSUFFICIENT_BUFFER;
8633 goto out;
8636 if (!rpcbuf_alloc_size(buffer, *needed)) {
8637 result = WERR_NOMEM;
8638 goto out;
8641 smb_io_job_info_1("", buffer, info_1, 0);
8643 out:
8644 SAFE_FREE(info_1);
8646 return result;
8649 /****************************************************************************
8650 ****************************************************************************/
8652 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8653 NT_PRINTER_INFO_LEVEL *ntprinter,
8654 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8655 uint32 *needed)
8657 int i = 0;
8658 BOOL found = False;
8659 JOB_INFO_2 *info_2;
8660 WERROR result;
8661 DEVICEMODE *devmode = NULL;
8662 NT_DEVICEMODE *nt_devmode = NULL;
8664 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8665 return WERR_NOMEM;
8667 ZERO_STRUCTP(info_2);
8669 for ( i=0; i<count && found==False; i++ )
8671 if ((*queue)[i].job == (int)jobid)
8672 found = True;
8675 if ( !found ) {
8676 /* NT treats not found as bad param... yet another bad
8677 choice */
8678 result = WERR_INVALID_PARAM;
8679 goto done;
8683 * if the print job does not have a DEVMODE associated with it,
8684 * just use the one for the printer. A NULL devicemode is not
8685 * a failure condition
8688 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8689 devmode = construct_dev_mode(snum);
8690 else {
8691 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8692 ZERO_STRUCTP( devmode );
8693 convert_nt_devicemode( devmode, nt_devmode );
8697 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8699 *needed += spoolss_size_job_info_2(info_2);
8701 if (*needed > offered) {
8702 result = WERR_INSUFFICIENT_BUFFER;
8703 goto done;
8706 if (!rpcbuf_alloc_size(buffer, *needed)) {
8707 result = WERR_NOMEM;
8708 goto done;
8711 smb_io_job_info_2("", buffer, info_2, 0);
8713 result = WERR_OK;
8715 done:
8716 /* Cleanup allocated memory */
8718 free_job_info_2(info_2); /* Also frees devmode */
8719 SAFE_FREE(info_2);
8721 return result;
8724 /****************************************************************************
8725 ****************************************************************************/
8727 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8729 POLICY_HND *handle = &q_u->handle;
8730 uint32 jobid = q_u->jobid;
8731 uint32 level = q_u->level;
8732 RPC_BUFFER *buffer = NULL;
8733 uint32 offered = q_u->offered;
8734 uint32 *needed = &r_u->needed;
8735 WERROR wstatus = WERR_OK;
8736 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8737 int snum;
8738 int count;
8739 print_queue_struct *queue = NULL;
8740 print_status_struct prt_status;
8742 /* that's an [in out] buffer */
8744 if ( q_u->buffer ) {
8745 rpcbuf_move(q_u->buffer, &r_u->buffer);
8746 buffer = r_u->buffer;
8749 DEBUG(5,("spoolss_getjob\n"));
8751 *needed = 0;
8753 if (!get_printer_snum(p, handle, &snum))
8754 return WERR_BADFID;
8756 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8757 if ( !W_ERROR_IS_OK(wstatus) )
8758 return wstatus;
8760 count = print_queue_status(snum, &queue, &prt_status);
8762 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8763 count, prt_status.status, prt_status.message));
8765 switch ( level ) {
8766 case 1:
8767 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8768 buffer, offered, needed);
8769 break;
8770 case 2:
8771 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8772 buffer, offered, needed);
8773 break;
8774 default:
8775 wstatus = WERR_UNKNOWN_LEVEL;
8776 break;
8779 SAFE_FREE(queue);
8780 free_a_printer( &ntprinter, 2 );
8782 return wstatus;
8785 /********************************************************************
8786 spoolss_getprinterdataex
8788 From MSDN documentation of GetPrinterDataEx: pass request
8789 to GetPrinterData if key is "PrinterDriverData".
8790 ********************************************************************/
8792 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8794 POLICY_HND *handle = &q_u->handle;
8795 uint32 in_size = q_u->size;
8796 uint32 *type = &r_u->type;
8797 uint32 *out_size = &r_u->size;
8798 uint8 **data = &r_u->data;
8799 uint32 *needed = &r_u->needed;
8800 fstring keyname, valuename;
8802 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8804 NT_PRINTER_INFO_LEVEL *printer = NULL;
8805 int snum = 0;
8806 WERROR status = WERR_OK;
8808 DEBUG(4,("_spoolss_getprinterdataex\n"));
8810 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8811 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8813 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8814 keyname, valuename));
8816 /* in case of problem, return some default values */
8818 *needed = 0;
8819 *type = 0;
8820 *out_size = in_size;
8822 if (!Printer) {
8823 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8824 status = WERR_BADFID;
8825 goto done;
8828 /* Is the handle to a printer or to the server? */
8830 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8831 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8832 status = WERR_INVALID_PARAM;
8833 goto done;
8836 if ( !get_printer_snum(p,handle, &snum) )
8837 return WERR_BADFID;
8839 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8840 if ( !W_ERROR_IS_OK(status) )
8841 goto done;
8843 /* check to see if the keyname is valid */
8844 if ( !strlen(keyname) ) {
8845 status = WERR_INVALID_PARAM;
8846 goto done;
8849 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8850 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8851 free_a_printer( &printer, 2 );
8852 status = WERR_BADFILE;
8853 goto done;
8856 /* When given a new keyname, we should just create it */
8858 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8860 if (*needed > *out_size)
8861 status = WERR_MORE_DATA;
8863 done:
8864 if ( !W_ERROR_IS_OK(status) )
8866 DEBUG(5, ("error: allocating %d\n", *out_size));
8868 /* reply this param doesn't exist */
8870 if ( *out_size )
8872 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8873 status = WERR_NOMEM;
8874 goto done;
8877 else {
8878 *data = NULL;
8882 if ( printer )
8883 free_a_printer( &printer, 2 );
8885 return status;
8888 /********************************************************************
8889 * spoolss_setprinterdataex
8890 ********************************************************************/
8892 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8894 POLICY_HND *handle = &q_u->handle;
8895 uint32 type = q_u->type;
8896 uint8 *data = q_u->data;
8897 uint32 real_len = q_u->real_len;
8899 NT_PRINTER_INFO_LEVEL *printer = NULL;
8900 int snum = 0;
8901 WERROR status = WERR_OK;
8902 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8903 fstring valuename;
8904 fstring keyname;
8905 char *oid_string;
8907 DEBUG(4,("_spoolss_setprinterdataex\n"));
8909 /* From MSDN documentation of SetPrinterDataEx: pass request to
8910 SetPrinterData if key is "PrinterDriverData" */
8912 if (!Printer) {
8913 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8914 return WERR_BADFID;
8917 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8918 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8919 return WERR_INVALID_PARAM;
8922 if ( !get_printer_snum(p,handle, &snum) )
8923 return WERR_BADFID;
8926 * Access check : NT returns "access denied" if you make a
8927 * SetPrinterData call without the necessary privildge.
8928 * we were originally returning OK if nothing changed
8929 * which made Win2k issue **a lot** of SetPrinterData
8930 * when connecting to a printer --jerry
8933 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8935 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8936 return WERR_ACCESS_DENIED;
8939 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8940 if (!W_ERROR_IS_OK(status))
8941 return status;
8943 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8944 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8946 /* check for OID in valuename */
8948 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8950 *oid_string = '\0';
8951 oid_string++;
8954 /* save the registry data */
8956 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8958 if ( W_ERROR_IS_OK(status) )
8960 /* save the OID if one was specified */
8961 if ( oid_string ) {
8962 fstrcat( keyname, "\\" );
8963 fstrcat( keyname, SPOOL_OID_KEY );
8966 * I'm not checking the status here on purpose. Don't know
8967 * if this is right, but I'm returning the status from the
8968 * previous set_printer_dataex() call. I have no idea if
8969 * this is right. --jerry
8972 set_printer_dataex( printer, keyname, valuename,
8973 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8976 status = mod_a_printer(printer, 2);
8979 free_a_printer(&printer, 2);
8981 return status;
8985 /********************************************************************
8986 * spoolss_deleteprinterdataex
8987 ********************************************************************/
8989 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8991 POLICY_HND *handle = &q_u->handle;
8992 UNISTR2 *value = &q_u->valuename;
8993 UNISTR2 *key = &q_u->keyname;
8995 NT_PRINTER_INFO_LEVEL *printer = NULL;
8996 int snum=0;
8997 WERROR status = WERR_OK;
8998 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8999 pstring valuename, keyname;
9001 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9003 if (!Printer) {
9004 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9005 return WERR_BADFID;
9008 if (!get_printer_snum(p, handle, &snum))
9009 return WERR_BADFID;
9011 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9012 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9013 return WERR_ACCESS_DENIED;
9016 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9017 if (!W_ERROR_IS_OK(status))
9018 return status;
9020 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9021 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9023 status = delete_printer_dataex( printer, keyname, valuename );
9025 if ( W_ERROR_IS_OK(status) )
9026 mod_a_printer( printer, 2 );
9028 free_a_printer(&printer, 2);
9030 return status;
9033 /********************************************************************
9034 * spoolss_enumprinterkey
9035 ********************************************************************/
9038 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9040 fstring key;
9041 fstring *keynames = NULL;
9042 uint16 *enumkeys = NULL;
9043 int num_keys;
9044 int printerkey_len;
9045 POLICY_HND *handle = &q_u->handle;
9046 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9047 NT_PRINTER_DATA *data;
9048 NT_PRINTER_INFO_LEVEL *printer = NULL;
9049 int snum = 0;
9050 WERROR status = WERR_BADFILE;
9053 DEBUG(4,("_spoolss_enumprinterkey\n"));
9055 if (!Printer) {
9056 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9057 return WERR_BADFID;
9060 if ( !get_printer_snum(p,handle, &snum) )
9061 return WERR_BADFID;
9063 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9064 if (!W_ERROR_IS_OK(status))
9065 return status;
9067 /* get the list of subkey names */
9069 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9070 data = printer->info_2->data;
9072 num_keys = get_printer_subkeys( data, key, &keynames );
9074 if ( num_keys == -1 ) {
9075 status = WERR_BADFILE;
9076 goto done;
9079 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9081 r_u->needed = printerkey_len*2;
9083 if ( q_u->size < r_u->needed ) {
9084 status = WERR_MORE_DATA;
9085 goto done;
9088 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9089 status = WERR_NOMEM;
9090 goto done;
9093 status = WERR_OK;
9095 if ( q_u->size < r_u->needed )
9096 status = WERR_MORE_DATA;
9098 done:
9099 free_a_printer( &printer, 2 );
9100 SAFE_FREE( keynames );
9102 return status;
9105 /********************************************************************
9106 * spoolss_deleteprinterkey
9107 ********************************************************************/
9109 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9111 POLICY_HND *handle = &q_u->handle;
9112 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9113 fstring key;
9114 NT_PRINTER_INFO_LEVEL *printer = NULL;
9115 int snum=0;
9116 WERROR status;
9118 DEBUG(5,("spoolss_deleteprinterkey\n"));
9120 if (!Printer) {
9121 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9122 return WERR_BADFID;
9125 /* if keyname == NULL, return error */
9127 if ( !q_u->keyname.buffer )
9128 return WERR_INVALID_PARAM;
9130 if (!get_printer_snum(p, handle, &snum))
9131 return WERR_BADFID;
9133 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9134 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9135 return WERR_ACCESS_DENIED;
9138 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9139 if (!W_ERROR_IS_OK(status))
9140 return status;
9142 /* delete the key and all subneys */
9144 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9146 status = delete_all_printer_data( printer->info_2, key );
9148 if ( W_ERROR_IS_OK(status) )
9149 status = mod_a_printer(printer, 2);
9151 free_a_printer( &printer, 2 );
9153 return status;
9157 /********************************************************************
9158 * spoolss_enumprinterdataex
9159 ********************************************************************/
9161 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9163 POLICY_HND *handle = &q_u->handle;
9164 uint32 in_size = q_u->size;
9165 uint32 num_entries,
9166 needed;
9167 NT_PRINTER_INFO_LEVEL *printer = NULL;
9168 PRINTER_ENUM_VALUES *enum_values = NULL;
9169 NT_PRINTER_DATA *p_data;
9170 fstring key;
9171 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9172 int snum;
9173 WERROR result;
9174 int key_index;
9175 int i;
9176 REGISTRY_VALUE *val;
9177 char *value_name;
9178 uint32 data_len;
9181 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9183 if (!Printer) {
9184 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9185 return WERR_BADFID;
9189 * first check for a keyname of NULL or "". Win2k seems to send
9190 * this a lot and we should send back WERR_INVALID_PARAM
9191 * no need to spend time looking up the printer in this case.
9192 * --jerry
9195 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9196 if ( !strlen(key) ) {
9197 result = WERR_INVALID_PARAM;
9198 goto done;
9201 /* get the printer off of disk */
9203 if (!get_printer_snum(p,handle, &snum))
9204 return WERR_BADFID;
9206 ZERO_STRUCT(printer);
9207 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9208 if (!W_ERROR_IS_OK(result))
9209 return result;
9211 /* now look for a match on the key name */
9213 p_data = printer->info_2->data;
9215 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9216 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9218 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9219 result = WERR_INVALID_PARAM;
9220 goto done;
9223 result = WERR_OK;
9224 needed = 0;
9226 /* allocate the memory for the array of pointers -- if necessary */
9228 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9229 if ( num_entries )
9231 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9233 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9234 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9235 result = WERR_NOMEM;
9236 goto done;
9239 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9243 * loop through all params and build the array to pass
9244 * back to the client
9247 for ( i=0; i<num_entries; i++ )
9249 /* lookup the registry value */
9251 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9252 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9254 /* copy the data */
9256 value_name = regval_name( val );
9257 init_unistr( &enum_values[i].valuename, value_name );
9258 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9259 enum_values[i].type = regval_type( val );
9261 data_len = regval_size( val );
9262 if ( data_len ) {
9263 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9265 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9266 data_len ));
9267 result = WERR_NOMEM;
9268 goto done;
9271 enum_values[i].data_len = data_len;
9273 /* keep track of the size of the array in bytes */
9275 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9278 /* housekeeping information in the reply */
9280 r_u->needed = needed;
9281 r_u->returned = num_entries;
9283 if (needed > in_size) {
9284 result = WERR_MORE_DATA;
9285 goto done;
9288 /* copy data into the reply */
9290 r_u->ctr.size = r_u->needed;
9291 r_u->ctr.size_of_array = r_u->returned;
9292 r_u->ctr.values = enum_values;
9296 done:
9297 if ( printer )
9298 free_a_printer(&printer, 2);
9300 return result;
9303 /****************************************************************************
9304 ****************************************************************************/
9306 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9308 init_unistr(&info->name, name);
9311 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9312 UNISTR2 *environment,
9313 RPC_BUFFER *buffer,
9314 uint32 offered,
9315 uint32 *needed)
9317 pstring path;
9318 pstring long_archi;
9319 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9320 WERROR result = WERR_OK;
9322 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9324 if (!get_short_archi(long_archi))
9325 return WERR_INVALID_ENVIRONMENT;
9327 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9328 return WERR_NOMEM;
9330 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9332 fill_printprocessordirectory_1(info, path);
9334 *needed += spoolss_size_printprocessordirectory_info_1(info);
9336 if (*needed > offered) {
9337 result = WERR_INSUFFICIENT_BUFFER;
9338 goto out;
9341 if (!rpcbuf_alloc_size(buffer, *needed)) {
9342 result = WERR_INSUFFICIENT_BUFFER;
9343 goto out;
9346 smb_io_printprocessordirectory_1("", buffer, info, 0);
9348 out:
9349 SAFE_FREE(info);
9351 return result;
9354 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9356 uint32 level = q_u->level;
9357 RPC_BUFFER *buffer = NULL;
9358 uint32 offered = q_u->offered;
9359 uint32 *needed = &r_u->needed;
9360 WERROR result;
9362 /* that's an [in out] buffer */
9364 if ( q_u->buffer ) {
9365 rpcbuf_move(q_u->buffer, &r_u->buffer);
9366 buffer = r_u->buffer;
9369 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9371 *needed=0;
9373 switch(level) {
9374 case 1:
9375 result = getprintprocessordirectory_level_1
9376 (&q_u->name, &q_u->environment, buffer, offered, needed);
9377 break;
9378 default:
9379 result = WERR_UNKNOWN_LEVEL;
9382 return result;
9385 #if 0
9387 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9388 SPOOL_R_REPLYOPENPRINTER *r_u)
9390 DEBUG(5,("_spoolss_replyopenprinter\n"));
9392 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9394 return WERR_OK;
9397 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9398 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9400 DEBUG(5,("_spoolss_replycloseprinter\n"));
9401 return WERR_OK;
9404 #endif