r12224: adding more characters to the invalid share name string
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobf0ba863b4d706676d1e6e973c67348675dba8127
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 rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
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 = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->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) {
178 cli_shutdown( notify_cli_pipe->cli );
179 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181 message_deregister(MSG_PRINTER_NOTIFY2);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
189 smb_connections--;
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static void free_printer_entry(void *ptr)
198 Printer_entry *Printer = (Printer_entry *)ptr;
200 if (Printer->notify.client_connected==True) {
201 int snum = -1;
203 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
204 snum = -1;
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
208 if (snum != -1)
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 free_spool_notify_option(&Printer->notify.option);
219 Printer->notify.option=NULL;
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 talloc_destroy( Printer->ctx );
227 /* Remove from the internal list. */
228 DLIST_REMOVE(printers_list, Printer);
230 SAFE_FREE(Printer);
233 /****************************************************************************
234 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
235 ****************************************************************************/
237 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
239 SPOOL_NOTIFY_OPTION *new_sp = NULL;
241 if (!sp)
242 return NULL;
244 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
245 if (!new_sp)
246 return NULL;
248 *new_sp = *sp;
250 if (sp->ctr.count) {
251 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
253 if (!new_sp->ctr.type) {
254 SAFE_FREE(new_sp);
255 return NULL;
259 return new_sp;
262 /****************************************************************************
263 find printer index by handle
264 ****************************************************************************/
266 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
268 Printer_entry *find_printer = NULL;
270 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
271 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
272 return NULL;
275 return find_printer;
278 /****************************************************************************
279 Close printer index by handle.
280 ****************************************************************************/
282 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
284 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
286 if (!Printer) {
287 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
288 return False;
291 close_policy_hnd(p, hnd);
293 return True;
296 /****************************************************************************
297 Delete a printer given a handle.
298 ****************************************************************************/
299 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
301 char *cmd = lp_deleteprinter_cmd();
302 pstring command;
303 int ret;
304 SE_PRIV se_printop = SE_PRINT_OPERATOR;
305 BOOL is_print_op = False;
307 /* can't fail if we don't try */
309 if ( !*cmd )
310 return WERR_OK;
312 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
314 if ( token )
315 is_print_op = user_has_privileges( token, &se_printop );
317 DEBUG(10,("Running [%s]\n", command));
319 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
321 if ( is_print_op )
322 become_root();
324 if ( (ret = smbrun(command, NULL)) == 0 ) {
325 /* Tell everyone we updated smb.conf. */
326 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
329 if ( is_print_op )
330 unbecome_root();
332 /********** END SePrintOperatorPrivlege BLOCK **********/
334 DEBUGADD(10,("returned [%d]\n", ret));
336 if (ret != 0)
337 return WERR_BADFID; /* What to return here? */
339 /* go ahead and re-read the services immediately */
340 reload_services( False );
342 if ( lp_servicenumber( sharename ) < 0 )
343 return WERR_ACCESS_DENIED;
345 return WERR_OK;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
356 if (!Printer) {
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
358 return WERR_BADFID;
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
365 * JRA.
368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED;
373 /* this does not need a become root since the access check has been
374 done on the handle already */
376 if (del_a_printer( Printer->sharename ) != 0) {
377 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
378 return WERR_BADFID;
381 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
384 /****************************************************************************
385 Return the snum of a printer corresponding to an handle.
386 ****************************************************************************/
388 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
390 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
392 if (!Printer) {
393 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
394 return False;
397 switch (Printer->printer_type) {
398 case PRINTER_HANDLE_IS_PRINTER:
399 DEBUG(4,("short name:%s\n", Printer->sharename));
400 *number = print_queue_snum(Printer->sharename);
401 return (*number != -1);
402 case PRINTER_HANDLE_IS_PRINTSERVER:
403 return False;
404 default:
405 return False;
409 /****************************************************************************
410 Set printer handle type.
411 Check if it's \\server or \\server\printer
412 ****************************************************************************/
414 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
416 DEBUG(3,("Setting printer type=%s\n", handlename));
418 if ( strlen(handlename) < 3 ) {
419 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
420 return False;
423 /* it's a print server */
424 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
425 DEBUGADD(4,("Printer is a print server\n"));
426 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
428 /* it's a printer */
429 else {
430 DEBUGADD(4,("Printer is a printer\n"));
431 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
434 return True;
437 /****************************************************************************
438 Set printer handle name.
439 ****************************************************************************/
441 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
443 int snum;
444 int n_services=lp_numservices();
445 char *aprinter, *printername;
446 const char *servername;
447 fstring sname;
448 BOOL found=False;
449 NT_PRINTER_INFO_LEVEL *printer;
450 WERROR result;
452 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
454 aprinter = handlename;
455 if ( *handlename == '\\' ) {
456 servername = handlename + 2;
457 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
458 *aprinter = '\0';
459 aprinter++;
462 else {
463 servername = "";
466 /* save the servername to fill in replies on this handle */
468 if ( !is_myname_or_ipaddr( servername ) )
469 return False;
471 fstrcpy( Printer->servername, servername );
473 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
474 return True;
476 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
477 return False;
479 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
481 /* Search all sharenames first as this is easier than pulling
482 the printer_info_2 off of disk. Don't use find_service() since
483 that calls out to map_username() */
485 /* do another loop to look for printernames */
487 for (snum=0; !found && snum<n_services; snum++) {
489 /* no point going on if this is not a printer */
491 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
492 continue;
494 fstrcpy(sname, lp_servicename(snum));
495 if ( strequal( aprinter, sname ) ) {
496 found = True;
497 break;
500 /* no point looking up the printer object if
501 we aren't allowing printername != sharename */
503 if ( lp_force_printername(snum) )
504 continue;
506 fstrcpy(sname, lp_servicename(snum));
508 printer = NULL;
509 result = get_a_printer( NULL, &printer, 2, sname );
510 if ( !W_ERROR_IS_OK(result) ) {
511 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512 sname, dos_errstr(result)));
513 continue;
516 /* printername is always returned as \\server\printername */
517 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
518 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519 printer->info_2->printername));
520 free_a_printer( &printer, 2);
521 continue;
524 printername++;
526 if ( strequal(printername, aprinter) ) {
527 found = True;
528 break;
531 DEBUGADD(10, ("printername: %s\n", printername));
533 free_a_printer( &printer, 2);
536 if ( !found ) {
537 DEBUGADD(4,("Printer not found\n"));
538 return False;
541 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
543 fstrcpy(Printer->sharename, sname);
545 return True;
548 /****************************************************************************
549 Find first available printer slot. creates a printer handle for you.
550 ****************************************************************************/
552 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
554 Printer_entry *new_printer;
556 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
558 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
559 return False;
561 ZERO_STRUCTP(new_printer);
563 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
564 SAFE_FREE(new_printer);
565 return False;
568 /* Add to the internal list. */
569 DLIST_ADD(printers_list, new_printer);
571 new_printer->notify.option=NULL;
573 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
574 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
575 close_printer_handle(p, hnd);
576 return False;
579 if (!set_printer_hnd_printertype(new_printer, name)) {
580 close_printer_handle(p, hnd);
581 return False;
584 if (!set_printer_hnd_name(new_printer, name)) {
585 close_printer_handle(p, hnd);
586 return False;
589 new_printer->access_granted = access_granted;
591 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
593 return True;
596 /***************************************************************************
597 check to see if the client motify handle is monitoring the notification
598 given by (notify_type, notify_field).
599 **************************************************************************/
601 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
602 uint16 notify_field)
604 return True;
607 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
608 uint16 notify_field)
610 SPOOL_NOTIFY_OPTION *option = p->notify.option;
611 uint32 i, j;
614 * Flags should always be zero when the change notify
615 * is registered by the client's spooler. A user Win32 app
616 * might use the flags though instead of the NOTIFY_OPTION_INFO
617 * --jerry
620 if (!option) {
621 return False;
624 if (p->notify.flags)
625 return is_monitoring_event_flags(
626 p->notify.flags, notify_type, notify_field);
628 for (i = 0; i < option->count; i++) {
630 /* Check match for notify_type */
632 if (option->ctr.type[i].type != notify_type)
633 continue;
635 /* Check match for field */
637 for (j = 0; j < option->ctr.type[i].count; j++) {
638 if (option->ctr.type[i].fields[j] == notify_field) {
639 return True;
644 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
645 p->servername, p->sharename, notify_type, notify_field));
647 return False;
650 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
652 static void notify_one_value(struct spoolss_notify_msg *msg,
653 SPOOL_NOTIFY_INFO_DATA *data,
654 TALLOC_CTX *mem_ctx)
656 data->notify_data.value[0] = msg->notify.value[0];
657 data->notify_data.value[1] = 0;
660 static void notify_string(struct spoolss_notify_msg *msg,
661 SPOOL_NOTIFY_INFO_DATA *data,
662 TALLOC_CTX *mem_ctx)
664 UNISTR2 unistr;
666 /* The length of the message includes the trailing \0 */
668 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
670 data->notify_data.data.length = msg->len * 2;
671 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
673 if (!data->notify_data.data.string) {
674 data->notify_data.data.length = 0;
675 return;
678 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
681 static void notify_system_time(struct spoolss_notify_msg *msg,
682 SPOOL_NOTIFY_INFO_DATA *data,
683 TALLOC_CTX *mem_ctx)
685 SYSTEMTIME systime;
686 prs_struct ps;
688 if (msg->len != sizeof(time_t)) {
689 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
690 msg->len));
691 return;
694 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
695 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
696 return;
699 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
700 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
701 return;
704 if (!spoolss_io_system_time("", &ps, 0, &systime))
705 return;
707 data->notify_data.data.length = prs_offset(&ps);
708 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
710 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
712 prs_mem_free(&ps);
715 struct notify2_message_table {
716 const char *name;
717 void (*fn)(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
721 static struct notify2_message_table printer_notify_table[] = {
722 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
723 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
724 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
725 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
726 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
727 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
728 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
729 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
730 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
731 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
732 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
733 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
734 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
735 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
736 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
737 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
738 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
739 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
740 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
743 static struct notify2_message_table job_notify_table[] = {
744 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
745 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
746 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
747 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
748 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
749 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
750 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
751 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
752 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
753 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
754 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
755 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
756 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
757 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
758 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
759 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
760 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
761 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
762 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
763 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
764 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
765 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
766 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
767 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
771 /***********************************************************************
772 Allocate talloc context for container object
773 **********************************************************************/
775 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
777 if ( !ctr )
778 return;
780 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
782 return;
785 /***********************************************************************
786 release all allocated memory and zero out structure
787 **********************************************************************/
789 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
791 if ( !ctr )
792 return;
794 if ( ctr->ctx )
795 talloc_destroy(ctr->ctx);
797 ZERO_STRUCTP(ctr);
799 return;
802 /***********************************************************************
803 **********************************************************************/
805 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
807 if ( !ctr )
808 return NULL;
810 return ctr->ctx;
813 /***********************************************************************
814 **********************************************************************/
816 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
818 if ( !ctr || !ctr->msg_groups )
819 return NULL;
821 if ( idx >= ctr->num_groups )
822 return NULL;
824 return &ctr->msg_groups[idx];
828 /***********************************************************************
829 How many groups of change messages do we have ?
830 **********************************************************************/
832 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
834 if ( !ctr )
835 return 0;
837 return ctr->num_groups;
840 /***********************************************************************
841 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
842 **********************************************************************/
844 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
846 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
847 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
848 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
849 int i, new_slot;
851 if ( !ctr || !msg )
852 return 0;
854 /* loop over all groups looking for a matching printer name */
856 for ( i=0; i<ctr->num_groups; i++ ) {
857 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
858 break;
861 /* add a new group? */
863 if ( i == ctr->num_groups ) {
864 ctr->num_groups++;
866 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
867 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
868 return 0;
870 ctr->msg_groups = groups;
872 /* clear the new entry and set the printer name */
874 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
875 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
878 /* add the change messages; 'i' is the correct index now regardless */
880 msg_grp = &ctr->msg_groups[i];
882 msg_grp->num_msgs++;
884 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
886 return 0;
888 msg_grp->msgs = msg_list;
890 new_slot = msg_grp->num_msgs-1;
891 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
893 /* need to allocate own copy of data */
895 if ( msg->len != 0 )
896 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
898 return ctr->num_groups;
901 /***********************************************************************
902 Send a change notication message on all handles which have a call
903 back registered
904 **********************************************************************/
906 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
908 Printer_entry *p;
909 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
910 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
911 SPOOLSS_NOTIFY_MSG *messages;
912 int sending_msg_count;
914 if ( !msg_group ) {
915 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
916 return;
919 messages = msg_group->msgs;
921 if ( !messages ) {
922 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
923 return;
926 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
928 /* loop over all printers */
930 for (p = printers_list; p; p = p->next) {
931 SPOOL_NOTIFY_INFO_DATA *data;
932 uint32 data_len = 0;
933 uint32 id;
934 int i;
936 /* Is there notification on this handle? */
938 if ( !p->notify.client_connected )
939 continue;
941 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
943 /* For this printer? Print servers always receive
944 notifications. */
946 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
947 ( !strequal(msg_group->printername, p->sharename) ) )
948 continue;
950 DEBUG(10,("Our printer\n"));
952 /* allocate the max entries possible */
954 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
955 ZERO_STRUCTP(data);
957 /* build the array of change notifications */
959 sending_msg_count = 0;
961 for ( i=0; i<msg_group->num_msgs; i++ ) {
962 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
964 /* Are we monitoring this event? */
966 if (!is_monitoring_event(p, msg->type, msg->field))
967 continue;
969 sending_msg_count++;
972 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
973 msg->type, msg->field, p->sharename));
976 * if the is a printer notification handle and not a job notification
977 * type, then set the id to 0. Other wise just use what was specified
978 * in the message.
980 * When registering change notification on a print server handle
981 * we always need to send back the id (snum) matching the printer
982 * for which the change took place. For change notify registered
983 * on a printer handle, this does not matter and the id should be 0.
985 * --jerry
988 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
989 id = 0;
990 else
991 id = msg->id;
994 /* Convert unix jobid to smb jobid */
996 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
997 id = sysjob_to_jobid(msg->id);
999 if (id == -1) {
1000 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1001 goto done;
1005 construct_info_data( &data[data_len], msg->type, msg->field, id );
1007 switch(msg->type) {
1008 case PRINTER_NOTIFY_TYPE:
1009 if ( printer_notify_table[msg->field].fn )
1010 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1011 break;
1013 case JOB_NOTIFY_TYPE:
1014 if ( job_notify_table[msg->field].fn )
1015 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1016 break;
1018 default:
1019 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1020 goto done;
1023 data_len++;
1026 if ( sending_msg_count ) {
1027 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1028 data_len, data, p->notify.change, 0 );
1032 done:
1033 DEBUG(8,("send_notify2_changes: Exit...\n"));
1034 return;
1037 /***********************************************************************
1038 **********************************************************************/
1040 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1043 uint32 tv_sec, tv_usec;
1044 size_t offset = 0;
1046 /* Unpack message */
1048 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1049 msg->printer);
1051 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1052 &tv_sec, &tv_usec,
1053 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1055 if (msg->len == 0)
1056 tdb_unpack((char *)buf + offset, len - offset, "dd",
1057 &msg->notify.value[0], &msg->notify.value[1]);
1058 else
1059 tdb_unpack((char *)buf + offset, len - offset, "B",
1060 &msg->len, &msg->notify.data);
1062 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1063 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1065 tv->tv_sec = tv_sec;
1066 tv->tv_usec = tv_usec;
1068 if (msg->len == 0)
1069 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1070 msg->notify.value[1]));
1071 else
1072 dump_data(3, msg->notify.data, msg->len);
1074 return True;
1077 /********************************************************************
1078 Receive a notify2 message list
1079 ********************************************************************/
1081 static void receive_notify2_message_list(int msg_type, struct process_id src,
1082 void *msg, size_t len)
1084 size_t msg_count, i;
1085 char *buf = (char *)msg;
1086 char *msg_ptr;
1087 size_t msg_len;
1088 SPOOLSS_NOTIFY_MSG notify;
1089 SPOOLSS_NOTIFY_MSG_CTR messages;
1090 int num_groups;
1092 if (len < 4) {
1093 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1094 return;
1097 msg_count = IVAL(buf, 0);
1098 msg_ptr = buf + 4;
1100 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1102 if (msg_count == 0) {
1103 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1104 return;
1107 /* initialize the container */
1109 ZERO_STRUCT( messages );
1110 notify_msg_ctr_init( &messages );
1113 * build message groups for each printer identified
1114 * in a change_notify msg. Remember that a PCN message
1115 * includes the handle returned for the srv_spoolss_replyopenprinter()
1116 * call. Therefore messages are grouped according to printer handle.
1119 for ( i=0; i<msg_count; i++ ) {
1120 struct timeval msg_tv;
1122 if (msg_ptr + 4 - buf > len) {
1123 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1124 return;
1127 msg_len = IVAL(msg_ptr,0);
1128 msg_ptr += 4;
1130 if (msg_ptr + msg_len - buf > len) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1132 return;
1135 /* unpack messages */
1137 ZERO_STRUCT( notify );
1138 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1139 msg_ptr += msg_len;
1141 /* add to correct list in container */
1143 notify_msg_ctr_addmsg( &messages, &notify );
1145 /* free memory that might have been allocated by notify2_unpack_msg() */
1147 if ( notify.len != 0 )
1148 SAFE_FREE( notify.notify.data );
1151 /* process each group of messages */
1153 num_groups = notify_msg_ctr_numgroups( &messages );
1154 for ( i=0; i<num_groups; i++ )
1155 send_notify2_changes( &messages, i );
1158 /* cleanup */
1160 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1162 notify_msg_ctr_destroy( &messages );
1164 return;
1167 /********************************************************************
1168 Send a message to ourself about new driver being installed
1169 so we can upgrade the information for each printer bound to this
1170 driver
1171 ********************************************************************/
1173 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1175 int len = strlen(drivername);
1177 if (!len)
1178 return False;
1180 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1181 drivername));
1183 message_send_pid(pid_to_procid(sys_getpid()),
1184 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1186 return True;
1189 /**********************************************************************
1190 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1191 over all printers, upgrading ones as necessary
1192 **********************************************************************/
1194 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1196 fstring drivername;
1197 int snum;
1198 int n_services = lp_numservices();
1200 len = MIN(len,sizeof(drivername)-1);
1201 strncpy(drivername, buf, len);
1203 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1205 /* Iterate the printer list */
1207 for (snum=0; snum<n_services; snum++)
1209 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1211 WERROR result;
1212 NT_PRINTER_INFO_LEVEL *printer = NULL;
1214 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1215 if (!W_ERROR_IS_OK(result))
1216 continue;
1218 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1220 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1222 /* all we care about currently is the change_id */
1224 result = mod_a_printer(printer, 2);
1225 if (!W_ERROR_IS_OK(result)) {
1226 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1227 dos_errstr(result)));
1231 free_a_printer(&printer, 2);
1235 /* all done */
1238 /********************************************************************
1239 Update the cache for all printq's with a registered client
1240 connection
1241 ********************************************************************/
1243 void update_monitored_printq_cache( void )
1245 Printer_entry *printer = printers_list;
1246 int snum;
1248 /* loop through all printers and update the cache where
1249 client_connected == True */
1250 while ( printer )
1252 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1253 && printer->notify.client_connected )
1255 snum = print_queue_snum(printer->sharename);
1256 print_queue_status( snum, NULL, NULL );
1259 printer = printer->next;
1262 return;
1264 /********************************************************************
1265 Send a message to ourself about new driver being installed
1266 so we can upgrade the information for each printer bound to this
1267 driver
1268 ********************************************************************/
1270 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1272 int len = strlen(drivername);
1274 if (!len)
1275 return False;
1277 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1278 drivername));
1280 message_send_pid(pid_to_procid(sys_getpid()),
1281 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1283 return True;
1286 /**********************************************************************
1287 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1288 over all printers, resetting printer data as neessary
1289 **********************************************************************/
1291 void reset_all_printerdata(int msg_type, struct process_id src,
1292 void *buf, size_t len)
1294 fstring drivername;
1295 int snum;
1296 int n_services = lp_numservices();
1298 len = MIN( len, sizeof(drivername)-1 );
1299 strncpy( drivername, buf, len );
1301 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1303 /* Iterate the printer list */
1305 for ( snum=0; snum<n_services; snum++ )
1307 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1309 WERROR result;
1310 NT_PRINTER_INFO_LEVEL *printer = NULL;
1312 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1313 if ( !W_ERROR_IS_OK(result) )
1314 continue;
1317 * if the printer is bound to the driver,
1318 * then reset to the new driver initdata
1321 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1323 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1325 if ( !set_driver_init(printer, 2) ) {
1326 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1327 printer->info_2->printername, printer->info_2->drivername));
1330 result = mod_a_printer( printer, 2 );
1331 if ( !W_ERROR_IS_OK(result) ) {
1332 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1333 get_dos_error_msg(result)));
1337 free_a_printer( &printer, 2 );
1341 /* all done */
1343 return;
1346 /********************************************************************
1347 Copy routines used by convert_to_openprinterex()
1348 *******************************************************************/
1350 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1352 DEVICEMODE *d;
1353 int len;
1355 if (!devmode)
1356 return NULL;
1358 DEBUG (8,("dup_devmode\n"));
1360 /* bulk copy first */
1362 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1363 if (!d)
1364 return NULL;
1366 /* dup the pointer members separately */
1368 len = unistrlen(devmode->devicename.buffer);
1369 if (len != -1) {
1370 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1371 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1372 return NULL;
1376 len = unistrlen(devmode->formname.buffer);
1377 if (len != -1) {
1378 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1379 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1380 return NULL;
1383 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1385 return d;
1388 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1390 if (!new_ctr || !ctr)
1391 return;
1393 DEBUG(8,("copy_devmode_ctr\n"));
1395 new_ctr->size = ctr->size;
1396 new_ctr->devmode_ptr = ctr->devmode_ptr;
1398 if(ctr->devmode_ptr)
1399 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1402 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1404 if (!new_def || !def)
1405 return;
1407 DEBUG(8,("copy_printer_defaults\n"));
1409 new_def->datatype_ptr = def->datatype_ptr;
1411 if (def->datatype_ptr)
1412 copy_unistr2(&new_def->datatype, &def->datatype);
1414 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1416 new_def->access_required = def->access_required;
1419 /********************************************************************
1420 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1421 * SPOOL_Q_OPEN_PRINTER_EX structure
1422 ********************************************************************/
1424 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1426 if (!q_u_ex || !q_u)
1427 return WERR_OK;
1429 DEBUG(8,("convert_to_openprinterex\n"));
1431 if ( q_u->printername ) {
1432 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1433 if (q_u_ex->printername == NULL)
1434 return WERR_NOMEM;
1435 copy_unistr2(q_u_ex->printername, q_u->printername);
1438 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1440 return WERR_OK;
1443 /********************************************************************
1444 * spoolss_open_printer
1446 * called from the spoolss dispatcher
1447 ********************************************************************/
1449 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1451 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1452 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1454 if (!q_u || !r_u)
1455 return WERR_NOMEM;
1457 ZERO_STRUCT(q_u_ex);
1458 ZERO_STRUCT(r_u_ex);
1460 /* convert the OpenPrinter() call to OpenPrinterEx() */
1462 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1463 if (!W_ERROR_IS_OK(r_u_ex.status))
1464 return r_u_ex.status;
1466 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1468 /* convert back to OpenPrinter() */
1470 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1472 return r_u->status;
1475 /********************************************************************
1476 * spoolss_open_printer
1478 * If the openprinterex rpc call contains a devmode,
1479 * it's a per-user one. This per-user devmode is derivated
1480 * from the global devmode. Openprinterex() contains a per-user
1481 * devmode for when you do EMF printing and spooling.
1482 * In the EMF case, the NT workstation is only doing half the job
1483 * of rendering the page. The other half is done by running the printer
1484 * driver on the server.
1485 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1486 * The EMF file only contains what is to be printed on the page.
1487 * So in order for the server to know how to print, the NT client sends
1488 * a devicemode attached to the openprinterex call.
1489 * But this devicemode is short lived, it's only valid for the current print job.
1491 * If Samba would have supported EMF spooling, this devicemode would
1492 * have been attached to the handle, to sent it to the driver to correctly
1493 * rasterize the EMF file.
1495 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1496 * we just act as a pass-thru between windows and the printer.
1498 * In order to know that Samba supports only RAW spooling, NT has to call
1499 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1500 * and until NT sends a RAW job, we refuse it.
1502 * But to call getprinter() or startdoc(), you first need a valid handle,
1503 * and to get an handle you have to call openprintex(). Hence why you have
1504 * a devicemode in the openprinterex() call.
1507 * Differences between NT4 and NT 2000.
1508 * NT4:
1509 * ---
1510 * On NT4, you only have a global devicemode. This global devicemode can be changed
1511 * by the administrator (or by a user with enough privs). Everytime a user
1512 * wants to print, the devicemode is resetted to the default. In Word, everytime
1513 * you print, the printer's characteristics are always reset to the global devicemode.
1515 * NT 2000:
1516 * -------
1517 * In W2K, there is the notion of per-user devicemode. The first time you use
1518 * a printer, a per-user devicemode is build from the global devicemode.
1519 * If you change your per-user devicemode, it is saved in the registry, under the
1520 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1521 * printer preferences available.
1523 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1524 * on the General Tab of the printer properties windows.
1526 * To change the global devicemode: it's the "Printing Defaults..." button
1527 * on the Advanced Tab of the printer properties window.
1529 * JFM.
1530 ********************************************************************/
1532 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1534 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1535 POLICY_HND *handle = &r_u->handle;
1537 fstring name;
1538 int snum;
1539 struct current_user user;
1540 Printer_entry *Printer=NULL;
1542 if ( !q_u->printername )
1543 return WERR_INVALID_PRINTER_NAME;
1545 /* some sanity check because you can open a printer or a print server */
1546 /* aka: \\server\printer or \\server */
1548 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1550 DEBUGADD(3,("checking name: %s\n",name));
1552 if (!open_printer_hnd(p, handle, name, 0))
1553 return WERR_INVALID_PRINTER_NAME;
1555 Printer=find_printer_index_by_hnd(p, handle);
1556 if ( !Printer ) {
1557 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1558 "handle we created for printer %s\n", name ));
1559 close_printer_handle(p,handle);
1560 return WERR_INVALID_PRINTER_NAME;
1563 get_current_user(&user, p);
1566 * First case: the user is opening the print server:
1568 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1569 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1572 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1573 * or if the user is listed in the smb.conf printer admin parameter.
1575 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1576 * client view printer folder, but does not show the MSAPW.
1578 * Note: this test needs code to check access rights here too. Jeremy
1579 * could you look at this?
1581 * Second case: the user is opening a printer:
1582 * NT doesn't let us connect to a printer if the connecting user
1583 * doesn't have print permission.
1586 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1588 /* Printserver handles use global struct... */
1590 snum = -1;
1592 /* Map standard access rights to object specific access rights */
1594 se_map_standard(&printer_default->access_required,
1595 &printserver_std_mapping);
1597 /* Deny any object specific bits that don't apply to print
1598 servers (i.e printer and job specific bits) */
1600 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1602 if (printer_default->access_required &
1603 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1604 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1605 close_printer_handle(p, handle);
1606 return WERR_ACCESS_DENIED;
1609 /* Allow admin access */
1611 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1613 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1615 if (!lp_ms_add_printer_wizard()) {
1616 close_printer_handle(p, handle);
1617 return WERR_ACCESS_DENIED;
1620 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1621 and not a printer admin, then fail */
1623 if ( user.uid != 0
1624 && !user_has_privileges( user.nt_user_token, &se_printop )
1625 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1627 close_printer_handle(p, handle);
1628 return WERR_ACCESS_DENIED;
1631 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1633 else
1635 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1638 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1639 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1641 /* We fall through to return WERR_OK */
1644 else
1646 /* NT doesn't let us connect to a printer if the connecting user
1647 doesn't have print permission. */
1649 if (!get_printer_snum(p, handle, &snum)) {
1650 close_printer_handle(p, handle);
1651 return WERR_BADFID;
1654 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1656 /* map an empty access mask to the minimum access mask */
1657 if (printer_default->access_required == 0x0)
1658 printer_default->access_required = PRINTER_ACCESS_USE;
1661 * If we are not serving the printer driver for this printer,
1662 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1663 * will keep NT clients happy --jerry
1666 if (lp_use_client_driver(snum)
1667 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1669 printer_default->access_required = PRINTER_ACCESS_USE;
1672 /* check smb.conf parameters and the the sec_desc */
1674 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1675 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1676 return WERR_ACCESS_DENIED;
1679 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1680 DEBUG(3, ("access DENIED for printer open\n"));
1681 close_printer_handle(p, handle);
1682 return WERR_ACCESS_DENIED;
1685 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1686 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1692 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1693 else
1694 printer_default->access_required = PRINTER_ACCESS_USE;
1696 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1697 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1701 Printer->access_granted = printer_default->access_required;
1704 * If the client sent a devmode in the OpenPrinter() call, then
1705 * save it here in case we get a job submission on this handle
1708 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1709 && q_u->printer_default.devmode_cont.devmode_ptr )
1711 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1712 &Printer->nt_devmode );
1715 #if 0 /* JERRY -- I'm doubtful this is really effective */
1716 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1717 optimization in Windows 2000 clients --jerry */
1719 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1720 && (RA_WIN2K == get_remote_arch()) )
1722 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1723 sys_usleep( 500000 );
1725 #endif
1727 return WERR_OK;
1730 /****************************************************************************
1731 ****************************************************************************/
1733 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1734 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1736 BOOL ret;
1738 switch (level) {
1739 case 2:
1740 /* allocate memory if needed. Messy because
1741 convert_printer_info is used to update an existing
1742 printer or build a new one */
1744 if ( !printer->info_2 ) {
1745 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1746 if ( !printer->info_2 ) {
1747 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1748 return False;
1752 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1753 printer->info_2->setuptime = time(NULL);
1755 return ret;
1758 return False;
1761 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1762 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1764 BOOL result = True;
1766 switch (level) {
1767 case 3:
1768 printer->info_3=NULL;
1769 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1770 result = False;
1771 break;
1772 case 6:
1773 printer->info_6=NULL;
1774 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1775 result = False;
1776 break;
1777 default:
1778 break;
1781 return result;
1784 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1785 NT_DEVICEMODE **pp_nt_devmode)
1787 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1790 * Ensure nt_devmode is a valid pointer
1791 * as we will be overwriting it.
1794 if (nt_devmode == NULL) {
1795 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1796 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1797 return False;
1800 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1801 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1803 nt_devmode->specversion=devmode->specversion;
1804 nt_devmode->driverversion=devmode->driverversion;
1805 nt_devmode->size=devmode->size;
1806 nt_devmode->fields=devmode->fields;
1807 nt_devmode->orientation=devmode->orientation;
1808 nt_devmode->papersize=devmode->papersize;
1809 nt_devmode->paperlength=devmode->paperlength;
1810 nt_devmode->paperwidth=devmode->paperwidth;
1811 nt_devmode->scale=devmode->scale;
1812 nt_devmode->copies=devmode->copies;
1813 nt_devmode->defaultsource=devmode->defaultsource;
1814 nt_devmode->printquality=devmode->printquality;
1815 nt_devmode->color=devmode->color;
1816 nt_devmode->duplex=devmode->duplex;
1817 nt_devmode->yresolution=devmode->yresolution;
1818 nt_devmode->ttoption=devmode->ttoption;
1819 nt_devmode->collate=devmode->collate;
1821 nt_devmode->logpixels=devmode->logpixels;
1822 nt_devmode->bitsperpel=devmode->bitsperpel;
1823 nt_devmode->pelswidth=devmode->pelswidth;
1824 nt_devmode->pelsheight=devmode->pelsheight;
1825 nt_devmode->displayflags=devmode->displayflags;
1826 nt_devmode->displayfrequency=devmode->displayfrequency;
1827 nt_devmode->icmmethod=devmode->icmmethod;
1828 nt_devmode->icmintent=devmode->icmintent;
1829 nt_devmode->mediatype=devmode->mediatype;
1830 nt_devmode->dithertype=devmode->dithertype;
1831 nt_devmode->reserved1=devmode->reserved1;
1832 nt_devmode->reserved2=devmode->reserved2;
1833 nt_devmode->panningwidth=devmode->panningwidth;
1834 nt_devmode->panningheight=devmode->panningheight;
1837 * Only change private and driverextra if the incoming devmode
1838 * has a new one. JRA.
1841 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1842 SAFE_FREE(nt_devmode->nt_dev_private);
1843 nt_devmode->driverextra=devmode->driverextra;
1844 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1845 return False;
1846 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1849 *pp_nt_devmode = nt_devmode;
1851 return True;
1854 /********************************************************************
1855 * _spoolss_enddocprinter_internal.
1856 ********************************************************************/
1858 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1860 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1861 int snum;
1863 if (!Printer) {
1864 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1865 return WERR_BADFID;
1868 if (!get_printer_snum(p, handle, &snum))
1869 return WERR_BADFID;
1871 Printer->document_started=False;
1872 print_job_end(snum, Printer->jobid,True);
1873 /* error codes unhandled so far ... */
1875 return WERR_OK;
1878 /********************************************************************
1879 * api_spoolss_closeprinter
1880 ********************************************************************/
1882 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1884 POLICY_HND *handle = &q_u->handle;
1886 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1888 if (Printer && Printer->document_started)
1889 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1891 if (!close_printer_handle(p, handle))
1892 return WERR_BADFID;
1894 /* clear the returned printer handle. Observed behavior
1895 from Win2k server. Don't think this really matters.
1896 Previous code just copied the value of the closed
1897 handle. --jerry */
1899 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1901 return WERR_OK;
1904 /********************************************************************
1905 * api_spoolss_deleteprinter
1907 ********************************************************************/
1909 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1911 POLICY_HND *handle = &q_u->handle;
1912 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1913 WERROR result;
1915 if (Printer && Printer->document_started)
1916 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1918 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1920 result = delete_printer_handle(p, handle);
1922 update_c_setprinter(False);
1924 return result;
1927 /*******************************************************************
1928 * static function to lookup the version id corresponding to an
1929 * long architecture string
1930 ******************************************************************/
1932 static int get_version_id (char * arch)
1934 int i;
1935 struct table_node archi_table[]= {
1937 {"Windows 4.0", "WIN40", 0 },
1938 {"Windows NT x86", "W32X86", 2 },
1939 {"Windows NT R4000", "W32MIPS", 2 },
1940 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1941 {"Windows NT PowerPC", "W32PPC", 2 },
1942 {"Windows IA64", "IA64", 3 },
1943 {"Windows x64", "x64", 3 },
1944 {NULL, "", -1 }
1947 for (i=0; archi_table[i].long_archi != NULL; i++)
1949 if (strcmp(arch, archi_table[i].long_archi) == 0)
1950 return (archi_table[i].version);
1953 return -1;
1956 /********************************************************************
1957 * _spoolss_deleteprinterdriver
1958 ********************************************************************/
1960 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1962 fstring driver;
1963 fstring arch;
1964 NT_PRINTER_DRIVER_INFO_LEVEL info;
1965 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1966 int version;
1967 struct current_user user;
1968 WERROR status;
1969 WERROR status_win2k = WERR_ACCESS_DENIED;
1971 get_current_user(&user, p);
1973 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1974 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1976 /* check that we have a valid driver name first */
1978 if ((version=get_version_id(arch)) == -1)
1979 return WERR_INVALID_ENVIRONMENT;
1981 ZERO_STRUCT(info);
1982 ZERO_STRUCT(info_win2k);
1984 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1986 /* try for Win2k driver if "Windows NT x86" */
1988 if ( version == 2 ) {
1989 version = 3;
1990 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1991 status = WERR_UNKNOWN_PRINTER_DRIVER;
1992 goto done;
1995 /* otherwise it was a failure */
1996 else {
1997 status = WERR_UNKNOWN_PRINTER_DRIVER;
1998 goto done;
2003 if (printer_driver_in_use(info.info_3)) {
2004 status = WERR_PRINTER_DRIVER_IN_USE;
2005 goto done;
2008 if ( version == 2 )
2010 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2012 /* if we get to here, we now have 2 driver info structures to remove */
2013 /* remove the Win2k driver first*/
2015 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2016 free_a_printer_driver( info_win2k, 3 );
2018 /* this should not have failed---if it did, report to client */
2019 if ( !W_ERROR_IS_OK(status_win2k) )
2021 status = status_win2k;
2022 goto done;
2027 status = delete_printer_driver(info.info_3, &user, version, False);
2029 /* if at least one of the deletes succeeded return OK */
2031 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2032 status = WERR_OK;
2034 done:
2035 free_a_printer_driver( info, 3 );
2037 return status;
2040 /********************************************************************
2041 * spoolss_deleteprinterdriverex
2042 ********************************************************************/
2044 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2046 fstring driver;
2047 fstring arch;
2048 NT_PRINTER_DRIVER_INFO_LEVEL info;
2049 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2050 int version;
2051 uint32 flags = q_u->delete_flags;
2052 BOOL delete_files;
2053 struct current_user user;
2054 WERROR status;
2055 WERROR status_win2k = WERR_ACCESS_DENIED;
2057 get_current_user(&user, p);
2059 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2060 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2062 /* check that we have a valid driver name first */
2063 if ((version=get_version_id(arch)) == -1) {
2064 /* this is what NT returns */
2065 return WERR_INVALID_ENVIRONMENT;
2068 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2069 version = q_u->version;
2071 ZERO_STRUCT(info);
2072 ZERO_STRUCT(info_win2k);
2074 status = get_a_printer_driver(&info, 3, driver, arch, version);
2076 if ( !W_ERROR_IS_OK(status) )
2079 * if the client asked for a specific version,
2080 * or this is something other than Windows NT x86,
2081 * then we've failed
2084 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2085 goto done;
2087 /* try for Win2k driver if "Windows NT x86" */
2089 version = 3;
2090 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2091 status = WERR_UNKNOWN_PRINTER_DRIVER;
2092 goto done;
2096 if ( printer_driver_in_use(info.info_3) ) {
2097 status = WERR_PRINTER_DRIVER_IN_USE;
2098 goto done;
2102 * we have a couple of cases to consider.
2103 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2104 * then the delete should fail if **any** files overlap with
2105 * other drivers
2106 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2107 * non-overlapping files
2108 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2109 * is set, the do not delete any files
2110 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2113 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2115 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2117 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2118 /* no idea of the correct error here */
2119 status = WERR_ACCESS_DENIED;
2120 goto done;
2124 /* also check for W32X86/3 if necessary; maybe we already have? */
2126 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2127 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2130 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2131 /* no idea of the correct error here */
2132 free_a_printer_driver( info_win2k, 3 );
2133 status = WERR_ACCESS_DENIED;
2134 goto done;
2137 /* if we get to here, we now have 2 driver info structures to remove */
2138 /* remove the Win2k driver first*/
2140 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2141 free_a_printer_driver( info_win2k, 3 );
2143 /* this should not have failed---if it did, report to client */
2145 if ( !W_ERROR_IS_OK(status_win2k) )
2146 goto done;
2150 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2152 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2153 status = WERR_OK;
2154 done:
2155 free_a_printer_driver( info, 3 );
2157 return status;
2161 /****************************************************************************
2162 Internal routine for retreiving printerdata
2163 ***************************************************************************/
2165 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2166 const char *key, const char *value, uint32 *type, uint8 **data,
2167 uint32 *needed, uint32 in_size )
2169 REGISTRY_VALUE *val;
2170 uint32 size;
2171 int data_len;
2173 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2174 return WERR_BADFILE;
2176 *type = regval_type( val );
2178 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2180 size = regval_size( val );
2182 /* copy the min(in_size, len) */
2184 if ( in_size ) {
2185 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2187 /* special case for 0 length values */
2188 if ( data_len ) {
2189 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2190 return WERR_NOMEM;
2192 else {
2193 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2194 return WERR_NOMEM;
2197 else
2198 *data = NULL;
2200 *needed = size;
2202 DEBUG(5,("get_printer_dataex: copy done\n"));
2204 return WERR_OK;
2207 /****************************************************************************
2208 Internal routine for removing printerdata
2209 ***************************************************************************/
2211 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2213 return delete_printer_data( printer->info_2, key, value );
2216 /****************************************************************************
2217 Internal routine for storing printerdata
2218 ***************************************************************************/
2220 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2221 uint32 type, uint8 *data, int real_len )
2223 /* the registry objects enforce uniqueness based on value name */
2225 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2228 /********************************************************************
2229 GetPrinterData on a printer server Handle.
2230 ********************************************************************/
2232 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2234 int i;
2236 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2238 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2239 *type = REG_DWORD;
2240 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2241 return WERR_NOMEM;
2242 *needed = 0x4;
2243 return WERR_OK;
2246 if (!StrCaseCmp(value, "BeepEnabled")) {
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, "EventLog")) {
2256 *type = REG_DWORD;
2257 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2258 return WERR_NOMEM;
2259 /* formally was 0x1b */
2260 SIVAL(*data, 0, 0x0);
2261 *needed = 0x4;
2262 return WERR_OK;
2265 if (!StrCaseCmp(value, "NetPopup")) {
2266 *type = REG_DWORD;
2267 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2268 return WERR_NOMEM;
2269 SIVAL(*data, 0, 0x00);
2270 *needed = 0x4;
2271 return WERR_OK;
2274 if (!StrCaseCmp(value, "MajorVersion")) {
2275 *type = REG_DWORD;
2276 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2277 return WERR_NOMEM;
2279 /* Windows NT 4.0 seems to not allow uploading of drivers
2280 to a server that reports 0x3 as the MajorVersion.
2281 need to investigate more how Win2k gets around this .
2282 -- jerry */
2284 if ( RA_WINNT == get_remote_arch() )
2285 SIVAL(*data, 0, 2);
2286 else
2287 SIVAL(*data, 0, 3);
2289 *needed = 0x4;
2290 return WERR_OK;
2293 if (!StrCaseCmp(value, "MinorVersion")) {
2294 *type = REG_DWORD;
2295 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2296 return WERR_NOMEM;
2297 SIVAL(*data, 0, 0);
2298 *needed = 0x4;
2299 return WERR_OK;
2302 /* REG_BINARY
2303 * uint32 size = 0x114
2304 * uint32 major = 5
2305 * uint32 minor = [0|1]
2306 * uint32 build = [2195|2600]
2307 * extra unicode string = e.g. "Service Pack 3"
2309 if (!StrCaseCmp(value, "OSVersion")) {
2310 *type = REG_BINARY;
2311 *needed = 0x114;
2313 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2314 return WERR_NOMEM;
2316 SIVAL(*data, 0, *needed); /* size */
2317 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2318 SIVAL(*data, 8, 0);
2319 SIVAL(*data, 12, 2195); /* build */
2321 /* leave extra string empty */
2323 return WERR_OK;
2327 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2328 const char *string="C:\\PRINTERS";
2329 *type = REG_SZ;
2330 *needed = 2*(strlen(string)+1);
2331 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2332 return WERR_NOMEM;
2333 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2335 /* it's done by hand ready to go on the wire */
2336 for (i=0; i<strlen(string); i++) {
2337 (*data)[2*i]=string[i];
2338 (*data)[2*i+1]='\0';
2340 return WERR_OK;
2343 if (!StrCaseCmp(value, "Architecture")) {
2344 const char *string="Windows NT x86";
2345 *type = REG_SZ;
2346 *needed = 2*(strlen(string)+1);
2347 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2348 return WERR_NOMEM;
2349 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2350 for (i=0; i<strlen(string); i++) {
2351 (*data)[2*i]=string[i];
2352 (*data)[2*i+1]='\0';
2354 return WERR_OK;
2357 if (!StrCaseCmp(value, "DsPresent")) {
2358 *type = REG_DWORD;
2359 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2360 return WERR_NOMEM;
2362 /* only show the publish check box if we are a
2363 memeber of a AD domain */
2365 if ( lp_security() == SEC_ADS )
2366 SIVAL(*data, 0, 0x01);
2367 else
2368 SIVAL(*data, 0, 0x00);
2370 *needed = 0x4;
2371 return WERR_OK;
2374 if (!StrCaseCmp(value, "DNSMachineName")) {
2375 pstring hostname;
2377 if (!get_mydnsfullname(hostname))
2378 return WERR_BADFILE;
2379 *type = REG_SZ;
2380 *needed = 2*(strlen(hostname)+1);
2381 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2382 return WERR_NOMEM;
2383 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2384 for (i=0; i<strlen(hostname); i++) {
2385 (*data)[2*i]=hostname[i];
2386 (*data)[2*i+1]='\0';
2388 return WERR_OK;
2392 return WERR_BADFILE;
2395 /********************************************************************
2396 * spoolss_getprinterdata
2397 ********************************************************************/
2399 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2401 POLICY_HND *handle = &q_u->handle;
2402 UNISTR2 *valuename = &q_u->valuename;
2403 uint32 in_size = q_u->size;
2404 uint32 *type = &r_u->type;
2405 uint32 *out_size = &r_u->size;
2406 uint8 **data = &r_u->data;
2407 uint32 *needed = &r_u->needed;
2408 WERROR status;
2409 fstring value;
2410 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2411 NT_PRINTER_INFO_LEVEL *printer = NULL;
2412 int snum = 0;
2415 * Reminder: when it's a string, the length is in BYTES
2416 * even if UNICODE is negociated.
2418 * JFM, 4/19/1999
2421 *out_size = in_size;
2423 /* in case of problem, return some default values */
2425 *needed = 0;
2426 *type = 0;
2428 DEBUG(4,("_spoolss_getprinterdata\n"));
2430 if ( !Printer ) {
2431 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2432 status = WERR_BADFID;
2433 goto done;
2436 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2438 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2439 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2440 else
2442 if ( !get_printer_snum(p,handle, &snum) ) {
2443 status = WERR_BADFID;
2444 goto done;
2447 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2448 if ( !W_ERROR_IS_OK(status) )
2449 goto done;
2451 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2453 if ( strequal(value, "ChangeId") ) {
2454 *type = REG_DWORD;
2455 *needed = sizeof(uint32);
2456 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2457 status = WERR_NOMEM;
2458 goto done;
2460 SIVAL( *data, 0, printer->info_2->changeid );
2461 status = WERR_OK;
2463 else
2464 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2467 if (*needed > *out_size)
2468 status = WERR_MORE_DATA;
2470 done:
2471 if ( !W_ERROR_IS_OK(status) )
2473 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2475 /* reply this param doesn't exist */
2477 if ( *out_size ) {
2478 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2479 if ( printer )
2480 free_a_printer( &printer, 2 );
2481 return WERR_NOMEM;
2484 else {
2485 *data = NULL;
2489 /* cleanup & exit */
2491 if ( printer )
2492 free_a_printer( &printer, 2 );
2494 return status;
2497 /*********************************************************
2498 Connect to the client machine.
2499 **********************************************************/
2501 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2502 struct in_addr *client_ip, const char *remote_machine)
2504 NTSTATUS ret;
2505 struct cli_state *the_cli;
2506 struct in_addr rm_addr;
2508 if ( is_zero_ip(*client_ip) ) {
2509 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2510 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2511 return False;
2514 if ( ismyip( rm_addr )) {
2515 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2516 return False;
2518 } else {
2519 rm_addr.s_addr = client_ip->s_addr;
2520 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2521 inet_ntoa(*client_ip) ));
2524 /* setup the connection */
2526 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2527 &rm_addr, 0, "IPC$", "IPC",
2528 "", /* username */
2529 "", /* domain */
2530 "", /* password */
2531 0, lp_client_signing(), NULL );
2533 if ( !NT_STATUS_IS_OK( ret ) ) {
2534 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2535 remote_machine ));
2536 return False;
2539 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2540 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2541 cli_shutdown(the_cli);
2542 return False;
2546 * Ok - we have an anonymous connection to the IPC$ share.
2547 * Now start the NT Domain stuff :-).
2550 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2551 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2552 remote_machine, nt_errstr(ret)));
2553 cli_shutdown(the_cli);
2554 return False;
2557 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2559 (*pp_pipe)->cli = the_cli;
2561 return True;
2564 /***************************************************************************
2565 Connect to the client.
2566 ****************************************************************************/
2568 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2569 uint32 localprinter, uint32 type,
2570 POLICY_HND *handle, struct in_addr *client_ip)
2572 WERROR result;
2575 * If it's the first connection, contact the client
2576 * and connect to the IPC$ share anonymously
2578 if (smb_connections==0) {
2579 fstring unix_printer;
2581 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2583 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2584 return False;
2586 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2587 /* Tell the connections db we're now interested in printer
2588 * notify messages. */
2589 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2593 * Tell the specific printing tdb we want messages for this printer
2594 * by registering our PID.
2597 if (!print_notify_register_pid(snum))
2598 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2600 smb_connections++;
2602 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2603 type, handle);
2605 if (!W_ERROR_IS_OK(result))
2606 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2607 dos_errstr(result)));
2609 return (W_ERROR_IS_OK(result));
2612 /********************************************************************
2613 * _spoolss_rffpcnex
2614 * ReplyFindFirstPrinterChangeNotifyEx
2616 * before replying OK: status=0 a rpc call is made to the workstation
2617 * asking ReplyOpenPrinter
2619 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2620 * called from api_spoolss_rffpcnex
2621 ********************************************************************/
2623 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2625 POLICY_HND *handle = &q_u->handle;
2626 uint32 flags = q_u->flags;
2627 uint32 options = q_u->options;
2628 UNISTR2 *localmachine = &q_u->localmachine;
2629 uint32 printerlocal = q_u->printerlocal;
2630 int snum = -1;
2631 SPOOL_NOTIFY_OPTION *option = q_u->option;
2632 struct in_addr client_ip;
2634 /* store the notify value in the printer struct */
2636 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2638 if (!Printer) {
2639 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2640 return WERR_BADFID;
2643 Printer->notify.flags=flags;
2644 Printer->notify.options=options;
2645 Printer->notify.printerlocal=printerlocal;
2647 if (Printer->notify.option)
2648 free_spool_notify_option(&Printer->notify.option);
2650 Printer->notify.option=dup_spool_notify_option(option);
2652 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2653 sizeof(Printer->notify.localmachine)-1);
2655 /* Connect to the client machine and send a ReplyOpenPrinter */
2657 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2658 snum = -1;
2659 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2660 !get_printer_snum(p, handle, &snum) )
2661 return WERR_BADFID;
2663 client_ip.s_addr = inet_addr(p->conn->client_address);
2665 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2666 Printer->notify.printerlocal, 1,
2667 &Printer->notify.client_hnd, &client_ip))
2668 return WERR_SERVER_UNAVAILABLE;
2670 Printer->notify.client_connected=True;
2672 return WERR_OK;
2675 /*******************************************************************
2676 * fill a notify_info_data with the servername
2677 ********************************************************************/
2679 void spoolss_notify_server_name(int snum,
2680 SPOOL_NOTIFY_INFO_DATA *data,
2681 print_queue_struct *queue,
2682 NT_PRINTER_INFO_LEVEL *printer,
2683 TALLOC_CTX *mem_ctx)
2685 pstring temp;
2686 uint32 len;
2688 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2690 data->notify_data.data.length = len;
2691 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2693 if (!data->notify_data.data.string) {
2694 data->notify_data.data.length = 0;
2695 return;
2698 memcpy(data->notify_data.data.string, temp, len);
2701 /*******************************************************************
2702 * fill a notify_info_data with the printername (not including the servername).
2703 ********************************************************************/
2705 void spoolss_notify_printer_name(int snum,
2706 SPOOL_NOTIFY_INFO_DATA *data,
2707 print_queue_struct *queue,
2708 NT_PRINTER_INFO_LEVEL *printer,
2709 TALLOC_CTX *mem_ctx)
2711 pstring temp;
2712 uint32 len;
2714 /* the notify name should not contain the \\server\ part */
2715 char *p = strrchr(printer->info_2->printername, '\\');
2717 if (!p) {
2718 p = printer->info_2->printername;
2719 } else {
2720 p++;
2723 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2725 data->notify_data.data.length = len;
2726 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2728 if (!data->notify_data.data.string) {
2729 data->notify_data.data.length = 0;
2730 return;
2733 memcpy(data->notify_data.data.string, temp, len);
2736 /*******************************************************************
2737 * fill a notify_info_data with the servicename
2738 ********************************************************************/
2740 void spoolss_notify_share_name(int snum,
2741 SPOOL_NOTIFY_INFO_DATA *data,
2742 print_queue_struct *queue,
2743 NT_PRINTER_INFO_LEVEL *printer,
2744 TALLOC_CTX *mem_ctx)
2746 pstring temp;
2747 uint32 len;
2749 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2751 data->notify_data.data.length = len;
2752 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2754 if (!data->notify_data.data.string) {
2755 data->notify_data.data.length = 0;
2756 return;
2759 memcpy(data->notify_data.data.string, temp, len);
2762 /*******************************************************************
2763 * fill a notify_info_data with the port name
2764 ********************************************************************/
2766 void spoolss_notify_port_name(int snum,
2767 SPOOL_NOTIFY_INFO_DATA *data,
2768 print_queue_struct *queue,
2769 NT_PRINTER_INFO_LEVEL *printer,
2770 TALLOC_CTX *mem_ctx)
2772 pstring temp;
2773 uint32 len;
2775 /* even if it's strange, that's consistant in all the code */
2777 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2779 data->notify_data.data.length = len;
2780 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2782 if (!data->notify_data.data.string) {
2783 data->notify_data.data.length = 0;
2784 return;
2787 memcpy(data->notify_data.data.string, temp, len);
2790 /*******************************************************************
2791 * fill a notify_info_data with the printername
2792 * but it doesn't exist, have to see what to do
2793 ********************************************************************/
2795 void spoolss_notify_driver_name(int snum,
2796 SPOOL_NOTIFY_INFO_DATA *data,
2797 print_queue_struct *queue,
2798 NT_PRINTER_INFO_LEVEL *printer,
2799 TALLOC_CTX *mem_ctx)
2801 pstring temp;
2802 uint32 len;
2804 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2806 data->notify_data.data.length = len;
2807 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2809 if (!data->notify_data.data.string) {
2810 data->notify_data.data.length = 0;
2811 return;
2814 memcpy(data->notify_data.data.string, temp, len);
2817 /*******************************************************************
2818 * fill a notify_info_data with the comment
2819 ********************************************************************/
2821 void spoolss_notify_comment(int snum,
2822 SPOOL_NOTIFY_INFO_DATA *data,
2823 print_queue_struct *queue,
2824 NT_PRINTER_INFO_LEVEL *printer,
2825 TALLOC_CTX *mem_ctx)
2827 pstring temp;
2828 uint32 len;
2830 if (*printer->info_2->comment == '\0')
2831 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2832 else
2833 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2835 data->notify_data.data.length = len;
2836 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2838 if (!data->notify_data.data.string) {
2839 data->notify_data.data.length = 0;
2840 return;
2843 memcpy(data->notify_data.data.string, temp, len);
2846 /*******************************************************************
2847 * fill a notify_info_data with the comment
2848 * location = "Room 1, floor 2, building 3"
2849 ********************************************************************/
2851 void spoolss_notify_location(int snum,
2852 SPOOL_NOTIFY_INFO_DATA *data,
2853 print_queue_struct *queue,
2854 NT_PRINTER_INFO_LEVEL *printer,
2855 TALLOC_CTX *mem_ctx)
2857 pstring temp;
2858 uint32 len;
2860 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2862 data->notify_data.data.length = len;
2863 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2865 if (!data->notify_data.data.string) {
2866 data->notify_data.data.length = 0;
2867 return;
2870 memcpy(data->notify_data.data.string, temp, len);
2873 /*******************************************************************
2874 * fill a notify_info_data with the device mode
2875 * jfm:xxxx don't to it for know but that's a real problem !!!
2876 ********************************************************************/
2878 static void spoolss_notify_devmode(int snum,
2879 SPOOL_NOTIFY_INFO_DATA *data,
2880 print_queue_struct *queue,
2881 NT_PRINTER_INFO_LEVEL *printer,
2882 TALLOC_CTX *mem_ctx)
2886 /*******************************************************************
2887 * fill a notify_info_data with the separator file name
2888 ********************************************************************/
2890 void spoolss_notify_sepfile(int snum,
2891 SPOOL_NOTIFY_INFO_DATA *data,
2892 print_queue_struct *queue,
2893 NT_PRINTER_INFO_LEVEL *printer,
2894 TALLOC_CTX *mem_ctx)
2896 pstring temp;
2897 uint32 len;
2899 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2901 data->notify_data.data.length = len;
2902 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2904 if (!data->notify_data.data.string) {
2905 data->notify_data.data.length = 0;
2906 return;
2909 memcpy(data->notify_data.data.string, temp, len);
2912 /*******************************************************************
2913 * fill a notify_info_data with the print processor
2914 * jfm:xxxx return always winprint to indicate we don't do anything to it
2915 ********************************************************************/
2917 void spoolss_notify_print_processor(int snum,
2918 SPOOL_NOTIFY_INFO_DATA *data,
2919 print_queue_struct *queue,
2920 NT_PRINTER_INFO_LEVEL *printer,
2921 TALLOC_CTX *mem_ctx)
2923 pstring temp;
2924 uint32 len;
2926 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2928 data->notify_data.data.length = len;
2929 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2931 if (!data->notify_data.data.string) {
2932 data->notify_data.data.length = 0;
2933 return;
2936 memcpy(data->notify_data.data.string, temp, len);
2939 /*******************************************************************
2940 * fill a notify_info_data with the print processor options
2941 * jfm:xxxx send an empty string
2942 ********************************************************************/
2944 void spoolss_notify_parameters(int snum,
2945 SPOOL_NOTIFY_INFO_DATA *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2950 pstring temp;
2951 uint32 len;
2953 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2955 data->notify_data.data.length = len;
2956 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2958 if (!data->notify_data.data.string) {
2959 data->notify_data.data.length = 0;
2960 return;
2963 memcpy(data->notify_data.data.string, temp, len);
2966 /*******************************************************************
2967 * fill a notify_info_data with the data type
2968 * jfm:xxxx always send RAW as data type
2969 ********************************************************************/
2971 void spoolss_notify_datatype(int snum,
2972 SPOOL_NOTIFY_INFO_DATA *data,
2973 print_queue_struct *queue,
2974 NT_PRINTER_INFO_LEVEL *printer,
2975 TALLOC_CTX *mem_ctx)
2977 pstring temp;
2978 uint32 len;
2980 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2982 data->notify_data.data.length = len;
2983 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2985 if (!data->notify_data.data.string) {
2986 data->notify_data.data.length = 0;
2987 return;
2990 memcpy(data->notify_data.data.string, temp, len);
2993 /*******************************************************************
2994 * fill a notify_info_data with the security descriptor
2995 * jfm:xxxx send an null pointer to say no security desc
2996 * have to implement security before !
2997 ********************************************************************/
2999 static void spoolss_notify_security_desc(int snum,
3000 SPOOL_NOTIFY_INFO_DATA *data,
3001 print_queue_struct *queue,
3002 NT_PRINTER_INFO_LEVEL *printer,
3003 TALLOC_CTX *mem_ctx)
3005 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3006 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3009 /*******************************************************************
3010 * fill a notify_info_data with the attributes
3011 * jfm:xxxx a samba printer is always shared
3012 ********************************************************************/
3014 void spoolss_notify_attributes(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.value[0] = printer->info_2->attributes;
3021 data->notify_data.value[1] = 0;
3024 /*******************************************************************
3025 * fill a notify_info_data with the priority
3026 ********************************************************************/
3028 static void spoolss_notify_priority(int snum,
3029 SPOOL_NOTIFY_INFO_DATA *data,
3030 print_queue_struct *queue,
3031 NT_PRINTER_INFO_LEVEL *printer,
3032 TALLOC_CTX *mem_ctx)
3034 data->notify_data.value[0] = printer->info_2->priority;
3035 data->notify_data.value[1] = 0;
3038 /*******************************************************************
3039 * fill a notify_info_data with the default priority
3040 ********************************************************************/
3042 static void spoolss_notify_default_priority(int snum,
3043 SPOOL_NOTIFY_INFO_DATA *data,
3044 print_queue_struct *queue,
3045 NT_PRINTER_INFO_LEVEL *printer,
3046 TALLOC_CTX *mem_ctx)
3048 data->notify_data.value[0] = printer->info_2->default_priority;
3049 data->notify_data.value[1] = 0;
3052 /*******************************************************************
3053 * fill a notify_info_data with the start time
3054 ********************************************************************/
3056 static void spoolss_notify_start_time(int snum,
3057 SPOOL_NOTIFY_INFO_DATA *data,
3058 print_queue_struct *queue,
3059 NT_PRINTER_INFO_LEVEL *printer,
3060 TALLOC_CTX *mem_ctx)
3062 data->notify_data.value[0] = printer->info_2->starttime;
3063 data->notify_data.value[1] = 0;
3066 /*******************************************************************
3067 * fill a notify_info_data with the until time
3068 ********************************************************************/
3070 static void spoolss_notify_until_time(int snum,
3071 SPOOL_NOTIFY_INFO_DATA *data,
3072 print_queue_struct *queue,
3073 NT_PRINTER_INFO_LEVEL *printer,
3074 TALLOC_CTX *mem_ctx)
3076 data->notify_data.value[0] = printer->info_2->untiltime;
3077 data->notify_data.value[1] = 0;
3080 /*******************************************************************
3081 * fill a notify_info_data with the status
3082 ********************************************************************/
3084 static void spoolss_notify_status(int snum,
3085 SPOOL_NOTIFY_INFO_DATA *data,
3086 print_queue_struct *queue,
3087 NT_PRINTER_INFO_LEVEL *printer,
3088 TALLOC_CTX *mem_ctx)
3090 print_status_struct status;
3092 print_queue_length(snum, &status);
3093 data->notify_data.value[0]=(uint32) status.status;
3094 data->notify_data.value[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the number of jobs queued
3099 ********************************************************************/
3101 void spoolss_notify_cjobs(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 data->notify_data.value[0] = print_queue_length(snum, NULL);
3108 data->notify_data.value[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the average ppm
3113 ********************************************************************/
3115 static void spoolss_notify_average_ppm(int snum,
3116 SPOOL_NOTIFY_INFO_DATA *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 /* always respond 8 pages per minutes */
3122 /* a little hard ! */
3123 data->notify_data.value[0] = printer->info_2->averageppm;
3124 data->notify_data.value[1] = 0;
3127 /*******************************************************************
3128 * fill a notify_info_data with username
3129 ********************************************************************/
3131 static void spoolss_notify_username(int snum,
3132 SPOOL_NOTIFY_INFO_DATA *data,
3133 print_queue_struct *queue,
3134 NT_PRINTER_INFO_LEVEL *printer,
3135 TALLOC_CTX *mem_ctx)
3137 pstring temp;
3138 uint32 len;
3140 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3142 data->notify_data.data.length = len;
3143 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3145 if (!data->notify_data.data.string) {
3146 data->notify_data.data.length = 0;
3147 return;
3150 memcpy(data->notify_data.data.string, temp, len);
3153 /*******************************************************************
3154 * fill a notify_info_data with job status
3155 ********************************************************************/
3157 static void spoolss_notify_job_status(int snum,
3158 SPOOL_NOTIFY_INFO_DATA *data,
3159 print_queue_struct *queue,
3160 NT_PRINTER_INFO_LEVEL *printer,
3161 TALLOC_CTX *mem_ctx)
3163 data->notify_data.value[0]=nt_printj_status(queue->status);
3164 data->notify_data.value[1] = 0;
3167 /*******************************************************************
3168 * fill a notify_info_data with job name
3169 ********************************************************************/
3171 static void spoolss_notify_job_name(int snum,
3172 SPOOL_NOTIFY_INFO_DATA *data,
3173 print_queue_struct *queue,
3174 NT_PRINTER_INFO_LEVEL *printer,
3175 TALLOC_CTX *mem_ctx)
3177 pstring temp;
3178 uint32 len;
3180 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3182 data->notify_data.data.length = len;
3183 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3185 if (!data->notify_data.data.string) {
3186 data->notify_data.data.length = 0;
3187 return;
3190 memcpy(data->notify_data.data.string, temp, len);
3193 /*******************************************************************
3194 * fill a notify_info_data with job status
3195 ********************************************************************/
3197 static void spoolss_notify_job_status_string(int snum,
3198 SPOOL_NOTIFY_INFO_DATA *data,
3199 print_queue_struct *queue,
3200 NT_PRINTER_INFO_LEVEL *printer,
3201 TALLOC_CTX *mem_ctx)
3204 * Now we're returning job status codes we just return a "" here. JRA.
3207 const char *p = "";
3208 pstring temp;
3209 uint32 len;
3211 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3212 p = "unknown";
3214 switch (queue->status) {
3215 case LPQ_QUEUED:
3216 p = "Queued";
3217 break;
3218 case LPQ_PAUSED:
3219 p = ""; /* NT provides the paused string */
3220 break;
3221 case LPQ_SPOOLING:
3222 p = "Spooling";
3223 break;
3224 case LPQ_PRINTING:
3225 p = "Printing";
3226 break;
3228 #endif /* NO LONGER NEEDED. */
3230 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3232 data->notify_data.data.length = len;
3233 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3235 if (!data->notify_data.data.string) {
3236 data->notify_data.data.length = 0;
3237 return;
3240 memcpy(data->notify_data.data.string, temp, len);
3243 /*******************************************************************
3244 * fill a notify_info_data with job time
3245 ********************************************************************/
3247 static void spoolss_notify_job_time(int snum,
3248 SPOOL_NOTIFY_INFO_DATA *data,
3249 print_queue_struct *queue,
3250 NT_PRINTER_INFO_LEVEL *printer,
3251 TALLOC_CTX *mem_ctx)
3253 data->notify_data.value[0]=0x0;
3254 data->notify_data.value[1]=0;
3257 /*******************************************************************
3258 * fill a notify_info_data with job size
3259 ********************************************************************/
3261 static void spoolss_notify_job_size(int snum,
3262 SPOOL_NOTIFY_INFO_DATA *data,
3263 print_queue_struct *queue,
3264 NT_PRINTER_INFO_LEVEL *printer,
3265 TALLOC_CTX *mem_ctx)
3267 data->notify_data.value[0]=queue->size;
3268 data->notify_data.value[1]=0;
3271 /*******************************************************************
3272 * fill a notify_info_data with page info
3273 ********************************************************************/
3274 static void spoolss_notify_total_pages(int snum,
3275 SPOOL_NOTIFY_INFO_DATA *data,
3276 print_queue_struct *queue,
3277 NT_PRINTER_INFO_LEVEL *printer,
3278 TALLOC_CTX *mem_ctx)
3280 data->notify_data.value[0]=queue->page_count;
3281 data->notify_data.value[1]=0;
3284 /*******************************************************************
3285 * fill a notify_info_data with pages printed info.
3286 ********************************************************************/
3287 static void spoolss_notify_pages_printed(int snum,
3288 SPOOL_NOTIFY_INFO_DATA *data,
3289 print_queue_struct *queue,
3290 NT_PRINTER_INFO_LEVEL *printer,
3291 TALLOC_CTX *mem_ctx)
3293 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3294 data->notify_data.value[1]=0;
3297 /*******************************************************************
3298 Fill a notify_info_data with job position.
3299 ********************************************************************/
3301 static void spoolss_notify_job_position(int snum,
3302 SPOOL_NOTIFY_INFO_DATA *data,
3303 print_queue_struct *queue,
3304 NT_PRINTER_INFO_LEVEL *printer,
3305 TALLOC_CTX *mem_ctx)
3307 data->notify_data.value[0]=queue->job;
3308 data->notify_data.value[1]=0;
3311 /*******************************************************************
3312 Fill a notify_info_data with submitted time.
3313 ********************************************************************/
3315 static void spoolss_notify_submitted_time(int snum,
3316 SPOOL_NOTIFY_INFO_DATA *data,
3317 print_queue_struct *queue,
3318 NT_PRINTER_INFO_LEVEL *printer,
3319 TALLOC_CTX *mem_ctx)
3321 struct tm *t;
3322 uint32 len;
3323 SYSTEMTIME st;
3324 char *p;
3326 t=gmtime(&queue->time);
3328 len = sizeof(SYSTEMTIME);
3330 data->notify_data.data.length = len;
3331 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3333 if (!data->notify_data.data.string) {
3334 data->notify_data.data.length = 0;
3335 return;
3338 make_systemtime(&st, t);
3341 * Systemtime must be linearized as a set of UINT16's.
3342 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3345 p = (char *)data->notify_data.data.string;
3346 SSVAL(p, 0, st.year);
3347 SSVAL(p, 2, st.month);
3348 SSVAL(p, 4, st.dayofweek);
3349 SSVAL(p, 6, st.day);
3350 SSVAL(p, 8, st.hour);
3351 SSVAL(p, 10, st.minute);
3352 SSVAL(p, 12, st.second);
3353 SSVAL(p, 14, st.milliseconds);
3356 struct s_notify_info_data_table
3358 uint16 type;
3359 uint16 field;
3360 const char *name;
3361 uint32 size;
3362 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3363 print_queue_struct *queue,
3364 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3367 /* A table describing the various print notification constants and
3368 whether the notification data is a pointer to a variable sized
3369 buffer, a one value uint32 or a two value uint32. */
3371 static const struct s_notify_info_data_table notify_info_data_table[] =
3373 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3374 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3375 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3376 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3377 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3378 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3379 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3399 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3400 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3401 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3402 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3403 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3404 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3405 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3406 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3407 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3408 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3422 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3425 /*******************************************************************
3426 Return the size of info_data structure.
3427 ********************************************************************/
3429 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3431 int i=0;
3433 for (i = 0; i < sizeof(notify_info_data_table); i++)
3435 if ( (notify_info_data_table[i].type == type)
3436 && (notify_info_data_table[i].field == field) )
3438 switch(notify_info_data_table[i].size)
3440 case NOTIFY_ONE_VALUE:
3441 case NOTIFY_TWO_VALUE:
3442 return 1;
3443 case NOTIFY_STRING:
3444 return 2;
3446 /* The only pointer notify data I have seen on
3447 the wire is the submitted time and this has
3448 the notify size set to 4. -tpot */
3450 case NOTIFY_POINTER:
3451 return 4;
3453 case NOTIFY_SECDESC:
3454 return 5;
3459 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3461 return 0;
3464 /*******************************************************************
3465 Return the type of notify_info_data.
3466 ********************************************************************/
3468 static int type_of_notify_info_data(uint16 type, uint16 field)
3470 int i=0;
3472 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3473 if (notify_info_data_table[i].type == type &&
3474 notify_info_data_table[i].field == field)
3475 return notify_info_data_table[i].size;
3478 return False;
3481 /****************************************************************************
3482 ****************************************************************************/
3484 static int search_notify(uint16 type, uint16 field, int *value)
3486 int i;
3488 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3489 if (notify_info_data_table[i].type == type &&
3490 notify_info_data_table[i].field == field &&
3491 notify_info_data_table[i].fn != NULL) {
3492 *value = i;
3493 return True;
3497 return False;
3500 /****************************************************************************
3501 ****************************************************************************/
3503 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3505 info_data->type = type;
3506 info_data->field = field;
3507 info_data->reserved = 0;
3509 info_data->size = size_of_notify_info_data(type, field);
3510 info_data->enc_type = type_of_notify_info_data(type, field);
3512 info_data->id = id;
3517 /*******************************************************************
3519 * fill a notify_info struct with info asked
3521 ********************************************************************/
3523 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3524 snum, SPOOL_NOTIFY_OPTION_TYPE
3525 *option_type, uint32 id,
3526 TALLOC_CTX *mem_ctx)
3528 int field_num,j;
3529 uint16 type;
3530 uint16 field;
3532 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3533 NT_PRINTER_INFO_LEVEL *printer = NULL;
3534 print_queue_struct *queue=NULL;
3536 type=option_type->type;
3538 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3539 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3540 option_type->count, lp_servicename(snum)));
3542 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3543 return False;
3545 for(field_num=0; field_num<option_type->count; field_num++) {
3546 field = option_type->fields[field_num];
3548 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3550 if (!search_notify(type, field, &j) )
3551 continue;
3553 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3554 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3555 return False;
3556 } else
3557 info->data = tid;
3559 current_data = &info->data[info->count];
3561 construct_info_data(current_data, type, field, id);
3563 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3564 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3566 notify_info_data_table[j].fn(snum, current_data, queue,
3567 printer, mem_ctx);
3569 info->count++;
3572 free_a_printer(&printer, 2);
3573 return True;
3576 /*******************************************************************
3578 * fill a notify_info struct with info asked
3580 ********************************************************************/
3582 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3583 SPOOL_NOTIFY_INFO *info,
3584 NT_PRINTER_INFO_LEVEL *printer,
3585 int snum, SPOOL_NOTIFY_OPTION_TYPE
3586 *option_type, uint32 id,
3587 TALLOC_CTX *mem_ctx)
3589 int field_num,j;
3590 uint16 type;
3591 uint16 field;
3593 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3595 DEBUG(4,("construct_notify_jobs_info\n"));
3597 type = option_type->type;
3599 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3600 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3601 option_type->count));
3603 for(field_num=0; field_num<option_type->count; field_num++) {
3604 field = option_type->fields[field_num];
3606 if (!search_notify(type, field, &j) )
3607 continue;
3609 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3610 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3611 return False;
3613 else info->data = tid;
3615 current_data=&(info->data[info->count]);
3617 construct_info_data(current_data, type, field, id);
3618 notify_info_data_table[j].fn(snum, current_data, queue,
3619 printer, mem_ctx);
3620 info->count++;
3623 return True;
3627 * JFM: The enumeration is not that simple, it's even non obvious.
3629 * let's take an example: I want to monitor the PRINTER SERVER for
3630 * the printer's name and the number of jobs currently queued.
3631 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3632 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3634 * I have 3 printers on the back of my server.
3636 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3637 * structures.
3638 * Number Data Id
3639 * 1 printer 1 name 1
3640 * 2 printer 1 cjob 1
3641 * 3 printer 2 name 2
3642 * 4 printer 2 cjob 2
3643 * 5 printer 3 name 3
3644 * 6 printer 3 name 3
3646 * that's the print server case, the printer case is even worse.
3649 /*******************************************************************
3651 * enumerate all printers on the printserver
3652 * fill a notify_info struct with info asked
3654 ********************************************************************/
3656 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3657 SPOOL_NOTIFY_INFO *info,
3658 TALLOC_CTX *mem_ctx)
3660 int snum;
3661 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3662 int n_services=lp_numservices();
3663 int i;
3664 SPOOL_NOTIFY_OPTION *option;
3665 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3667 DEBUG(4,("printserver_notify_info\n"));
3669 if (!Printer)
3670 return WERR_BADFID;
3672 option=Printer->notify.option;
3673 info->version=2;
3674 info->data=NULL;
3675 info->count=0;
3677 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3678 sending a ffpcn() request first */
3680 if ( !option )
3681 return WERR_BADFID;
3683 for (i=0; i<option->count; i++) {
3684 option_type=&(option->ctr.type[i]);
3686 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3687 continue;
3689 for (snum=0; snum<n_services; snum++)
3691 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3692 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3696 #if 0
3698 * Debugging information, don't delete.
3701 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3702 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3703 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3705 for (i=0; i<info->count; i++) {
3706 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3707 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3708 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3710 #endif
3712 return WERR_OK;
3715 /*******************************************************************
3717 * fill a notify_info struct with info asked
3719 ********************************************************************/
3721 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3722 TALLOC_CTX *mem_ctx)
3724 int snum;
3725 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3726 int i;
3727 uint32 id;
3728 SPOOL_NOTIFY_OPTION *option;
3729 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3730 int count,j;
3731 print_queue_struct *queue=NULL;
3732 print_status_struct status;
3734 DEBUG(4,("printer_notify_info\n"));
3736 if (!Printer)
3737 return WERR_BADFID;
3739 option=Printer->notify.option;
3740 id = 0x0;
3741 info->version=2;
3742 info->data=NULL;
3743 info->count=0;
3745 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3746 sending a ffpcn() request first */
3748 if ( !option )
3749 return WERR_BADFID;
3751 get_printer_snum(p, hnd, &snum);
3753 for (i=0; i<option->count; i++) {
3754 option_type=&option->ctr.type[i];
3756 switch ( option_type->type ) {
3757 case PRINTER_NOTIFY_TYPE:
3758 if(construct_notify_printer_info(Printer, info, snum,
3759 option_type, id,
3760 mem_ctx))
3761 id--;
3762 break;
3764 case JOB_NOTIFY_TYPE: {
3765 NT_PRINTER_INFO_LEVEL *printer = NULL;
3767 count = print_queue_status(snum, &queue, &status);
3769 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3770 goto done;
3772 for (j=0; j<count; j++) {
3773 construct_notify_jobs_info(&queue[j], info,
3774 printer, snum,
3775 option_type,
3776 queue[j].job,
3777 mem_ctx);
3780 free_a_printer(&printer, 2);
3782 done:
3783 SAFE_FREE(queue);
3784 break;
3790 * Debugging information, don't delete.
3793 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3794 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3795 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3797 for (i=0; i<info->count; i++) {
3798 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3799 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3800 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3803 return WERR_OK;
3806 /********************************************************************
3807 * spoolss_rfnpcnex
3808 ********************************************************************/
3810 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3812 POLICY_HND *handle = &q_u->handle;
3813 SPOOL_NOTIFY_INFO *info = &r_u->info;
3815 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3816 WERROR result = WERR_BADFID;
3818 /* we always have a NOTIFY_INFO struct */
3819 r_u->info_ptr=0x1;
3821 if (!Printer) {
3822 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3823 OUR_HANDLE(handle)));
3824 goto done;
3827 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3830 * We are now using the change value, and
3831 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3832 * I don't have a global notification system, I'm sending back all the
3833 * informations even when _NOTHING_ has changed.
3836 /* We need to keep track of the change value to send back in
3837 RRPCN replies otherwise our updates are ignored. */
3839 Printer->notify.fnpcn = True;
3841 if (Printer->notify.client_connected) {
3842 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3843 Printer->notify.change = q_u->change;
3846 /* just ignore the SPOOL_NOTIFY_OPTION */
3848 switch (Printer->printer_type) {
3849 case PRINTER_HANDLE_IS_PRINTSERVER:
3850 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3851 break;
3853 case PRINTER_HANDLE_IS_PRINTER:
3854 result = printer_notify_info(p, handle, info, p->mem_ctx);
3855 break;
3858 Printer->notify.fnpcn = False;
3860 done:
3861 return result;
3864 /********************************************************************
3865 * construct_printer_info_0
3866 * fill a printer_info_0 struct
3867 ********************************************************************/
3869 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3871 pstring chaine;
3872 int count;
3873 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3874 counter_printer_0 *session_counter;
3875 uint32 global_counter;
3876 struct tm *t;
3877 time_t setuptime;
3878 print_status_struct status;
3880 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3881 return False;
3883 count = print_queue_length(snum, &status);
3885 /* check if we already have a counter for this printer */
3886 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3887 if (session_counter->snum == snum)
3888 break;
3891 /* it's the first time, add it to the list */
3892 if (session_counter==NULL) {
3893 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3894 free_a_printer(&ntprinter, 2);
3895 return False;
3897 ZERO_STRUCTP(session_counter);
3898 session_counter->snum=snum;
3899 session_counter->counter=0;
3900 DLIST_ADD(counter_list, session_counter);
3903 /* increment it */
3904 session_counter->counter++;
3906 /* JFM:
3907 * the global_counter should be stored in a TDB as it's common to all the clients
3908 * and should be zeroed on samba startup
3910 global_counter=session_counter->counter;
3912 pstrcpy(chaine,ntprinter->info_2->printername);
3914 init_unistr(&printer->printername, chaine);
3916 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3917 init_unistr(&printer->servername, chaine);
3919 printer->cjobs = count;
3920 printer->total_jobs = 0;
3921 printer->total_bytes = 0;
3923 setuptime = (time_t)ntprinter->info_2->setuptime;
3924 t=gmtime(&setuptime);
3926 printer->year = t->tm_year+1900;
3927 printer->month = t->tm_mon+1;
3928 printer->dayofweek = t->tm_wday;
3929 printer->day = t->tm_mday;
3930 printer->hour = t->tm_hour;
3931 printer->minute = t->tm_min;
3932 printer->second = t->tm_sec;
3933 printer->milliseconds = 0;
3935 printer->global_counter = global_counter;
3936 printer->total_pages = 0;
3938 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3939 printer->major_version = 0x0005; /* NT 5 */
3940 printer->build_version = 0x0893; /* build 2195 */
3942 printer->unknown7 = 0x1;
3943 printer->unknown8 = 0x0;
3944 printer->unknown9 = 0x0;
3945 printer->session_counter = session_counter->counter;
3946 printer->unknown11 = 0x0;
3947 printer->printer_errors = 0x0; /* number of print failure */
3948 printer->unknown13 = 0x0;
3949 printer->unknown14 = 0x1;
3950 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3951 printer->unknown16 = 0x0;
3952 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3953 printer->unknown18 = 0x0;
3954 printer->status = nt_printq_status(status.status);
3955 printer->unknown20 = 0x0;
3956 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3957 printer->unknown22 = 0x0;
3958 printer->unknown23 = 0x6; /* 6 ???*/
3959 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3960 printer->unknown25 = 0;
3961 printer->unknown26 = 0;
3962 printer->unknown27 = 0;
3963 printer->unknown28 = 0;
3964 printer->unknown29 = 0;
3966 free_a_printer(&ntprinter,2);
3967 return (True);
3970 /********************************************************************
3971 * construct_printer_info_1
3972 * fill a printer_info_1 struct
3973 ********************************************************************/
3974 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3976 pstring chaine;
3977 pstring chaine2;
3978 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3980 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3981 return False;
3983 printer->flags=flags;
3985 if (*ntprinter->info_2->comment == '\0') {
3986 init_unistr(&printer->comment, lp_comment(snum));
3987 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3988 ntprinter->info_2->drivername, lp_comment(snum));
3990 else {
3991 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3992 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3993 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3996 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3998 init_unistr(&printer->description, chaine);
3999 init_unistr(&printer->name, chaine2);
4001 free_a_printer(&ntprinter,2);
4003 return True;
4006 /****************************************************************************
4007 Free a DEVMODE struct.
4008 ****************************************************************************/
4010 static void free_dev_mode(DEVICEMODE *dev)
4012 if (dev == NULL)
4013 return;
4015 SAFE_FREE(dev->dev_private);
4016 SAFE_FREE(dev);
4020 /****************************************************************************
4021 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4022 should be valid upon entry
4023 ****************************************************************************/
4025 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4027 if ( !devmode || !ntdevmode )
4028 return False;
4030 init_unistr(&devmode->devicename, ntdevmode->devicename);
4032 init_unistr(&devmode->formname, ntdevmode->formname);
4034 devmode->specversion = ntdevmode->specversion;
4035 devmode->driverversion = ntdevmode->driverversion;
4036 devmode->size = ntdevmode->size;
4037 devmode->driverextra = ntdevmode->driverextra;
4038 devmode->fields = ntdevmode->fields;
4040 devmode->orientation = ntdevmode->orientation;
4041 devmode->papersize = ntdevmode->papersize;
4042 devmode->paperlength = ntdevmode->paperlength;
4043 devmode->paperwidth = ntdevmode->paperwidth;
4044 devmode->scale = ntdevmode->scale;
4045 devmode->copies = ntdevmode->copies;
4046 devmode->defaultsource = ntdevmode->defaultsource;
4047 devmode->printquality = ntdevmode->printquality;
4048 devmode->color = ntdevmode->color;
4049 devmode->duplex = ntdevmode->duplex;
4050 devmode->yresolution = ntdevmode->yresolution;
4051 devmode->ttoption = ntdevmode->ttoption;
4052 devmode->collate = ntdevmode->collate;
4053 devmode->icmmethod = ntdevmode->icmmethod;
4054 devmode->icmintent = ntdevmode->icmintent;
4055 devmode->mediatype = ntdevmode->mediatype;
4056 devmode->dithertype = ntdevmode->dithertype;
4058 if (ntdevmode->nt_dev_private != NULL) {
4059 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4060 return False;
4063 return True;
4066 /****************************************************************************
4067 Create a DEVMODE struct. Returns malloced memory.
4068 ****************************************************************************/
4070 DEVICEMODE *construct_dev_mode(int snum)
4072 NT_PRINTER_INFO_LEVEL *printer = NULL;
4073 DEVICEMODE *devmode = NULL;
4075 DEBUG(7,("construct_dev_mode\n"));
4077 DEBUGADD(8,("getting printer characteristics\n"));
4079 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4080 return NULL;
4082 if ( !printer->info_2->devmode ) {
4083 DEBUG(5, ("BONG! There was no device mode!\n"));
4084 goto done;
4087 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4088 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4089 goto done;
4092 ZERO_STRUCTP(devmode);
4094 DEBUGADD(8,("loading DEVICEMODE\n"));
4096 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4097 free_dev_mode( devmode );
4098 devmode = NULL;
4101 done:
4102 free_a_printer(&printer,2);
4104 return devmode;
4107 /********************************************************************
4108 * construct_printer_info_2
4109 * fill a printer_info_2 struct
4110 ********************************************************************/
4112 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4114 int count;
4115 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4117 print_status_struct status;
4119 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4120 return False;
4122 count = print_queue_length(snum, &status);
4124 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4125 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4126 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4127 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4128 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4130 if (*ntprinter->info_2->comment == '\0')
4131 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4132 else
4133 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4135 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4136 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4137 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4138 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4139 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4141 printer->attributes = ntprinter->info_2->attributes;
4143 printer->priority = ntprinter->info_2->priority; /* priority */
4144 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4145 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4146 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4147 printer->status = nt_printq_status(status.status); /* status */
4148 printer->cjobs = count; /* jobs */
4149 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4151 if ( !(printer->devmode = construct_dev_mode(snum)) )
4152 DEBUG(8, ("Returning NULL Devicemode!\n"));
4154 printer->secdesc = NULL;
4156 if ( ntprinter->info_2->secdesc_buf
4157 && ntprinter->info_2->secdesc_buf->len != 0 )
4159 /* don't use talloc_steal() here unless you do a deep steal of all
4160 the SEC_DESC members */
4162 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4163 ntprinter->info_2->secdesc_buf->sec );
4166 free_a_printer(&ntprinter, 2);
4168 return True;
4171 /********************************************************************
4172 * construct_printer_info_3
4173 * fill a printer_info_3 struct
4174 ********************************************************************/
4176 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4178 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4179 PRINTER_INFO_3 *printer = NULL;
4181 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4182 return False;
4184 *pp_printer = NULL;
4185 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4186 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4187 return False;
4190 ZERO_STRUCTP(printer);
4192 /* These are the components of the SD we are returning. */
4194 printer->flags = 0x4;
4196 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4197 /* don't use talloc_steal() here unless you do a deep steal of all
4198 the SEC_DESC members */
4200 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4201 ntprinter->info_2->secdesc_buf->sec );
4204 free_a_printer(&ntprinter, 2);
4206 *pp_printer = printer;
4207 return True;
4210 /********************************************************************
4211 * construct_printer_info_4
4212 * fill a printer_info_4 struct
4213 ********************************************************************/
4215 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4217 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4219 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4220 return False;
4222 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4223 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4224 printer->attributes = ntprinter->info_2->attributes;
4226 free_a_printer(&ntprinter, 2);
4227 return True;
4230 /********************************************************************
4231 * construct_printer_info_5
4232 * fill a printer_info_5 struct
4233 ********************************************************************/
4235 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4237 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4239 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4240 return False;
4242 init_unistr(&printer->printername, ntprinter->info_2->printername);
4243 init_unistr(&printer->portname, ntprinter->info_2->portname);
4244 printer->attributes = ntprinter->info_2->attributes;
4246 /* these two are not used by NT+ according to MSDN */
4248 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4249 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4251 free_a_printer(&ntprinter, 2);
4253 return True;
4256 /********************************************************************
4257 * construct_printer_info_7
4258 * fill a printer_info_7 struct
4259 ********************************************************************/
4261 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4263 char *guid_str = NULL;
4264 struct uuid guid;
4266 if (is_printer_published(print_hnd, snum, &guid)) {
4267 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4268 strupper_m(guid_str);
4269 init_unistr(&printer->guid, guid_str);
4270 printer->action = SPOOL_DS_PUBLISH;
4271 } else {
4272 init_unistr(&printer->guid, "");
4273 printer->action = SPOOL_DS_UNPUBLISH;
4276 return True;
4279 /********************************************************************
4280 Spoolss_enumprinters.
4281 ********************************************************************/
4283 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4285 int snum;
4286 int i;
4287 int n_services=lp_numservices();
4288 PRINTER_INFO_1 *tp, *printers=NULL;
4289 PRINTER_INFO_1 current_prt;
4290 WERROR result = WERR_OK;
4292 DEBUG(4,("enum_all_printers_info_1\n"));
4294 for (snum=0; snum<n_services; snum++) {
4295 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4296 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4298 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4299 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4300 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4301 SAFE_FREE(printers);
4302 *returned=0;
4303 return WERR_NOMEM;
4305 else printers = tp;
4306 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4308 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4309 (*returned)++;
4314 /* check the required size. */
4315 for (i=0; i<*returned; i++)
4316 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4318 if (*needed > offered) {
4319 result = WERR_INSUFFICIENT_BUFFER;
4320 goto out;
4323 if (!rpcbuf_alloc_size(buffer, *needed)) {
4324 result = WERR_NOMEM;
4325 goto out;
4328 /* fill the buffer with the structures */
4329 for (i=0; i<*returned; i++)
4330 smb_io_printer_info_1("", buffer, &printers[i], 0);
4332 out:
4333 /* clear memory */
4335 SAFE_FREE(printers);
4337 if ( !W_ERROR_IS_OK(result) )
4338 *returned = 0;
4340 return result;
4343 /********************************************************************
4344 enum_all_printers_info_1_local.
4345 *********************************************************************/
4347 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4349 DEBUG(4,("enum_all_printers_info_1_local\n"));
4351 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4354 /********************************************************************
4355 enum_all_printers_info_1_name.
4356 *********************************************************************/
4358 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4360 char *s = name;
4362 DEBUG(4,("enum_all_printers_info_1_name\n"));
4364 if ((name[0] == '\\') && (name[1] == '\\'))
4365 s = name + 2;
4367 if (is_myname_or_ipaddr(s)) {
4368 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4370 else
4371 return WERR_INVALID_NAME;
4374 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4375 /********************************************************************
4376 enum_all_printers_info_1_remote.
4377 *********************************************************************/
4379 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4381 PRINTER_INFO_1 *printer;
4382 fstring printername;
4383 fstring desc;
4384 fstring comment;
4385 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4386 WERROR result = WERR_OK;
4388 /* JFM: currently it's more a place holder than anything else.
4389 * In the spooler world there is a notion of server registration.
4390 * the print servers are registered on the PDC (in the same domain)
4392 * We should have a TDB here. The registration is done thru an
4393 * undocumented RPC call.
4396 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4397 return WERR_NOMEM;
4399 *returned=1;
4401 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4402 slprintf(desc, sizeof(desc)-1,"%s", name);
4403 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4405 init_unistr(&printer->description, desc);
4406 init_unistr(&printer->name, printername);
4407 init_unistr(&printer->comment, comment);
4408 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4410 /* check the required size. */
4411 *needed += spoolss_size_printer_info_1(printer);
4413 if (*needed > offered) {
4414 result = WERR_INSUFFICIENT_BUFFER;
4415 goto out;
4418 if (!rpcbuf_alloc_size(buffer, *needed)) {
4419 result = WERR_NOMEM;
4420 goto out;
4423 /* fill the buffer with the structures */
4424 smb_io_printer_info_1("", buffer, printer, 0);
4426 out:
4427 /* clear memory */
4428 SAFE_FREE(printer);
4430 if ( !W_ERROR_IS_OK(result) )
4431 *returned = 0;
4433 return result;
4436 #endif
4438 /********************************************************************
4439 enum_all_printers_info_1_network.
4440 *********************************************************************/
4442 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4444 char *s = name;
4446 DEBUG(4,("enum_all_printers_info_1_network\n"));
4448 /* If we respond to a enum_printers level 1 on our name with flags
4449 set to PRINTER_ENUM_REMOTE with a list of printers then these
4450 printers incorrectly appear in the APW browse list.
4451 Specifically the printers for the server appear at the workgroup
4452 level where all the other servers in the domain are
4453 listed. Windows responds to this call with a
4454 WERR_CAN_NOT_COMPLETE so we should do the same. */
4456 if (name[0] == '\\' && name[1] == '\\')
4457 s = name + 2;
4459 if (is_myname_or_ipaddr(s))
4460 return WERR_CAN_NOT_COMPLETE;
4462 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4465 /********************************************************************
4466 * api_spoolss_enumprinters
4468 * called from api_spoolss_enumprinters (see this to understand)
4469 ********************************************************************/
4471 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 int snum;
4474 int i;
4475 int n_services=lp_numservices();
4476 PRINTER_INFO_2 *tp, *printers=NULL;
4477 PRINTER_INFO_2 current_prt;
4478 WERROR result = WERR_OK;
4480 for (snum=0; snum<n_services; snum++) {
4481 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4482 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4484 if (construct_printer_info_2(NULL, &current_prt, snum))
4486 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4487 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4488 SAFE_FREE(printers);
4489 *returned = 0;
4490 return WERR_NOMEM;
4493 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4495 printers = tp;
4496 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4498 (*returned)++;
4503 /* check the required size. */
4504 for (i=0; i<*returned; i++)
4505 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4507 if (*needed > offered) {
4508 result = WERR_INSUFFICIENT_BUFFER;
4509 goto out;
4512 if (!rpcbuf_alloc_size(buffer, *needed)) {
4513 result = WERR_NOMEM;
4514 goto out;
4517 /* fill the buffer with the structures */
4518 for (i=0; i<*returned; i++)
4519 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4521 out:
4522 /* clear memory */
4524 for (i=0; i<*returned; i++)
4525 free_devmode(printers[i].devmode);
4527 SAFE_FREE(printers);
4529 if ( !W_ERROR_IS_OK(result) )
4530 *returned = 0;
4532 return result;
4535 /********************************************************************
4536 * handle enumeration of printers at level 1
4537 ********************************************************************/
4539 static WERROR enumprinters_level1( uint32 flags, fstring name,
4540 RPC_BUFFER *buffer, uint32 offered,
4541 uint32 *needed, uint32 *returned)
4543 /* Not all the flags are equals */
4545 if (flags & PRINTER_ENUM_LOCAL)
4546 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4548 if (flags & PRINTER_ENUM_NAME)
4549 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4551 #if 0 /* JERRY - disabled for now */
4552 if (flags & PRINTER_ENUM_REMOTE)
4553 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4554 #endif
4556 if (flags & PRINTER_ENUM_NETWORK)
4557 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4559 return WERR_OK; /* NT4sp5 does that */
4562 /********************************************************************
4563 * handle enumeration of printers at level 2
4564 ********************************************************************/
4566 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4567 RPC_BUFFER *buffer, uint32 offered,
4568 uint32 *needed, uint32 *returned)
4570 char *s = servername;
4572 if (flags & PRINTER_ENUM_LOCAL) {
4573 return enum_all_printers_info_2(buffer, offered, needed, returned);
4576 if (flags & PRINTER_ENUM_NAME) {
4577 if ((servername[0] == '\\') && (servername[1] == '\\'))
4578 s = servername + 2;
4579 if (is_myname_or_ipaddr(s))
4580 return enum_all_printers_info_2(buffer, offered, needed, returned);
4581 else
4582 return WERR_INVALID_NAME;
4585 if (flags & PRINTER_ENUM_REMOTE)
4586 return WERR_UNKNOWN_LEVEL;
4588 return WERR_OK;
4591 /********************************************************************
4592 * handle enumeration of printers at level 5
4593 ********************************************************************/
4595 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4596 RPC_BUFFER *buffer, uint32 offered,
4597 uint32 *needed, uint32 *returned)
4599 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4600 return WERR_OK;
4603 /********************************************************************
4604 * api_spoolss_enumprinters
4606 * called from api_spoolss_enumprinters (see this to understand)
4607 ********************************************************************/
4609 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4611 uint32 flags = q_u->flags;
4612 UNISTR2 *servername = &q_u->servername;
4613 uint32 level = q_u->level;
4614 RPC_BUFFER *buffer = NULL;
4615 uint32 offered = q_u->offered;
4616 uint32 *needed = &r_u->needed;
4617 uint32 *returned = &r_u->returned;
4619 fstring name;
4621 /* that's an [in out] buffer */
4623 if ( q_u->buffer ) {
4624 rpcbuf_move(q_u->buffer, &r_u->buffer);
4625 buffer = r_u->buffer;
4628 DEBUG(4,("_spoolss_enumprinters\n"));
4630 *needed=0;
4631 *returned=0;
4634 * Level 1:
4635 * flags==PRINTER_ENUM_NAME
4636 * if name=="" then enumerates all printers
4637 * if name!="" then enumerate the printer
4638 * flags==PRINTER_ENUM_REMOTE
4639 * name is NULL, enumerate printers
4640 * Level 2: name!="" enumerates printers, name can't be NULL
4641 * Level 3: doesn't exist
4642 * Level 4: does a local registry lookup
4643 * Level 5: same as Level 2
4646 unistr2_to_ascii(name, servername, sizeof(name)-1);
4647 strupper_m(name);
4649 switch (level) {
4650 case 1:
4651 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4652 case 2:
4653 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4654 case 5:
4655 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4656 case 3:
4657 case 4:
4658 break;
4660 return WERR_UNKNOWN_LEVEL;
4663 /****************************************************************************
4664 ****************************************************************************/
4666 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4668 PRINTER_INFO_0 *printer=NULL;
4669 WERROR result = WERR_OK;
4671 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4672 return WERR_NOMEM;
4674 construct_printer_info_0(print_hnd, printer, snum);
4676 /* check the required size. */
4677 *needed += spoolss_size_printer_info_0(printer);
4679 if (*needed > offered) {
4680 result = WERR_INSUFFICIENT_BUFFER;
4681 goto out;
4684 if (!rpcbuf_alloc_size(buffer, *needed)) {
4685 result = WERR_NOMEM;
4686 goto out;
4689 /* fill the buffer with the structures */
4690 smb_io_printer_info_0("", buffer, printer, 0);
4692 out:
4693 /* clear memory */
4695 SAFE_FREE(printer);
4697 return result;
4700 /****************************************************************************
4701 ****************************************************************************/
4703 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4705 PRINTER_INFO_1 *printer=NULL;
4706 WERROR result = WERR_OK;
4708 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4709 return WERR_NOMEM;
4711 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4713 /* check the required size. */
4714 *needed += spoolss_size_printer_info_1(printer);
4716 if (*needed > offered) {
4717 result = WERR_INSUFFICIENT_BUFFER;
4718 goto out;
4721 if (!rpcbuf_alloc_size(buffer, *needed)) {
4722 result = WERR_NOMEM;
4723 goto out;
4726 /* fill the buffer with the structures */
4727 smb_io_printer_info_1("", buffer, printer, 0);
4729 out:
4730 /* clear memory */
4731 SAFE_FREE(printer);
4733 return result;
4736 /****************************************************************************
4737 ****************************************************************************/
4739 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4741 PRINTER_INFO_2 *printer=NULL;
4742 WERROR result = WERR_OK;
4744 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4745 return WERR_NOMEM;
4747 construct_printer_info_2(print_hnd, printer, snum);
4749 /* check the required size. */
4750 *needed += spoolss_size_printer_info_2(printer);
4752 if (*needed > offered) {
4753 result = WERR_INSUFFICIENT_BUFFER;
4754 goto out;
4757 if (!rpcbuf_alloc_size(buffer, *needed)) {
4758 result = WERR_NOMEM;
4759 goto out;
4762 /* fill the buffer with the structures */
4763 if (!smb_io_printer_info_2("", buffer, printer, 0))
4764 result = WERR_NOMEM;
4766 out:
4767 /* clear memory */
4768 free_printer_info_2(printer);
4770 return result;
4773 /****************************************************************************
4774 ****************************************************************************/
4776 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4778 PRINTER_INFO_3 *printer=NULL;
4779 WERROR result = WERR_OK;
4781 if (!construct_printer_info_3(print_hnd, &printer, snum))
4782 return WERR_NOMEM;
4784 /* check the required size. */
4785 *needed += spoolss_size_printer_info_3(printer);
4787 if (*needed > offered) {
4788 result = WERR_INSUFFICIENT_BUFFER;
4789 goto out;
4792 if (!rpcbuf_alloc_size(buffer, *needed)) {
4793 result = WERR_NOMEM;
4794 goto out;
4797 /* fill the buffer with the structures */
4798 smb_io_printer_info_3("", buffer, printer, 0);
4800 out:
4801 /* clear memory */
4802 free_printer_info_3(printer);
4804 return result;
4807 /****************************************************************************
4808 ****************************************************************************/
4810 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4812 PRINTER_INFO_4 *printer=NULL;
4813 WERROR result = WERR_OK;
4815 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4816 return WERR_NOMEM;
4818 if (!construct_printer_info_4(print_hnd, printer, snum))
4819 return WERR_NOMEM;
4821 /* check the required size. */
4822 *needed += spoolss_size_printer_info_4(printer);
4824 if (*needed > offered) {
4825 result = WERR_INSUFFICIENT_BUFFER;
4826 goto out;
4829 if (!rpcbuf_alloc_size(buffer, *needed)) {
4830 result = WERR_NOMEM;
4831 goto out;
4834 /* fill the buffer with the structures */
4835 smb_io_printer_info_4("", buffer, printer, 0);
4837 out:
4838 /* clear memory */
4839 free_printer_info_4(printer);
4841 return result;
4844 /****************************************************************************
4845 ****************************************************************************/
4847 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4849 PRINTER_INFO_5 *printer=NULL;
4850 WERROR result = WERR_OK;
4852 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4853 return WERR_NOMEM;
4855 if (!construct_printer_info_5(print_hnd, printer, snum))
4856 return WERR_NOMEM;
4858 /* check the required size. */
4859 *needed += spoolss_size_printer_info_5(printer);
4861 if (*needed > offered) {
4862 result = WERR_INSUFFICIENT_BUFFER;
4863 goto out;
4866 if (!rpcbuf_alloc_size(buffer, *needed)) {
4867 result = WERR_NOMEM;
4868 goto out;
4871 /* fill the buffer with the structures */
4872 smb_io_printer_info_5("", buffer, printer, 0);
4874 out:
4875 /* clear memory */
4876 free_printer_info_5(printer);
4878 return result;
4881 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4883 PRINTER_INFO_7 *printer=NULL;
4884 WERROR result = WERR_OK;
4886 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4887 return WERR_NOMEM;
4889 if (!construct_printer_info_7(print_hnd, printer, snum))
4890 return WERR_NOMEM;
4892 /* check the required size. */
4893 *needed += spoolss_size_printer_info_7(printer);
4895 if (*needed > offered) {
4896 result = WERR_INSUFFICIENT_BUFFER;
4897 goto out;
4900 if (!rpcbuf_alloc_size(buffer, *needed)) {
4901 result = WERR_NOMEM;
4902 goto out;
4906 /* fill the buffer with the structures */
4907 smb_io_printer_info_7("", buffer, printer, 0);
4909 out:
4910 /* clear memory */
4911 free_printer_info_7(printer);
4913 return result;
4916 /****************************************************************************
4917 ****************************************************************************/
4919 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4921 POLICY_HND *handle = &q_u->handle;
4922 uint32 level = q_u->level;
4923 RPC_BUFFER *buffer = NULL;
4924 uint32 offered = q_u->offered;
4925 uint32 *needed = &r_u->needed;
4926 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4928 int snum;
4930 /* that's an [in out] buffer */
4932 if ( q_u->buffer ) {
4933 rpcbuf_move(q_u->buffer, &r_u->buffer);
4934 buffer = r_u->buffer;
4937 *needed=0;
4939 if (!get_printer_snum(p, handle, &snum))
4940 return WERR_BADFID;
4942 switch (level) {
4943 case 0:
4944 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4945 case 1:
4946 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4947 case 2:
4948 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4949 case 3:
4950 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4951 case 4:
4952 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4953 case 5:
4954 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4955 case 7:
4956 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4958 return WERR_UNKNOWN_LEVEL;
4961 /********************************************************************
4962 * fill a DRIVER_INFO_1 struct
4963 ********************************************************************/
4965 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4967 init_unistr( &info->name, driver.info_3->name);
4970 /********************************************************************
4971 * construct_printer_driver_info_1
4972 ********************************************************************/
4974 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4976 NT_PRINTER_INFO_LEVEL *printer = NULL;
4977 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4979 ZERO_STRUCT(driver);
4981 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4982 return WERR_INVALID_PRINTER_NAME;
4984 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4985 return WERR_UNKNOWN_PRINTER_DRIVER;
4987 fill_printer_driver_info_1(info, driver, servername, architecture);
4989 free_a_printer(&printer,2);
4991 return WERR_OK;
4994 /********************************************************************
4995 * construct_printer_driver_info_2
4996 * fill a printer_info_2 struct
4997 ********************************************************************/
4999 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5001 pstring temp;
5003 info->version=driver.info_3->cversion;
5005 init_unistr( &info->name, driver.info_3->name );
5006 init_unistr( &info->architecture, driver.info_3->environment );
5009 if (strlen(driver.info_3->driverpath)) {
5010 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5011 init_unistr( &info->driverpath, temp );
5012 } else
5013 init_unistr( &info->driverpath, "" );
5015 if (strlen(driver.info_3->datafile)) {
5016 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5017 init_unistr( &info->datafile, temp );
5018 } else
5019 init_unistr( &info->datafile, "" );
5021 if (strlen(driver.info_3->configfile)) {
5022 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5023 init_unistr( &info->configfile, temp );
5024 } else
5025 init_unistr( &info->configfile, "" );
5028 /********************************************************************
5029 * construct_printer_driver_info_2
5030 * fill a printer_info_2 struct
5031 ********************************************************************/
5033 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5035 NT_PRINTER_INFO_LEVEL *printer = NULL;
5036 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5038 ZERO_STRUCT(printer);
5039 ZERO_STRUCT(driver);
5041 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5042 return WERR_INVALID_PRINTER_NAME;
5044 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5045 return WERR_UNKNOWN_PRINTER_DRIVER;
5047 fill_printer_driver_info_2(info, driver, servername);
5049 free_a_printer(&printer,2);
5051 return WERR_OK;
5054 /********************************************************************
5055 * copy a strings array and convert to UNICODE
5057 * convert an array of ascii string to a UNICODE string
5058 ********************************************************************/
5060 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5062 int i=0;
5063 int j=0;
5064 const char *v;
5065 pstring line;
5066 uint16 *tuary;
5068 DEBUG(6,("init_unistr_array\n"));
5069 *uni_array=NULL;
5071 while (True)
5073 if ( !char_array )
5074 v = "";
5075 else
5077 v = char_array[i];
5078 if (!v)
5079 v = ""; /* hack to handle null lists */
5082 /* hack to allow this to be used in places other than when generating
5083 the list of dependent files */
5085 if ( servername )
5086 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5087 else
5088 pstrcpy( line, v );
5090 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5092 /* add one extra unit16 for the second terminating NULL */
5094 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5095 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5096 return 0;
5097 } else
5098 *uni_array = tuary;
5100 if ( !strlen(v) )
5101 break;
5103 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5104 i++;
5107 if (*uni_array) {
5108 /* special case for ""; we need to add both NULL's here */
5109 if (!j)
5110 (*uni_array)[j++]=0x0000;
5111 (*uni_array)[j]=0x0000;
5114 DEBUGADD(6,("last one:done\n"));
5116 /* return size of array in uint16's */
5118 return j+1;
5121 /********************************************************************
5122 * construct_printer_info_3
5123 * fill a printer_info_3 struct
5124 ********************************************************************/
5126 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5128 pstring temp;
5130 ZERO_STRUCTP(info);
5132 info->version=driver.info_3->cversion;
5134 init_unistr( &info->name, driver.info_3->name );
5135 init_unistr( &info->architecture, driver.info_3->environment );
5137 if (strlen(driver.info_3->driverpath)) {
5138 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5139 init_unistr( &info->driverpath, temp );
5140 } else
5141 init_unistr( &info->driverpath, "" );
5143 if (strlen(driver.info_3->datafile)) {
5144 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5145 init_unistr( &info->datafile, temp );
5146 } else
5147 init_unistr( &info->datafile, "" );
5149 if (strlen(driver.info_3->configfile)) {
5150 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5151 init_unistr( &info->configfile, temp );
5152 } else
5153 init_unistr( &info->configfile, "" );
5155 if (strlen(driver.info_3->helpfile)) {
5156 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5157 init_unistr( &info->helpfile, temp );
5158 } else
5159 init_unistr( &info->helpfile, "" );
5161 init_unistr( &info->monitorname, driver.info_3->monitorname );
5162 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5164 info->dependentfiles=NULL;
5165 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5168 /********************************************************************
5169 * construct_printer_info_3
5170 * fill a printer_info_3 struct
5171 ********************************************************************/
5173 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5175 NT_PRINTER_INFO_LEVEL *printer = NULL;
5176 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5177 WERROR status;
5178 ZERO_STRUCT(driver);
5180 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5181 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5182 if (!W_ERROR_IS_OK(status))
5183 return WERR_INVALID_PRINTER_NAME;
5185 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5186 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5188 #if 0 /* JERRY */
5191 * I put this code in during testing. Helpful when commenting out the
5192 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5193 * as win2k always queries the driver using an infor level of 6.
5194 * I've left it in (but ifdef'd out) because I'll probably
5195 * use it in experimentation again in the future. --jerry 22/01/2002
5198 if (!W_ERROR_IS_OK(status)) {
5200 * Is this a W2k client ?
5202 if (version == 3) {
5203 /* Yes - try again with a WinNT driver. */
5204 version = 2;
5205 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5206 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5208 #endif
5210 if (!W_ERROR_IS_OK(status)) {
5211 free_a_printer(&printer,2);
5212 return WERR_UNKNOWN_PRINTER_DRIVER;
5215 #if 0 /* JERRY */
5217 #endif
5220 fill_printer_driver_info_3(info, driver, servername);
5222 free_a_printer(&printer,2);
5224 return WERR_OK;
5227 /********************************************************************
5228 * construct_printer_info_6
5229 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5230 ********************************************************************/
5232 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5234 pstring temp;
5235 fstring nullstr;
5237 ZERO_STRUCTP(info);
5238 memset(&nullstr, '\0', sizeof(fstring));
5240 info->version=driver.info_3->cversion;
5242 init_unistr( &info->name, driver.info_3->name );
5243 init_unistr( &info->architecture, driver.info_3->environment );
5245 if (strlen(driver.info_3->driverpath)) {
5246 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5247 init_unistr( &info->driverpath, temp );
5248 } else
5249 init_unistr( &info->driverpath, "" );
5251 if (strlen(driver.info_3->datafile)) {
5252 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5253 init_unistr( &info->datafile, temp );
5254 } else
5255 init_unistr( &info->datafile, "" );
5257 if (strlen(driver.info_3->configfile)) {
5258 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5259 init_unistr( &info->configfile, temp );
5260 } else
5261 init_unistr( &info->configfile, "" );
5263 if (strlen(driver.info_3->helpfile)) {
5264 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5265 init_unistr( &info->helpfile, temp );
5266 } else
5267 init_unistr( &info->helpfile, "" );
5269 init_unistr( &info->monitorname, driver.info_3->monitorname );
5270 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5272 info->dependentfiles = NULL;
5273 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5275 info->previousdrivernames=NULL;
5276 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5278 info->driver_date.low=0;
5279 info->driver_date.high=0;
5281 info->padding=0;
5282 info->driver_version_low=0;
5283 info->driver_version_high=0;
5285 init_unistr( &info->mfgname, "");
5286 init_unistr( &info->oem_url, "");
5287 init_unistr( &info->hardware_id, "");
5288 init_unistr( &info->provider, "");
5291 /********************************************************************
5292 * construct_printer_info_6
5293 * fill a printer_info_6 struct
5294 ********************************************************************/
5296 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5297 fstring servername, fstring architecture, uint32 version)
5299 NT_PRINTER_INFO_LEVEL *printer = NULL;
5300 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5301 WERROR status;
5303 ZERO_STRUCT(driver);
5305 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5307 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5309 if (!W_ERROR_IS_OK(status))
5310 return WERR_INVALID_PRINTER_NAME;
5312 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5314 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5316 if (!W_ERROR_IS_OK(status))
5319 * Is this a W2k client ?
5322 if (version < 3) {
5323 free_a_printer(&printer,2);
5324 return WERR_UNKNOWN_PRINTER_DRIVER;
5327 /* Yes - try again with a WinNT driver. */
5328 version = 2;
5329 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5330 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5331 if (!W_ERROR_IS_OK(status)) {
5332 free_a_printer(&printer,2);
5333 return WERR_UNKNOWN_PRINTER_DRIVER;
5337 fill_printer_driver_info_6(info, driver, servername);
5339 free_a_printer(&printer,2);
5340 free_a_printer_driver(driver, 3);
5342 return WERR_OK;
5345 /****************************************************************************
5346 ****************************************************************************/
5348 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5350 SAFE_FREE(info->dependentfiles);
5353 /****************************************************************************
5354 ****************************************************************************/
5356 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5358 SAFE_FREE(info->dependentfiles);
5361 /****************************************************************************
5362 ****************************************************************************/
5364 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5366 DRIVER_INFO_1 *info=NULL;
5367 WERROR result;
5369 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5370 return WERR_NOMEM;
5372 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5373 if (!W_ERROR_IS_OK(result))
5374 goto out;
5376 /* check the required size. */
5377 *needed += spoolss_size_printer_driver_info_1(info);
5379 if (*needed > offered) {
5380 result = WERR_INSUFFICIENT_BUFFER;
5381 goto out;
5384 if (!rpcbuf_alloc_size(buffer, *needed)) {
5385 result = WERR_NOMEM;
5386 goto out;
5389 /* fill the buffer with the structures */
5390 smb_io_printer_driver_info_1("", buffer, info, 0);
5392 out:
5393 /* clear memory */
5394 SAFE_FREE(info);
5396 return result;
5399 /****************************************************************************
5400 ****************************************************************************/
5402 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5404 DRIVER_INFO_2 *info=NULL;
5405 WERROR result;
5407 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5408 return WERR_NOMEM;
5410 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5411 if (!W_ERROR_IS_OK(result))
5412 goto out;
5414 /* check the required size. */
5415 *needed += spoolss_size_printer_driver_info_2(info);
5417 if (*needed > offered) {
5418 result = WERR_INSUFFICIENT_BUFFER;
5419 goto out;
5422 if (!rpcbuf_alloc_size(buffer, *needed)) {
5423 result = WERR_NOMEM;
5424 goto out;
5427 /* fill the buffer with the structures */
5428 smb_io_printer_driver_info_2("", buffer, info, 0);
5430 out:
5431 /* clear memory */
5432 SAFE_FREE(info);
5434 return result;
5437 /****************************************************************************
5438 ****************************************************************************/
5440 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5442 DRIVER_INFO_3 info;
5443 WERROR result;
5445 ZERO_STRUCT(info);
5447 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5448 if (!W_ERROR_IS_OK(result))
5449 goto out;
5451 /* check the required size. */
5452 *needed += spoolss_size_printer_driver_info_3(&info);
5454 if (*needed > offered) {
5455 result = WERR_INSUFFICIENT_BUFFER;
5456 goto out;
5459 if (!rpcbuf_alloc_size(buffer, *needed)) {
5460 result = WERR_NOMEM;
5461 goto out;
5464 /* fill the buffer with the structures */
5465 smb_io_printer_driver_info_3("", buffer, &info, 0);
5467 out:
5468 free_printer_driver_info_3(&info);
5470 return result;
5473 /****************************************************************************
5474 ****************************************************************************/
5476 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5478 DRIVER_INFO_6 info;
5479 WERROR result;
5481 ZERO_STRUCT(info);
5483 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5484 if (!W_ERROR_IS_OK(result))
5485 goto out;
5487 /* check the required size. */
5488 *needed += spoolss_size_printer_driver_info_6(&info);
5490 if (*needed > offered) {
5491 result = WERR_INSUFFICIENT_BUFFER;
5492 goto out;
5495 if (!rpcbuf_alloc_size(buffer, *needed)) {
5496 result = WERR_NOMEM;
5497 goto out;
5500 /* fill the buffer with the structures */
5501 smb_io_printer_driver_info_6("", buffer, &info, 0);
5503 out:
5504 free_printer_driver_info_6(&info);
5506 return result;
5509 /****************************************************************************
5510 ****************************************************************************/
5512 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5514 POLICY_HND *handle = &q_u->handle;
5515 UNISTR2 *uni_arch = &q_u->architecture;
5516 uint32 level = q_u->level;
5517 uint32 clientmajorversion = q_u->clientmajorversion;
5518 RPC_BUFFER *buffer = NULL;
5519 uint32 offered = q_u->offered;
5520 uint32 *needed = &r_u->needed;
5521 uint32 *servermajorversion = &r_u->servermajorversion;
5522 uint32 *serverminorversion = &r_u->serverminorversion;
5523 Printer_entry *printer;
5525 fstring servername;
5526 fstring architecture;
5527 int snum;
5529 /* that's an [in out] buffer */
5531 if ( q_u->buffer ) {
5532 rpcbuf_move(q_u->buffer, &r_u->buffer);
5533 buffer = r_u->buffer;
5536 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5538 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5539 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5540 return WERR_INVALID_PRINTER_NAME;
5543 *needed = 0;
5544 *servermajorversion = 0;
5545 *serverminorversion = 0;
5547 fstrcpy(servername, get_server_name( printer ));
5548 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5550 if (!get_printer_snum(p, handle, &snum))
5551 return WERR_BADFID;
5553 switch (level) {
5554 case 1:
5555 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5556 case 2:
5557 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5558 case 3:
5559 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5560 case 6:
5561 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5562 #if 0 /* JERRY */
5563 case 101:
5564 /* apparently this call is the equivalent of
5565 EnumPrinterDataEx() for the DsDriver key */
5566 break;
5567 #endif
5570 return WERR_UNKNOWN_LEVEL;
5573 /****************************************************************************
5574 ****************************************************************************/
5576 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5578 POLICY_HND *handle = &q_u->handle;
5580 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5582 if (!Printer) {
5583 DEBUG(3,("Error in startpageprinter printer handle\n"));
5584 return WERR_BADFID;
5587 Printer->page_started=True;
5588 return WERR_OK;
5591 /****************************************************************************
5592 ****************************************************************************/
5594 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5596 POLICY_HND *handle = &q_u->handle;
5597 int snum;
5599 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5601 if (!Printer) {
5602 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5603 return WERR_BADFID;
5606 if (!get_printer_snum(p, handle, &snum))
5607 return WERR_BADFID;
5609 Printer->page_started=False;
5610 print_job_endpage(snum, Printer->jobid);
5612 return WERR_OK;
5615 /********************************************************************
5616 * api_spoolss_getprinter
5617 * called from the spoolss dispatcher
5619 ********************************************************************/
5621 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5623 POLICY_HND *handle = &q_u->handle;
5624 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5625 uint32 *jobid = &r_u->jobid;
5627 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5628 int snum;
5629 pstring jobname;
5630 fstring datatype;
5631 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5632 struct current_user user;
5634 if (!Printer) {
5635 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5636 return WERR_BADFID;
5639 get_current_user(&user, p);
5642 * a nice thing with NT is it doesn't listen to what you tell it.
5643 * when asked to send _only_ RAW datas, it tries to send datas
5644 * in EMF format.
5646 * So I add checks like in NT Server ...
5649 if (info_1->p_datatype != 0) {
5650 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5651 if (strcmp(datatype, "RAW") != 0) {
5652 (*jobid)=0;
5653 return WERR_INVALID_DATATYPE;
5657 /* get the share number of the printer */
5658 if (!get_printer_snum(p, handle, &snum)) {
5659 return WERR_BADFID;
5662 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5664 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5666 /* An error occured in print_job_start() so return an appropriate
5667 NT error code. */
5669 if (Printer->jobid == -1) {
5670 return map_werror_from_unix(errno);
5673 Printer->document_started=True;
5674 (*jobid) = Printer->jobid;
5676 return WERR_OK;
5679 /********************************************************************
5680 * api_spoolss_getprinter
5681 * called from the spoolss dispatcher
5683 ********************************************************************/
5685 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5687 POLICY_HND *handle = &q_u->handle;
5689 return _spoolss_enddocprinter_internal(p, handle);
5692 /****************************************************************************
5693 ****************************************************************************/
5695 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5697 POLICY_HND *handle = &q_u->handle;
5698 uint32 buffer_size = q_u->buffer_size;
5699 uint8 *buffer = q_u->buffer;
5700 uint32 *buffer_written = &q_u->buffer_size2;
5701 int snum;
5702 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5704 if (!Printer) {
5705 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5706 r_u->buffer_written = q_u->buffer_size2;
5707 return WERR_BADFID;
5710 if (!get_printer_snum(p, handle, &snum))
5711 return WERR_BADFID;
5713 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5714 (SMB_OFF_T)-1, (size_t)buffer_size);
5715 if (*buffer_written == (uint32)-1) {
5716 r_u->buffer_written = 0;
5717 if (errno == ENOSPC)
5718 return WERR_NO_SPOOL_SPACE;
5719 else
5720 return WERR_ACCESS_DENIED;
5723 r_u->buffer_written = q_u->buffer_size2;
5725 return WERR_OK;
5728 /********************************************************************
5729 * api_spoolss_getprinter
5730 * called from the spoolss dispatcher
5732 ********************************************************************/
5734 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5735 pipes_struct *p)
5737 struct current_user user;
5738 int snum;
5739 WERROR errcode = WERR_BADFUNC;
5740 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5742 get_current_user(&user, p);
5744 if (!Printer) {
5745 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5746 return WERR_BADFID;
5749 if (!get_printer_snum(p, handle, &snum))
5750 return WERR_BADFID;
5752 switch (command) {
5753 case PRINTER_CONTROL_PAUSE:
5754 if (print_queue_pause(&user, snum, &errcode)) {
5755 errcode = WERR_OK;
5757 break;
5758 case PRINTER_CONTROL_RESUME:
5759 case PRINTER_CONTROL_UNPAUSE:
5760 if (print_queue_resume(&user, snum, &errcode)) {
5761 errcode = WERR_OK;
5763 break;
5764 case PRINTER_CONTROL_PURGE:
5765 if (print_queue_purge(&user, snum, &errcode)) {
5766 errcode = WERR_OK;
5768 break;
5769 default:
5770 return WERR_UNKNOWN_LEVEL;
5773 return errcode;
5776 /********************************************************************
5777 * api_spoolss_abortprinter
5778 * From MSDN: "Deletes printer's spool file if printer is configured
5779 * for spooling"
5780 ********************************************************************/
5782 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5784 POLICY_HND *handle = &q_u->handle;
5785 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5786 int snum;
5787 struct current_user user;
5788 WERROR errcode = WERR_OK;
5790 if (!Printer) {
5791 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5792 return WERR_BADFID;
5795 if (!get_printer_snum(p, handle, &snum))
5796 return WERR_BADFID;
5798 get_current_user( &user, p );
5800 print_job_delete( &user, snum, Printer->jobid, &errcode );
5802 return errcode;
5805 /********************************************************************
5806 * called by spoolss_api_setprinter
5807 * when updating a printer description
5808 ********************************************************************/
5810 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5811 const SPOOL_PRINTER_INFO_LEVEL *info,
5812 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5814 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5815 WERROR result;
5816 int snum;
5818 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5820 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5821 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5822 OUR_HANDLE(handle)));
5824 result = WERR_BADFID;
5825 goto done;
5828 /* Check the user has permissions to change the security
5829 descriptor. By experimentation with two NT machines, the user
5830 requires Full Access to the printer to change security
5831 information. */
5833 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5834 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5835 result = WERR_ACCESS_DENIED;
5836 goto done;
5839 /* NT seems to like setting the security descriptor even though
5840 nothing may have actually changed. */
5842 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5844 if (DEBUGLEVEL >= 10) {
5845 SEC_ACL *the_acl;
5846 int i;
5848 the_acl = old_secdesc_ctr->sec->dacl;
5849 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5850 PRINTERNAME(snum), the_acl->num_aces));
5852 for (i = 0; i < the_acl->num_aces; i++) {
5853 fstring sid_str;
5855 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5857 DEBUG(10, ("%s 0x%08x\n", sid_str,
5858 the_acl->ace[i].info.mask));
5861 the_acl = secdesc_ctr->sec->dacl;
5863 if (the_acl) {
5864 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5865 PRINTERNAME(snum), the_acl->num_aces));
5867 for (i = 0; i < the_acl->num_aces; i++) {
5868 fstring sid_str;
5870 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5872 DEBUG(10, ("%s 0x%08x\n", sid_str,
5873 the_acl->ace[i].info.mask));
5875 } else {
5876 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5880 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5882 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5883 result = WERR_OK;
5884 goto done;
5887 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5889 done:
5891 return result;
5894 /********************************************************************
5895 Canonicalize printer info from a client
5897 ATTN: It does not matter what we set the servername to hear
5898 since we do the necessary work in get_a_printer() to set it to
5899 the correct value based on what the client sent in the
5900 _spoolss_open_printer_ex().
5901 ********************************************************************/
5903 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5905 fstring printername;
5906 const char *p;
5908 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5909 "portname=%s drivername=%s comment=%s location=%s\n",
5910 info->servername, info->printername, info->sharename,
5911 info->portname, info->drivername, info->comment, info->location));
5913 /* we force some elements to "correct" values */
5914 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5915 fstrcpy(info->sharename, lp_servicename(snum));
5917 /* check to see if we allow printername != sharename */
5919 if ( lp_force_printername(snum) ) {
5920 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5921 global_myname(), info->sharename );
5922 } else {
5924 /* make sure printername is in \\server\printername format */
5926 fstrcpy( printername, info->printername );
5927 p = printername;
5928 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5929 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5930 p++;
5933 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5934 global_myname(), p );
5937 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5938 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5942 return True;
5945 /****************************************************************************
5946 ****************************************************************************/
5948 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5950 char *cmd = lp_addprinter_cmd();
5951 char **qlines;
5952 pstring command;
5953 int numlines;
5954 int ret;
5955 int fd;
5956 fstring remote_machine = "%m";
5957 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5958 BOOL is_print_op = False;
5960 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5962 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5963 cmd, printer->info_2->printername, printer->info_2->sharename,
5964 printer->info_2->portname, printer->info_2->drivername,
5965 printer->info_2->location, printer->info_2->comment, remote_machine);
5967 if ( token )
5968 is_print_op = user_has_privileges( token, &se_printop );
5970 DEBUG(10,("Running [%s]\n", command));
5972 /********* BEGIN SePrintOperatorPrivilege **********/
5974 if ( is_print_op )
5975 become_root();
5977 if ( (ret = smbrun(command, &fd)) == 0 ) {
5978 /* Tell everyone we updated smb.conf. */
5979 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
5982 if ( is_print_op )
5983 unbecome_root();
5985 /********* END SePrintOperatorPrivilege **********/
5987 DEBUGADD(10,("returned [%d]\n", ret));
5989 if ( ret != 0 ) {
5990 if (fd != -1)
5991 close(fd);
5992 return False;
5995 /* reload our services immediately */
5996 reload_services( False );
5998 numlines = 0;
5999 /* Get lines and convert them back to dos-codepage */
6000 qlines = fd_lines_load(fd, &numlines);
6001 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6002 close(fd);
6004 /* Set the portname to what the script says the portname should be. */
6005 /* but don't require anything to be return from the script exit a good error code */
6007 if (numlines) {
6008 /* Set the portname to what the script says the portname should be. */
6009 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6010 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6013 file_lines_free(qlines);
6014 return True;
6017 /********************************************************************
6018 * Called by spoolss_api_setprinter
6019 * when updating a printer description.
6020 ********************************************************************/
6022 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6023 const SPOOL_PRINTER_INFO_LEVEL *info,
6024 DEVICEMODE *devmode)
6026 int snum;
6027 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6028 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6029 WERROR result;
6030 UNISTR2 buffer;
6031 fstring asc_buffer;
6033 DEBUG(8,("update_printer\n"));
6035 result = WERR_OK;
6037 if (!Printer) {
6038 result = WERR_BADFID;
6039 goto done;
6042 if (!get_printer_snum(p, handle, &snum)) {
6043 result = WERR_BADFID;
6044 goto done;
6047 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6048 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6049 result = WERR_BADFID;
6050 goto done;
6053 DEBUGADD(8,("Converting info_2 struct\n"));
6056 * convert_printer_info converts the incoming
6057 * info from the client and overwrites the info
6058 * just read from the tdb in the pointer 'printer'.
6061 if (!convert_printer_info(info, printer, level)) {
6062 result = WERR_NOMEM;
6063 goto done;
6066 if (devmode) {
6067 /* we have a valid devmode
6068 convert it and link it*/
6070 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6071 if (!convert_devicemode(printer->info_2->printername, devmode,
6072 &printer->info_2->devmode)) {
6073 result = WERR_NOMEM;
6074 goto done;
6078 /* Do sanity check on the requested changes for Samba */
6080 if (!check_printer_ok(printer->info_2, snum)) {
6081 result = WERR_INVALID_PARAM;
6082 goto done;
6085 /* FIXME!!! If the driver has changed we really should verify that
6086 it is installed before doing much else --jerry */
6088 /* Check calling user has permission to update printer description */
6090 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6091 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6092 result = WERR_ACCESS_DENIED;
6093 goto done;
6096 /* Call addprinter hook */
6097 /* Check changes to see if this is really needed */
6099 if ( *lp_addprinter_cmd()
6100 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6101 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6102 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6103 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6105 /* add_printer_hook() will call reload_services() */
6107 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6108 result = WERR_ACCESS_DENIED;
6109 goto done;
6114 * When a *new* driver is bound to a printer, the drivername is used to
6115 * lookup previously saved driver initialization info, which is then
6116 * bound to the printer, simulating what happens in the Windows arch.
6118 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6120 if (!set_driver_init(printer, 2))
6122 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6123 printer->info_2->drivername));
6126 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6127 printer->info_2->drivername));
6129 notify_printer_driver(snum, printer->info_2->drivername);
6133 * flag which changes actually occured. This is a small subset of
6134 * all the possible changes. We also have to update things in the
6135 * DsSpooler key.
6138 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6139 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6140 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6141 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6143 notify_printer_comment(snum, printer->info_2->comment);
6146 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6147 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6148 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6149 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6151 notify_printer_sharename(snum, printer->info_2->sharename);
6154 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6155 char *pname;
6157 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6158 pname++;
6159 else
6160 pname = printer->info_2->printername;
6163 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6164 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6165 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6167 notify_printer_printername( snum, pname );
6170 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6171 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6172 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6173 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6175 notify_printer_port(snum, printer->info_2->portname);
6178 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6179 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6180 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6181 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6183 notify_printer_location(snum, printer->info_2->location);
6186 /* here we need to update some more DsSpooler keys */
6187 /* uNCName, serverName, shortServerName */
6189 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6190 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6191 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6192 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6193 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6195 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6196 global_myname(), printer->info_2->sharename );
6197 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6198 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6199 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6201 /* Update printer info */
6202 result = mod_a_printer(printer, 2);
6204 done:
6205 free_a_printer(&printer, 2);
6206 free_a_printer(&old_printer, 2);
6209 return result;
6212 /****************************************************************************
6213 ****************************************************************************/
6214 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6215 const SPOOL_PRINTER_INFO_LEVEL *info)
6217 #ifdef HAVE_ADS
6218 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6219 int snum;
6220 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6222 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6224 if (!Printer)
6225 return WERR_BADFID;
6227 if (!get_printer_snum(p, handle, &snum))
6228 return WERR_BADFID;
6230 nt_printer_publish(Printer, snum, info7->action);
6232 return WERR_OK;
6233 #else
6234 return WERR_UNKNOWN_LEVEL;
6235 #endif
6237 /****************************************************************************
6238 ****************************************************************************/
6240 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6242 POLICY_HND *handle = &q_u->handle;
6243 uint32 level = q_u->level;
6244 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6245 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6246 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6247 uint32 command = q_u->command;
6248 WERROR result;
6250 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6252 if (!Printer) {
6253 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6254 return WERR_BADFID;
6257 /* check the level */
6258 switch (level) {
6259 case 0:
6260 return control_printer(handle, command, p);
6261 case 2:
6262 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6263 if (!W_ERROR_IS_OK(result))
6264 return result;
6265 if (secdesc_ctr)
6266 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6267 return result;
6268 case 3:
6269 return update_printer_sec(handle, level, info, p,
6270 secdesc_ctr);
6271 case 7:
6272 return publish_or_unpublish_printer(p, handle, info);
6273 default:
6274 return WERR_UNKNOWN_LEVEL;
6278 /****************************************************************************
6279 ****************************************************************************/
6281 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6283 POLICY_HND *handle = &q_u->handle;
6284 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6286 if (!Printer) {
6287 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6288 return WERR_BADFID;
6291 if (Printer->notify.client_connected==True) {
6292 int snum = -1;
6294 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6295 snum = -1;
6296 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6297 !get_printer_snum(p, handle, &snum) )
6298 return WERR_BADFID;
6300 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6303 Printer->notify.flags=0;
6304 Printer->notify.options=0;
6305 Printer->notify.localmachine[0]='\0';
6306 Printer->notify.printerlocal=0;
6307 if (Printer->notify.option)
6308 free_spool_notify_option(&Printer->notify.option);
6309 Printer->notify.client_connected=False;
6311 return WERR_OK;
6314 /****************************************************************************
6315 ****************************************************************************/
6317 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6319 /* that's an [in out] buffer */
6321 if ( q_u->buffer )
6322 rpcbuf_move(q_u->buffer, &r_u->buffer);
6324 r_u->needed = 0;
6325 return WERR_INVALID_PARAM; /* this is what a NT server
6326 returns for AddJob. AddJob
6327 must fail on non-local
6328 printers */
6331 /****************************************************************************
6332 ****************************************************************************/
6334 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6335 int position, int snum,
6336 NT_PRINTER_INFO_LEVEL *ntprinter)
6338 struct tm *t;
6340 t=gmtime(&queue->time);
6342 job_info->jobid=queue->job;
6343 init_unistr(&job_info->printername, lp_servicename(snum));
6344 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6345 init_unistr(&job_info->username, queue->fs_user);
6346 init_unistr(&job_info->document, queue->fs_file);
6347 init_unistr(&job_info->datatype, "RAW");
6348 init_unistr(&job_info->text_status, "");
6349 job_info->status=nt_printj_status(queue->status);
6350 job_info->priority=queue->priority;
6351 job_info->position=position;
6352 job_info->totalpages=queue->page_count;
6353 job_info->pagesprinted=0;
6355 make_systemtime(&job_info->submitted, t);
6358 /****************************************************************************
6359 ****************************************************************************/
6361 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6362 int position, int snum,
6363 NT_PRINTER_INFO_LEVEL *ntprinter,
6364 DEVICEMODE *devmode)
6366 struct tm *t;
6368 t=gmtime(&queue->time);
6370 job_info->jobid=queue->job;
6372 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6374 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6375 init_unistr(&job_info->username, queue->fs_user);
6376 init_unistr(&job_info->document, queue->fs_file);
6377 init_unistr(&job_info->notifyname, queue->fs_user);
6378 init_unistr(&job_info->datatype, "RAW");
6379 init_unistr(&job_info->printprocessor, "winprint");
6380 init_unistr(&job_info->parameters, "");
6381 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6382 init_unistr(&job_info->text_status, "");
6384 /* and here the security descriptor */
6386 job_info->status=nt_printj_status(queue->status);
6387 job_info->priority=queue->priority;
6388 job_info->position=position;
6389 job_info->starttime=0;
6390 job_info->untiltime=0;
6391 job_info->totalpages=queue->page_count;
6392 job_info->size=queue->size;
6393 make_systemtime(&(job_info->submitted), t);
6394 job_info->timeelapsed=0;
6395 job_info->pagesprinted=0;
6397 job_info->devmode = devmode;
6399 return (True);
6402 /****************************************************************************
6403 Enumjobs at level 1.
6404 ****************************************************************************/
6406 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6407 NT_PRINTER_INFO_LEVEL *ntprinter,
6408 RPC_BUFFER *buffer, uint32 offered,
6409 uint32 *needed, uint32 *returned)
6411 JOB_INFO_1 *info;
6412 int i;
6413 WERROR result = WERR_OK;
6415 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6416 if (info==NULL) {
6417 SAFE_FREE(queue);
6418 *returned=0;
6419 return WERR_NOMEM;
6422 for (i=0; i<*returned; i++)
6423 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6425 SAFE_FREE(queue);
6427 /* check the required size. */
6428 for (i=0; i<*returned; i++)
6429 (*needed) += spoolss_size_job_info_1(&info[i]);
6431 if (*needed > offered) {
6432 result = WERR_INSUFFICIENT_BUFFER;
6433 goto out;
6436 if (!rpcbuf_alloc_size(buffer, *needed)) {
6437 result = WERR_NOMEM;
6438 goto out;
6441 /* fill the buffer with the structures */
6442 for (i=0; i<*returned; i++)
6443 smb_io_job_info_1("", buffer, &info[i], 0);
6445 out:
6446 /* clear memory */
6447 SAFE_FREE(info);
6449 if ( !W_ERROR_IS_OK(result) )
6450 *returned = 0;
6452 return result;
6455 /****************************************************************************
6456 Enumjobs at level 2.
6457 ****************************************************************************/
6459 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6460 NT_PRINTER_INFO_LEVEL *ntprinter,
6461 RPC_BUFFER *buffer, uint32 offered,
6462 uint32 *needed, uint32 *returned)
6464 JOB_INFO_2 *info = NULL;
6465 int i;
6466 WERROR result = WERR_OK;
6467 DEVICEMODE *devmode = NULL;
6469 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6470 *returned=0;
6471 return WERR_NOMEM;
6474 /* this should not be a failure condition if the devmode is NULL */
6476 devmode = construct_dev_mode(snum);
6478 for (i=0; i<*returned; i++)
6479 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6481 free_a_printer(&ntprinter, 2);
6482 SAFE_FREE(queue);
6484 /* check the required size. */
6485 for (i=0; i<*returned; i++)
6486 (*needed) += spoolss_size_job_info_2(&info[i]);
6488 if (*needed > offered) {
6489 result = WERR_INSUFFICIENT_BUFFER;
6490 goto out;
6493 if (!rpcbuf_alloc_size(buffer, *needed)) {
6494 result = WERR_NOMEM;
6495 goto out;
6498 /* fill the buffer with the structures */
6499 for (i=0; i<*returned; i++)
6500 smb_io_job_info_2("", buffer, &info[i], 0);
6502 out:
6503 free_devmode(devmode);
6504 SAFE_FREE(info);
6506 if ( !W_ERROR_IS_OK(result) )
6507 *returned = 0;
6509 return result;
6513 /****************************************************************************
6514 Enumjobs.
6515 ****************************************************************************/
6517 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6519 POLICY_HND *handle = &q_u->handle;
6520 uint32 level = q_u->level;
6521 RPC_BUFFER *buffer = NULL;
6522 uint32 offered = q_u->offered;
6523 uint32 *needed = &r_u->needed;
6524 uint32 *returned = &r_u->returned;
6525 WERROR wret;
6526 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6527 int snum;
6528 print_status_struct prt_status;
6529 print_queue_struct *queue=NULL;
6531 /* that's an [in out] buffer */
6533 if ( q_u->buffer ) {
6534 rpcbuf_move(q_u->buffer, &r_u->buffer);
6535 buffer = r_u->buffer;
6538 DEBUG(4,("_spoolss_enumjobs\n"));
6540 *needed=0;
6541 *returned=0;
6543 /* lookup the printer snum and tdb entry */
6545 if (!get_printer_snum(p, handle, &snum))
6546 return WERR_BADFID;
6548 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6549 if ( !W_ERROR_IS_OK(wret) )
6550 return wret;
6552 *returned = print_queue_status(snum, &queue, &prt_status);
6553 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6555 if (*returned == 0) {
6556 SAFE_FREE(queue);
6557 return WERR_OK;
6560 switch (level) {
6561 case 1:
6562 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6563 return wret;
6564 case 2:
6565 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6566 return wret;
6567 default:
6568 SAFE_FREE(queue);
6569 *returned=0;
6570 wret = WERR_UNKNOWN_LEVEL;
6573 free_a_printer( &ntprinter, 2 );
6574 return wret;
6577 /****************************************************************************
6578 ****************************************************************************/
6580 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6582 return WERR_OK;
6585 /****************************************************************************
6586 ****************************************************************************/
6588 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6590 POLICY_HND *handle = &q_u->handle;
6591 uint32 jobid = q_u->jobid;
6592 uint32 command = q_u->command;
6594 struct current_user user;
6595 int snum;
6596 WERROR errcode = WERR_BADFUNC;
6598 if (!get_printer_snum(p, handle, &snum)) {
6599 return WERR_BADFID;
6602 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6603 return WERR_INVALID_PRINTER_NAME;
6606 get_current_user(&user, p);
6608 switch (command) {
6609 case JOB_CONTROL_CANCEL:
6610 case JOB_CONTROL_DELETE:
6611 if (print_job_delete(&user, snum, jobid, &errcode)) {
6612 errcode = WERR_OK;
6614 break;
6615 case JOB_CONTROL_PAUSE:
6616 if (print_job_pause(&user, snum, jobid, &errcode)) {
6617 errcode = WERR_OK;
6619 break;
6620 case JOB_CONTROL_RESTART:
6621 case JOB_CONTROL_RESUME:
6622 if (print_job_resume(&user, snum, jobid, &errcode)) {
6623 errcode = WERR_OK;
6625 break;
6626 default:
6627 return WERR_UNKNOWN_LEVEL;
6630 return errcode;
6633 /****************************************************************************
6634 Enumerates all printer drivers at level 1.
6635 ****************************************************************************/
6637 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6639 int i;
6640 int ndrivers;
6641 uint32 version;
6642 fstring *list = NULL;
6643 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6644 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6645 WERROR result = WERR_OK;
6647 *returned=0;
6649 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6650 list=NULL;
6651 ndrivers=get_ntdrivers(&list, architecture, version);
6652 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6654 if(ndrivers == -1)
6655 return WERR_NOMEM;
6657 if(ndrivers != 0) {
6658 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6659 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6660 SAFE_FREE(driver_info_1);
6661 SAFE_FREE(list);
6662 return WERR_NOMEM;
6664 else driver_info_1 = tdi1;
6667 for (i=0; i<ndrivers; i++) {
6668 WERROR status;
6669 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6670 ZERO_STRUCT(driver);
6671 status = get_a_printer_driver(&driver, 3, list[i],
6672 architecture, version);
6673 if (!W_ERROR_IS_OK(status)) {
6674 SAFE_FREE(list);
6675 return status;
6677 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6678 free_a_printer_driver(driver, 3);
6681 *returned+=ndrivers;
6682 SAFE_FREE(list);
6685 /* check the required size. */
6686 for (i=0; i<*returned; i++) {
6687 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6688 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6691 if (*needed > offered) {
6692 result = WERR_INSUFFICIENT_BUFFER;
6693 goto out;
6696 if (!rpcbuf_alloc_size(buffer, *needed)) {
6697 result = WERR_NOMEM;
6698 goto out;
6701 /* fill the buffer with the driver structures */
6702 for (i=0; i<*returned; i++) {
6703 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6704 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6707 out:
6708 SAFE_FREE(driver_info_1);
6710 if ( !W_ERROR_IS_OK(result) )
6711 *returned = 0;
6713 return result;
6716 /****************************************************************************
6717 Enumerates all printer drivers at level 2.
6718 ****************************************************************************/
6720 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6722 int i;
6723 int ndrivers;
6724 uint32 version;
6725 fstring *list = NULL;
6726 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6727 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6728 WERROR result = WERR_OK;
6730 *returned=0;
6732 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6733 list=NULL;
6734 ndrivers=get_ntdrivers(&list, architecture, version);
6735 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6737 if(ndrivers == -1)
6738 return WERR_NOMEM;
6740 if(ndrivers != 0) {
6741 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6742 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6743 SAFE_FREE(driver_info_2);
6744 SAFE_FREE(list);
6745 return WERR_NOMEM;
6747 else driver_info_2 = tdi2;
6750 for (i=0; i<ndrivers; i++) {
6751 WERROR status;
6753 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6754 ZERO_STRUCT(driver);
6755 status = get_a_printer_driver(&driver, 3, list[i],
6756 architecture, version);
6757 if (!W_ERROR_IS_OK(status)) {
6758 SAFE_FREE(list);
6759 return status;
6761 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6762 free_a_printer_driver(driver, 3);
6765 *returned+=ndrivers;
6766 SAFE_FREE(list);
6769 /* check the required size. */
6770 for (i=0; i<*returned; i++) {
6771 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6772 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6775 if (*needed > offered) {
6776 result = WERR_INSUFFICIENT_BUFFER;
6777 goto out;
6780 if (!rpcbuf_alloc_size(buffer, *needed)) {
6781 result = WERR_NOMEM;
6782 goto out;
6785 /* fill the buffer with the form structures */
6786 for (i=0; i<*returned; i++) {
6787 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6788 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6791 out:
6792 SAFE_FREE(driver_info_2);
6794 if ( !W_ERROR_IS_OK(result) )
6795 *returned = 0;
6797 return result;
6800 /****************************************************************************
6801 Enumerates all printer drivers at level 3.
6802 ****************************************************************************/
6804 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6806 int i;
6807 int ndrivers;
6808 uint32 version;
6809 fstring *list = NULL;
6810 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6811 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6812 WERROR result = WERR_OK;
6814 *returned=0;
6816 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6817 list=NULL;
6818 ndrivers=get_ntdrivers(&list, architecture, version);
6819 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6821 if(ndrivers == -1)
6822 return WERR_NOMEM;
6824 if(ndrivers != 0) {
6825 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6826 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6827 SAFE_FREE(driver_info_3);
6828 SAFE_FREE(list);
6829 return WERR_NOMEM;
6831 else driver_info_3 = tdi3;
6834 for (i=0; i<ndrivers; i++) {
6835 WERROR status;
6837 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6838 ZERO_STRUCT(driver);
6839 status = get_a_printer_driver(&driver, 3, list[i],
6840 architecture, version);
6841 if (!W_ERROR_IS_OK(status)) {
6842 SAFE_FREE(list);
6843 return status;
6845 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6846 free_a_printer_driver(driver, 3);
6849 *returned+=ndrivers;
6850 SAFE_FREE(list);
6853 /* check the required size. */
6854 for (i=0; i<*returned; i++) {
6855 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6856 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6859 if (*needed > offered) {
6860 result = WERR_INSUFFICIENT_BUFFER;
6861 goto out;
6864 if (!rpcbuf_alloc_size(buffer, *needed)) {
6865 result = WERR_NOMEM;
6866 goto out;
6869 /* fill the buffer with the driver structures */
6870 for (i=0; i<*returned; i++) {
6871 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6872 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6875 out:
6876 for (i=0; i<*returned; i++)
6877 SAFE_FREE(driver_info_3[i].dependentfiles);
6879 SAFE_FREE(driver_info_3);
6881 if ( !W_ERROR_IS_OK(result) )
6882 *returned = 0;
6884 return result;
6887 /****************************************************************************
6888 Enumerates all printer drivers.
6889 ****************************************************************************/
6891 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6893 uint32 level = q_u->level;
6894 RPC_BUFFER *buffer = NULL;
6895 uint32 offered = q_u->offered;
6896 uint32 *needed = &r_u->needed;
6897 uint32 *returned = &r_u->returned;
6899 fstring servername;
6900 fstring architecture;
6902 /* that's an [in out] buffer */
6904 if ( q_u->buffer ) {
6905 rpcbuf_move(q_u->buffer, &r_u->buffer);
6906 buffer = r_u->buffer;
6909 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6911 *needed = 0;
6912 *returned = 0;
6914 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6915 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6917 if ( !is_myname_or_ipaddr( servername ) )
6918 return WERR_UNKNOWN_PRINTER_DRIVER;
6920 switch (level) {
6921 case 1:
6922 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6923 case 2:
6924 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6925 case 3:
6926 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6927 default:
6928 return WERR_UNKNOWN_LEVEL;
6932 /****************************************************************************
6933 ****************************************************************************/
6935 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6937 form->flag=list->flag;
6938 init_unistr(&form->name, list->name);
6939 form->width=list->width;
6940 form->length=list->length;
6941 form->left=list->left;
6942 form->top=list->top;
6943 form->right=list->right;
6944 form->bottom=list->bottom;
6947 /****************************************************************************
6948 ****************************************************************************/
6950 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6952 uint32 level = q_u->level;
6953 RPC_BUFFER *buffer = NULL;
6954 uint32 offered = q_u->offered;
6955 uint32 *needed = &r_u->needed;
6956 uint32 *numofforms = &r_u->numofforms;
6957 uint32 numbuiltinforms;
6959 nt_forms_struct *list=NULL;
6960 nt_forms_struct *builtinlist=NULL;
6961 FORM_1 *forms_1;
6962 int buffer_size=0;
6963 int i;
6965 /* that's an [in out] buffer */
6967 if ( q_u->buffer ) {
6968 rpcbuf_move(q_u->buffer, &r_u->buffer);
6969 buffer = r_u->buffer;
6972 DEBUG(4,("_spoolss_enumforms\n"));
6973 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6974 DEBUGADD(5,("Info level [%d]\n", level));
6976 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6977 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6978 *numofforms = get_ntforms(&list);
6979 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6980 *numofforms += numbuiltinforms;
6982 if (*numofforms == 0)
6983 return WERR_NO_MORE_ITEMS;
6985 switch (level) {
6986 case 1:
6987 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
6988 *numofforms=0;
6989 return WERR_NOMEM;
6992 /* construct the list of form structures */
6993 for (i=0; i<numbuiltinforms; i++) {
6994 DEBUGADD(6,("Filling form number [%d]\n",i));
6995 fill_form_1(&forms_1[i], &builtinlist[i]);
6998 SAFE_FREE(builtinlist);
7000 for (; i<*numofforms; i++) {
7001 DEBUGADD(6,("Filling form number [%d]\n",i));
7002 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7005 SAFE_FREE(list);
7007 /* check the required size. */
7008 for (i=0; i<numbuiltinforms; i++) {
7009 DEBUGADD(6,("adding form [%d]'s size\n",i));
7010 buffer_size += spoolss_size_form_1(&forms_1[i]);
7012 for (; i<*numofforms; i++) {
7013 DEBUGADD(6,("adding form [%d]'s size\n",i));
7014 buffer_size += spoolss_size_form_1(&forms_1[i]);
7017 *needed=buffer_size;
7019 if (*needed > offered) {
7020 SAFE_FREE(forms_1);
7021 *numofforms=0;
7022 return WERR_INSUFFICIENT_BUFFER;
7025 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7026 SAFE_FREE(forms_1);
7027 *numofforms=0;
7028 return WERR_NOMEM;
7031 /* fill the buffer with the form structures */
7032 for (i=0; i<numbuiltinforms; i++) {
7033 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7034 smb_io_form_1("", buffer, &forms_1[i], 0);
7036 for (; i<*numofforms; i++) {
7037 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7038 smb_io_form_1("", buffer, &forms_1[i], 0);
7041 SAFE_FREE(forms_1);
7043 return WERR_OK;
7045 default:
7046 SAFE_FREE(list);
7047 SAFE_FREE(builtinlist);
7048 return WERR_UNKNOWN_LEVEL;
7053 /****************************************************************************
7054 ****************************************************************************/
7056 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7058 uint32 level = q_u->level;
7059 UNISTR2 *uni_formname = &q_u->formname;
7060 RPC_BUFFER *buffer = NULL;
7061 uint32 offered = q_u->offered;
7062 uint32 *needed = &r_u->needed;
7064 nt_forms_struct *list=NULL;
7065 nt_forms_struct builtin_form;
7066 BOOL foundBuiltin;
7067 FORM_1 form_1;
7068 fstring form_name;
7069 int buffer_size=0;
7070 int numofforms=0, i=0;
7072 /* that's an [in out] buffer */
7074 if ( q_u->buffer ) {
7075 rpcbuf_move(q_u->buffer, &r_u->buffer);
7076 buffer = r_u->buffer;
7079 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7081 DEBUG(4,("_spoolss_getform\n"));
7082 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7083 DEBUGADD(5,("Info level [%d]\n", level));
7085 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7086 if (!foundBuiltin) {
7087 numofforms = get_ntforms(&list);
7088 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7090 if (numofforms == 0)
7091 return WERR_BADFID;
7094 switch (level) {
7095 case 1:
7096 if (foundBuiltin) {
7097 fill_form_1(&form_1, &builtin_form);
7098 } else {
7100 /* Check if the requested name is in the list of form structures */
7101 for (i=0; i<numofforms; i++) {
7103 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7105 if (strequal(form_name, list[i].name)) {
7106 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7107 fill_form_1(&form_1, &list[i]);
7108 break;
7112 SAFE_FREE(list);
7113 if (i == numofforms) {
7114 return WERR_BADFID;
7117 /* check the required size. */
7119 *needed=spoolss_size_form_1(&form_1);
7121 if (*needed > offered)
7122 return WERR_INSUFFICIENT_BUFFER;
7124 if (!rpcbuf_alloc_size(buffer, buffer_size))
7125 return WERR_NOMEM;
7127 /* fill the buffer with the form structures */
7128 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7129 smb_io_form_1("", buffer, &form_1, 0);
7131 return WERR_OK;
7133 default:
7134 SAFE_FREE(list);
7135 return WERR_UNKNOWN_LEVEL;
7139 /****************************************************************************
7140 ****************************************************************************/
7142 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7144 init_unistr(&port->port_name, name);
7147 /****************************************************************************
7148 ****************************************************************************/
7150 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7152 init_unistr(&port->port_name, name);
7153 init_unistr(&port->monitor_name, "Local Monitor");
7154 init_unistr(&port->description, "Local Port");
7155 port->port_type=PORT_TYPE_WRITE;
7156 port->reserved=0x0;
7160 /****************************************************************************
7161 wrapper around the enumer ports command
7162 ****************************************************************************/
7164 WERROR enumports_hook( int *count, char ***lines )
7166 char *cmd = lp_enumports_cmd();
7167 char **qlines;
7168 pstring command;
7169 int numlines;
7170 int ret;
7171 int fd;
7174 /* if no hook then just fill in the default port */
7176 if ( !*cmd ) {
7177 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7178 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7179 qlines[1] = NULL;
7180 numlines = 1;
7182 else {
7183 /* we have a valid enumport command */
7185 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7187 DEBUG(10,("Running [%s]\n", command));
7188 ret = smbrun(command, &fd);
7189 DEBUG(10,("Returned [%d]\n", ret));
7190 if (ret != 0) {
7191 if (fd != -1)
7192 close(fd);
7194 return WERR_ACCESS_DENIED;
7197 numlines = 0;
7198 qlines = fd_lines_load(fd, &numlines);
7199 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7200 close(fd);
7203 *count = numlines;
7204 *lines = qlines;
7206 return WERR_OK;
7209 /****************************************************************************
7210 enumports level 1.
7211 ****************************************************************************/
7213 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7215 PORT_INFO_1 *ports=NULL;
7216 int i=0;
7217 WERROR result = WERR_OK;
7218 char **qlines;
7219 int numlines;
7221 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7222 return result;
7224 if(numlines) {
7225 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7226 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7227 dos_errstr(WERR_NOMEM)));
7228 file_lines_free(qlines);
7229 return WERR_NOMEM;
7232 for (i=0; i<numlines; i++) {
7233 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7234 fill_port_1(&ports[i], qlines[i]);
7237 file_lines_free(qlines);
7240 *returned = numlines;
7242 /* check the required size. */
7243 for (i=0; i<*returned; i++) {
7244 DEBUGADD(6,("adding port [%d]'s size\n", i));
7245 *needed += spoolss_size_port_info_1(&ports[i]);
7248 if (*needed > offered) {
7249 result = WERR_INSUFFICIENT_BUFFER;
7250 goto out;
7253 if (!rpcbuf_alloc_size(buffer, *needed)) {
7254 result = WERR_NOMEM;
7255 goto out;
7258 /* fill the buffer with the ports structures */
7259 for (i=0; i<*returned; i++) {
7260 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7261 smb_io_port_1("", buffer, &ports[i], 0);
7264 out:
7265 SAFE_FREE(ports);
7267 if ( !W_ERROR_IS_OK(result) )
7268 *returned = 0;
7270 return result;
7273 /****************************************************************************
7274 enumports level 2.
7275 ****************************************************************************/
7277 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7279 PORT_INFO_2 *ports=NULL;
7280 int i=0;
7281 WERROR result = WERR_OK;
7282 char **qlines;
7283 int numlines;
7285 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7286 return result;
7289 if(numlines) {
7290 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7291 file_lines_free(qlines);
7292 return WERR_NOMEM;
7295 for (i=0; i<numlines; i++) {
7296 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7297 fill_port_2(&(ports[i]), qlines[i]);
7300 file_lines_free(qlines);
7303 *returned = numlines;
7305 /* check the required size. */
7306 for (i=0; i<*returned; i++) {
7307 DEBUGADD(6,("adding port [%d]'s size\n", i));
7308 *needed += spoolss_size_port_info_2(&ports[i]);
7311 if (*needed > offered) {
7312 result = WERR_INSUFFICIENT_BUFFER;
7313 goto out;
7316 if (!rpcbuf_alloc_size(buffer, *needed)) {
7317 result = WERR_NOMEM;
7318 goto out;
7321 /* fill the buffer with the ports structures */
7322 for (i=0; i<*returned; i++) {
7323 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7324 smb_io_port_2("", buffer, &ports[i], 0);
7327 out:
7328 SAFE_FREE(ports);
7330 if ( !W_ERROR_IS_OK(result) )
7331 *returned = 0;
7333 return result;
7336 /****************************************************************************
7337 enumports.
7338 ****************************************************************************/
7340 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7342 uint32 level = q_u->level;
7343 RPC_BUFFER *buffer = NULL;
7344 uint32 offered = q_u->offered;
7345 uint32 *needed = &r_u->needed;
7346 uint32 *returned = &r_u->returned;
7348 /* that's an [in out] buffer */
7350 if ( q_u->buffer ) {
7351 rpcbuf_move(q_u->buffer, &r_u->buffer);
7352 buffer = r_u->buffer;
7355 DEBUG(4,("_spoolss_enumports\n"));
7357 *returned=0;
7358 *needed=0;
7360 switch (level) {
7361 case 1:
7362 return enumports_level_1(buffer, offered, needed, returned);
7363 case 2:
7364 return enumports_level_2(buffer, offered, needed, returned);
7365 default:
7366 return WERR_UNKNOWN_LEVEL;
7370 /****************************************************************************
7371 ****************************************************************************/
7373 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7374 const SPOOL_PRINTER_INFO_LEVEL *info,
7375 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7376 uint32 user_switch, const SPOOL_USER_CTR *user,
7377 POLICY_HND *handle)
7379 NT_PRINTER_INFO_LEVEL *printer = NULL;
7380 fstring name;
7381 int snum;
7382 WERROR err = WERR_OK;
7384 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7385 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7386 return WERR_NOMEM;
7389 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7390 if (!convert_printer_info(info, printer, 2)) {
7391 free_a_printer(&printer, 2);
7392 return WERR_NOMEM;
7395 /* check to see if the printer already exists */
7397 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7398 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7399 printer->info_2->sharename));
7400 free_a_printer(&printer, 2);
7401 return WERR_PRINTER_ALREADY_EXISTS;
7404 /* FIXME!!! smbd should check to see if the driver is installed before
7405 trying to add a printer like this --jerry */
7407 if (*lp_addprinter_cmd() ) {
7408 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7409 free_a_printer(&printer,2);
7410 return WERR_ACCESS_DENIED;
7412 } else {
7413 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7414 "smb.conf parameter \"addprinter command\" is defined. This"
7415 "parameter must exist for this call to succeed\n",
7416 printer->info_2->sharename ));
7419 /* use our primary netbios name since get_a_printer() will convert
7420 it to what the client expects on a case by case basis */
7422 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7423 printer->info_2->sharename);
7426 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7427 free_a_printer(&printer,2);
7428 return WERR_ACCESS_DENIED;
7431 /* you must be a printer admin to add a new printer */
7432 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7433 free_a_printer(&printer,2);
7434 return WERR_ACCESS_DENIED;
7438 * Do sanity check on the requested changes for Samba.
7441 if (!check_printer_ok(printer->info_2, snum)) {
7442 free_a_printer(&printer,2);
7443 return WERR_INVALID_PARAM;
7447 * When a printer is created, the drivername bound to the printer is used
7448 * to lookup previously saved driver initialization info, which is then
7449 * bound to the new printer, simulating what happens in the Windows arch.
7452 if (!devmode)
7454 set_driver_init(printer, 2);
7456 else
7458 /* A valid devmode was included, convert and link it
7460 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7462 if (!convert_devicemode(printer->info_2->printername, devmode,
7463 &printer->info_2->devmode))
7464 return WERR_NOMEM;
7467 /* write the ASCII on disk */
7468 err = mod_a_printer(printer, 2);
7469 if (!W_ERROR_IS_OK(err)) {
7470 free_a_printer(&printer,2);
7471 return err;
7474 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7475 /* Handle open failed - remove addition. */
7476 del_a_printer(printer->info_2->sharename);
7477 free_a_printer(&printer,2);
7478 return WERR_ACCESS_DENIED;
7481 update_c_setprinter(False);
7482 free_a_printer(&printer,2);
7484 return WERR_OK;
7487 /****************************************************************************
7488 ****************************************************************************/
7490 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7492 UNISTR2 *uni_srv_name = q_u->server_name;
7493 uint32 level = q_u->level;
7494 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7495 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7496 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7497 uint32 user_switch = q_u->user_switch;
7498 SPOOL_USER_CTR *user = &q_u->user_ctr;
7499 POLICY_HND *handle = &r_u->handle;
7501 switch (level) {
7502 case 1:
7503 /* we don't handle yet */
7504 /* but I know what to do ... */
7505 return WERR_UNKNOWN_LEVEL;
7506 case 2:
7507 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7508 devmode, sdb,
7509 user_switch, user, handle);
7510 default:
7511 return WERR_UNKNOWN_LEVEL;
7515 /****************************************************************************
7516 ****************************************************************************/
7518 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7520 uint32 level = q_u->level;
7521 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7522 WERROR err = WERR_OK;
7523 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7524 struct current_user user;
7525 fstring driver_name;
7526 uint32 version;
7528 ZERO_STRUCT(driver);
7530 get_current_user(&user, p);
7532 if (!convert_printer_driver_info(info, &driver, level)) {
7533 err = WERR_NOMEM;
7534 goto done;
7537 DEBUG(5,("Cleaning driver's information\n"));
7538 err = clean_up_driver_struct(driver, level, &user);
7539 if (!W_ERROR_IS_OK(err))
7540 goto done;
7542 DEBUG(5,("Moving driver to final destination\n"));
7543 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7544 goto done;
7547 if (add_a_printer_driver(driver, level)!=0) {
7548 err = WERR_ACCESS_DENIED;
7549 goto done;
7552 /* BEGIN_ADMIN_LOG */
7553 switch(level) {
7554 case 3:
7555 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7556 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7557 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7558 break;
7559 case 6:
7560 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7561 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7562 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7563 break;
7565 /* END_ADMIN_LOG */
7568 * I think this is where he DrvUpgradePrinter() hook would be
7569 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7570 * server. Right now, we just need to send ourselves a message
7571 * to update each printer bound to this driver. --jerry
7574 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7575 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7576 driver_name));
7580 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7581 * decide if the driver init data should be deleted. The rules are:
7582 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7583 * 2) delete init data only if there is no 2k/Xp driver
7584 * 3) always delete init data
7585 * The generalized rule is always use init data from the highest order driver.
7586 * It is necessary to follow the driver install by an initialization step to
7587 * finish off this process.
7589 if (level == 3)
7590 version = driver.info_3->cversion;
7591 else if (level == 6)
7592 version = driver.info_6->version;
7593 else
7594 version = -1;
7595 switch (version) {
7597 * 9x printer driver - never delete init data
7599 case 0:
7600 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7601 driver_name));
7602 break;
7605 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7606 * there is no 2k/Xp driver init data for this driver name.
7608 case 2:
7610 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7612 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7614 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7616 if (!del_driver_init(driver_name))
7617 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7618 } else {
7620 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7622 free_a_printer_driver(driver1,3);
7623 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7624 driver_name));
7627 break;
7630 * 2k or Xp printer driver - always delete init data
7632 case 3:
7633 if (!del_driver_init(driver_name))
7634 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7635 break;
7637 default:
7638 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7639 break;
7643 done:
7644 free_a_printer_driver(driver, level);
7645 return err;
7648 /********************************************************************
7649 * spoolss_addprinterdriverex
7650 ********************************************************************/
7652 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7654 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7655 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7658 * we only support the semantics of AddPrinterDriver()
7659 * i.e. only copy files that are newer than existing ones
7662 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7663 return WERR_ACCESS_DENIED;
7665 ZERO_STRUCT(q_u_local);
7666 ZERO_STRUCT(r_u_local);
7668 /* just pass the information off to _spoolss_addprinterdriver() */
7669 q_u_local.server_name_ptr = q_u->server_name_ptr;
7670 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7671 q_u_local.level = q_u->level;
7672 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7674 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7677 /****************************************************************************
7678 ****************************************************************************/
7680 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7682 init_unistr(&info->name, name);
7685 /****************************************************************************
7686 ****************************************************************************/
7688 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7690 pstring path;
7691 pstring long_archi;
7692 fstring servername;
7693 char *pservername;
7694 const char *short_archi;
7695 DRIVER_DIRECTORY_1 *info=NULL;
7696 WERROR result = WERR_OK;
7698 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7699 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7701 /* check for beginning double '\'s and that the server
7702 long enough */
7704 pservername = servername;
7705 if ( *pservername == '\\' && strlen(servername)>2 ) {
7706 pservername += 2;
7709 if ( !is_myname_or_ipaddr( pservername ) )
7710 return WERR_INVALID_PARAM;
7712 if (!(short_archi = get_short_archi(long_archi)))
7713 return WERR_INVALID_ENVIRONMENT;
7715 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7716 return WERR_NOMEM;
7718 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7720 DEBUG(4,("printer driver directory: [%s]\n", path));
7722 fill_driverdir_1(info, path);
7724 *needed += spoolss_size_driverdir_info_1(info);
7726 if (*needed > offered) {
7727 result = WERR_INSUFFICIENT_BUFFER;
7728 goto out;
7731 if (!rpcbuf_alloc_size(buffer, *needed)) {
7732 result = WERR_NOMEM;
7733 goto out;
7736 smb_io_driverdir_1("", buffer, info, 0);
7738 out:
7739 SAFE_FREE(info);
7741 return result;
7744 /****************************************************************************
7745 ****************************************************************************/
7747 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7749 UNISTR2 *name = &q_u->name;
7750 UNISTR2 *uni_environment = &q_u->environment;
7751 uint32 level = q_u->level;
7752 RPC_BUFFER *buffer = NULL;
7753 uint32 offered = q_u->offered;
7754 uint32 *needed = &r_u->needed;
7756 /* that's an [in out] buffer */
7758 if ( q_u->buffer ) {
7759 rpcbuf_move(q_u->buffer, &r_u->buffer);
7760 buffer = r_u->buffer;
7763 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7765 *needed=0;
7767 switch(level) {
7768 case 1:
7769 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7770 default:
7771 return WERR_UNKNOWN_LEVEL;
7775 /****************************************************************************
7776 ****************************************************************************/
7778 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7780 POLICY_HND *handle = &q_u->handle;
7781 uint32 idx = q_u->index;
7782 uint32 in_value_len = q_u->valuesize;
7783 uint32 in_data_len = q_u->datasize;
7784 uint32 *out_max_value_len = &r_u->valuesize;
7785 uint16 **out_value = &r_u->value;
7786 uint32 *out_value_len = &r_u->realvaluesize;
7787 uint32 *out_type = &r_u->type;
7788 uint32 *out_max_data_len = &r_u->datasize;
7789 uint8 **data_out = &r_u->data;
7790 uint32 *out_data_len = &r_u->realdatasize;
7792 NT_PRINTER_INFO_LEVEL *printer = NULL;
7794 uint32 biggest_valuesize;
7795 uint32 biggest_datasize;
7796 uint32 data_len;
7797 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7798 int snum;
7799 WERROR result;
7800 REGISTRY_VALUE *val = NULL;
7801 NT_PRINTER_DATA *p_data;
7802 int i, key_index, num_values;
7803 int name_length;
7805 *out_type = 0;
7807 *out_max_data_len = 0;
7808 *data_out = NULL;
7809 *out_data_len = 0;
7811 DEBUG(5,("spoolss_enumprinterdata\n"));
7813 if (!Printer) {
7814 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7815 return WERR_BADFID;
7818 if (!get_printer_snum(p,handle, &snum))
7819 return WERR_BADFID;
7821 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7822 if (!W_ERROR_IS_OK(result))
7823 return result;
7825 p_data = printer->info_2->data;
7826 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7828 result = WERR_OK;
7831 * The NT machine wants to know the biggest size of value and data
7833 * cf: MSDN EnumPrinterData remark section
7836 if ( !in_value_len && !in_data_len && (key_index != -1) )
7838 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7840 biggest_valuesize = 0;
7841 biggest_datasize = 0;
7843 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7845 for ( i=0; i<num_values; i++ )
7847 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7849 name_length = strlen(val->valuename);
7850 if ( strlen(val->valuename) > biggest_valuesize )
7851 biggest_valuesize = name_length;
7853 if ( val->size > biggest_datasize )
7854 biggest_datasize = val->size;
7856 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7857 biggest_datasize));
7860 /* the value is an UNICODE string but real_value_size is the length
7861 in bytes including the trailing 0 */
7863 *out_value_len = 2 * (1+biggest_valuesize);
7864 *out_data_len = biggest_datasize;
7866 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7868 goto done;
7872 * the value len is wrong in NT sp3
7873 * that's the number of bytes not the number of unicode chars
7876 if ( key_index != -1 )
7877 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7879 if ( !val )
7882 /* out_value should default to "" or else NT4 has
7883 problems unmarshalling the response */
7885 *out_max_value_len=(in_value_len/sizeof(uint16));
7887 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7889 result = WERR_NOMEM;
7890 goto done;
7893 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7895 /* the data is counted in bytes */
7897 *out_max_data_len = in_data_len;
7898 *out_data_len = in_data_len;
7900 /* only allocate when given a non-zero data_len */
7902 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7904 result = WERR_NOMEM;
7905 goto done;
7908 result = WERR_NO_MORE_ITEMS;
7910 else
7913 * the value is:
7914 * - counted in bytes in the request
7915 * - counted in UNICODE chars in the max reply
7916 * - counted in bytes in the real size
7918 * take a pause *before* coding not *during* coding
7921 /* name */
7922 *out_max_value_len=(in_value_len/sizeof(uint16));
7923 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7925 result = WERR_NOMEM;
7926 goto done;
7929 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7931 /* type */
7933 *out_type = regval_type( val );
7935 /* data - counted in bytes */
7937 *out_max_data_len = in_data_len;
7938 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7940 result = WERR_NOMEM;
7941 goto done;
7943 data_len = regval_size(val);
7944 if ( *data_out )
7945 memcpy( *data_out, regval_data_p(val), data_len );
7946 *out_data_len = data_len;
7949 done:
7950 free_a_printer(&printer, 2);
7951 return result;
7954 /****************************************************************************
7955 ****************************************************************************/
7957 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7959 POLICY_HND *handle = &q_u->handle;
7960 UNISTR2 *value = &q_u->value;
7961 uint32 type = q_u->type;
7962 uint8 *data = q_u->data;
7963 uint32 real_len = q_u->real_len;
7965 NT_PRINTER_INFO_LEVEL *printer = NULL;
7966 int snum=0;
7967 WERROR status = WERR_OK;
7968 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7969 fstring valuename;
7971 DEBUG(5,("spoolss_setprinterdata\n"));
7973 if (!Printer) {
7974 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7975 return WERR_BADFID;
7978 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7979 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7980 return WERR_INVALID_PARAM;
7983 if (!get_printer_snum(p,handle, &snum))
7984 return WERR_BADFID;
7987 * Access check : NT returns "access denied" if you make a
7988 * SetPrinterData call without the necessary privildge.
7989 * we were originally returning OK if nothing changed
7990 * which made Win2k issue **a lot** of SetPrinterData
7991 * when connecting to a printer --jerry
7994 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7996 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7997 status = WERR_ACCESS_DENIED;
7998 goto done;
8001 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8002 if (!W_ERROR_IS_OK(status))
8003 return status;
8005 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8008 * When client side code sets a magic printer data key, detect it and save
8009 * the current printer data and the magic key's data (its the DEVMODE) for
8010 * future printer/driver initializations.
8012 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8014 /* Set devmode and printer initialization info */
8015 status = save_driver_init( printer, 2, data, real_len );
8017 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8019 else
8021 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8022 type, data, real_len );
8023 if ( W_ERROR_IS_OK(status) )
8024 status = mod_a_printer(printer, 2);
8027 done:
8028 free_a_printer(&printer, 2);
8030 return status;
8033 /****************************************************************************
8034 ****************************************************************************/
8036 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8038 POLICY_HND *handle = &q_u->handle;
8039 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8040 int snum;
8042 DEBUG(5,("_spoolss_resetprinter\n"));
8045 * All we do is to check to see if the handle and queue is valid.
8046 * This call really doesn't mean anything to us because we only
8047 * support RAW printing. --jerry
8050 if (!Printer) {
8051 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8052 return WERR_BADFID;
8055 if (!get_printer_snum(p,handle, &snum))
8056 return WERR_BADFID;
8059 /* blindly return success */
8060 return WERR_OK;
8064 /****************************************************************************
8065 ****************************************************************************/
8067 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8069 POLICY_HND *handle = &q_u->handle;
8070 UNISTR2 *value = &q_u->valuename;
8072 NT_PRINTER_INFO_LEVEL *printer = NULL;
8073 int snum=0;
8074 WERROR status = WERR_OK;
8075 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8076 pstring valuename;
8078 DEBUG(5,("spoolss_deleteprinterdata\n"));
8080 if (!Printer) {
8081 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8082 return WERR_BADFID;
8085 if (!get_printer_snum(p, handle, &snum))
8086 return WERR_BADFID;
8088 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8089 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8090 return WERR_ACCESS_DENIED;
8093 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8094 if (!W_ERROR_IS_OK(status))
8095 return status;
8097 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8099 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8101 if ( W_ERROR_IS_OK(status) )
8102 mod_a_printer( printer, 2 );
8104 free_a_printer(&printer, 2);
8106 return status;
8109 /****************************************************************************
8110 ****************************************************************************/
8112 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8114 POLICY_HND *handle = &q_u->handle;
8115 FORM *form = &q_u->form;
8116 nt_forms_struct tmpForm;
8117 int snum;
8118 WERROR status = WERR_OK;
8119 NT_PRINTER_INFO_LEVEL *printer = NULL;
8121 int count=0;
8122 nt_forms_struct *list=NULL;
8123 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8125 DEBUG(5,("spoolss_addform\n"));
8127 if (!Printer) {
8128 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8129 return WERR_BADFID;
8133 /* forms can be added on printer of on the print server handle */
8135 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8137 if (!get_printer_snum(p,handle, &snum))
8138 return WERR_BADFID;
8140 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8141 if (!W_ERROR_IS_OK(status))
8142 goto done;
8145 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8146 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8147 status = WERR_ACCESS_DENIED;
8148 goto done;
8151 /* can't add if builtin */
8153 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8154 status = WERR_ALREADY_EXISTS;
8155 goto done;
8158 count = get_ntforms(&list);
8160 if(!add_a_form(&list, form, &count)) {
8161 status = WERR_NOMEM;
8162 goto done;
8165 write_ntforms(&list, count);
8168 * ChangeID must always be set if this is a printer
8171 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8172 status = mod_a_printer(printer, 2);
8174 done:
8175 if ( printer )
8176 free_a_printer(&printer, 2);
8177 SAFE_FREE(list);
8179 return status;
8182 /****************************************************************************
8183 ****************************************************************************/
8185 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8187 POLICY_HND *handle = &q_u->handle;
8188 UNISTR2 *form_name = &q_u->name;
8189 nt_forms_struct tmpForm;
8190 int count=0;
8191 nt_forms_struct *list=NULL;
8192 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8193 int snum;
8194 WERROR status = WERR_OK;
8195 NT_PRINTER_INFO_LEVEL *printer = NULL;
8197 DEBUG(5,("spoolss_deleteform\n"));
8199 if (!Printer) {
8200 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8201 return WERR_BADFID;
8204 /* forms can be deleted on printer of on the print server handle */
8206 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8208 if (!get_printer_snum(p,handle, &snum))
8209 return WERR_BADFID;
8211 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8212 if (!W_ERROR_IS_OK(status))
8213 goto done;
8216 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8217 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8218 status = WERR_ACCESS_DENIED;
8219 goto done;
8222 /* can't delete if builtin */
8224 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8225 status = WERR_INVALID_PARAM;
8226 goto done;
8229 count = get_ntforms(&list);
8231 if ( !delete_a_form(&list, form_name, &count, &status ))
8232 goto done;
8235 * ChangeID must always be set if this is a printer
8238 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8239 status = mod_a_printer(printer, 2);
8241 done:
8242 if ( printer )
8243 free_a_printer(&printer, 2);
8244 SAFE_FREE(list);
8246 return status;
8249 /****************************************************************************
8250 ****************************************************************************/
8252 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8254 POLICY_HND *handle = &q_u->handle;
8255 FORM *form = &q_u->form;
8256 nt_forms_struct tmpForm;
8257 int snum;
8258 WERROR status = WERR_OK;
8259 NT_PRINTER_INFO_LEVEL *printer = NULL;
8261 int count=0;
8262 nt_forms_struct *list=NULL;
8263 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8265 DEBUG(5,("spoolss_setform\n"));
8267 if (!Printer) {
8268 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8269 return WERR_BADFID;
8272 /* forms can be modified on printer of on the print server handle */
8274 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8276 if (!get_printer_snum(p,handle, &snum))
8277 return WERR_BADFID;
8279 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8280 if (!W_ERROR_IS_OK(status))
8281 goto done;
8284 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8285 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8286 status = WERR_ACCESS_DENIED;
8287 goto done;
8290 /* can't set if builtin */
8291 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8292 status = WERR_INVALID_PARAM;
8293 goto done;
8296 count = get_ntforms(&list);
8297 update_a_form(&list, form, count);
8298 write_ntforms(&list, count);
8301 * ChangeID must always be set if this is a printer
8304 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8305 status = mod_a_printer(printer, 2);
8308 done:
8309 if ( printer )
8310 free_a_printer(&printer, 2);
8311 SAFE_FREE(list);
8313 return status;
8316 /****************************************************************************
8317 enumprintprocessors level 1.
8318 ****************************************************************************/
8320 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8322 PRINTPROCESSOR_1 *info_1=NULL;
8323 WERROR result = WERR_OK;
8325 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8326 return WERR_NOMEM;
8328 (*returned) = 0x1;
8330 init_unistr(&info_1->name, "winprint");
8332 *needed += spoolss_size_printprocessor_info_1(info_1);
8334 if (*needed > offered) {
8335 result = WERR_INSUFFICIENT_BUFFER;
8336 goto out;
8339 if (!rpcbuf_alloc_size(buffer, *needed)) {
8340 result = WERR_NOMEM;
8341 goto out;
8344 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8346 out:
8347 SAFE_FREE(info_1);
8349 if ( !W_ERROR_IS_OK(result) )
8350 *returned = 0;
8352 return result;
8355 /****************************************************************************
8356 ****************************************************************************/
8358 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8360 uint32 level = q_u->level;
8361 RPC_BUFFER *buffer = NULL;
8362 uint32 offered = q_u->offered;
8363 uint32 *needed = &r_u->needed;
8364 uint32 *returned = &r_u->returned;
8366 /* that's an [in out] buffer */
8368 if ( q_u->buffer ) {
8369 rpcbuf_move(q_u->buffer, &r_u->buffer);
8370 buffer = r_u->buffer;
8373 DEBUG(5,("spoolss_enumprintprocessors\n"));
8376 * Enumerate the print processors ...
8378 * Just reply with "winprint", to keep NT happy
8379 * and I can use my nice printer checker.
8382 *returned=0;
8383 *needed=0;
8385 switch (level) {
8386 case 1:
8387 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8388 default:
8389 return WERR_UNKNOWN_LEVEL;
8393 /****************************************************************************
8394 enumprintprocdatatypes level 1.
8395 ****************************************************************************/
8397 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8399 PRINTPROCDATATYPE_1 *info_1=NULL;
8400 WERROR result = WERR_NOMEM;
8402 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8403 return WERR_NOMEM;
8405 (*returned) = 0x1;
8407 init_unistr(&info_1->name, "RAW");
8409 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8411 if (*needed > offered) {
8412 result = WERR_INSUFFICIENT_BUFFER;
8413 goto out;
8416 if (!rpcbuf_alloc_size(buffer, *needed)) {
8417 result = WERR_NOMEM;
8418 goto out;
8421 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8423 out:
8424 SAFE_FREE(info_1);
8426 if ( !W_ERROR_IS_OK(result) )
8427 *returned = 0;
8429 return result;
8432 /****************************************************************************
8433 ****************************************************************************/
8435 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8437 uint32 level = q_u->level;
8438 RPC_BUFFER *buffer = NULL;
8439 uint32 offered = q_u->offered;
8440 uint32 *needed = &r_u->needed;
8441 uint32 *returned = &r_u->returned;
8443 /* that's an [in out] buffer */
8445 if ( q_u->buffer ) {
8446 rpcbuf_move(q_u->buffer, &r_u->buffer);
8447 buffer = r_u->buffer;
8450 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8452 *returned=0;
8453 *needed=0;
8455 switch (level) {
8456 case 1:
8457 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8458 default:
8459 return WERR_UNKNOWN_LEVEL;
8463 /****************************************************************************
8464 enumprintmonitors level 1.
8465 ****************************************************************************/
8467 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8469 PRINTMONITOR_1 *info_1=NULL;
8470 WERROR result = WERR_OK;
8472 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8473 return WERR_NOMEM;
8475 (*returned) = 0x1;
8477 init_unistr(&info_1->name, "Local Port");
8479 *needed += spoolss_size_printmonitor_info_1(info_1);
8481 if (*needed > offered) {
8482 result = WERR_INSUFFICIENT_BUFFER;
8483 goto out;
8486 if (!rpcbuf_alloc_size(buffer, *needed)) {
8487 result = WERR_NOMEM;
8488 goto out;
8491 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8493 out:
8494 SAFE_FREE(info_1);
8496 if ( !W_ERROR_IS_OK(result) )
8497 *returned = 0;
8499 return result;
8502 /****************************************************************************
8503 enumprintmonitors level 2.
8504 ****************************************************************************/
8506 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8508 PRINTMONITOR_2 *info_2=NULL;
8509 WERROR result = WERR_OK;
8511 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8512 return WERR_NOMEM;
8514 (*returned) = 0x1;
8516 init_unistr(&info_2->name, "Local Port");
8517 init_unistr(&info_2->environment, "Windows NT X86");
8518 init_unistr(&info_2->dll_name, "localmon.dll");
8520 *needed += spoolss_size_printmonitor_info_2(info_2);
8522 if (*needed > offered) {
8523 result = WERR_INSUFFICIENT_BUFFER;
8524 goto out;
8527 if (!rpcbuf_alloc_size(buffer, *needed)) {
8528 result = WERR_NOMEM;
8529 goto out;
8532 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8534 out:
8535 SAFE_FREE(info_2);
8537 if ( !W_ERROR_IS_OK(result) )
8538 *returned = 0;
8540 return result;
8543 /****************************************************************************
8544 ****************************************************************************/
8546 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8548 uint32 level = q_u->level;
8549 RPC_BUFFER *buffer = NULL;
8550 uint32 offered = q_u->offered;
8551 uint32 *needed = &r_u->needed;
8552 uint32 *returned = &r_u->returned;
8554 /* that's an [in out] buffer */
8556 if ( q_u->buffer ) {
8557 rpcbuf_move(q_u->buffer, &r_u->buffer);
8558 buffer = r_u->buffer;
8561 DEBUG(5,("spoolss_enumprintmonitors\n"));
8564 * Enumerate the print monitors ...
8566 * Just reply with "Local Port", to keep NT happy
8567 * and I can use my nice printer checker.
8570 *returned=0;
8571 *needed=0;
8573 switch (level) {
8574 case 1:
8575 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8576 case 2:
8577 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8578 default:
8579 return WERR_UNKNOWN_LEVEL;
8583 /****************************************************************************
8584 ****************************************************************************/
8586 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8587 NT_PRINTER_INFO_LEVEL *ntprinter,
8588 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8589 uint32 *needed)
8591 int i=0;
8592 BOOL found=False;
8593 JOB_INFO_1 *info_1=NULL;
8594 WERROR result = WERR_OK;
8596 info_1=SMB_MALLOC_P(JOB_INFO_1);
8598 if (info_1 == NULL) {
8599 return WERR_NOMEM;
8602 for (i=0; i<count && found==False; i++) {
8603 if ((*queue)[i].job==(int)jobid)
8604 found=True;
8607 if (found==False) {
8608 SAFE_FREE(info_1);
8609 /* NT treats not found as bad param... yet another bad choice */
8610 return WERR_INVALID_PARAM;
8613 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8615 *needed += spoolss_size_job_info_1(info_1);
8617 if (*needed > offered) {
8618 result = WERR_INSUFFICIENT_BUFFER;
8619 goto out;
8622 if (!rpcbuf_alloc_size(buffer, *needed)) {
8623 result = WERR_NOMEM;
8624 goto out;
8627 smb_io_job_info_1("", buffer, info_1, 0);
8629 out:
8630 SAFE_FREE(info_1);
8632 return result;
8635 /****************************************************************************
8636 ****************************************************************************/
8638 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8639 NT_PRINTER_INFO_LEVEL *ntprinter,
8640 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8641 uint32 *needed)
8643 int i = 0;
8644 BOOL found = False;
8645 JOB_INFO_2 *info_2;
8646 WERROR result;
8647 DEVICEMODE *devmode = NULL;
8648 NT_DEVICEMODE *nt_devmode = NULL;
8650 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8651 return WERR_NOMEM;
8653 ZERO_STRUCTP(info_2);
8655 for ( i=0; i<count && found==False; i++ )
8657 if ((*queue)[i].job == (int)jobid)
8658 found = True;
8661 if ( !found ) {
8662 /* NT treats not found as bad param... yet another bad
8663 choice */
8664 result = WERR_INVALID_PARAM;
8665 goto done;
8669 * if the print job does not have a DEVMODE associated with it,
8670 * just use the one for the printer. A NULL devicemode is not
8671 * a failure condition
8674 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8675 devmode = construct_dev_mode(snum);
8676 else {
8677 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8678 ZERO_STRUCTP( devmode );
8679 convert_nt_devicemode( devmode, nt_devmode );
8683 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8685 *needed += spoolss_size_job_info_2(info_2);
8687 if (*needed > offered) {
8688 result = WERR_INSUFFICIENT_BUFFER;
8689 goto done;
8692 if (!rpcbuf_alloc_size(buffer, *needed)) {
8693 result = WERR_NOMEM;
8694 goto done;
8697 smb_io_job_info_2("", buffer, info_2, 0);
8699 result = WERR_OK;
8701 done:
8702 /* Cleanup allocated memory */
8704 free_job_info_2(info_2); /* Also frees devmode */
8705 SAFE_FREE(info_2);
8707 return result;
8710 /****************************************************************************
8711 ****************************************************************************/
8713 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8715 POLICY_HND *handle = &q_u->handle;
8716 uint32 jobid = q_u->jobid;
8717 uint32 level = q_u->level;
8718 RPC_BUFFER *buffer = NULL;
8719 uint32 offered = q_u->offered;
8720 uint32 *needed = &r_u->needed;
8721 WERROR wstatus = WERR_OK;
8722 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8723 int snum;
8724 int count;
8725 print_queue_struct *queue = NULL;
8726 print_status_struct prt_status;
8728 /* that's an [in out] buffer */
8730 if ( q_u->buffer ) {
8731 rpcbuf_move(q_u->buffer, &r_u->buffer);
8732 buffer = r_u->buffer;
8735 DEBUG(5,("spoolss_getjob\n"));
8737 *needed = 0;
8739 if (!get_printer_snum(p, handle, &snum))
8740 return WERR_BADFID;
8742 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8743 if ( !W_ERROR_IS_OK(wstatus) )
8744 return wstatus;
8746 count = print_queue_status(snum, &queue, &prt_status);
8748 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8749 count, prt_status.status, prt_status.message));
8751 switch ( level ) {
8752 case 1:
8753 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8754 buffer, offered, needed);
8755 break;
8756 case 2:
8757 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8758 buffer, offered, needed);
8759 break;
8760 default:
8761 wstatus = WERR_UNKNOWN_LEVEL;
8762 break;
8765 SAFE_FREE(queue);
8766 free_a_printer( &ntprinter, 2 );
8768 return wstatus;
8771 /********************************************************************
8772 spoolss_getprinterdataex
8774 From MSDN documentation of GetPrinterDataEx: pass request
8775 to GetPrinterData if key is "PrinterDriverData".
8776 ********************************************************************/
8778 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8780 POLICY_HND *handle = &q_u->handle;
8781 uint32 in_size = q_u->size;
8782 uint32 *type = &r_u->type;
8783 uint32 *out_size = &r_u->size;
8784 uint8 **data = &r_u->data;
8785 uint32 *needed = &r_u->needed;
8786 fstring keyname, valuename;
8788 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8790 NT_PRINTER_INFO_LEVEL *printer = NULL;
8791 int snum = 0;
8792 WERROR status = WERR_OK;
8794 DEBUG(4,("_spoolss_getprinterdataex\n"));
8796 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8797 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8799 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8800 keyname, valuename));
8802 /* in case of problem, return some default values */
8804 *needed = 0;
8805 *type = 0;
8806 *out_size = in_size;
8808 if (!Printer) {
8809 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8810 status = WERR_BADFID;
8811 goto done;
8814 /* Is the handle to a printer or to the server? */
8816 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8817 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8818 status = WERR_INVALID_PARAM;
8819 goto done;
8822 if ( !get_printer_snum(p,handle, &snum) )
8823 return WERR_BADFID;
8825 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8826 if ( !W_ERROR_IS_OK(status) )
8827 goto done;
8829 /* check to see if the keyname is valid */
8830 if ( !strlen(keyname) ) {
8831 status = WERR_INVALID_PARAM;
8832 goto done;
8835 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8836 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8837 free_a_printer( &printer, 2 );
8838 status = WERR_BADFILE;
8839 goto done;
8842 /* When given a new keyname, we should just create it */
8844 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8846 if (*needed > *out_size)
8847 status = WERR_MORE_DATA;
8849 done:
8850 if ( !W_ERROR_IS_OK(status) )
8852 DEBUG(5, ("error: allocating %d\n", *out_size));
8854 /* reply this param doesn't exist */
8856 if ( *out_size )
8858 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8859 status = WERR_NOMEM;
8860 goto done;
8863 else {
8864 *data = NULL;
8868 if ( printer )
8869 free_a_printer( &printer, 2 );
8871 return status;
8874 /********************************************************************
8875 * spoolss_setprinterdataex
8876 ********************************************************************/
8878 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8880 POLICY_HND *handle = &q_u->handle;
8881 uint32 type = q_u->type;
8882 uint8 *data = q_u->data;
8883 uint32 real_len = q_u->real_len;
8885 NT_PRINTER_INFO_LEVEL *printer = NULL;
8886 int snum = 0;
8887 WERROR status = WERR_OK;
8888 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8889 fstring valuename;
8890 fstring keyname;
8891 char *oid_string;
8893 DEBUG(4,("_spoolss_setprinterdataex\n"));
8895 /* From MSDN documentation of SetPrinterDataEx: pass request to
8896 SetPrinterData if key is "PrinterDriverData" */
8898 if (!Printer) {
8899 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8900 return WERR_BADFID;
8903 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8904 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8905 return WERR_INVALID_PARAM;
8908 if ( !get_printer_snum(p,handle, &snum) )
8909 return WERR_BADFID;
8912 * Access check : NT returns "access denied" if you make a
8913 * SetPrinterData call without the necessary privildge.
8914 * we were originally returning OK if nothing changed
8915 * which made Win2k issue **a lot** of SetPrinterData
8916 * when connecting to a printer --jerry
8919 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8921 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8922 return WERR_ACCESS_DENIED;
8925 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8926 if (!W_ERROR_IS_OK(status))
8927 return status;
8929 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8930 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8932 /* check for OID in valuename */
8934 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8936 *oid_string = '\0';
8937 oid_string++;
8940 /* save the registry data */
8942 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8944 if ( W_ERROR_IS_OK(status) )
8946 /* save the OID if one was specified */
8947 if ( oid_string ) {
8948 fstrcat( keyname, "\\" );
8949 fstrcat( keyname, SPOOL_OID_KEY );
8952 * I'm not checking the status here on purpose. Don't know
8953 * if this is right, but I'm returning the status from the
8954 * previous set_printer_dataex() call. I have no idea if
8955 * this is right. --jerry
8958 set_printer_dataex( printer, keyname, valuename,
8959 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8962 status = mod_a_printer(printer, 2);
8965 free_a_printer(&printer, 2);
8967 return status;
8971 /********************************************************************
8972 * spoolss_deleteprinterdataex
8973 ********************************************************************/
8975 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8977 POLICY_HND *handle = &q_u->handle;
8978 UNISTR2 *value = &q_u->valuename;
8979 UNISTR2 *key = &q_u->keyname;
8981 NT_PRINTER_INFO_LEVEL *printer = NULL;
8982 int snum=0;
8983 WERROR status = WERR_OK;
8984 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8985 pstring valuename, keyname;
8987 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8989 if (!Printer) {
8990 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8991 return WERR_BADFID;
8994 if (!get_printer_snum(p, handle, &snum))
8995 return WERR_BADFID;
8997 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8998 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8999 return WERR_ACCESS_DENIED;
9002 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9003 if (!W_ERROR_IS_OK(status))
9004 return status;
9006 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9007 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9009 status = delete_printer_dataex( printer, keyname, valuename );
9011 if ( W_ERROR_IS_OK(status) )
9012 mod_a_printer( printer, 2 );
9014 free_a_printer(&printer, 2);
9016 return status;
9019 /********************************************************************
9020 * spoolss_enumprinterkey
9021 ********************************************************************/
9024 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9026 fstring key;
9027 fstring *keynames = NULL;
9028 uint16 *enumkeys = NULL;
9029 int num_keys;
9030 int printerkey_len;
9031 POLICY_HND *handle = &q_u->handle;
9032 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9033 NT_PRINTER_DATA *data;
9034 NT_PRINTER_INFO_LEVEL *printer = NULL;
9035 int snum = 0;
9036 WERROR status = WERR_BADFILE;
9039 DEBUG(4,("_spoolss_enumprinterkey\n"));
9041 if (!Printer) {
9042 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9043 return WERR_BADFID;
9046 if ( !get_printer_snum(p,handle, &snum) )
9047 return WERR_BADFID;
9049 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9050 if (!W_ERROR_IS_OK(status))
9051 return status;
9053 /* get the list of subkey names */
9055 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9056 data = printer->info_2->data;
9058 num_keys = get_printer_subkeys( data, key, &keynames );
9060 if ( num_keys == -1 ) {
9061 status = WERR_BADFILE;
9062 goto done;
9065 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9067 r_u->needed = printerkey_len*2;
9069 if ( q_u->size < r_u->needed ) {
9070 status = WERR_MORE_DATA;
9071 goto done;
9074 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9075 status = WERR_NOMEM;
9076 goto done;
9079 status = WERR_OK;
9081 if ( q_u->size < r_u->needed )
9082 status = WERR_MORE_DATA;
9084 done:
9085 free_a_printer( &printer, 2 );
9086 SAFE_FREE( keynames );
9088 return status;
9091 /********************************************************************
9092 * spoolss_deleteprinterkey
9093 ********************************************************************/
9095 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9097 POLICY_HND *handle = &q_u->handle;
9098 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9099 fstring key;
9100 NT_PRINTER_INFO_LEVEL *printer = NULL;
9101 int snum=0;
9102 WERROR status;
9104 DEBUG(5,("spoolss_deleteprinterkey\n"));
9106 if (!Printer) {
9107 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9108 return WERR_BADFID;
9111 /* if keyname == NULL, return error */
9113 if ( !q_u->keyname.buffer )
9114 return WERR_INVALID_PARAM;
9116 if (!get_printer_snum(p, handle, &snum))
9117 return WERR_BADFID;
9119 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9120 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9121 return WERR_ACCESS_DENIED;
9124 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9125 if (!W_ERROR_IS_OK(status))
9126 return status;
9128 /* delete the key and all subneys */
9130 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9132 status = delete_all_printer_data( printer->info_2, key );
9134 if ( W_ERROR_IS_OK(status) )
9135 status = mod_a_printer(printer, 2);
9137 free_a_printer( &printer, 2 );
9139 return status;
9143 /********************************************************************
9144 * spoolss_enumprinterdataex
9145 ********************************************************************/
9147 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9149 POLICY_HND *handle = &q_u->handle;
9150 uint32 in_size = q_u->size;
9151 uint32 num_entries,
9152 needed;
9153 NT_PRINTER_INFO_LEVEL *printer = NULL;
9154 PRINTER_ENUM_VALUES *enum_values = NULL;
9155 NT_PRINTER_DATA *p_data;
9156 fstring key;
9157 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9158 int snum;
9159 WERROR result;
9160 int key_index;
9161 int i;
9162 REGISTRY_VALUE *val;
9163 char *value_name;
9164 uint32 data_len;
9167 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9169 if (!Printer) {
9170 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9171 return WERR_BADFID;
9175 * first check for a keyname of NULL or "". Win2k seems to send
9176 * this a lot and we should send back WERR_INVALID_PARAM
9177 * no need to spend time looking up the printer in this case.
9178 * --jerry
9181 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9182 if ( !strlen(key) ) {
9183 result = WERR_INVALID_PARAM;
9184 goto done;
9187 /* get the printer off of disk */
9189 if (!get_printer_snum(p,handle, &snum))
9190 return WERR_BADFID;
9192 ZERO_STRUCT(printer);
9193 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9194 if (!W_ERROR_IS_OK(result))
9195 return result;
9197 /* now look for a match on the key name */
9199 p_data = printer->info_2->data;
9201 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9202 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9204 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9205 result = WERR_INVALID_PARAM;
9206 goto done;
9209 result = WERR_OK;
9210 needed = 0;
9212 /* allocate the memory for the array of pointers -- if necessary */
9214 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9215 if ( num_entries )
9217 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9219 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9220 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9221 result = WERR_NOMEM;
9222 goto done;
9225 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9229 * loop through all params and build the array to pass
9230 * back to the client
9233 for ( i=0; i<num_entries; i++ )
9235 /* lookup the registry value */
9237 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9238 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9240 /* copy the data */
9242 value_name = regval_name( val );
9243 init_unistr( &enum_values[i].valuename, value_name );
9244 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9245 enum_values[i].type = regval_type( val );
9247 data_len = regval_size( val );
9248 if ( data_len ) {
9249 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9251 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9252 data_len ));
9253 result = WERR_NOMEM;
9254 goto done;
9257 enum_values[i].data_len = data_len;
9259 /* keep track of the size of the array in bytes */
9261 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9264 /* housekeeping information in the reply */
9266 r_u->needed = needed;
9267 r_u->returned = num_entries;
9269 if (needed > in_size) {
9270 result = WERR_MORE_DATA;
9271 goto done;
9274 /* copy data into the reply */
9276 r_u->ctr.size = r_u->needed;
9277 r_u->ctr.size_of_array = r_u->returned;
9278 r_u->ctr.values = enum_values;
9282 done:
9283 if ( printer )
9284 free_a_printer(&printer, 2);
9286 return result;
9289 /****************************************************************************
9290 ****************************************************************************/
9292 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9294 init_unistr(&info->name, name);
9297 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9298 UNISTR2 *environment,
9299 RPC_BUFFER *buffer,
9300 uint32 offered,
9301 uint32 *needed)
9303 pstring path;
9304 pstring long_archi;
9305 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9306 WERROR result = WERR_OK;
9308 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9310 if (!get_short_archi(long_archi))
9311 return WERR_INVALID_ENVIRONMENT;
9313 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9314 return WERR_NOMEM;
9316 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9318 fill_printprocessordirectory_1(info, path);
9320 *needed += spoolss_size_printprocessordirectory_info_1(info);
9322 if (*needed > offered) {
9323 result = WERR_INSUFFICIENT_BUFFER;
9324 goto out;
9327 if (!rpcbuf_alloc_size(buffer, *needed)) {
9328 result = WERR_INSUFFICIENT_BUFFER;
9329 goto out;
9332 smb_io_printprocessordirectory_1("", buffer, info, 0);
9334 out:
9335 SAFE_FREE(info);
9337 return result;
9340 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9342 uint32 level = q_u->level;
9343 RPC_BUFFER *buffer = NULL;
9344 uint32 offered = q_u->offered;
9345 uint32 *needed = &r_u->needed;
9346 WERROR result;
9348 /* that's an [in out] buffer */
9350 if ( q_u->buffer ) {
9351 rpcbuf_move(q_u->buffer, &r_u->buffer);
9352 buffer = r_u->buffer;
9355 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9357 *needed=0;
9359 switch(level) {
9360 case 1:
9361 result = getprintprocessordirectory_level_1
9362 (&q_u->name, &q_u->environment, buffer, offered, needed);
9363 break;
9364 default:
9365 result = WERR_UNKNOWN_LEVEL;
9368 return result;
9371 #if 0
9373 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9374 SPOOL_R_REPLYOPENPRINTER *r_u)
9376 DEBUG(5,("_spoolss_replyopenprinter\n"));
9378 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9380 return WERR_OK;
9383 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9384 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9386 DEBUG(5,("_spoolss_replycloseprinter\n"));
9387 return WERR_OK;
9390 #endif