r13547: add earlier checks to deny deleting a printer driver. The previous
[Samba/gbeck.git] / source / rpc_server / srv_spoolss_nt.c
blobc767daf88caf3aebb8f71bf0c88e020b041368b1
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 **)(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.ut.uid != 0) &&
1624 !user_has_privileges(user.nt_user_token,
1625 &se_printop ) &&
1626 !token_contains_name_in_list(
1627 uidtoname(user.ut.uid), NULL,
1628 user.nt_user_token,
1629 lp_printer_admin(snum))) {
1630 close_printer_handle(p, handle);
1631 return WERR_ACCESS_DENIED;
1634 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1636 else
1638 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1641 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1642 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1644 /* We fall through to return WERR_OK */
1647 else
1649 /* NT doesn't let us connect to a printer if the connecting user
1650 doesn't have print permission. */
1652 if (!get_printer_snum(p, handle, &snum)) {
1653 close_printer_handle(p, handle);
1654 return WERR_BADFID;
1657 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1659 /* map an empty access mask to the minimum access mask */
1660 if (printer_default->access_required == 0x0)
1661 printer_default->access_required = PRINTER_ACCESS_USE;
1664 * If we are not serving the printer driver for this printer,
1665 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1666 * will keep NT clients happy --jerry
1669 if (lp_use_client_driver(snum)
1670 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1672 printer_default->access_required = PRINTER_ACCESS_USE;
1675 /* check smb.conf parameters and the the sec_desc */
1677 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1678 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1679 return WERR_ACCESS_DENIED;
1682 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1683 snum) ||
1684 !print_access_check(&user, snum,
1685 printer_default->access_required)) {
1686 DEBUG(3, ("access DENIED for printer open\n"));
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1692 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1693 close_printer_handle(p, handle);
1694 return WERR_ACCESS_DENIED;
1697 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1698 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1699 else
1700 printer_default->access_required = PRINTER_ACCESS_USE;
1702 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1703 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1707 Printer->access_granted = printer_default->access_required;
1710 * If the client sent a devmode in the OpenPrinter() call, then
1711 * save it here in case we get a job submission on this handle
1714 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1715 && q_u->printer_default.devmode_cont.devmode_ptr )
1717 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1718 &Printer->nt_devmode );
1721 #if 0 /* JERRY -- I'm doubtful this is really effective */
1722 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1723 optimization in Windows 2000 clients --jerry */
1725 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1726 && (RA_WIN2K == get_remote_arch()) )
1728 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1729 sys_usleep( 500000 );
1731 #endif
1733 return WERR_OK;
1736 /****************************************************************************
1737 ****************************************************************************/
1739 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1740 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1742 BOOL ret;
1744 switch (level) {
1745 case 2:
1746 /* allocate memory if needed. Messy because
1747 convert_printer_info is used to update an existing
1748 printer or build a new one */
1750 if ( !printer->info_2 ) {
1751 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1752 if ( !printer->info_2 ) {
1753 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1754 return False;
1758 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1759 printer->info_2->setuptime = time(NULL);
1761 return ret;
1764 return False;
1767 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1768 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1770 BOOL result = True;
1772 switch (level) {
1773 case 3:
1774 printer->info_3=NULL;
1775 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1776 result = False;
1777 break;
1778 case 6:
1779 printer->info_6=NULL;
1780 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1781 result = False;
1782 break;
1783 default:
1784 break;
1787 return result;
1790 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1791 NT_DEVICEMODE **pp_nt_devmode)
1793 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1796 * Ensure nt_devmode is a valid pointer
1797 * as we will be overwriting it.
1800 if (nt_devmode == NULL) {
1801 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1802 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1803 return False;
1806 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1807 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1809 nt_devmode->specversion=devmode->specversion;
1810 nt_devmode->driverversion=devmode->driverversion;
1811 nt_devmode->size=devmode->size;
1812 nt_devmode->fields=devmode->fields;
1813 nt_devmode->orientation=devmode->orientation;
1814 nt_devmode->papersize=devmode->papersize;
1815 nt_devmode->paperlength=devmode->paperlength;
1816 nt_devmode->paperwidth=devmode->paperwidth;
1817 nt_devmode->scale=devmode->scale;
1818 nt_devmode->copies=devmode->copies;
1819 nt_devmode->defaultsource=devmode->defaultsource;
1820 nt_devmode->printquality=devmode->printquality;
1821 nt_devmode->color=devmode->color;
1822 nt_devmode->duplex=devmode->duplex;
1823 nt_devmode->yresolution=devmode->yresolution;
1824 nt_devmode->ttoption=devmode->ttoption;
1825 nt_devmode->collate=devmode->collate;
1827 nt_devmode->logpixels=devmode->logpixels;
1828 nt_devmode->bitsperpel=devmode->bitsperpel;
1829 nt_devmode->pelswidth=devmode->pelswidth;
1830 nt_devmode->pelsheight=devmode->pelsheight;
1831 nt_devmode->displayflags=devmode->displayflags;
1832 nt_devmode->displayfrequency=devmode->displayfrequency;
1833 nt_devmode->icmmethod=devmode->icmmethod;
1834 nt_devmode->icmintent=devmode->icmintent;
1835 nt_devmode->mediatype=devmode->mediatype;
1836 nt_devmode->dithertype=devmode->dithertype;
1837 nt_devmode->reserved1=devmode->reserved1;
1838 nt_devmode->reserved2=devmode->reserved2;
1839 nt_devmode->panningwidth=devmode->panningwidth;
1840 nt_devmode->panningheight=devmode->panningheight;
1843 * Only change private and driverextra if the incoming devmode
1844 * has a new one. JRA.
1847 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1848 SAFE_FREE(nt_devmode->nt_dev_private);
1849 nt_devmode->driverextra=devmode->driverextra;
1850 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1851 return False;
1852 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1855 *pp_nt_devmode = nt_devmode;
1857 return True;
1860 /********************************************************************
1861 * _spoolss_enddocprinter_internal.
1862 ********************************************************************/
1864 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1866 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1867 int snum;
1869 if (!Printer) {
1870 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1871 return WERR_BADFID;
1874 if (!get_printer_snum(p, handle, &snum))
1875 return WERR_BADFID;
1877 Printer->document_started=False;
1878 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1879 /* error codes unhandled so far ... */
1881 return WERR_OK;
1884 /********************************************************************
1885 * api_spoolss_closeprinter
1886 ********************************************************************/
1888 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1890 POLICY_HND *handle = &q_u->handle;
1892 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1894 if (Printer && Printer->document_started)
1895 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1897 if (!close_printer_handle(p, handle))
1898 return WERR_BADFID;
1900 /* clear the returned printer handle. Observed behavior
1901 from Win2k server. Don't think this really matters.
1902 Previous code just copied the value of the closed
1903 handle. --jerry */
1905 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1907 return WERR_OK;
1910 /********************************************************************
1911 * api_spoolss_deleteprinter
1913 ********************************************************************/
1915 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1917 POLICY_HND *handle = &q_u->handle;
1918 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1919 WERROR result;
1921 if (Printer && Printer->document_started)
1922 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1924 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1926 result = delete_printer_handle(p, handle);
1928 update_c_setprinter(False);
1930 return result;
1933 /*******************************************************************
1934 * static function to lookup the version id corresponding to an
1935 * long architecture string
1936 ******************************************************************/
1938 static int get_version_id (char * arch)
1940 int i;
1941 struct table_node archi_table[]= {
1943 {"Windows 4.0", "WIN40", 0 },
1944 {"Windows NT x86", "W32X86", 2 },
1945 {"Windows NT R4000", "W32MIPS", 2 },
1946 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1947 {"Windows NT PowerPC", "W32PPC", 2 },
1948 {"Windows IA64", "IA64", 3 },
1949 {"Windows x64", "x64", 3 },
1950 {NULL, "", -1 }
1953 for (i=0; archi_table[i].long_archi != NULL; i++)
1955 if (strcmp(arch, archi_table[i].long_archi) == 0)
1956 return (archi_table[i].version);
1959 return -1;
1962 /********************************************************************
1963 * _spoolss_deleteprinterdriver
1964 ********************************************************************/
1966 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1968 fstring driver;
1969 fstring arch;
1970 NT_PRINTER_DRIVER_INFO_LEVEL info;
1971 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1972 int version;
1973 struct current_user user;
1974 WERROR status;
1975 WERROR status_win2k = WERR_ACCESS_DENIED;
1976 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1978 get_current_user(&user, p);
1980 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1981 and not a printer admin, then fail */
1983 if ( (user.ut.uid != 0)
1984 && !user_has_privileges(user.nt_user_token, &se_printop )
1985 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1986 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1988 return WERR_ACCESS_DENIED;
1991 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1992 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1994 /* check that we have a valid driver name first */
1996 if ((version=get_version_id(arch)) == -1)
1997 return WERR_INVALID_ENVIRONMENT;
1999 ZERO_STRUCT(info);
2000 ZERO_STRUCT(info_win2k);
2002 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2004 /* try for Win2k driver if "Windows NT x86" */
2006 if ( version == 2 ) {
2007 version = 3;
2008 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2009 status = WERR_UNKNOWN_PRINTER_DRIVER;
2010 goto done;
2013 /* otherwise it was a failure */
2014 else {
2015 status = WERR_UNKNOWN_PRINTER_DRIVER;
2016 goto done;
2021 if (printer_driver_in_use(info.info_3)) {
2022 status = WERR_PRINTER_DRIVER_IN_USE;
2023 goto done;
2026 if ( version == 2 )
2028 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2030 /* if we get to here, we now have 2 driver info structures to remove */
2031 /* remove the Win2k driver first*/
2033 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2034 free_a_printer_driver( info_win2k, 3 );
2036 /* this should not have failed---if it did, report to client */
2037 if ( !W_ERROR_IS_OK(status_win2k) )
2039 status = status_win2k;
2040 goto done;
2045 status = delete_printer_driver(info.info_3, &user, version, False);
2047 /* if at least one of the deletes succeeded return OK */
2049 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2050 status = WERR_OK;
2052 done:
2053 free_a_printer_driver( info, 3 );
2055 return status;
2058 /********************************************************************
2059 * spoolss_deleteprinterdriverex
2060 ********************************************************************/
2062 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2064 fstring driver;
2065 fstring arch;
2066 NT_PRINTER_DRIVER_INFO_LEVEL info;
2067 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2068 int version;
2069 uint32 flags = q_u->delete_flags;
2070 BOOL delete_files;
2071 struct current_user user;
2072 WERROR status;
2073 WERROR status_win2k = WERR_ACCESS_DENIED;
2074 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2076 get_current_user(&user, p);
2078 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2079 and not a printer admin, then fail */
2081 if ( (user.ut.uid != 0)
2082 && !user_has_privileges(user.nt_user_token, &se_printop )
2083 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2084 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2086 return WERR_ACCESS_DENIED;
2089 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2090 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2092 /* check that we have a valid driver name first */
2093 if ((version=get_version_id(arch)) == -1) {
2094 /* this is what NT returns */
2095 return WERR_INVALID_ENVIRONMENT;
2098 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2099 version = q_u->version;
2101 ZERO_STRUCT(info);
2102 ZERO_STRUCT(info_win2k);
2104 status = get_a_printer_driver(&info, 3, driver, arch, version);
2106 if ( !W_ERROR_IS_OK(status) )
2109 * if the client asked for a specific version,
2110 * or this is something other than Windows NT x86,
2111 * then we've failed
2114 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2115 goto done;
2117 /* try for Win2k driver if "Windows NT x86" */
2119 version = 3;
2120 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2121 status = WERR_UNKNOWN_PRINTER_DRIVER;
2122 goto done;
2126 if ( printer_driver_in_use(info.info_3) ) {
2127 status = WERR_PRINTER_DRIVER_IN_USE;
2128 goto done;
2132 * we have a couple of cases to consider.
2133 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2134 * then the delete should fail if **any** files overlap with
2135 * other drivers
2136 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2137 * non-overlapping files
2138 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2139 * is set, the do not delete any files
2140 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2143 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2145 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2147 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2148 /* no idea of the correct error here */
2149 status = WERR_ACCESS_DENIED;
2150 goto done;
2154 /* also check for W32X86/3 if necessary; maybe we already have? */
2156 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2157 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2160 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2161 /* no idea of the correct error here */
2162 free_a_printer_driver( info_win2k, 3 );
2163 status = WERR_ACCESS_DENIED;
2164 goto done;
2167 /* if we get to here, we now have 2 driver info structures to remove */
2168 /* remove the Win2k driver first*/
2170 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2171 free_a_printer_driver( info_win2k, 3 );
2173 /* this should not have failed---if it did, report to client */
2175 if ( !W_ERROR_IS_OK(status_win2k) )
2176 goto done;
2180 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2182 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2183 status = WERR_OK;
2184 done:
2185 free_a_printer_driver( info, 3 );
2187 return status;
2191 /****************************************************************************
2192 Internal routine for retreiving printerdata
2193 ***************************************************************************/
2195 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2196 const char *key, const char *value, uint32 *type, uint8 **data,
2197 uint32 *needed, uint32 in_size )
2199 REGISTRY_VALUE *val;
2200 uint32 size;
2201 int data_len;
2203 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2204 return WERR_BADFILE;
2206 *type = regval_type( val );
2208 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2210 size = regval_size( val );
2212 /* copy the min(in_size, len) */
2214 if ( in_size ) {
2215 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2217 /* special case for 0 length values */
2218 if ( data_len ) {
2219 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2220 return WERR_NOMEM;
2222 else {
2223 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2224 return WERR_NOMEM;
2227 else
2228 *data = NULL;
2230 *needed = size;
2232 DEBUG(5,("get_printer_dataex: copy done\n"));
2234 return WERR_OK;
2237 /****************************************************************************
2238 Internal routine for removing printerdata
2239 ***************************************************************************/
2241 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2243 return delete_printer_data( printer->info_2, key, value );
2246 /****************************************************************************
2247 Internal routine for storing printerdata
2248 ***************************************************************************/
2250 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2251 uint32 type, uint8 *data, int real_len )
2253 /* the registry objects enforce uniqueness based on value name */
2255 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2258 /********************************************************************
2259 GetPrinterData on a printer server Handle.
2260 ********************************************************************/
2262 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2264 int i;
2266 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2268 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2269 *type = REG_DWORD;
2270 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2271 return WERR_NOMEM;
2272 *needed = 0x4;
2273 return WERR_OK;
2276 if (!StrCaseCmp(value, "BeepEnabled")) {
2277 *type = REG_DWORD;
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2279 return WERR_NOMEM;
2280 SIVAL(*data, 0, 0x00);
2281 *needed = 0x4;
2282 return WERR_OK;
2285 if (!StrCaseCmp(value, "EventLog")) {
2286 *type = REG_DWORD;
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2288 return WERR_NOMEM;
2289 /* formally was 0x1b */
2290 SIVAL(*data, 0, 0x0);
2291 *needed = 0x4;
2292 return WERR_OK;
2295 if (!StrCaseCmp(value, "NetPopup")) {
2296 *type = REG_DWORD;
2297 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2298 return WERR_NOMEM;
2299 SIVAL(*data, 0, 0x00);
2300 *needed = 0x4;
2301 return WERR_OK;
2304 if (!StrCaseCmp(value, "MajorVersion")) {
2305 *type = REG_DWORD;
2306 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2307 return WERR_NOMEM;
2309 /* Windows NT 4.0 seems to not allow uploading of drivers
2310 to a server that reports 0x3 as the MajorVersion.
2311 need to investigate more how Win2k gets around this .
2312 -- jerry */
2314 if ( RA_WINNT == get_remote_arch() )
2315 SIVAL(*data, 0, 2);
2316 else
2317 SIVAL(*data, 0, 3);
2319 *needed = 0x4;
2320 return WERR_OK;
2323 if (!StrCaseCmp(value, "MinorVersion")) {
2324 *type = REG_DWORD;
2325 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2326 return WERR_NOMEM;
2327 SIVAL(*data, 0, 0);
2328 *needed = 0x4;
2329 return WERR_OK;
2332 /* REG_BINARY
2333 * uint32 size = 0x114
2334 * uint32 major = 5
2335 * uint32 minor = [0|1]
2336 * uint32 build = [2195|2600]
2337 * extra unicode string = e.g. "Service Pack 3"
2339 if (!StrCaseCmp(value, "OSVersion")) {
2340 *type = REG_BINARY;
2341 *needed = 0x114;
2343 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2344 return WERR_NOMEM;
2346 SIVAL(*data, 0, *needed); /* size */
2347 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2348 SIVAL(*data, 8, 0);
2349 SIVAL(*data, 12, 2195); /* build */
2351 /* leave extra string empty */
2353 return WERR_OK;
2357 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2358 const char *string="C:\\PRINTERS";
2359 *type = REG_SZ;
2360 *needed = 2*(strlen(string)+1);
2361 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2362 return WERR_NOMEM;
2363 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2365 /* it's done by hand ready to go on the wire */
2366 for (i=0; i<strlen(string); i++) {
2367 (*data)[2*i]=string[i];
2368 (*data)[2*i+1]='\0';
2370 return WERR_OK;
2373 if (!StrCaseCmp(value, "Architecture")) {
2374 const char *string="Windows NT x86";
2375 *type = REG_SZ;
2376 *needed = 2*(strlen(string)+1);
2377 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2378 return WERR_NOMEM;
2379 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2380 for (i=0; i<strlen(string); i++) {
2381 (*data)[2*i]=string[i];
2382 (*data)[2*i+1]='\0';
2384 return WERR_OK;
2387 if (!StrCaseCmp(value, "DsPresent")) {
2388 *type = REG_DWORD;
2389 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2390 return WERR_NOMEM;
2392 /* only show the publish check box if we are a
2393 memeber of a AD domain */
2395 if ( lp_security() == SEC_ADS )
2396 SIVAL(*data, 0, 0x01);
2397 else
2398 SIVAL(*data, 0, 0x00);
2400 *needed = 0x4;
2401 return WERR_OK;
2404 if (!StrCaseCmp(value, "DNSMachineName")) {
2405 pstring hostname;
2407 if (!get_mydnsfullname(hostname))
2408 return WERR_BADFILE;
2409 *type = REG_SZ;
2410 *needed = 2*(strlen(hostname)+1);
2411 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2412 return WERR_NOMEM;
2413 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2414 for (i=0; i<strlen(hostname); i++) {
2415 (*data)[2*i]=hostname[i];
2416 (*data)[2*i+1]='\0';
2418 return WERR_OK;
2422 return WERR_BADFILE;
2425 /********************************************************************
2426 * spoolss_getprinterdata
2427 ********************************************************************/
2429 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2431 POLICY_HND *handle = &q_u->handle;
2432 UNISTR2 *valuename = &q_u->valuename;
2433 uint32 in_size = q_u->size;
2434 uint32 *type = &r_u->type;
2435 uint32 *out_size = &r_u->size;
2436 uint8 **data = &r_u->data;
2437 uint32 *needed = &r_u->needed;
2438 WERROR status;
2439 fstring value;
2440 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2441 NT_PRINTER_INFO_LEVEL *printer = NULL;
2442 int snum = 0;
2445 * Reminder: when it's a string, the length is in BYTES
2446 * even if UNICODE is negociated.
2448 * JFM, 4/19/1999
2451 *out_size = in_size;
2453 /* in case of problem, return some default values */
2455 *needed = 0;
2456 *type = 0;
2458 DEBUG(4,("_spoolss_getprinterdata\n"));
2460 if ( !Printer ) {
2461 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2462 status = WERR_BADFID;
2463 goto done;
2466 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2468 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2469 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2470 else
2472 if ( !get_printer_snum(p,handle, &snum) ) {
2473 status = WERR_BADFID;
2474 goto done;
2477 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2478 if ( !W_ERROR_IS_OK(status) )
2479 goto done;
2481 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2483 if ( strequal(value, "ChangeId") ) {
2484 *type = REG_DWORD;
2485 *needed = sizeof(uint32);
2486 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2487 status = WERR_NOMEM;
2488 goto done;
2490 SIVAL( *data, 0, printer->info_2->changeid );
2491 status = WERR_OK;
2493 else
2494 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2497 if (*needed > *out_size)
2498 status = WERR_MORE_DATA;
2500 done:
2501 if ( !W_ERROR_IS_OK(status) )
2503 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2505 /* reply this param doesn't exist */
2507 if ( *out_size ) {
2508 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2509 if ( printer )
2510 free_a_printer( &printer, 2 );
2511 return WERR_NOMEM;
2514 else {
2515 *data = NULL;
2519 /* cleanup & exit */
2521 if ( printer )
2522 free_a_printer( &printer, 2 );
2524 return status;
2527 /*********************************************************
2528 Connect to the client machine.
2529 **********************************************************/
2531 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2532 struct in_addr *client_ip, const char *remote_machine)
2534 NTSTATUS ret;
2535 struct cli_state *the_cli;
2536 struct in_addr rm_addr;
2538 if ( is_zero_ip(*client_ip) ) {
2539 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2540 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2541 return False;
2544 if ( ismyip( rm_addr )) {
2545 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2546 return False;
2548 } else {
2549 rm_addr.s_addr = client_ip->s_addr;
2550 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2551 inet_ntoa(*client_ip) ));
2554 /* setup the connection */
2556 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2557 &rm_addr, 0, "IPC$", "IPC",
2558 "", /* username */
2559 "", /* domain */
2560 "", /* password */
2561 0, lp_client_signing(), NULL );
2563 if ( !NT_STATUS_IS_OK( ret ) ) {
2564 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2565 remote_machine ));
2566 return False;
2569 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2570 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2571 cli_shutdown(the_cli);
2572 return False;
2576 * Ok - we have an anonymous connection to the IPC$ share.
2577 * Now start the NT Domain stuff :-).
2580 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2581 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2582 remote_machine, nt_errstr(ret)));
2583 cli_shutdown(the_cli);
2584 return False;
2587 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2589 (*pp_pipe)->cli = the_cli;
2591 return True;
2594 /***************************************************************************
2595 Connect to the client.
2596 ****************************************************************************/
2598 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2599 uint32 localprinter, uint32 type,
2600 POLICY_HND *handle, struct in_addr *client_ip)
2602 WERROR result;
2605 * If it's the first connection, contact the client
2606 * and connect to the IPC$ share anonymously
2608 if (smb_connections==0) {
2609 fstring unix_printer;
2611 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2613 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2614 return False;
2616 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2617 /* Tell the connections db we're now interested in printer
2618 * notify messages. */
2619 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2623 * Tell the specific printing tdb we want messages for this printer
2624 * by registering our PID.
2627 if (!print_notify_register_pid(snum))
2628 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2630 smb_connections++;
2632 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2633 type, handle);
2635 if (!W_ERROR_IS_OK(result))
2636 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2637 dos_errstr(result)));
2639 return (W_ERROR_IS_OK(result));
2642 /********************************************************************
2643 * _spoolss_rffpcnex
2644 * ReplyFindFirstPrinterChangeNotifyEx
2646 * before replying OK: status=0 a rpc call is made to the workstation
2647 * asking ReplyOpenPrinter
2649 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2650 * called from api_spoolss_rffpcnex
2651 ********************************************************************/
2653 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2655 POLICY_HND *handle = &q_u->handle;
2656 uint32 flags = q_u->flags;
2657 uint32 options = q_u->options;
2658 UNISTR2 *localmachine = &q_u->localmachine;
2659 uint32 printerlocal = q_u->printerlocal;
2660 int snum = -1;
2661 SPOOL_NOTIFY_OPTION *option = q_u->option;
2662 struct in_addr client_ip;
2664 /* store the notify value in the printer struct */
2666 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2668 if (!Printer) {
2669 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2670 return WERR_BADFID;
2673 Printer->notify.flags=flags;
2674 Printer->notify.options=options;
2675 Printer->notify.printerlocal=printerlocal;
2677 if (Printer->notify.option)
2678 free_spool_notify_option(&Printer->notify.option);
2680 Printer->notify.option=dup_spool_notify_option(option);
2682 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2683 sizeof(Printer->notify.localmachine)-1);
2685 /* Connect to the client machine and send a ReplyOpenPrinter */
2687 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2688 snum = -1;
2689 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2690 !get_printer_snum(p, handle, &snum) )
2691 return WERR_BADFID;
2693 client_ip.s_addr = inet_addr(p->conn->client_address);
2695 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2696 Printer->notify.printerlocal, 1,
2697 &Printer->notify.client_hnd, &client_ip))
2698 return WERR_SERVER_UNAVAILABLE;
2700 Printer->notify.client_connected=True;
2702 return WERR_OK;
2705 /*******************************************************************
2706 * fill a notify_info_data with the servername
2707 ********************************************************************/
2709 void spoolss_notify_server_name(int snum,
2710 SPOOL_NOTIFY_INFO_DATA *data,
2711 print_queue_struct *queue,
2712 NT_PRINTER_INFO_LEVEL *printer,
2713 TALLOC_CTX *mem_ctx)
2715 pstring temp;
2716 uint32 len;
2718 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2720 data->notify_data.data.length = len;
2721 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2723 if (!data->notify_data.data.string) {
2724 data->notify_data.data.length = 0;
2725 return;
2728 memcpy(data->notify_data.data.string, temp, len);
2731 /*******************************************************************
2732 * fill a notify_info_data with the printername (not including the servername).
2733 ********************************************************************/
2735 void spoolss_notify_printer_name(int snum,
2736 SPOOL_NOTIFY_INFO_DATA *data,
2737 print_queue_struct *queue,
2738 NT_PRINTER_INFO_LEVEL *printer,
2739 TALLOC_CTX *mem_ctx)
2741 pstring temp;
2742 uint32 len;
2744 /* the notify name should not contain the \\server\ part */
2745 char *p = strrchr(printer->info_2->printername, '\\');
2747 if (!p) {
2748 p = printer->info_2->printername;
2749 } else {
2750 p++;
2753 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2755 data->notify_data.data.length = len;
2756 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2758 if (!data->notify_data.data.string) {
2759 data->notify_data.data.length = 0;
2760 return;
2763 memcpy(data->notify_data.data.string, temp, len);
2766 /*******************************************************************
2767 * fill a notify_info_data with the servicename
2768 ********************************************************************/
2770 void spoolss_notify_share_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2776 pstring temp;
2777 uint32 len;
2779 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2781 data->notify_data.data.length = len;
2782 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2784 if (!data->notify_data.data.string) {
2785 data->notify_data.data.length = 0;
2786 return;
2789 memcpy(data->notify_data.data.string, temp, len);
2792 /*******************************************************************
2793 * fill a notify_info_data with the port name
2794 ********************************************************************/
2796 void spoolss_notify_port_name(int snum,
2797 SPOOL_NOTIFY_INFO_DATA *data,
2798 print_queue_struct *queue,
2799 NT_PRINTER_INFO_LEVEL *printer,
2800 TALLOC_CTX *mem_ctx)
2802 pstring temp;
2803 uint32 len;
2805 /* even if it's strange, that's consistant in all the code */
2807 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2809 data->notify_data.data.length = len;
2810 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2812 if (!data->notify_data.data.string) {
2813 data->notify_data.data.length = 0;
2814 return;
2817 memcpy(data->notify_data.data.string, temp, len);
2820 /*******************************************************************
2821 * fill a notify_info_data with the printername
2822 * but it doesn't exist, have to see what to do
2823 ********************************************************************/
2825 void spoolss_notify_driver_name(int snum,
2826 SPOOL_NOTIFY_INFO_DATA *data,
2827 print_queue_struct *queue,
2828 NT_PRINTER_INFO_LEVEL *printer,
2829 TALLOC_CTX *mem_ctx)
2831 pstring temp;
2832 uint32 len;
2834 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2836 data->notify_data.data.length = len;
2837 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2839 if (!data->notify_data.data.string) {
2840 data->notify_data.data.length = 0;
2841 return;
2844 memcpy(data->notify_data.data.string, temp, len);
2847 /*******************************************************************
2848 * fill a notify_info_data with the comment
2849 ********************************************************************/
2851 void spoolss_notify_comment(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 if (*printer->info_2->comment == '\0')
2861 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2862 else
2863 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2865 data->notify_data.data.length = len;
2866 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2868 if (!data->notify_data.data.string) {
2869 data->notify_data.data.length = 0;
2870 return;
2873 memcpy(data->notify_data.data.string, temp, len);
2876 /*******************************************************************
2877 * fill a notify_info_data with the comment
2878 * location = "Room 1, floor 2, building 3"
2879 ********************************************************************/
2881 void spoolss_notify_location(int snum,
2882 SPOOL_NOTIFY_INFO_DATA *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2887 pstring temp;
2888 uint32 len;
2890 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2892 data->notify_data.data.length = len;
2893 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2895 if (!data->notify_data.data.string) {
2896 data->notify_data.data.length = 0;
2897 return;
2900 memcpy(data->notify_data.data.string, temp, len);
2903 /*******************************************************************
2904 * fill a notify_info_data with the device mode
2905 * jfm:xxxx don't to it for know but that's a real problem !!!
2906 ********************************************************************/
2908 static void spoolss_notify_devmode(int snum,
2909 SPOOL_NOTIFY_INFO_DATA *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2916 /*******************************************************************
2917 * fill a notify_info_data with the separator file name
2918 ********************************************************************/
2920 void spoolss_notify_sepfile(int snum,
2921 SPOOL_NOTIFY_INFO_DATA *data,
2922 print_queue_struct *queue,
2923 NT_PRINTER_INFO_LEVEL *printer,
2924 TALLOC_CTX *mem_ctx)
2926 pstring temp;
2927 uint32 len;
2929 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2931 data->notify_data.data.length = len;
2932 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2934 if (!data->notify_data.data.string) {
2935 data->notify_data.data.length = 0;
2936 return;
2939 memcpy(data->notify_data.data.string, temp, len);
2942 /*******************************************************************
2943 * fill a notify_info_data with the print processor
2944 * jfm:xxxx return always winprint to indicate we don't do anything to it
2945 ********************************************************************/
2947 void spoolss_notify_print_processor(int snum,
2948 SPOOL_NOTIFY_INFO_DATA *data,
2949 print_queue_struct *queue,
2950 NT_PRINTER_INFO_LEVEL *printer,
2951 TALLOC_CTX *mem_ctx)
2953 pstring temp;
2954 uint32 len;
2956 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2958 data->notify_data.data.length = len;
2959 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2961 if (!data->notify_data.data.string) {
2962 data->notify_data.data.length = 0;
2963 return;
2966 memcpy(data->notify_data.data.string, temp, len);
2969 /*******************************************************************
2970 * fill a notify_info_data with the print processor options
2971 * jfm:xxxx send an empty string
2972 ********************************************************************/
2974 void spoolss_notify_parameters(int snum,
2975 SPOOL_NOTIFY_INFO_DATA *data,
2976 print_queue_struct *queue,
2977 NT_PRINTER_INFO_LEVEL *printer,
2978 TALLOC_CTX *mem_ctx)
2980 pstring temp;
2981 uint32 len;
2983 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2985 data->notify_data.data.length = len;
2986 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2988 if (!data->notify_data.data.string) {
2989 data->notify_data.data.length = 0;
2990 return;
2993 memcpy(data->notify_data.data.string, temp, len);
2996 /*******************************************************************
2997 * fill a notify_info_data with the data type
2998 * jfm:xxxx always send RAW as data type
2999 ********************************************************************/
3001 void spoolss_notify_datatype(int snum,
3002 SPOOL_NOTIFY_INFO_DATA *data,
3003 print_queue_struct *queue,
3004 NT_PRINTER_INFO_LEVEL *printer,
3005 TALLOC_CTX *mem_ctx)
3007 pstring temp;
3008 uint32 len;
3010 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3012 data->notify_data.data.length = len;
3013 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3015 if (!data->notify_data.data.string) {
3016 data->notify_data.data.length = 0;
3017 return;
3020 memcpy(data->notify_data.data.string, temp, len);
3023 /*******************************************************************
3024 * fill a notify_info_data with the security descriptor
3025 * jfm:xxxx send an null pointer to say no security desc
3026 * have to implement security before !
3027 ********************************************************************/
3029 static void spoolss_notify_security_desc(int snum,
3030 SPOOL_NOTIFY_INFO_DATA *data,
3031 print_queue_struct *queue,
3032 NT_PRINTER_INFO_LEVEL *printer,
3033 TALLOC_CTX *mem_ctx)
3035 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3036 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3039 /*******************************************************************
3040 * fill a notify_info_data with the attributes
3041 * jfm:xxxx a samba printer is always shared
3042 ********************************************************************/
3044 void spoolss_notify_attributes(int snum,
3045 SPOOL_NOTIFY_INFO_DATA *data,
3046 print_queue_struct *queue,
3047 NT_PRINTER_INFO_LEVEL *printer,
3048 TALLOC_CTX *mem_ctx)
3050 data->notify_data.value[0] = printer->info_2->attributes;
3051 data->notify_data.value[1] = 0;
3054 /*******************************************************************
3055 * fill a notify_info_data with the priority
3056 ********************************************************************/
3058 static void spoolss_notify_priority(int snum,
3059 SPOOL_NOTIFY_INFO_DATA *data,
3060 print_queue_struct *queue,
3061 NT_PRINTER_INFO_LEVEL *printer,
3062 TALLOC_CTX *mem_ctx)
3064 data->notify_data.value[0] = printer->info_2->priority;
3065 data->notify_data.value[1] = 0;
3068 /*******************************************************************
3069 * fill a notify_info_data with the default priority
3070 ********************************************************************/
3072 static void spoolss_notify_default_priority(int snum,
3073 SPOOL_NOTIFY_INFO_DATA *data,
3074 print_queue_struct *queue,
3075 NT_PRINTER_INFO_LEVEL *printer,
3076 TALLOC_CTX *mem_ctx)
3078 data->notify_data.value[0] = printer->info_2->default_priority;
3079 data->notify_data.value[1] = 0;
3082 /*******************************************************************
3083 * fill a notify_info_data with the start time
3084 ********************************************************************/
3086 static void spoolss_notify_start_time(int snum,
3087 SPOOL_NOTIFY_INFO_DATA *data,
3088 print_queue_struct *queue,
3089 NT_PRINTER_INFO_LEVEL *printer,
3090 TALLOC_CTX *mem_ctx)
3092 data->notify_data.value[0] = printer->info_2->starttime;
3093 data->notify_data.value[1] = 0;
3096 /*******************************************************************
3097 * fill a notify_info_data with the until time
3098 ********************************************************************/
3100 static void spoolss_notify_until_time(int snum,
3101 SPOOL_NOTIFY_INFO_DATA *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 data->notify_data.value[0] = printer->info_2->untiltime;
3107 data->notify_data.value[1] = 0;
3110 /*******************************************************************
3111 * fill a notify_info_data with the status
3112 ********************************************************************/
3114 static void spoolss_notify_status(int snum,
3115 SPOOL_NOTIFY_INFO_DATA *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3120 print_status_struct status;
3122 print_queue_length(snum, &status);
3123 data->notify_data.value[0]=(uint32) status.status;
3124 data->notify_data.value[1] = 0;
3127 /*******************************************************************
3128 * fill a notify_info_data with the number of jobs queued
3129 ********************************************************************/
3131 void spoolss_notify_cjobs(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 data->notify_data.value[0] = print_queue_length(snum, NULL);
3138 data->notify_data.value[1] = 0;
3141 /*******************************************************************
3142 * fill a notify_info_data with the average ppm
3143 ********************************************************************/
3145 static void spoolss_notify_average_ppm(int snum,
3146 SPOOL_NOTIFY_INFO_DATA *data,
3147 print_queue_struct *queue,
3148 NT_PRINTER_INFO_LEVEL *printer,
3149 TALLOC_CTX *mem_ctx)
3151 /* always respond 8 pages per minutes */
3152 /* a little hard ! */
3153 data->notify_data.value[0] = printer->info_2->averageppm;
3154 data->notify_data.value[1] = 0;
3157 /*******************************************************************
3158 * fill a notify_info_data with username
3159 ********************************************************************/
3161 static void spoolss_notify_username(int snum,
3162 SPOOL_NOTIFY_INFO_DATA *data,
3163 print_queue_struct *queue,
3164 NT_PRINTER_INFO_LEVEL *printer,
3165 TALLOC_CTX *mem_ctx)
3167 pstring temp;
3168 uint32 len;
3170 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3172 data->notify_data.data.length = len;
3173 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3175 if (!data->notify_data.data.string) {
3176 data->notify_data.data.length = 0;
3177 return;
3180 memcpy(data->notify_data.data.string, temp, len);
3183 /*******************************************************************
3184 * fill a notify_info_data with job status
3185 ********************************************************************/
3187 static void spoolss_notify_job_status(int snum,
3188 SPOOL_NOTIFY_INFO_DATA *data,
3189 print_queue_struct *queue,
3190 NT_PRINTER_INFO_LEVEL *printer,
3191 TALLOC_CTX *mem_ctx)
3193 data->notify_data.value[0]=nt_printj_status(queue->status);
3194 data->notify_data.value[1] = 0;
3197 /*******************************************************************
3198 * fill a notify_info_data with job name
3199 ********************************************************************/
3201 static void spoolss_notify_job_name(int snum,
3202 SPOOL_NOTIFY_INFO_DATA *data,
3203 print_queue_struct *queue,
3204 NT_PRINTER_INFO_LEVEL *printer,
3205 TALLOC_CTX *mem_ctx)
3207 pstring temp;
3208 uint32 len;
3210 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3212 data->notify_data.data.length = len;
3213 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3215 if (!data->notify_data.data.string) {
3216 data->notify_data.data.length = 0;
3217 return;
3220 memcpy(data->notify_data.data.string, temp, len);
3223 /*******************************************************************
3224 * fill a notify_info_data with job status
3225 ********************************************************************/
3227 static void spoolss_notify_job_status_string(int snum,
3228 SPOOL_NOTIFY_INFO_DATA *data,
3229 print_queue_struct *queue,
3230 NT_PRINTER_INFO_LEVEL *printer,
3231 TALLOC_CTX *mem_ctx)
3234 * Now we're returning job status codes we just return a "" here. JRA.
3237 const char *p = "";
3238 pstring temp;
3239 uint32 len;
3241 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3242 p = "unknown";
3244 switch (queue->status) {
3245 case LPQ_QUEUED:
3246 p = "Queued";
3247 break;
3248 case LPQ_PAUSED:
3249 p = ""; /* NT provides the paused string */
3250 break;
3251 case LPQ_SPOOLING:
3252 p = "Spooling";
3253 break;
3254 case LPQ_PRINTING:
3255 p = "Printing";
3256 break;
3258 #endif /* NO LONGER NEEDED. */
3260 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3262 data->notify_data.data.length = len;
3263 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3265 if (!data->notify_data.data.string) {
3266 data->notify_data.data.length = 0;
3267 return;
3270 memcpy(data->notify_data.data.string, temp, len);
3273 /*******************************************************************
3274 * fill a notify_info_data with job time
3275 ********************************************************************/
3277 static void spoolss_notify_job_time(int snum,
3278 SPOOL_NOTIFY_INFO_DATA *data,
3279 print_queue_struct *queue,
3280 NT_PRINTER_INFO_LEVEL *printer,
3281 TALLOC_CTX *mem_ctx)
3283 data->notify_data.value[0]=0x0;
3284 data->notify_data.value[1]=0;
3287 /*******************************************************************
3288 * fill a notify_info_data with job size
3289 ********************************************************************/
3291 static void spoolss_notify_job_size(int snum,
3292 SPOOL_NOTIFY_INFO_DATA *data,
3293 print_queue_struct *queue,
3294 NT_PRINTER_INFO_LEVEL *printer,
3295 TALLOC_CTX *mem_ctx)
3297 data->notify_data.value[0]=queue->size;
3298 data->notify_data.value[1]=0;
3301 /*******************************************************************
3302 * fill a notify_info_data with page info
3303 ********************************************************************/
3304 static void spoolss_notify_total_pages(int snum,
3305 SPOOL_NOTIFY_INFO_DATA *data,
3306 print_queue_struct *queue,
3307 NT_PRINTER_INFO_LEVEL *printer,
3308 TALLOC_CTX *mem_ctx)
3310 data->notify_data.value[0]=queue->page_count;
3311 data->notify_data.value[1]=0;
3314 /*******************************************************************
3315 * fill a notify_info_data with pages printed info.
3316 ********************************************************************/
3317 static void spoolss_notify_pages_printed(int snum,
3318 SPOOL_NOTIFY_INFO_DATA *data,
3319 print_queue_struct *queue,
3320 NT_PRINTER_INFO_LEVEL *printer,
3321 TALLOC_CTX *mem_ctx)
3323 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3324 data->notify_data.value[1]=0;
3327 /*******************************************************************
3328 Fill a notify_info_data with job position.
3329 ********************************************************************/
3331 static void spoolss_notify_job_position(int snum,
3332 SPOOL_NOTIFY_INFO_DATA *data,
3333 print_queue_struct *queue,
3334 NT_PRINTER_INFO_LEVEL *printer,
3335 TALLOC_CTX *mem_ctx)
3337 data->notify_data.value[0]=queue->job;
3338 data->notify_data.value[1]=0;
3341 /*******************************************************************
3342 Fill a notify_info_data with submitted time.
3343 ********************************************************************/
3345 static void spoolss_notify_submitted_time(int snum,
3346 SPOOL_NOTIFY_INFO_DATA *data,
3347 print_queue_struct *queue,
3348 NT_PRINTER_INFO_LEVEL *printer,
3349 TALLOC_CTX *mem_ctx)
3351 struct tm *t;
3352 uint32 len;
3353 SYSTEMTIME st;
3354 char *p;
3356 t=gmtime(&queue->time);
3358 len = sizeof(SYSTEMTIME);
3360 data->notify_data.data.length = len;
3361 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3363 if (!data->notify_data.data.string) {
3364 data->notify_data.data.length = 0;
3365 return;
3368 make_systemtime(&st, t);
3371 * Systemtime must be linearized as a set of UINT16's.
3372 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3375 p = (char *)data->notify_data.data.string;
3376 SSVAL(p, 0, st.year);
3377 SSVAL(p, 2, st.month);
3378 SSVAL(p, 4, st.dayofweek);
3379 SSVAL(p, 6, st.day);
3380 SSVAL(p, 8, st.hour);
3381 SSVAL(p, 10, st.minute);
3382 SSVAL(p, 12, st.second);
3383 SSVAL(p, 14, st.milliseconds);
3386 struct s_notify_info_data_table
3388 uint16 type;
3389 uint16 field;
3390 const char *name;
3391 uint32 size;
3392 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3393 print_queue_struct *queue,
3394 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3397 /* A table describing the various print notification constants and
3398 whether the notification data is a pointer to a variable sized
3399 buffer, a one value uint32 or a two value uint32. */
3401 static const struct s_notify_info_data_table notify_info_data_table[] =
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3452 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3455 /*******************************************************************
3456 Return the size of info_data structure.
3457 ********************************************************************/
3459 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3461 int i=0;
3463 for (i = 0; i < sizeof(notify_info_data_table); i++)
3465 if ( (notify_info_data_table[i].type == type)
3466 && (notify_info_data_table[i].field == field) )
3468 switch(notify_info_data_table[i].size)
3470 case NOTIFY_ONE_VALUE:
3471 case NOTIFY_TWO_VALUE:
3472 return 1;
3473 case NOTIFY_STRING:
3474 return 2;
3476 /* The only pointer notify data I have seen on
3477 the wire is the submitted time and this has
3478 the notify size set to 4. -tpot */
3480 case NOTIFY_POINTER:
3481 return 4;
3483 case NOTIFY_SECDESC:
3484 return 5;
3489 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3491 return 0;
3494 /*******************************************************************
3495 Return the type of notify_info_data.
3496 ********************************************************************/
3498 static int type_of_notify_info_data(uint16 type, uint16 field)
3500 int i=0;
3502 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3503 if (notify_info_data_table[i].type == type &&
3504 notify_info_data_table[i].field == field)
3505 return notify_info_data_table[i].size;
3508 return False;
3511 /****************************************************************************
3512 ****************************************************************************/
3514 static int search_notify(uint16 type, uint16 field, int *value)
3516 int i;
3518 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3519 if (notify_info_data_table[i].type == type &&
3520 notify_info_data_table[i].field == field &&
3521 notify_info_data_table[i].fn != NULL) {
3522 *value = i;
3523 return True;
3527 return False;
3530 /****************************************************************************
3531 ****************************************************************************/
3533 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3535 info_data->type = type;
3536 info_data->field = field;
3537 info_data->reserved = 0;
3539 info_data->size = size_of_notify_info_data(type, field);
3540 info_data->enc_type = type_of_notify_info_data(type, field);
3542 info_data->id = id;
3547 /*******************************************************************
3549 * fill a notify_info struct with info asked
3551 ********************************************************************/
3553 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3554 snum, SPOOL_NOTIFY_OPTION_TYPE
3555 *option_type, uint32 id,
3556 TALLOC_CTX *mem_ctx)
3558 int field_num,j;
3559 uint16 type;
3560 uint16 field;
3562 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3563 NT_PRINTER_INFO_LEVEL *printer = NULL;
3564 print_queue_struct *queue=NULL;
3566 type=option_type->type;
3568 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3569 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3570 option_type->count, lp_servicename(snum)));
3572 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3573 return False;
3575 for(field_num=0; field_num<option_type->count; field_num++) {
3576 field = option_type->fields[field_num];
3578 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3580 if (!search_notify(type, field, &j) )
3581 continue;
3583 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3584 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3585 return False;
3586 } else
3587 info->data = tid;
3589 current_data = &info->data[info->count];
3591 construct_info_data(current_data, type, field, id);
3593 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3594 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3596 notify_info_data_table[j].fn(snum, current_data, queue,
3597 printer, mem_ctx);
3599 info->count++;
3602 free_a_printer(&printer, 2);
3603 return True;
3606 /*******************************************************************
3608 * fill a notify_info struct with info asked
3610 ********************************************************************/
3612 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3613 SPOOL_NOTIFY_INFO *info,
3614 NT_PRINTER_INFO_LEVEL *printer,
3615 int snum, SPOOL_NOTIFY_OPTION_TYPE
3616 *option_type, uint32 id,
3617 TALLOC_CTX *mem_ctx)
3619 int field_num,j;
3620 uint16 type;
3621 uint16 field;
3623 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3625 DEBUG(4,("construct_notify_jobs_info\n"));
3627 type = option_type->type;
3629 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3630 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3631 option_type->count));
3633 for(field_num=0; field_num<option_type->count; field_num++) {
3634 field = option_type->fields[field_num];
3636 if (!search_notify(type, field, &j) )
3637 continue;
3639 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3640 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3641 return False;
3643 else info->data = tid;
3645 current_data=&(info->data[info->count]);
3647 construct_info_data(current_data, type, field, id);
3648 notify_info_data_table[j].fn(snum, current_data, queue,
3649 printer, mem_ctx);
3650 info->count++;
3653 return True;
3657 * JFM: The enumeration is not that simple, it's even non obvious.
3659 * let's take an example: I want to monitor the PRINTER SERVER for
3660 * the printer's name and the number of jobs currently queued.
3661 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3662 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3664 * I have 3 printers on the back of my server.
3666 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3667 * structures.
3668 * Number Data Id
3669 * 1 printer 1 name 1
3670 * 2 printer 1 cjob 1
3671 * 3 printer 2 name 2
3672 * 4 printer 2 cjob 2
3673 * 5 printer 3 name 3
3674 * 6 printer 3 name 3
3676 * that's the print server case, the printer case is even worse.
3679 /*******************************************************************
3681 * enumerate all printers on the printserver
3682 * fill a notify_info struct with info asked
3684 ********************************************************************/
3686 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3687 SPOOL_NOTIFY_INFO *info,
3688 TALLOC_CTX *mem_ctx)
3690 int snum;
3691 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3692 int n_services=lp_numservices();
3693 int i;
3694 SPOOL_NOTIFY_OPTION *option;
3695 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3697 DEBUG(4,("printserver_notify_info\n"));
3699 if (!Printer)
3700 return WERR_BADFID;
3702 option=Printer->notify.option;
3703 info->version=2;
3704 info->data=NULL;
3705 info->count=0;
3707 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3708 sending a ffpcn() request first */
3710 if ( !option )
3711 return WERR_BADFID;
3713 for (i=0; i<option->count; i++) {
3714 option_type=&(option->ctr.type[i]);
3716 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3717 continue;
3719 for (snum=0; snum<n_services; snum++)
3721 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3722 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3726 #if 0
3728 * Debugging information, don't delete.
3731 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3732 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3733 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3735 for (i=0; i<info->count; i++) {
3736 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3737 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3738 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3740 #endif
3742 return WERR_OK;
3745 /*******************************************************************
3747 * fill a notify_info struct with info asked
3749 ********************************************************************/
3751 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3752 TALLOC_CTX *mem_ctx)
3754 int snum;
3755 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3756 int i;
3757 uint32 id;
3758 SPOOL_NOTIFY_OPTION *option;
3759 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3760 int count,j;
3761 print_queue_struct *queue=NULL;
3762 print_status_struct status;
3764 DEBUG(4,("printer_notify_info\n"));
3766 if (!Printer)
3767 return WERR_BADFID;
3769 option=Printer->notify.option;
3770 id = 0x0;
3771 info->version=2;
3772 info->data=NULL;
3773 info->count=0;
3775 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3776 sending a ffpcn() request first */
3778 if ( !option )
3779 return WERR_BADFID;
3781 get_printer_snum(p, hnd, &snum);
3783 for (i=0; i<option->count; i++) {
3784 option_type=&option->ctr.type[i];
3786 switch ( option_type->type ) {
3787 case PRINTER_NOTIFY_TYPE:
3788 if(construct_notify_printer_info(Printer, info, snum,
3789 option_type, id,
3790 mem_ctx))
3791 id--;
3792 break;
3794 case JOB_NOTIFY_TYPE: {
3795 NT_PRINTER_INFO_LEVEL *printer = NULL;
3797 count = print_queue_status(snum, &queue, &status);
3799 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3800 goto done;
3802 for (j=0; j<count; j++) {
3803 construct_notify_jobs_info(&queue[j], info,
3804 printer, snum,
3805 option_type,
3806 queue[j].job,
3807 mem_ctx);
3810 free_a_printer(&printer, 2);
3812 done:
3813 SAFE_FREE(queue);
3814 break;
3820 * Debugging information, don't delete.
3823 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3824 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3825 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3827 for (i=0; i<info->count; i++) {
3828 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3829 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3830 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3833 return WERR_OK;
3836 /********************************************************************
3837 * spoolss_rfnpcnex
3838 ********************************************************************/
3840 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3842 POLICY_HND *handle = &q_u->handle;
3843 SPOOL_NOTIFY_INFO *info = &r_u->info;
3845 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3846 WERROR result = WERR_BADFID;
3848 /* we always have a NOTIFY_INFO struct */
3849 r_u->info_ptr=0x1;
3851 if (!Printer) {
3852 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3853 OUR_HANDLE(handle)));
3854 goto done;
3857 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3860 * We are now using the change value, and
3861 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3862 * I don't have a global notification system, I'm sending back all the
3863 * informations even when _NOTHING_ has changed.
3866 /* We need to keep track of the change value to send back in
3867 RRPCN replies otherwise our updates are ignored. */
3869 Printer->notify.fnpcn = True;
3871 if (Printer->notify.client_connected) {
3872 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3873 Printer->notify.change = q_u->change;
3876 /* just ignore the SPOOL_NOTIFY_OPTION */
3878 switch (Printer->printer_type) {
3879 case PRINTER_HANDLE_IS_PRINTSERVER:
3880 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3881 break;
3883 case PRINTER_HANDLE_IS_PRINTER:
3884 result = printer_notify_info(p, handle, info, p->mem_ctx);
3885 break;
3888 Printer->notify.fnpcn = False;
3890 done:
3891 return result;
3894 /********************************************************************
3895 * construct_printer_info_0
3896 * fill a printer_info_0 struct
3897 ********************************************************************/
3899 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3901 pstring chaine;
3902 int count;
3903 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3904 counter_printer_0 *session_counter;
3905 uint32 global_counter;
3906 struct tm *t;
3907 time_t setuptime;
3908 print_status_struct status;
3910 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3911 return False;
3913 count = print_queue_length(snum, &status);
3915 /* check if we already have a counter for this printer */
3916 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3917 if (session_counter->snum == snum)
3918 break;
3921 /* it's the first time, add it to the list */
3922 if (session_counter==NULL) {
3923 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3924 free_a_printer(&ntprinter, 2);
3925 return False;
3927 ZERO_STRUCTP(session_counter);
3928 session_counter->snum=snum;
3929 session_counter->counter=0;
3930 DLIST_ADD(counter_list, session_counter);
3933 /* increment it */
3934 session_counter->counter++;
3936 /* JFM:
3937 * the global_counter should be stored in a TDB as it's common to all the clients
3938 * and should be zeroed on samba startup
3940 global_counter=session_counter->counter;
3942 pstrcpy(chaine,ntprinter->info_2->printername);
3944 init_unistr(&printer->printername, chaine);
3946 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3947 init_unistr(&printer->servername, chaine);
3949 printer->cjobs = count;
3950 printer->total_jobs = 0;
3951 printer->total_bytes = 0;
3953 setuptime = (time_t)ntprinter->info_2->setuptime;
3954 t=gmtime(&setuptime);
3956 printer->year = t->tm_year+1900;
3957 printer->month = t->tm_mon+1;
3958 printer->dayofweek = t->tm_wday;
3959 printer->day = t->tm_mday;
3960 printer->hour = t->tm_hour;
3961 printer->minute = t->tm_min;
3962 printer->second = t->tm_sec;
3963 printer->milliseconds = 0;
3965 printer->global_counter = global_counter;
3966 printer->total_pages = 0;
3968 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3969 printer->major_version = 0x0005; /* NT 5 */
3970 printer->build_version = 0x0893; /* build 2195 */
3972 printer->unknown7 = 0x1;
3973 printer->unknown8 = 0x0;
3974 printer->unknown9 = 0x0;
3975 printer->session_counter = session_counter->counter;
3976 printer->unknown11 = 0x0;
3977 printer->printer_errors = 0x0; /* number of print failure */
3978 printer->unknown13 = 0x0;
3979 printer->unknown14 = 0x1;
3980 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3981 printer->unknown16 = 0x0;
3982 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3983 printer->unknown18 = 0x0;
3984 printer->status = nt_printq_status(status.status);
3985 printer->unknown20 = 0x0;
3986 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3987 printer->unknown22 = 0x0;
3988 printer->unknown23 = 0x6; /* 6 ???*/
3989 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3990 printer->unknown25 = 0;
3991 printer->unknown26 = 0;
3992 printer->unknown27 = 0;
3993 printer->unknown28 = 0;
3994 printer->unknown29 = 0;
3996 free_a_printer(&ntprinter,2);
3997 return (True);
4000 /********************************************************************
4001 * construct_printer_info_1
4002 * fill a printer_info_1 struct
4003 ********************************************************************/
4004 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4006 pstring chaine;
4007 pstring chaine2;
4008 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4010 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4011 return False;
4013 printer->flags=flags;
4015 if (*ntprinter->info_2->comment == '\0') {
4016 init_unistr(&printer->comment, lp_comment(snum));
4017 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4018 ntprinter->info_2->drivername, lp_comment(snum));
4020 else {
4021 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4022 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4023 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4026 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4028 init_unistr(&printer->description, chaine);
4029 init_unistr(&printer->name, chaine2);
4031 free_a_printer(&ntprinter,2);
4033 return True;
4036 /****************************************************************************
4037 Free a DEVMODE struct.
4038 ****************************************************************************/
4040 static void free_dev_mode(DEVICEMODE *dev)
4042 if (dev == NULL)
4043 return;
4045 SAFE_FREE(dev->dev_private);
4046 SAFE_FREE(dev);
4050 /****************************************************************************
4051 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4052 should be valid upon entry
4053 ****************************************************************************/
4055 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4057 if ( !devmode || !ntdevmode )
4058 return False;
4060 init_unistr(&devmode->devicename, ntdevmode->devicename);
4062 init_unistr(&devmode->formname, ntdevmode->formname);
4064 devmode->specversion = ntdevmode->specversion;
4065 devmode->driverversion = ntdevmode->driverversion;
4066 devmode->size = ntdevmode->size;
4067 devmode->driverextra = ntdevmode->driverextra;
4068 devmode->fields = ntdevmode->fields;
4070 devmode->orientation = ntdevmode->orientation;
4071 devmode->papersize = ntdevmode->papersize;
4072 devmode->paperlength = ntdevmode->paperlength;
4073 devmode->paperwidth = ntdevmode->paperwidth;
4074 devmode->scale = ntdevmode->scale;
4075 devmode->copies = ntdevmode->copies;
4076 devmode->defaultsource = ntdevmode->defaultsource;
4077 devmode->printquality = ntdevmode->printquality;
4078 devmode->color = ntdevmode->color;
4079 devmode->duplex = ntdevmode->duplex;
4080 devmode->yresolution = ntdevmode->yresolution;
4081 devmode->ttoption = ntdevmode->ttoption;
4082 devmode->collate = ntdevmode->collate;
4083 devmode->icmmethod = ntdevmode->icmmethod;
4084 devmode->icmintent = ntdevmode->icmintent;
4085 devmode->mediatype = ntdevmode->mediatype;
4086 devmode->dithertype = ntdevmode->dithertype;
4088 if (ntdevmode->nt_dev_private != NULL) {
4089 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4090 return False;
4093 return True;
4096 /****************************************************************************
4097 Create a DEVMODE struct. Returns malloced memory.
4098 ****************************************************************************/
4100 DEVICEMODE *construct_dev_mode(int snum)
4102 NT_PRINTER_INFO_LEVEL *printer = NULL;
4103 DEVICEMODE *devmode = NULL;
4105 DEBUG(7,("construct_dev_mode\n"));
4107 DEBUGADD(8,("getting printer characteristics\n"));
4109 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4110 return NULL;
4112 if ( !printer->info_2->devmode ) {
4113 DEBUG(5, ("BONG! There was no device mode!\n"));
4114 goto done;
4117 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4118 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4119 goto done;
4122 ZERO_STRUCTP(devmode);
4124 DEBUGADD(8,("loading DEVICEMODE\n"));
4126 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4127 free_dev_mode( devmode );
4128 devmode = NULL;
4131 done:
4132 free_a_printer(&printer,2);
4134 return devmode;
4137 /********************************************************************
4138 * construct_printer_info_2
4139 * fill a printer_info_2 struct
4140 ********************************************************************/
4142 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4144 int count;
4145 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4147 print_status_struct status;
4149 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4150 return False;
4152 count = print_queue_length(snum, &status);
4154 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4155 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4156 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4157 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4158 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4160 if (*ntprinter->info_2->comment == '\0')
4161 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4162 else
4163 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4165 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4166 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4167 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4168 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4169 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4171 printer->attributes = ntprinter->info_2->attributes;
4173 printer->priority = ntprinter->info_2->priority; /* priority */
4174 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4175 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4176 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4177 printer->status = nt_printq_status(status.status); /* status */
4178 printer->cjobs = count; /* jobs */
4179 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4181 if ( !(printer->devmode = construct_dev_mode(snum)) )
4182 DEBUG(8, ("Returning NULL Devicemode!\n"));
4184 printer->secdesc = NULL;
4186 if ( ntprinter->info_2->secdesc_buf
4187 && ntprinter->info_2->secdesc_buf->len != 0 )
4189 /* don't use talloc_steal() here unless you do a deep steal of all
4190 the SEC_DESC members */
4192 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4193 ntprinter->info_2->secdesc_buf->sec );
4196 free_a_printer(&ntprinter, 2);
4198 return True;
4201 /********************************************************************
4202 * construct_printer_info_3
4203 * fill a printer_info_3 struct
4204 ********************************************************************/
4206 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4208 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4209 PRINTER_INFO_3 *printer = NULL;
4211 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4212 return False;
4214 *pp_printer = NULL;
4215 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4216 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4217 return False;
4220 ZERO_STRUCTP(printer);
4222 /* These are the components of the SD we are returning. */
4224 printer->flags = 0x4;
4226 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4227 /* don't use talloc_steal() here unless you do a deep steal of all
4228 the SEC_DESC members */
4230 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4231 ntprinter->info_2->secdesc_buf->sec );
4234 free_a_printer(&ntprinter, 2);
4236 *pp_printer = printer;
4237 return True;
4240 /********************************************************************
4241 * construct_printer_info_4
4242 * fill a printer_info_4 struct
4243 ********************************************************************/
4245 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4247 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4249 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4250 return False;
4252 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4253 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4254 printer->attributes = ntprinter->info_2->attributes;
4256 free_a_printer(&ntprinter, 2);
4257 return True;
4260 /********************************************************************
4261 * construct_printer_info_5
4262 * fill a printer_info_5 struct
4263 ********************************************************************/
4265 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4267 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4269 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4270 return False;
4272 init_unistr(&printer->printername, ntprinter->info_2->printername);
4273 init_unistr(&printer->portname, ntprinter->info_2->portname);
4274 printer->attributes = ntprinter->info_2->attributes;
4276 /* these two are not used by NT+ according to MSDN */
4278 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4279 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4281 free_a_printer(&ntprinter, 2);
4283 return True;
4286 /********************************************************************
4287 * construct_printer_info_7
4288 * fill a printer_info_7 struct
4289 ********************************************************************/
4291 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4293 char *guid_str = NULL;
4294 struct uuid guid;
4296 if (is_printer_published(print_hnd, snum, &guid)) {
4297 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4298 strupper_m(guid_str);
4299 init_unistr(&printer->guid, guid_str);
4300 printer->action = SPOOL_DS_PUBLISH;
4301 } else {
4302 init_unistr(&printer->guid, "");
4303 printer->action = SPOOL_DS_UNPUBLISH;
4306 return True;
4309 /********************************************************************
4310 Spoolss_enumprinters.
4311 ********************************************************************/
4313 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4315 int snum;
4316 int i;
4317 int n_services=lp_numservices();
4318 PRINTER_INFO_1 *tp, *printers=NULL;
4319 PRINTER_INFO_1 current_prt;
4320 WERROR result = WERR_OK;
4322 DEBUG(4,("enum_all_printers_info_1\n"));
4324 for (snum=0; snum<n_services; snum++) {
4325 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4326 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4328 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4329 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4330 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4331 SAFE_FREE(printers);
4332 *returned=0;
4333 return WERR_NOMEM;
4335 else printers = tp;
4336 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4338 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4339 (*returned)++;
4344 /* check the required size. */
4345 for (i=0; i<*returned; i++)
4346 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4348 if (*needed > offered) {
4349 result = WERR_INSUFFICIENT_BUFFER;
4350 goto out;
4353 if (!rpcbuf_alloc_size(buffer, *needed)) {
4354 result = WERR_NOMEM;
4355 goto out;
4358 /* fill the buffer with the structures */
4359 for (i=0; i<*returned; i++)
4360 smb_io_printer_info_1("", buffer, &printers[i], 0);
4362 out:
4363 /* clear memory */
4365 SAFE_FREE(printers);
4367 if ( !W_ERROR_IS_OK(result) )
4368 *returned = 0;
4370 return result;
4373 /********************************************************************
4374 enum_all_printers_info_1_local.
4375 *********************************************************************/
4377 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4379 DEBUG(4,("enum_all_printers_info_1_local\n"));
4381 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4384 /********************************************************************
4385 enum_all_printers_info_1_name.
4386 *********************************************************************/
4388 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4390 char *s = name;
4392 DEBUG(4,("enum_all_printers_info_1_name\n"));
4394 if ((name[0] == '\\') && (name[1] == '\\'))
4395 s = name + 2;
4397 if (is_myname_or_ipaddr(s)) {
4398 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4400 else
4401 return WERR_INVALID_NAME;
4404 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4405 /********************************************************************
4406 enum_all_printers_info_1_remote.
4407 *********************************************************************/
4409 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4411 PRINTER_INFO_1 *printer;
4412 fstring printername;
4413 fstring desc;
4414 fstring comment;
4415 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4416 WERROR result = WERR_OK;
4418 /* JFM: currently it's more a place holder than anything else.
4419 * In the spooler world there is a notion of server registration.
4420 * the print servers are registered on the PDC (in the same domain)
4422 * We should have a TDB here. The registration is done thru an
4423 * undocumented RPC call.
4426 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4427 return WERR_NOMEM;
4429 *returned=1;
4431 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4432 slprintf(desc, sizeof(desc)-1,"%s", name);
4433 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4435 init_unistr(&printer->description, desc);
4436 init_unistr(&printer->name, printername);
4437 init_unistr(&printer->comment, comment);
4438 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4440 /* check the required size. */
4441 *needed += spoolss_size_printer_info_1(printer);
4443 if (*needed > offered) {
4444 result = WERR_INSUFFICIENT_BUFFER;
4445 goto out;
4448 if (!rpcbuf_alloc_size(buffer, *needed)) {
4449 result = WERR_NOMEM;
4450 goto out;
4453 /* fill the buffer with the structures */
4454 smb_io_printer_info_1("", buffer, printer, 0);
4456 out:
4457 /* clear memory */
4458 SAFE_FREE(printer);
4460 if ( !W_ERROR_IS_OK(result) )
4461 *returned = 0;
4463 return result;
4466 #endif
4468 /********************************************************************
4469 enum_all_printers_info_1_network.
4470 *********************************************************************/
4472 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4474 char *s = name;
4476 DEBUG(4,("enum_all_printers_info_1_network\n"));
4478 /* If we respond to a enum_printers level 1 on our name with flags
4479 set to PRINTER_ENUM_REMOTE with a list of printers then these
4480 printers incorrectly appear in the APW browse list.
4481 Specifically the printers for the server appear at the workgroup
4482 level where all the other servers in the domain are
4483 listed. Windows responds to this call with a
4484 WERR_CAN_NOT_COMPLETE so we should do the same. */
4486 if (name[0] == '\\' && name[1] == '\\')
4487 s = name + 2;
4489 if (is_myname_or_ipaddr(s))
4490 return WERR_CAN_NOT_COMPLETE;
4492 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4495 /********************************************************************
4496 * api_spoolss_enumprinters
4498 * called from api_spoolss_enumprinters (see this to understand)
4499 ********************************************************************/
4501 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4503 int snum;
4504 int i;
4505 int n_services=lp_numservices();
4506 PRINTER_INFO_2 *tp, *printers=NULL;
4507 PRINTER_INFO_2 current_prt;
4508 WERROR result = WERR_OK;
4510 for (snum=0; snum<n_services; snum++) {
4511 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4512 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4514 if (construct_printer_info_2(NULL, &current_prt, snum))
4516 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4517 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4518 SAFE_FREE(printers);
4519 *returned = 0;
4520 return WERR_NOMEM;
4523 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4525 printers = tp;
4526 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4528 (*returned)++;
4533 /* check the required size. */
4534 for (i=0; i<*returned; i++)
4535 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4537 if (*needed > offered) {
4538 result = WERR_INSUFFICIENT_BUFFER;
4539 goto out;
4542 if (!rpcbuf_alloc_size(buffer, *needed)) {
4543 result = WERR_NOMEM;
4544 goto out;
4547 /* fill the buffer with the structures */
4548 for (i=0; i<*returned; i++)
4549 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4551 out:
4552 /* clear memory */
4554 for (i=0; i<*returned; i++)
4555 free_devmode(printers[i].devmode);
4557 SAFE_FREE(printers);
4559 if ( !W_ERROR_IS_OK(result) )
4560 *returned = 0;
4562 return result;
4565 /********************************************************************
4566 * handle enumeration of printers at level 1
4567 ********************************************************************/
4569 static WERROR enumprinters_level1( uint32 flags, fstring name,
4570 RPC_BUFFER *buffer, uint32 offered,
4571 uint32 *needed, uint32 *returned)
4573 /* Not all the flags are equals */
4575 if (flags & PRINTER_ENUM_LOCAL)
4576 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4578 if (flags & PRINTER_ENUM_NAME)
4579 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4581 #if 0 /* JERRY - disabled for now */
4582 if (flags & PRINTER_ENUM_REMOTE)
4583 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4584 #endif
4586 if (flags & PRINTER_ENUM_NETWORK)
4587 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4589 return WERR_OK; /* NT4sp5 does that */
4592 /********************************************************************
4593 * handle enumeration of printers at level 2
4594 ********************************************************************/
4596 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4597 RPC_BUFFER *buffer, uint32 offered,
4598 uint32 *needed, uint32 *returned)
4600 char *s = servername;
4602 if (flags & PRINTER_ENUM_LOCAL) {
4603 return enum_all_printers_info_2(buffer, offered, needed, returned);
4606 if (flags & PRINTER_ENUM_NAME) {
4607 if ((servername[0] == '\\') && (servername[1] == '\\'))
4608 s = servername + 2;
4609 if (is_myname_or_ipaddr(s))
4610 return enum_all_printers_info_2(buffer, offered, needed, returned);
4611 else
4612 return WERR_INVALID_NAME;
4615 if (flags & PRINTER_ENUM_REMOTE)
4616 return WERR_UNKNOWN_LEVEL;
4618 return WERR_OK;
4621 /********************************************************************
4622 * handle enumeration of printers at level 5
4623 ********************************************************************/
4625 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4626 RPC_BUFFER *buffer, uint32 offered,
4627 uint32 *needed, uint32 *returned)
4629 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4630 return WERR_OK;
4633 /********************************************************************
4634 * api_spoolss_enumprinters
4636 * called from api_spoolss_enumprinters (see this to understand)
4637 ********************************************************************/
4639 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4641 uint32 flags = q_u->flags;
4642 UNISTR2 *servername = &q_u->servername;
4643 uint32 level = q_u->level;
4644 RPC_BUFFER *buffer = NULL;
4645 uint32 offered = q_u->offered;
4646 uint32 *needed = &r_u->needed;
4647 uint32 *returned = &r_u->returned;
4649 fstring name;
4651 /* that's an [in out] buffer */
4653 if ( q_u->buffer ) {
4654 rpcbuf_move(q_u->buffer, &r_u->buffer);
4655 buffer = r_u->buffer;
4658 DEBUG(4,("_spoolss_enumprinters\n"));
4660 *needed=0;
4661 *returned=0;
4664 * Level 1:
4665 * flags==PRINTER_ENUM_NAME
4666 * if name=="" then enumerates all printers
4667 * if name!="" then enumerate the printer
4668 * flags==PRINTER_ENUM_REMOTE
4669 * name is NULL, enumerate printers
4670 * Level 2: name!="" enumerates printers, name can't be NULL
4671 * Level 3: doesn't exist
4672 * Level 4: does a local registry lookup
4673 * Level 5: same as Level 2
4676 unistr2_to_ascii(name, servername, sizeof(name)-1);
4677 strupper_m(name);
4679 switch (level) {
4680 case 1:
4681 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4682 case 2:
4683 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4684 case 5:
4685 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4686 case 3:
4687 case 4:
4688 break;
4690 return WERR_UNKNOWN_LEVEL;
4693 /****************************************************************************
4694 ****************************************************************************/
4696 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4698 PRINTER_INFO_0 *printer=NULL;
4699 WERROR result = WERR_OK;
4701 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4702 return WERR_NOMEM;
4704 construct_printer_info_0(print_hnd, printer, snum);
4706 /* check the required size. */
4707 *needed += spoolss_size_printer_info_0(printer);
4709 if (*needed > offered) {
4710 result = WERR_INSUFFICIENT_BUFFER;
4711 goto out;
4714 if (!rpcbuf_alloc_size(buffer, *needed)) {
4715 result = WERR_NOMEM;
4716 goto out;
4719 /* fill the buffer with the structures */
4720 smb_io_printer_info_0("", buffer, printer, 0);
4722 out:
4723 /* clear memory */
4725 SAFE_FREE(printer);
4727 return result;
4730 /****************************************************************************
4731 ****************************************************************************/
4733 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4735 PRINTER_INFO_1 *printer=NULL;
4736 WERROR result = WERR_OK;
4738 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4739 return WERR_NOMEM;
4741 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4743 /* check the required size. */
4744 *needed += spoolss_size_printer_info_1(printer);
4746 if (*needed > offered) {
4747 result = WERR_INSUFFICIENT_BUFFER;
4748 goto out;
4751 if (!rpcbuf_alloc_size(buffer, *needed)) {
4752 result = WERR_NOMEM;
4753 goto out;
4756 /* fill the buffer with the structures */
4757 smb_io_printer_info_1("", buffer, printer, 0);
4759 out:
4760 /* clear memory */
4761 SAFE_FREE(printer);
4763 return result;
4766 /****************************************************************************
4767 ****************************************************************************/
4769 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4771 PRINTER_INFO_2 *printer=NULL;
4772 WERROR result = WERR_OK;
4774 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4775 return WERR_NOMEM;
4777 construct_printer_info_2(print_hnd, printer, snum);
4779 /* check the required size. */
4780 *needed += spoolss_size_printer_info_2(printer);
4782 if (*needed > offered) {
4783 result = WERR_INSUFFICIENT_BUFFER;
4784 goto out;
4787 if (!rpcbuf_alloc_size(buffer, *needed)) {
4788 result = WERR_NOMEM;
4789 goto out;
4792 /* fill the buffer with the structures */
4793 if (!smb_io_printer_info_2("", buffer, printer, 0))
4794 result = WERR_NOMEM;
4796 out:
4797 /* clear memory */
4798 free_printer_info_2(printer);
4800 return result;
4803 /****************************************************************************
4804 ****************************************************************************/
4806 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4808 PRINTER_INFO_3 *printer=NULL;
4809 WERROR result = WERR_OK;
4811 if (!construct_printer_info_3(print_hnd, &printer, snum))
4812 return WERR_NOMEM;
4814 /* check the required size. */
4815 *needed += spoolss_size_printer_info_3(printer);
4817 if (*needed > offered) {
4818 result = WERR_INSUFFICIENT_BUFFER;
4819 goto out;
4822 if (!rpcbuf_alloc_size(buffer, *needed)) {
4823 result = WERR_NOMEM;
4824 goto out;
4827 /* fill the buffer with the structures */
4828 smb_io_printer_info_3("", buffer, printer, 0);
4830 out:
4831 /* clear memory */
4832 free_printer_info_3(printer);
4834 return result;
4837 /****************************************************************************
4838 ****************************************************************************/
4840 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4842 PRINTER_INFO_4 *printer=NULL;
4843 WERROR result = WERR_OK;
4845 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4846 return WERR_NOMEM;
4848 if (!construct_printer_info_4(print_hnd, printer, snum))
4849 return WERR_NOMEM;
4851 /* check the required size. */
4852 *needed += spoolss_size_printer_info_4(printer);
4854 if (*needed > offered) {
4855 result = WERR_INSUFFICIENT_BUFFER;
4856 goto out;
4859 if (!rpcbuf_alloc_size(buffer, *needed)) {
4860 result = WERR_NOMEM;
4861 goto out;
4864 /* fill the buffer with the structures */
4865 smb_io_printer_info_4("", buffer, printer, 0);
4867 out:
4868 /* clear memory */
4869 free_printer_info_4(printer);
4871 return result;
4874 /****************************************************************************
4875 ****************************************************************************/
4877 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4879 PRINTER_INFO_5 *printer=NULL;
4880 WERROR result = WERR_OK;
4882 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4883 return WERR_NOMEM;
4885 if (!construct_printer_info_5(print_hnd, printer, snum))
4886 return WERR_NOMEM;
4888 /* check the required size. */
4889 *needed += spoolss_size_printer_info_5(printer);
4891 if (*needed > offered) {
4892 result = WERR_INSUFFICIENT_BUFFER;
4893 goto out;
4896 if (!rpcbuf_alloc_size(buffer, *needed)) {
4897 result = WERR_NOMEM;
4898 goto out;
4901 /* fill the buffer with the structures */
4902 smb_io_printer_info_5("", buffer, printer, 0);
4904 out:
4905 /* clear memory */
4906 free_printer_info_5(printer);
4908 return result;
4911 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4913 PRINTER_INFO_7 *printer=NULL;
4914 WERROR result = WERR_OK;
4916 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4917 return WERR_NOMEM;
4919 if (!construct_printer_info_7(print_hnd, printer, snum))
4920 return WERR_NOMEM;
4922 /* check the required size. */
4923 *needed += spoolss_size_printer_info_7(printer);
4925 if (*needed > offered) {
4926 result = WERR_INSUFFICIENT_BUFFER;
4927 goto out;
4930 if (!rpcbuf_alloc_size(buffer, *needed)) {
4931 result = WERR_NOMEM;
4932 goto out;
4936 /* fill the buffer with the structures */
4937 smb_io_printer_info_7("", buffer, printer, 0);
4939 out:
4940 /* clear memory */
4941 free_printer_info_7(printer);
4943 return result;
4946 /****************************************************************************
4947 ****************************************************************************/
4949 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4951 POLICY_HND *handle = &q_u->handle;
4952 uint32 level = q_u->level;
4953 RPC_BUFFER *buffer = NULL;
4954 uint32 offered = q_u->offered;
4955 uint32 *needed = &r_u->needed;
4956 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4958 int snum;
4960 /* that's an [in out] buffer */
4962 if ( q_u->buffer ) {
4963 rpcbuf_move(q_u->buffer, &r_u->buffer);
4964 buffer = r_u->buffer;
4967 *needed=0;
4969 if (!get_printer_snum(p, handle, &snum))
4970 return WERR_BADFID;
4972 switch (level) {
4973 case 0:
4974 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4975 case 1:
4976 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4977 case 2:
4978 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4979 case 3:
4980 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4981 case 4:
4982 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4983 case 5:
4984 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4985 case 7:
4986 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4988 return WERR_UNKNOWN_LEVEL;
4991 /********************************************************************
4992 * fill a DRIVER_INFO_1 struct
4993 ********************************************************************/
4995 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4997 init_unistr( &info->name, driver.info_3->name);
5000 /********************************************************************
5001 * construct_printer_driver_info_1
5002 ********************************************************************/
5004 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5006 NT_PRINTER_INFO_LEVEL *printer = NULL;
5007 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5009 ZERO_STRUCT(driver);
5011 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5012 return WERR_INVALID_PRINTER_NAME;
5014 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5015 return WERR_UNKNOWN_PRINTER_DRIVER;
5017 fill_printer_driver_info_1(info, driver, servername, architecture);
5019 free_a_printer(&printer,2);
5021 return WERR_OK;
5024 /********************************************************************
5025 * construct_printer_driver_info_2
5026 * fill a printer_info_2 struct
5027 ********************************************************************/
5029 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5031 pstring temp;
5033 info->version=driver.info_3->cversion;
5035 init_unistr( &info->name, driver.info_3->name );
5036 init_unistr( &info->architecture, driver.info_3->environment );
5039 if (strlen(driver.info_3->driverpath)) {
5040 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5041 init_unistr( &info->driverpath, temp );
5042 } else
5043 init_unistr( &info->driverpath, "" );
5045 if (strlen(driver.info_3->datafile)) {
5046 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5047 init_unistr( &info->datafile, temp );
5048 } else
5049 init_unistr( &info->datafile, "" );
5051 if (strlen(driver.info_3->configfile)) {
5052 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5053 init_unistr( &info->configfile, temp );
5054 } else
5055 init_unistr( &info->configfile, "" );
5058 /********************************************************************
5059 * construct_printer_driver_info_2
5060 * fill a printer_info_2 struct
5061 ********************************************************************/
5063 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5065 NT_PRINTER_INFO_LEVEL *printer = NULL;
5066 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5068 ZERO_STRUCT(printer);
5069 ZERO_STRUCT(driver);
5071 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5072 return WERR_INVALID_PRINTER_NAME;
5074 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5075 return WERR_UNKNOWN_PRINTER_DRIVER;
5077 fill_printer_driver_info_2(info, driver, servername);
5079 free_a_printer(&printer,2);
5081 return WERR_OK;
5084 /********************************************************************
5085 * copy a strings array and convert to UNICODE
5087 * convert an array of ascii string to a UNICODE string
5088 ********************************************************************/
5090 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5092 int i=0;
5093 int j=0;
5094 const char *v;
5095 pstring line;
5096 uint16 *tuary;
5098 DEBUG(6,("init_unistr_array\n"));
5099 *uni_array=NULL;
5101 while (True)
5103 if ( !char_array )
5104 v = "";
5105 else
5107 v = char_array[i];
5108 if (!v)
5109 v = ""; /* hack to handle null lists */
5112 /* hack to allow this to be used in places other than when generating
5113 the list of dependent files */
5115 if ( servername )
5116 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5117 else
5118 pstrcpy( line, v );
5120 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5122 /* add one extra unit16 for the second terminating NULL */
5124 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5125 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5126 return 0;
5127 } else
5128 *uni_array = tuary;
5130 if ( !strlen(v) )
5131 break;
5133 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5134 i++;
5137 if (*uni_array) {
5138 /* special case for ""; we need to add both NULL's here */
5139 if (!j)
5140 (*uni_array)[j++]=0x0000;
5141 (*uni_array)[j]=0x0000;
5144 DEBUGADD(6,("last one:done\n"));
5146 /* return size of array in uint16's */
5148 return j+1;
5151 /********************************************************************
5152 * construct_printer_info_3
5153 * fill a printer_info_3 struct
5154 ********************************************************************/
5156 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5158 pstring temp;
5160 ZERO_STRUCTP(info);
5162 info->version=driver.info_3->cversion;
5164 init_unistr( &info->name, driver.info_3->name );
5165 init_unistr( &info->architecture, driver.info_3->environment );
5167 if (strlen(driver.info_3->driverpath)) {
5168 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5169 init_unistr( &info->driverpath, temp );
5170 } else
5171 init_unistr( &info->driverpath, "" );
5173 if (strlen(driver.info_3->datafile)) {
5174 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5175 init_unistr( &info->datafile, temp );
5176 } else
5177 init_unistr( &info->datafile, "" );
5179 if (strlen(driver.info_3->configfile)) {
5180 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5181 init_unistr( &info->configfile, temp );
5182 } else
5183 init_unistr( &info->configfile, "" );
5185 if (strlen(driver.info_3->helpfile)) {
5186 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5187 init_unistr( &info->helpfile, temp );
5188 } else
5189 init_unistr( &info->helpfile, "" );
5191 init_unistr( &info->monitorname, driver.info_3->monitorname );
5192 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5194 info->dependentfiles=NULL;
5195 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5198 /********************************************************************
5199 * construct_printer_info_3
5200 * fill a printer_info_3 struct
5201 ********************************************************************/
5203 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5205 NT_PRINTER_INFO_LEVEL *printer = NULL;
5206 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5207 WERROR status;
5208 ZERO_STRUCT(driver);
5210 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5211 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5212 if (!W_ERROR_IS_OK(status))
5213 return WERR_INVALID_PRINTER_NAME;
5215 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5216 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5218 #if 0 /* JERRY */
5221 * I put this code in during testing. Helpful when commenting out the
5222 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5223 * as win2k always queries the driver using an infor level of 6.
5224 * I've left it in (but ifdef'd out) because I'll probably
5225 * use it in experimentation again in the future. --jerry 22/01/2002
5228 if (!W_ERROR_IS_OK(status)) {
5230 * Is this a W2k client ?
5232 if (version == 3) {
5233 /* Yes - try again with a WinNT driver. */
5234 version = 2;
5235 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5236 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5238 #endif
5240 if (!W_ERROR_IS_OK(status)) {
5241 free_a_printer(&printer,2);
5242 return WERR_UNKNOWN_PRINTER_DRIVER;
5245 #if 0 /* JERRY */
5247 #endif
5250 fill_printer_driver_info_3(info, driver, servername);
5252 free_a_printer(&printer,2);
5254 return WERR_OK;
5257 /********************************************************************
5258 * construct_printer_info_6
5259 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5260 ********************************************************************/
5262 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5264 pstring temp;
5265 fstring nullstr;
5267 ZERO_STRUCTP(info);
5268 memset(&nullstr, '\0', sizeof(fstring));
5270 info->version=driver.info_3->cversion;
5272 init_unistr( &info->name, driver.info_3->name );
5273 init_unistr( &info->architecture, driver.info_3->environment );
5275 if (strlen(driver.info_3->driverpath)) {
5276 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5277 init_unistr( &info->driverpath, temp );
5278 } else
5279 init_unistr( &info->driverpath, "" );
5281 if (strlen(driver.info_3->datafile)) {
5282 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5283 init_unistr( &info->datafile, temp );
5284 } else
5285 init_unistr( &info->datafile, "" );
5287 if (strlen(driver.info_3->configfile)) {
5288 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5289 init_unistr( &info->configfile, temp );
5290 } else
5291 init_unistr( &info->configfile, "" );
5293 if (strlen(driver.info_3->helpfile)) {
5294 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5295 init_unistr( &info->helpfile, temp );
5296 } else
5297 init_unistr( &info->helpfile, "" );
5299 init_unistr( &info->monitorname, driver.info_3->monitorname );
5300 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5302 info->dependentfiles = NULL;
5303 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5305 info->previousdrivernames=NULL;
5306 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5308 info->driver_date.low=0;
5309 info->driver_date.high=0;
5311 info->padding=0;
5312 info->driver_version_low=0;
5313 info->driver_version_high=0;
5315 init_unistr( &info->mfgname, "");
5316 init_unistr( &info->oem_url, "");
5317 init_unistr( &info->hardware_id, "");
5318 init_unistr( &info->provider, "");
5321 /********************************************************************
5322 * construct_printer_info_6
5323 * fill a printer_info_6 struct
5324 ********************************************************************/
5326 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5327 fstring servername, fstring architecture, uint32 version)
5329 NT_PRINTER_INFO_LEVEL *printer = NULL;
5330 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5331 WERROR status;
5333 ZERO_STRUCT(driver);
5335 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5337 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5339 if (!W_ERROR_IS_OK(status))
5340 return WERR_INVALID_PRINTER_NAME;
5342 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5344 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5346 if (!W_ERROR_IS_OK(status))
5349 * Is this a W2k client ?
5352 if (version < 3) {
5353 free_a_printer(&printer,2);
5354 return WERR_UNKNOWN_PRINTER_DRIVER;
5357 /* Yes - try again with a WinNT driver. */
5358 version = 2;
5359 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5360 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5361 if (!W_ERROR_IS_OK(status)) {
5362 free_a_printer(&printer,2);
5363 return WERR_UNKNOWN_PRINTER_DRIVER;
5367 fill_printer_driver_info_6(info, driver, servername);
5369 free_a_printer(&printer,2);
5370 free_a_printer_driver(driver, 3);
5372 return WERR_OK;
5375 /****************************************************************************
5376 ****************************************************************************/
5378 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5380 SAFE_FREE(info->dependentfiles);
5383 /****************************************************************************
5384 ****************************************************************************/
5386 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5388 SAFE_FREE(info->dependentfiles);
5391 /****************************************************************************
5392 ****************************************************************************/
5394 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5396 DRIVER_INFO_1 *info=NULL;
5397 WERROR result;
5399 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5400 return WERR_NOMEM;
5402 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5403 if (!W_ERROR_IS_OK(result))
5404 goto out;
5406 /* check the required size. */
5407 *needed += spoolss_size_printer_driver_info_1(info);
5409 if (*needed > offered) {
5410 result = WERR_INSUFFICIENT_BUFFER;
5411 goto out;
5414 if (!rpcbuf_alloc_size(buffer, *needed)) {
5415 result = WERR_NOMEM;
5416 goto out;
5419 /* fill the buffer with the structures */
5420 smb_io_printer_driver_info_1("", buffer, info, 0);
5422 out:
5423 /* clear memory */
5424 SAFE_FREE(info);
5426 return result;
5429 /****************************************************************************
5430 ****************************************************************************/
5432 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5434 DRIVER_INFO_2 *info=NULL;
5435 WERROR result;
5437 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5438 return WERR_NOMEM;
5440 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5441 if (!W_ERROR_IS_OK(result))
5442 goto out;
5444 /* check the required size. */
5445 *needed += spoolss_size_printer_driver_info_2(info);
5447 if (*needed > offered) {
5448 result = WERR_INSUFFICIENT_BUFFER;
5449 goto out;
5452 if (!rpcbuf_alloc_size(buffer, *needed)) {
5453 result = WERR_NOMEM;
5454 goto out;
5457 /* fill the buffer with the structures */
5458 smb_io_printer_driver_info_2("", buffer, info, 0);
5460 out:
5461 /* clear memory */
5462 SAFE_FREE(info);
5464 return result;
5467 /****************************************************************************
5468 ****************************************************************************/
5470 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5472 DRIVER_INFO_3 info;
5473 WERROR result;
5475 ZERO_STRUCT(info);
5477 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5478 if (!W_ERROR_IS_OK(result))
5479 goto out;
5481 /* check the required size. */
5482 *needed += spoolss_size_printer_driver_info_3(&info);
5484 if (*needed > offered) {
5485 result = WERR_INSUFFICIENT_BUFFER;
5486 goto out;
5489 if (!rpcbuf_alloc_size(buffer, *needed)) {
5490 result = WERR_NOMEM;
5491 goto out;
5494 /* fill the buffer with the structures */
5495 smb_io_printer_driver_info_3("", buffer, &info, 0);
5497 out:
5498 free_printer_driver_info_3(&info);
5500 return result;
5503 /****************************************************************************
5504 ****************************************************************************/
5506 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5508 DRIVER_INFO_6 info;
5509 WERROR result;
5511 ZERO_STRUCT(info);
5513 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5514 if (!W_ERROR_IS_OK(result))
5515 goto out;
5517 /* check the required size. */
5518 *needed += spoolss_size_printer_driver_info_6(&info);
5520 if (*needed > offered) {
5521 result = WERR_INSUFFICIENT_BUFFER;
5522 goto out;
5525 if (!rpcbuf_alloc_size(buffer, *needed)) {
5526 result = WERR_NOMEM;
5527 goto out;
5530 /* fill the buffer with the structures */
5531 smb_io_printer_driver_info_6("", buffer, &info, 0);
5533 out:
5534 free_printer_driver_info_6(&info);
5536 return result;
5539 /****************************************************************************
5540 ****************************************************************************/
5542 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5544 POLICY_HND *handle = &q_u->handle;
5545 UNISTR2 *uni_arch = &q_u->architecture;
5546 uint32 level = q_u->level;
5547 uint32 clientmajorversion = q_u->clientmajorversion;
5548 RPC_BUFFER *buffer = NULL;
5549 uint32 offered = q_u->offered;
5550 uint32 *needed = &r_u->needed;
5551 uint32 *servermajorversion = &r_u->servermajorversion;
5552 uint32 *serverminorversion = &r_u->serverminorversion;
5553 Printer_entry *printer;
5555 fstring servername;
5556 fstring architecture;
5557 int snum;
5559 /* that's an [in out] buffer */
5561 if ( q_u->buffer ) {
5562 rpcbuf_move(q_u->buffer, &r_u->buffer);
5563 buffer = r_u->buffer;
5566 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5568 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5569 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5570 return WERR_INVALID_PRINTER_NAME;
5573 *needed = 0;
5574 *servermajorversion = 0;
5575 *serverminorversion = 0;
5577 fstrcpy(servername, get_server_name( printer ));
5578 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5580 if (!get_printer_snum(p, handle, &snum))
5581 return WERR_BADFID;
5583 switch (level) {
5584 case 1:
5585 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5586 case 2:
5587 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5588 case 3:
5589 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5590 case 6:
5591 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5592 #if 0 /* JERRY */
5593 case 101:
5594 /* apparently this call is the equivalent of
5595 EnumPrinterDataEx() for the DsDriver key */
5596 break;
5597 #endif
5600 return WERR_UNKNOWN_LEVEL;
5603 /****************************************************************************
5604 ****************************************************************************/
5606 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5608 POLICY_HND *handle = &q_u->handle;
5610 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5612 if (!Printer) {
5613 DEBUG(3,("Error in startpageprinter printer handle\n"));
5614 return WERR_BADFID;
5617 Printer->page_started=True;
5618 return WERR_OK;
5621 /****************************************************************************
5622 ****************************************************************************/
5624 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5626 POLICY_HND *handle = &q_u->handle;
5627 int snum;
5629 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5631 if (!Printer) {
5632 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5633 return WERR_BADFID;
5636 if (!get_printer_snum(p, handle, &snum))
5637 return WERR_BADFID;
5639 Printer->page_started=False;
5640 print_job_endpage(snum, Printer->jobid);
5642 return WERR_OK;
5645 /********************************************************************
5646 * api_spoolss_getprinter
5647 * called from the spoolss dispatcher
5649 ********************************************************************/
5651 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5653 POLICY_HND *handle = &q_u->handle;
5654 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5655 uint32 *jobid = &r_u->jobid;
5657 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5658 int snum;
5659 pstring jobname;
5660 fstring datatype;
5661 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5662 struct current_user user;
5664 if (!Printer) {
5665 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5666 return WERR_BADFID;
5669 get_current_user(&user, p);
5672 * a nice thing with NT is it doesn't listen to what you tell it.
5673 * when asked to send _only_ RAW datas, it tries to send datas
5674 * in EMF format.
5676 * So I add checks like in NT Server ...
5679 if (info_1->p_datatype != 0) {
5680 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5681 if (strcmp(datatype, "RAW") != 0) {
5682 (*jobid)=0;
5683 return WERR_INVALID_DATATYPE;
5687 /* get the share number of the printer */
5688 if (!get_printer_snum(p, handle, &snum)) {
5689 return WERR_BADFID;
5692 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5694 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5696 /* An error occured in print_job_start() so return an appropriate
5697 NT error code. */
5699 if (Printer->jobid == -1) {
5700 return map_werror_from_unix(errno);
5703 Printer->document_started=True;
5704 (*jobid) = Printer->jobid;
5706 return WERR_OK;
5709 /********************************************************************
5710 * api_spoolss_getprinter
5711 * called from the spoolss dispatcher
5713 ********************************************************************/
5715 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5717 POLICY_HND *handle = &q_u->handle;
5719 return _spoolss_enddocprinter_internal(p, handle);
5722 /****************************************************************************
5723 ****************************************************************************/
5725 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5727 POLICY_HND *handle = &q_u->handle;
5728 uint32 buffer_size = q_u->buffer_size;
5729 uint8 *buffer = q_u->buffer;
5730 uint32 *buffer_written = &q_u->buffer_size2;
5731 int snum;
5732 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5734 if (!Printer) {
5735 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5736 r_u->buffer_written = q_u->buffer_size2;
5737 return WERR_BADFID;
5740 if (!get_printer_snum(p, handle, &snum))
5741 return WERR_BADFID;
5743 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5744 (SMB_OFF_T)-1, (size_t)buffer_size);
5745 if (*buffer_written == (uint32)-1) {
5746 r_u->buffer_written = 0;
5747 if (errno == ENOSPC)
5748 return WERR_NO_SPOOL_SPACE;
5749 else
5750 return WERR_ACCESS_DENIED;
5753 r_u->buffer_written = q_u->buffer_size2;
5755 return WERR_OK;
5758 /********************************************************************
5759 * api_spoolss_getprinter
5760 * called from the spoolss dispatcher
5762 ********************************************************************/
5764 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5765 pipes_struct *p)
5767 struct current_user user;
5768 int snum;
5769 WERROR errcode = WERR_BADFUNC;
5770 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5772 get_current_user(&user, p);
5774 if (!Printer) {
5775 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5776 return WERR_BADFID;
5779 if (!get_printer_snum(p, handle, &snum))
5780 return WERR_BADFID;
5782 switch (command) {
5783 case PRINTER_CONTROL_PAUSE:
5784 if (print_queue_pause(&user, snum, &errcode)) {
5785 errcode = WERR_OK;
5787 break;
5788 case PRINTER_CONTROL_RESUME:
5789 case PRINTER_CONTROL_UNPAUSE:
5790 if (print_queue_resume(&user, snum, &errcode)) {
5791 errcode = WERR_OK;
5793 break;
5794 case PRINTER_CONTROL_PURGE:
5795 if (print_queue_purge(&user, snum, &errcode)) {
5796 errcode = WERR_OK;
5798 break;
5799 default:
5800 return WERR_UNKNOWN_LEVEL;
5803 return errcode;
5806 /********************************************************************
5807 * api_spoolss_abortprinter
5808 * From MSDN: "Deletes printer's spool file if printer is configured
5809 * for spooling"
5810 ********************************************************************/
5812 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5814 POLICY_HND *handle = &q_u->handle;
5815 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5816 int snum;
5817 struct current_user user;
5818 WERROR errcode = WERR_OK;
5820 if (!Printer) {
5821 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5822 return WERR_BADFID;
5825 if (!get_printer_snum(p, handle, &snum))
5826 return WERR_BADFID;
5828 get_current_user( &user, p );
5830 print_job_delete( &user, snum, Printer->jobid, &errcode );
5832 return errcode;
5835 /********************************************************************
5836 * called by spoolss_api_setprinter
5837 * when updating a printer description
5838 ********************************************************************/
5840 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5841 const SPOOL_PRINTER_INFO_LEVEL *info,
5842 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5844 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5845 WERROR result;
5846 int snum;
5848 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5850 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5851 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5852 OUR_HANDLE(handle)));
5854 result = WERR_BADFID;
5855 goto done;
5858 /* Check the user has permissions to change the security
5859 descriptor. By experimentation with two NT machines, the user
5860 requires Full Access to the printer to change security
5861 information. */
5863 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5864 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5865 result = WERR_ACCESS_DENIED;
5866 goto done;
5869 /* NT seems to like setting the security descriptor even though
5870 nothing may have actually changed. */
5872 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5874 if (DEBUGLEVEL >= 10) {
5875 SEC_ACL *the_acl;
5876 int i;
5878 the_acl = old_secdesc_ctr->sec->dacl;
5879 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5880 PRINTERNAME(snum), the_acl->num_aces));
5882 for (i = 0; i < the_acl->num_aces; i++) {
5883 fstring sid_str;
5885 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5887 DEBUG(10, ("%s 0x%08x\n", sid_str,
5888 the_acl->ace[i].info.mask));
5891 the_acl = secdesc_ctr->sec->dacl;
5893 if (the_acl) {
5894 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5895 PRINTERNAME(snum), the_acl->num_aces));
5897 for (i = 0; i < the_acl->num_aces; i++) {
5898 fstring sid_str;
5900 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5902 DEBUG(10, ("%s 0x%08x\n", sid_str,
5903 the_acl->ace[i].info.mask));
5905 } else {
5906 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5910 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5912 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5913 result = WERR_OK;
5914 goto done;
5917 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5919 done:
5921 return result;
5924 /********************************************************************
5925 Canonicalize printer info from a client
5927 ATTN: It does not matter what we set the servername to hear
5928 since we do the necessary work in get_a_printer() to set it to
5929 the correct value based on what the client sent in the
5930 _spoolss_open_printer_ex().
5931 ********************************************************************/
5933 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5935 fstring printername;
5936 const char *p;
5938 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5939 "portname=%s drivername=%s comment=%s location=%s\n",
5940 info->servername, info->printername, info->sharename,
5941 info->portname, info->drivername, info->comment, info->location));
5943 /* we force some elements to "correct" values */
5944 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5945 fstrcpy(info->sharename, lp_servicename(snum));
5947 /* check to see if we allow printername != sharename */
5949 if ( lp_force_printername(snum) ) {
5950 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5951 global_myname(), info->sharename );
5952 } else {
5954 /* make sure printername is in \\server\printername format */
5956 fstrcpy( printername, info->printername );
5957 p = printername;
5958 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5959 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5960 p++;
5963 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5964 global_myname(), p );
5967 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5968 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5972 return True;
5975 /****************************************************************************
5976 ****************************************************************************/
5978 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5980 char *cmd = lp_addprinter_cmd();
5981 char **qlines;
5982 pstring command;
5983 int numlines;
5984 int ret;
5985 int fd;
5986 fstring remote_machine = "%m";
5987 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5988 BOOL is_print_op = False;
5990 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5992 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5993 cmd, printer->info_2->printername, printer->info_2->sharename,
5994 printer->info_2->portname, printer->info_2->drivername,
5995 printer->info_2->location, printer->info_2->comment, remote_machine);
5997 if ( token )
5998 is_print_op = user_has_privileges( token, &se_printop );
6000 DEBUG(10,("Running [%s]\n", command));
6002 /********* BEGIN SePrintOperatorPrivilege **********/
6004 if ( is_print_op )
6005 become_root();
6007 if ( (ret = smbrun(command, &fd)) == 0 ) {
6008 /* Tell everyone we updated smb.conf. */
6009 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6012 if ( is_print_op )
6013 unbecome_root();
6015 /********* END SePrintOperatorPrivilege **********/
6017 DEBUGADD(10,("returned [%d]\n", ret));
6019 if ( ret != 0 ) {
6020 if (fd != -1)
6021 close(fd);
6022 return False;
6025 /* reload our services immediately */
6026 reload_services( False );
6028 numlines = 0;
6029 /* Get lines and convert them back to dos-codepage */
6030 qlines = fd_lines_load(fd, &numlines, 0);
6031 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6032 close(fd);
6034 /* Set the portname to what the script says the portname should be. */
6035 /* but don't require anything to be return from the script exit a good error code */
6037 if (numlines) {
6038 /* Set the portname to what the script says the portname should be. */
6039 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6040 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6043 file_lines_free(qlines);
6044 return True;
6047 /********************************************************************
6048 * Called by spoolss_api_setprinter
6049 * when updating a printer description.
6050 ********************************************************************/
6052 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6053 const SPOOL_PRINTER_INFO_LEVEL *info,
6054 DEVICEMODE *devmode)
6056 int snum;
6057 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6058 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6059 WERROR result;
6060 UNISTR2 buffer;
6061 fstring asc_buffer;
6063 DEBUG(8,("update_printer\n"));
6065 result = WERR_OK;
6067 if (!Printer) {
6068 result = WERR_BADFID;
6069 goto done;
6072 if (!get_printer_snum(p, handle, &snum)) {
6073 result = WERR_BADFID;
6074 goto done;
6077 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6078 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6079 result = WERR_BADFID;
6080 goto done;
6083 DEBUGADD(8,("Converting info_2 struct\n"));
6086 * convert_printer_info converts the incoming
6087 * info from the client and overwrites the info
6088 * just read from the tdb in the pointer 'printer'.
6091 if (!convert_printer_info(info, printer, level)) {
6092 result = WERR_NOMEM;
6093 goto done;
6096 if (devmode) {
6097 /* we have a valid devmode
6098 convert it and link it*/
6100 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6101 if (!convert_devicemode(printer->info_2->printername, devmode,
6102 &printer->info_2->devmode)) {
6103 result = WERR_NOMEM;
6104 goto done;
6108 /* Do sanity check on the requested changes for Samba */
6110 if (!check_printer_ok(printer->info_2, snum)) {
6111 result = WERR_INVALID_PARAM;
6112 goto done;
6115 /* FIXME!!! If the driver has changed we really should verify that
6116 it is installed before doing much else --jerry */
6118 /* Check calling user has permission to update printer description */
6120 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6121 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6122 result = WERR_ACCESS_DENIED;
6123 goto done;
6126 /* Call addprinter hook */
6127 /* Check changes to see if this is really needed */
6129 if ( *lp_addprinter_cmd()
6130 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6131 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6132 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6133 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6135 /* add_printer_hook() will call reload_services() */
6137 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6138 result = WERR_ACCESS_DENIED;
6139 goto done;
6144 * When a *new* driver is bound to a printer, the drivername is used to
6145 * lookup previously saved driver initialization info, which is then
6146 * bound to the printer, simulating what happens in the Windows arch.
6148 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6150 if (!set_driver_init(printer, 2))
6152 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6153 printer->info_2->drivername));
6156 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6157 printer->info_2->drivername));
6159 notify_printer_driver(snum, printer->info_2->drivername);
6163 * flag which changes actually occured. This is a small subset of
6164 * all the possible changes. We also have to update things in the
6165 * DsSpooler key.
6168 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6169 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6170 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6171 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6173 notify_printer_comment(snum, printer->info_2->comment);
6176 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6177 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6178 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6179 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6181 notify_printer_sharename(snum, printer->info_2->sharename);
6184 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6185 char *pname;
6187 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6188 pname++;
6189 else
6190 pname = printer->info_2->printername;
6193 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6194 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6195 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6197 notify_printer_printername( snum, pname );
6200 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6201 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6202 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6203 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6205 notify_printer_port(snum, printer->info_2->portname);
6208 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6209 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6210 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6211 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6213 notify_printer_location(snum, printer->info_2->location);
6216 /* here we need to update some more DsSpooler keys */
6217 /* uNCName, serverName, shortServerName */
6219 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6220 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6221 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6222 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6223 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6225 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6226 global_myname(), printer->info_2->sharename );
6227 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6228 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6229 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6231 /* Update printer info */
6232 result = mod_a_printer(printer, 2);
6234 done:
6235 free_a_printer(&printer, 2);
6236 free_a_printer(&old_printer, 2);
6239 return result;
6242 /****************************************************************************
6243 ****************************************************************************/
6244 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6245 const SPOOL_PRINTER_INFO_LEVEL *info)
6247 #ifdef HAVE_ADS
6248 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6249 int snum;
6250 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6252 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6254 if (!Printer)
6255 return WERR_BADFID;
6257 if (!get_printer_snum(p, handle, &snum))
6258 return WERR_BADFID;
6260 nt_printer_publish(Printer, snum, info7->action);
6262 return WERR_OK;
6263 #else
6264 return WERR_UNKNOWN_LEVEL;
6265 #endif
6267 /****************************************************************************
6268 ****************************************************************************/
6270 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6272 POLICY_HND *handle = &q_u->handle;
6273 uint32 level = q_u->level;
6274 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6275 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6276 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6277 uint32 command = q_u->command;
6278 WERROR result;
6280 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6282 if (!Printer) {
6283 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6284 return WERR_BADFID;
6287 /* check the level */
6288 switch (level) {
6289 case 0:
6290 return control_printer(handle, command, p);
6291 case 2:
6292 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6293 if (!W_ERROR_IS_OK(result))
6294 return result;
6295 if (secdesc_ctr)
6296 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6297 return result;
6298 case 3:
6299 return update_printer_sec(handle, level, info, p,
6300 secdesc_ctr);
6301 case 7:
6302 return publish_or_unpublish_printer(p, handle, info);
6303 default:
6304 return WERR_UNKNOWN_LEVEL;
6308 /****************************************************************************
6309 ****************************************************************************/
6311 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6313 POLICY_HND *handle = &q_u->handle;
6314 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6316 if (!Printer) {
6317 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6318 return WERR_BADFID;
6321 if (Printer->notify.client_connected==True) {
6322 int snum = -1;
6324 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6325 snum = -1;
6326 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6327 !get_printer_snum(p, handle, &snum) )
6328 return WERR_BADFID;
6330 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6333 Printer->notify.flags=0;
6334 Printer->notify.options=0;
6335 Printer->notify.localmachine[0]='\0';
6336 Printer->notify.printerlocal=0;
6337 if (Printer->notify.option)
6338 free_spool_notify_option(&Printer->notify.option);
6339 Printer->notify.client_connected=False;
6341 return WERR_OK;
6344 /****************************************************************************
6345 ****************************************************************************/
6347 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6349 /* that's an [in out] buffer */
6351 if ( q_u->buffer )
6352 rpcbuf_move(q_u->buffer, &r_u->buffer);
6354 r_u->needed = 0;
6355 return WERR_INVALID_PARAM; /* this is what a NT server
6356 returns for AddJob. AddJob
6357 must fail on non-local
6358 printers */
6361 /****************************************************************************
6362 ****************************************************************************/
6364 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6365 int position, int snum,
6366 NT_PRINTER_INFO_LEVEL *ntprinter)
6368 struct tm *t;
6370 t=gmtime(&queue->time);
6372 job_info->jobid=queue->job;
6373 init_unistr(&job_info->printername, lp_servicename(snum));
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->datatype, "RAW");
6378 init_unistr(&job_info->text_status, "");
6379 job_info->status=nt_printj_status(queue->status);
6380 job_info->priority=queue->priority;
6381 job_info->position=position;
6382 job_info->totalpages=queue->page_count;
6383 job_info->pagesprinted=0;
6385 make_systemtime(&job_info->submitted, t);
6388 /****************************************************************************
6389 ****************************************************************************/
6391 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6392 int position, int snum,
6393 NT_PRINTER_INFO_LEVEL *ntprinter,
6394 DEVICEMODE *devmode)
6396 struct tm *t;
6398 t=gmtime(&queue->time);
6400 job_info->jobid=queue->job;
6402 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6404 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6405 init_unistr(&job_info->username, queue->fs_user);
6406 init_unistr(&job_info->document, queue->fs_file);
6407 init_unistr(&job_info->notifyname, queue->fs_user);
6408 init_unistr(&job_info->datatype, "RAW");
6409 init_unistr(&job_info->printprocessor, "winprint");
6410 init_unistr(&job_info->parameters, "");
6411 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6412 init_unistr(&job_info->text_status, "");
6414 /* and here the security descriptor */
6416 job_info->status=nt_printj_status(queue->status);
6417 job_info->priority=queue->priority;
6418 job_info->position=position;
6419 job_info->starttime=0;
6420 job_info->untiltime=0;
6421 job_info->totalpages=queue->page_count;
6422 job_info->size=queue->size;
6423 make_systemtime(&(job_info->submitted), t);
6424 job_info->timeelapsed=0;
6425 job_info->pagesprinted=0;
6427 job_info->devmode = devmode;
6429 return (True);
6432 /****************************************************************************
6433 Enumjobs at level 1.
6434 ****************************************************************************/
6436 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6437 NT_PRINTER_INFO_LEVEL *ntprinter,
6438 RPC_BUFFER *buffer, uint32 offered,
6439 uint32 *needed, uint32 *returned)
6441 JOB_INFO_1 *info;
6442 int i;
6443 WERROR result = WERR_OK;
6445 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6446 if (info==NULL) {
6447 SAFE_FREE(queue);
6448 *returned=0;
6449 return WERR_NOMEM;
6452 for (i=0; i<*returned; i++)
6453 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6455 SAFE_FREE(queue);
6457 /* check the required size. */
6458 for (i=0; i<*returned; i++)
6459 (*needed) += spoolss_size_job_info_1(&info[i]);
6461 if (*needed > offered) {
6462 result = WERR_INSUFFICIENT_BUFFER;
6463 goto out;
6466 if (!rpcbuf_alloc_size(buffer, *needed)) {
6467 result = WERR_NOMEM;
6468 goto out;
6471 /* fill the buffer with the structures */
6472 for (i=0; i<*returned; i++)
6473 smb_io_job_info_1("", buffer, &info[i], 0);
6475 out:
6476 /* clear memory */
6477 SAFE_FREE(info);
6479 if ( !W_ERROR_IS_OK(result) )
6480 *returned = 0;
6482 return result;
6485 /****************************************************************************
6486 Enumjobs at level 2.
6487 ****************************************************************************/
6489 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6490 NT_PRINTER_INFO_LEVEL *ntprinter,
6491 RPC_BUFFER *buffer, uint32 offered,
6492 uint32 *needed, uint32 *returned)
6494 JOB_INFO_2 *info = NULL;
6495 int i;
6496 WERROR result = WERR_OK;
6497 DEVICEMODE *devmode = NULL;
6499 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6500 *returned=0;
6501 return WERR_NOMEM;
6504 /* this should not be a failure condition if the devmode is NULL */
6506 devmode = construct_dev_mode(snum);
6508 for (i=0; i<*returned; i++)
6509 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6511 free_a_printer(&ntprinter, 2);
6512 SAFE_FREE(queue);
6514 /* check the required size. */
6515 for (i=0; i<*returned; i++)
6516 (*needed) += spoolss_size_job_info_2(&info[i]);
6518 if (*needed > offered) {
6519 result = WERR_INSUFFICIENT_BUFFER;
6520 goto out;
6523 if (!rpcbuf_alloc_size(buffer, *needed)) {
6524 result = WERR_NOMEM;
6525 goto out;
6528 /* fill the buffer with the structures */
6529 for (i=0; i<*returned; i++)
6530 smb_io_job_info_2("", buffer, &info[i], 0);
6532 out:
6533 free_devmode(devmode);
6534 SAFE_FREE(info);
6536 if ( !W_ERROR_IS_OK(result) )
6537 *returned = 0;
6539 return result;
6543 /****************************************************************************
6544 Enumjobs.
6545 ****************************************************************************/
6547 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6549 POLICY_HND *handle = &q_u->handle;
6550 uint32 level = q_u->level;
6551 RPC_BUFFER *buffer = NULL;
6552 uint32 offered = q_u->offered;
6553 uint32 *needed = &r_u->needed;
6554 uint32 *returned = &r_u->returned;
6555 WERROR wret;
6556 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6557 int snum;
6558 print_status_struct prt_status;
6559 print_queue_struct *queue=NULL;
6561 /* that's an [in out] buffer */
6563 if ( q_u->buffer ) {
6564 rpcbuf_move(q_u->buffer, &r_u->buffer);
6565 buffer = r_u->buffer;
6568 DEBUG(4,("_spoolss_enumjobs\n"));
6570 *needed=0;
6571 *returned=0;
6573 /* lookup the printer snum and tdb entry */
6575 if (!get_printer_snum(p, handle, &snum))
6576 return WERR_BADFID;
6578 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6579 if ( !W_ERROR_IS_OK(wret) )
6580 return wret;
6582 *returned = print_queue_status(snum, &queue, &prt_status);
6583 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6585 if (*returned == 0) {
6586 SAFE_FREE(queue);
6587 return WERR_OK;
6590 switch (level) {
6591 case 1:
6592 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6593 return wret;
6594 case 2:
6595 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6596 return wret;
6597 default:
6598 SAFE_FREE(queue);
6599 *returned=0;
6600 wret = WERR_UNKNOWN_LEVEL;
6603 free_a_printer( &ntprinter, 2 );
6604 return wret;
6607 /****************************************************************************
6608 ****************************************************************************/
6610 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6612 return WERR_OK;
6615 /****************************************************************************
6616 ****************************************************************************/
6618 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6620 POLICY_HND *handle = &q_u->handle;
6621 uint32 jobid = q_u->jobid;
6622 uint32 command = q_u->command;
6624 struct current_user user;
6625 int snum;
6626 WERROR errcode = WERR_BADFUNC;
6628 if (!get_printer_snum(p, handle, &snum)) {
6629 return WERR_BADFID;
6632 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6633 return WERR_INVALID_PRINTER_NAME;
6636 get_current_user(&user, p);
6638 switch (command) {
6639 case JOB_CONTROL_CANCEL:
6640 case JOB_CONTROL_DELETE:
6641 if (print_job_delete(&user, snum, jobid, &errcode)) {
6642 errcode = WERR_OK;
6644 break;
6645 case JOB_CONTROL_PAUSE:
6646 if (print_job_pause(&user, snum, jobid, &errcode)) {
6647 errcode = WERR_OK;
6649 break;
6650 case JOB_CONTROL_RESTART:
6651 case JOB_CONTROL_RESUME:
6652 if (print_job_resume(&user, snum, jobid, &errcode)) {
6653 errcode = WERR_OK;
6655 break;
6656 default:
6657 return WERR_UNKNOWN_LEVEL;
6660 return errcode;
6663 /****************************************************************************
6664 Enumerates all printer drivers at level 1.
6665 ****************************************************************************/
6667 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6669 int i;
6670 int ndrivers;
6671 uint32 version;
6672 fstring *list = NULL;
6673 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6674 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6675 WERROR result = WERR_OK;
6677 *returned=0;
6679 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6680 list=NULL;
6681 ndrivers=get_ntdrivers(&list, architecture, version);
6682 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6684 if(ndrivers == -1)
6685 return WERR_NOMEM;
6687 if(ndrivers != 0) {
6688 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6689 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6690 SAFE_FREE(driver_info_1);
6691 SAFE_FREE(list);
6692 return WERR_NOMEM;
6694 else driver_info_1 = tdi1;
6697 for (i=0; i<ndrivers; i++) {
6698 WERROR status;
6699 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6700 ZERO_STRUCT(driver);
6701 status = get_a_printer_driver(&driver, 3, list[i],
6702 architecture, version);
6703 if (!W_ERROR_IS_OK(status)) {
6704 SAFE_FREE(list);
6705 return status;
6707 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6708 free_a_printer_driver(driver, 3);
6711 *returned+=ndrivers;
6712 SAFE_FREE(list);
6715 /* check the required size. */
6716 for (i=0; i<*returned; i++) {
6717 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6718 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6721 if (*needed > offered) {
6722 result = WERR_INSUFFICIENT_BUFFER;
6723 goto out;
6726 if (!rpcbuf_alloc_size(buffer, *needed)) {
6727 result = WERR_NOMEM;
6728 goto out;
6731 /* fill the buffer with the driver structures */
6732 for (i=0; i<*returned; i++) {
6733 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6734 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6737 out:
6738 SAFE_FREE(driver_info_1);
6740 if ( !W_ERROR_IS_OK(result) )
6741 *returned = 0;
6743 return result;
6746 /****************************************************************************
6747 Enumerates all printer drivers at level 2.
6748 ****************************************************************************/
6750 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6752 int i;
6753 int ndrivers;
6754 uint32 version;
6755 fstring *list = NULL;
6756 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6757 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6758 WERROR result = WERR_OK;
6760 *returned=0;
6762 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6763 list=NULL;
6764 ndrivers=get_ntdrivers(&list, architecture, version);
6765 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6767 if(ndrivers == -1)
6768 return WERR_NOMEM;
6770 if(ndrivers != 0) {
6771 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6772 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6773 SAFE_FREE(driver_info_2);
6774 SAFE_FREE(list);
6775 return WERR_NOMEM;
6777 else driver_info_2 = tdi2;
6780 for (i=0; i<ndrivers; i++) {
6781 WERROR status;
6783 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6784 ZERO_STRUCT(driver);
6785 status = get_a_printer_driver(&driver, 3, list[i],
6786 architecture, version);
6787 if (!W_ERROR_IS_OK(status)) {
6788 SAFE_FREE(list);
6789 return status;
6791 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6792 free_a_printer_driver(driver, 3);
6795 *returned+=ndrivers;
6796 SAFE_FREE(list);
6799 /* check the required size. */
6800 for (i=0; i<*returned; i++) {
6801 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6802 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6805 if (*needed > offered) {
6806 result = WERR_INSUFFICIENT_BUFFER;
6807 goto out;
6810 if (!rpcbuf_alloc_size(buffer, *needed)) {
6811 result = WERR_NOMEM;
6812 goto out;
6815 /* fill the buffer with the form structures */
6816 for (i=0; i<*returned; i++) {
6817 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6818 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6821 out:
6822 SAFE_FREE(driver_info_2);
6824 if ( !W_ERROR_IS_OK(result) )
6825 *returned = 0;
6827 return result;
6830 /****************************************************************************
6831 Enumerates all printer drivers at level 3.
6832 ****************************************************************************/
6834 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6836 int i;
6837 int ndrivers;
6838 uint32 version;
6839 fstring *list = NULL;
6840 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6841 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6842 WERROR result = WERR_OK;
6844 *returned=0;
6846 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6847 list=NULL;
6848 ndrivers=get_ntdrivers(&list, architecture, version);
6849 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6851 if(ndrivers == -1)
6852 return WERR_NOMEM;
6854 if(ndrivers != 0) {
6855 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6856 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6857 SAFE_FREE(driver_info_3);
6858 SAFE_FREE(list);
6859 return WERR_NOMEM;
6861 else driver_info_3 = tdi3;
6864 for (i=0; i<ndrivers; i++) {
6865 WERROR status;
6867 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6868 ZERO_STRUCT(driver);
6869 status = get_a_printer_driver(&driver, 3, list[i],
6870 architecture, version);
6871 if (!W_ERROR_IS_OK(status)) {
6872 SAFE_FREE(list);
6873 return status;
6875 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6876 free_a_printer_driver(driver, 3);
6879 *returned+=ndrivers;
6880 SAFE_FREE(list);
6883 /* check the required size. */
6884 for (i=0; i<*returned; i++) {
6885 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6886 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6889 if (*needed > offered) {
6890 result = WERR_INSUFFICIENT_BUFFER;
6891 goto out;
6894 if (!rpcbuf_alloc_size(buffer, *needed)) {
6895 result = WERR_NOMEM;
6896 goto out;
6899 /* fill the buffer with the driver structures */
6900 for (i=0; i<*returned; i++) {
6901 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6902 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6905 out:
6906 for (i=0; i<*returned; i++)
6907 SAFE_FREE(driver_info_3[i].dependentfiles);
6909 SAFE_FREE(driver_info_3);
6911 if ( !W_ERROR_IS_OK(result) )
6912 *returned = 0;
6914 return result;
6917 /****************************************************************************
6918 Enumerates all printer drivers.
6919 ****************************************************************************/
6921 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6923 uint32 level = q_u->level;
6924 RPC_BUFFER *buffer = NULL;
6925 uint32 offered = q_u->offered;
6926 uint32 *needed = &r_u->needed;
6927 uint32 *returned = &r_u->returned;
6929 fstring servername;
6930 fstring architecture;
6932 /* that's an [in out] buffer */
6934 if ( q_u->buffer ) {
6935 rpcbuf_move(q_u->buffer, &r_u->buffer);
6936 buffer = r_u->buffer;
6939 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6941 *needed = 0;
6942 *returned = 0;
6944 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6945 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6947 if ( !is_myname_or_ipaddr( servername ) )
6948 return WERR_UNKNOWN_PRINTER_DRIVER;
6950 switch (level) {
6951 case 1:
6952 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6953 case 2:
6954 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6955 case 3:
6956 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6957 default:
6958 return WERR_UNKNOWN_LEVEL;
6962 /****************************************************************************
6963 ****************************************************************************/
6965 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6967 form->flag=list->flag;
6968 init_unistr(&form->name, list->name);
6969 form->width=list->width;
6970 form->length=list->length;
6971 form->left=list->left;
6972 form->top=list->top;
6973 form->right=list->right;
6974 form->bottom=list->bottom;
6977 /****************************************************************************
6978 ****************************************************************************/
6980 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6982 uint32 level = q_u->level;
6983 RPC_BUFFER *buffer = NULL;
6984 uint32 offered = q_u->offered;
6985 uint32 *needed = &r_u->needed;
6986 uint32 *numofforms = &r_u->numofforms;
6987 uint32 numbuiltinforms;
6989 nt_forms_struct *list=NULL;
6990 nt_forms_struct *builtinlist=NULL;
6991 FORM_1 *forms_1;
6992 int buffer_size=0;
6993 int i;
6995 /* that's an [in out] buffer */
6997 if ( q_u->buffer ) {
6998 rpcbuf_move(q_u->buffer, &r_u->buffer);
6999 buffer = r_u->buffer;
7002 DEBUG(4,("_spoolss_enumforms\n"));
7003 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7004 DEBUGADD(5,("Info level [%d]\n", level));
7006 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7007 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7008 *numofforms = get_ntforms(&list);
7009 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7010 *numofforms += numbuiltinforms;
7012 if (*numofforms == 0)
7013 return WERR_NO_MORE_ITEMS;
7015 switch (level) {
7016 case 1:
7017 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7018 *numofforms=0;
7019 return WERR_NOMEM;
7022 /* construct the list of form structures */
7023 for (i=0; i<numbuiltinforms; i++) {
7024 DEBUGADD(6,("Filling form number [%d]\n",i));
7025 fill_form_1(&forms_1[i], &builtinlist[i]);
7028 SAFE_FREE(builtinlist);
7030 for (; i<*numofforms; i++) {
7031 DEBUGADD(6,("Filling form number [%d]\n",i));
7032 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7035 SAFE_FREE(list);
7037 /* check the required size. */
7038 for (i=0; i<numbuiltinforms; i++) {
7039 DEBUGADD(6,("adding form [%d]'s size\n",i));
7040 buffer_size += spoolss_size_form_1(&forms_1[i]);
7042 for (; i<*numofforms; i++) {
7043 DEBUGADD(6,("adding form [%d]'s size\n",i));
7044 buffer_size += spoolss_size_form_1(&forms_1[i]);
7047 *needed=buffer_size;
7049 if (*needed > offered) {
7050 SAFE_FREE(forms_1);
7051 *numofforms=0;
7052 return WERR_INSUFFICIENT_BUFFER;
7055 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7056 SAFE_FREE(forms_1);
7057 *numofforms=0;
7058 return WERR_NOMEM;
7061 /* fill the buffer with the form structures */
7062 for (i=0; i<numbuiltinforms; i++) {
7063 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7064 smb_io_form_1("", buffer, &forms_1[i], 0);
7066 for (; i<*numofforms; i++) {
7067 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7068 smb_io_form_1("", buffer, &forms_1[i], 0);
7071 SAFE_FREE(forms_1);
7073 return WERR_OK;
7075 default:
7076 SAFE_FREE(list);
7077 SAFE_FREE(builtinlist);
7078 return WERR_UNKNOWN_LEVEL;
7083 /****************************************************************************
7084 ****************************************************************************/
7086 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7088 uint32 level = q_u->level;
7089 UNISTR2 *uni_formname = &q_u->formname;
7090 RPC_BUFFER *buffer = NULL;
7091 uint32 offered = q_u->offered;
7092 uint32 *needed = &r_u->needed;
7094 nt_forms_struct *list=NULL;
7095 nt_forms_struct builtin_form;
7096 BOOL foundBuiltin;
7097 FORM_1 form_1;
7098 fstring form_name;
7099 int buffer_size=0;
7100 int numofforms=0, i=0;
7102 /* that's an [in out] buffer */
7104 if ( q_u->buffer ) {
7105 rpcbuf_move(q_u->buffer, &r_u->buffer);
7106 buffer = r_u->buffer;
7109 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7111 DEBUG(4,("_spoolss_getform\n"));
7112 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7113 DEBUGADD(5,("Info level [%d]\n", level));
7115 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7116 if (!foundBuiltin) {
7117 numofforms = get_ntforms(&list);
7118 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7120 if (numofforms == 0)
7121 return WERR_BADFID;
7124 switch (level) {
7125 case 1:
7126 if (foundBuiltin) {
7127 fill_form_1(&form_1, &builtin_form);
7128 } else {
7130 /* Check if the requested name is in the list of form structures */
7131 for (i=0; i<numofforms; i++) {
7133 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7135 if (strequal(form_name, list[i].name)) {
7136 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7137 fill_form_1(&form_1, &list[i]);
7138 break;
7142 SAFE_FREE(list);
7143 if (i == numofforms) {
7144 return WERR_BADFID;
7147 /* check the required size. */
7149 *needed=spoolss_size_form_1(&form_1);
7151 if (*needed > offered)
7152 return WERR_INSUFFICIENT_BUFFER;
7154 if (!rpcbuf_alloc_size(buffer, buffer_size))
7155 return WERR_NOMEM;
7157 /* fill the buffer with the form structures */
7158 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7159 smb_io_form_1("", buffer, &form_1, 0);
7161 return WERR_OK;
7163 default:
7164 SAFE_FREE(list);
7165 return WERR_UNKNOWN_LEVEL;
7169 /****************************************************************************
7170 ****************************************************************************/
7172 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7174 init_unistr(&port->port_name, name);
7177 /****************************************************************************
7178 ****************************************************************************/
7180 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7182 init_unistr(&port->port_name, name);
7183 init_unistr(&port->monitor_name, "Local Monitor");
7184 init_unistr(&port->description, "Local Port");
7185 port->port_type=PORT_TYPE_WRITE;
7186 port->reserved=0x0;
7190 /****************************************************************************
7191 wrapper around the enumer ports command
7192 ****************************************************************************/
7194 WERROR enumports_hook( int *count, char ***lines )
7196 char *cmd = lp_enumports_cmd();
7197 char **qlines;
7198 pstring command;
7199 int numlines;
7200 int ret;
7201 int fd;
7204 /* if no hook then just fill in the default port */
7206 if ( !*cmd ) {
7207 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7208 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7209 qlines[1] = NULL;
7210 numlines = 1;
7212 else {
7213 /* we have a valid enumport command */
7215 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7217 DEBUG(10,("Running [%s]\n", command));
7218 ret = smbrun(command, &fd);
7219 DEBUG(10,("Returned [%d]\n", ret));
7220 if (ret != 0) {
7221 if (fd != -1)
7222 close(fd);
7224 return WERR_ACCESS_DENIED;
7227 numlines = 0;
7228 qlines = fd_lines_load(fd, &numlines, 0);
7229 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7230 close(fd);
7233 *count = numlines;
7234 *lines = qlines;
7236 return WERR_OK;
7239 /****************************************************************************
7240 enumports level 1.
7241 ****************************************************************************/
7243 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7245 PORT_INFO_1 *ports=NULL;
7246 int i=0;
7247 WERROR result = WERR_OK;
7248 char **qlines;
7249 int numlines;
7251 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7252 return result;
7254 if(numlines) {
7255 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7256 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7257 dos_errstr(WERR_NOMEM)));
7258 file_lines_free(qlines);
7259 return WERR_NOMEM;
7262 for (i=0; i<numlines; i++) {
7263 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7264 fill_port_1(&ports[i], qlines[i]);
7267 file_lines_free(qlines);
7270 *returned = numlines;
7272 /* check the required size. */
7273 for (i=0; i<*returned; i++) {
7274 DEBUGADD(6,("adding port [%d]'s size\n", i));
7275 *needed += spoolss_size_port_info_1(&ports[i]);
7278 if (*needed > offered) {
7279 result = WERR_INSUFFICIENT_BUFFER;
7280 goto out;
7283 if (!rpcbuf_alloc_size(buffer, *needed)) {
7284 result = WERR_NOMEM;
7285 goto out;
7288 /* fill the buffer with the ports structures */
7289 for (i=0; i<*returned; i++) {
7290 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7291 smb_io_port_1("", buffer, &ports[i], 0);
7294 out:
7295 SAFE_FREE(ports);
7297 if ( !W_ERROR_IS_OK(result) )
7298 *returned = 0;
7300 return result;
7303 /****************************************************************************
7304 enumports level 2.
7305 ****************************************************************************/
7307 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7309 PORT_INFO_2 *ports=NULL;
7310 int i=0;
7311 WERROR result = WERR_OK;
7312 char **qlines;
7313 int numlines;
7315 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7316 return result;
7319 if(numlines) {
7320 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7321 file_lines_free(qlines);
7322 return WERR_NOMEM;
7325 for (i=0; i<numlines; i++) {
7326 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7327 fill_port_2(&(ports[i]), qlines[i]);
7330 file_lines_free(qlines);
7333 *returned = numlines;
7335 /* check the required size. */
7336 for (i=0; i<*returned; i++) {
7337 DEBUGADD(6,("adding port [%d]'s size\n", i));
7338 *needed += spoolss_size_port_info_2(&ports[i]);
7341 if (*needed > offered) {
7342 result = WERR_INSUFFICIENT_BUFFER;
7343 goto out;
7346 if (!rpcbuf_alloc_size(buffer, *needed)) {
7347 result = WERR_NOMEM;
7348 goto out;
7351 /* fill the buffer with the ports structures */
7352 for (i=0; i<*returned; i++) {
7353 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7354 smb_io_port_2("", buffer, &ports[i], 0);
7357 out:
7358 SAFE_FREE(ports);
7360 if ( !W_ERROR_IS_OK(result) )
7361 *returned = 0;
7363 return result;
7366 /****************************************************************************
7367 enumports.
7368 ****************************************************************************/
7370 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7372 uint32 level = q_u->level;
7373 RPC_BUFFER *buffer = NULL;
7374 uint32 offered = q_u->offered;
7375 uint32 *needed = &r_u->needed;
7376 uint32 *returned = &r_u->returned;
7378 /* that's an [in out] buffer */
7380 if ( q_u->buffer ) {
7381 rpcbuf_move(q_u->buffer, &r_u->buffer);
7382 buffer = r_u->buffer;
7385 DEBUG(4,("_spoolss_enumports\n"));
7387 *returned=0;
7388 *needed=0;
7390 switch (level) {
7391 case 1:
7392 return enumports_level_1(buffer, offered, needed, returned);
7393 case 2:
7394 return enumports_level_2(buffer, offered, needed, returned);
7395 default:
7396 return WERR_UNKNOWN_LEVEL;
7400 /****************************************************************************
7401 ****************************************************************************/
7403 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7404 const SPOOL_PRINTER_INFO_LEVEL *info,
7405 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7406 uint32 user_switch, const SPOOL_USER_CTR *user,
7407 POLICY_HND *handle)
7409 NT_PRINTER_INFO_LEVEL *printer = NULL;
7410 fstring name;
7411 int snum;
7412 WERROR err = WERR_OK;
7414 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7415 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7416 return WERR_NOMEM;
7419 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7420 if (!convert_printer_info(info, printer, 2)) {
7421 free_a_printer(&printer, 2);
7422 return WERR_NOMEM;
7425 /* check to see if the printer already exists */
7427 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7428 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7429 printer->info_2->sharename));
7430 free_a_printer(&printer, 2);
7431 return WERR_PRINTER_ALREADY_EXISTS;
7434 /* FIXME!!! smbd should check to see if the driver is installed before
7435 trying to add a printer like this --jerry */
7437 if (*lp_addprinter_cmd() ) {
7438 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7439 free_a_printer(&printer,2);
7440 return WERR_ACCESS_DENIED;
7442 } else {
7443 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7444 "smb.conf parameter \"addprinter command\" is defined. This"
7445 "parameter must exist for this call to succeed\n",
7446 printer->info_2->sharename ));
7449 /* use our primary netbios name since get_a_printer() will convert
7450 it to what the client expects on a case by case basis */
7452 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7453 printer->info_2->sharename);
7456 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7457 free_a_printer(&printer,2);
7458 return WERR_ACCESS_DENIED;
7461 /* you must be a printer admin to add a new printer */
7462 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7463 free_a_printer(&printer,2);
7464 return WERR_ACCESS_DENIED;
7468 * Do sanity check on the requested changes for Samba.
7471 if (!check_printer_ok(printer->info_2, snum)) {
7472 free_a_printer(&printer,2);
7473 return WERR_INVALID_PARAM;
7477 * When a printer is created, the drivername bound to the printer is used
7478 * to lookup previously saved driver initialization info, which is then
7479 * bound to the new printer, simulating what happens in the Windows arch.
7482 if (!devmode)
7484 set_driver_init(printer, 2);
7486 else
7488 /* A valid devmode was included, convert and link it
7490 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7492 if (!convert_devicemode(printer->info_2->printername, devmode,
7493 &printer->info_2->devmode))
7494 return WERR_NOMEM;
7497 /* write the ASCII on disk */
7498 err = mod_a_printer(printer, 2);
7499 if (!W_ERROR_IS_OK(err)) {
7500 free_a_printer(&printer,2);
7501 return err;
7504 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7505 /* Handle open failed - remove addition. */
7506 del_a_printer(printer->info_2->sharename);
7507 free_a_printer(&printer,2);
7508 return WERR_ACCESS_DENIED;
7511 update_c_setprinter(False);
7512 free_a_printer(&printer,2);
7514 return WERR_OK;
7517 /****************************************************************************
7518 ****************************************************************************/
7520 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7522 UNISTR2 *uni_srv_name = q_u->server_name;
7523 uint32 level = q_u->level;
7524 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7525 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7526 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7527 uint32 user_switch = q_u->user_switch;
7528 SPOOL_USER_CTR *user = &q_u->user_ctr;
7529 POLICY_HND *handle = &r_u->handle;
7531 switch (level) {
7532 case 1:
7533 /* we don't handle yet */
7534 /* but I know what to do ... */
7535 return WERR_UNKNOWN_LEVEL;
7536 case 2:
7537 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7538 devmode, sdb,
7539 user_switch, user, handle);
7540 default:
7541 return WERR_UNKNOWN_LEVEL;
7545 /****************************************************************************
7546 ****************************************************************************/
7548 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7550 uint32 level = q_u->level;
7551 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7552 WERROR err = WERR_OK;
7553 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7554 struct current_user user;
7555 fstring driver_name;
7556 uint32 version;
7558 ZERO_STRUCT(driver);
7560 get_current_user(&user, p);
7562 if (!convert_printer_driver_info(info, &driver, level)) {
7563 err = WERR_NOMEM;
7564 goto done;
7567 DEBUG(5,("Cleaning driver's information\n"));
7568 err = clean_up_driver_struct(driver, level, &user);
7569 if (!W_ERROR_IS_OK(err))
7570 goto done;
7572 DEBUG(5,("Moving driver to final destination\n"));
7573 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7574 goto done;
7577 if (add_a_printer_driver(driver, level)!=0) {
7578 err = WERR_ACCESS_DENIED;
7579 goto done;
7582 /* BEGIN_ADMIN_LOG */
7583 switch(level) {
7584 case 3:
7585 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7586 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7587 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7588 break;
7589 case 6:
7590 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7591 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7592 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7593 break;
7595 /* END_ADMIN_LOG */
7598 * I think this is where he DrvUpgradePrinter() hook would be
7599 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7600 * server. Right now, we just need to send ourselves a message
7601 * to update each printer bound to this driver. --jerry
7604 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7605 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7606 driver_name));
7610 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7611 * decide if the driver init data should be deleted. The rules are:
7612 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7613 * 2) delete init data only if there is no 2k/Xp driver
7614 * 3) always delete init data
7615 * The generalized rule is always use init data from the highest order driver.
7616 * It is necessary to follow the driver install by an initialization step to
7617 * finish off this process.
7619 if (level == 3)
7620 version = driver.info_3->cversion;
7621 else if (level == 6)
7622 version = driver.info_6->version;
7623 else
7624 version = -1;
7625 switch (version) {
7627 * 9x printer driver - never delete init data
7629 case 0:
7630 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7631 driver_name));
7632 break;
7635 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7636 * there is no 2k/Xp driver init data for this driver name.
7638 case 2:
7640 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7642 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7644 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7646 if (!del_driver_init(driver_name))
7647 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7648 } else {
7650 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7652 free_a_printer_driver(driver1,3);
7653 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7654 driver_name));
7657 break;
7660 * 2k or Xp printer driver - always delete init data
7662 case 3:
7663 if (!del_driver_init(driver_name))
7664 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7665 break;
7667 default:
7668 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7669 break;
7673 done:
7674 free_a_printer_driver(driver, level);
7675 return err;
7678 /********************************************************************
7679 * spoolss_addprinterdriverex
7680 ********************************************************************/
7682 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7684 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7685 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7688 * we only support the semantics of AddPrinterDriver()
7689 * i.e. only copy files that are newer than existing ones
7692 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7693 return WERR_ACCESS_DENIED;
7695 ZERO_STRUCT(q_u_local);
7696 ZERO_STRUCT(r_u_local);
7698 /* just pass the information off to _spoolss_addprinterdriver() */
7699 q_u_local.server_name_ptr = q_u->server_name_ptr;
7700 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7701 q_u_local.level = q_u->level;
7702 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7704 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7707 /****************************************************************************
7708 ****************************************************************************/
7710 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7712 init_unistr(&info->name, name);
7715 /****************************************************************************
7716 ****************************************************************************/
7718 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7720 pstring path;
7721 pstring long_archi;
7722 fstring servername;
7723 char *pservername;
7724 const char *short_archi;
7725 DRIVER_DIRECTORY_1 *info=NULL;
7726 WERROR result = WERR_OK;
7728 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7729 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7731 /* check for beginning double '\'s and that the server
7732 long enough */
7734 pservername = servername;
7735 if ( *pservername == '\\' && strlen(servername)>2 ) {
7736 pservername += 2;
7739 if ( !is_myname_or_ipaddr( pservername ) )
7740 return WERR_INVALID_PARAM;
7742 if (!(short_archi = get_short_archi(long_archi)))
7743 return WERR_INVALID_ENVIRONMENT;
7745 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7746 return WERR_NOMEM;
7748 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7750 DEBUG(4,("printer driver directory: [%s]\n", path));
7752 fill_driverdir_1(info, path);
7754 *needed += spoolss_size_driverdir_info_1(info);
7756 if (*needed > offered) {
7757 result = WERR_INSUFFICIENT_BUFFER;
7758 goto out;
7761 if (!rpcbuf_alloc_size(buffer, *needed)) {
7762 result = WERR_NOMEM;
7763 goto out;
7766 smb_io_driverdir_1("", buffer, info, 0);
7768 out:
7769 SAFE_FREE(info);
7771 return result;
7774 /****************************************************************************
7775 ****************************************************************************/
7777 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7779 UNISTR2 *name = &q_u->name;
7780 UNISTR2 *uni_environment = &q_u->environment;
7781 uint32 level = q_u->level;
7782 RPC_BUFFER *buffer = NULL;
7783 uint32 offered = q_u->offered;
7784 uint32 *needed = &r_u->needed;
7786 /* that's an [in out] buffer */
7788 if ( q_u->buffer ) {
7789 rpcbuf_move(q_u->buffer, &r_u->buffer);
7790 buffer = r_u->buffer;
7793 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7795 *needed=0;
7797 switch(level) {
7798 case 1:
7799 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7800 default:
7801 return WERR_UNKNOWN_LEVEL;
7805 /****************************************************************************
7806 ****************************************************************************/
7808 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7810 POLICY_HND *handle = &q_u->handle;
7811 uint32 idx = q_u->index;
7812 uint32 in_value_len = q_u->valuesize;
7813 uint32 in_data_len = q_u->datasize;
7814 uint32 *out_max_value_len = &r_u->valuesize;
7815 uint16 **out_value = &r_u->value;
7816 uint32 *out_value_len = &r_u->realvaluesize;
7817 uint32 *out_type = &r_u->type;
7818 uint32 *out_max_data_len = &r_u->datasize;
7819 uint8 **data_out = &r_u->data;
7820 uint32 *out_data_len = &r_u->realdatasize;
7822 NT_PRINTER_INFO_LEVEL *printer = NULL;
7824 uint32 biggest_valuesize;
7825 uint32 biggest_datasize;
7826 uint32 data_len;
7827 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7828 int snum;
7829 WERROR result;
7830 REGISTRY_VALUE *val = NULL;
7831 NT_PRINTER_DATA *p_data;
7832 int i, key_index, num_values;
7833 int name_length;
7835 *out_type = 0;
7837 *out_max_data_len = 0;
7838 *data_out = NULL;
7839 *out_data_len = 0;
7841 DEBUG(5,("spoolss_enumprinterdata\n"));
7843 if (!Printer) {
7844 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7845 return WERR_BADFID;
7848 if (!get_printer_snum(p,handle, &snum))
7849 return WERR_BADFID;
7851 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7852 if (!W_ERROR_IS_OK(result))
7853 return result;
7855 p_data = printer->info_2->data;
7856 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7858 result = WERR_OK;
7861 * The NT machine wants to know the biggest size of value and data
7863 * cf: MSDN EnumPrinterData remark section
7866 if ( !in_value_len && !in_data_len && (key_index != -1) )
7868 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7870 biggest_valuesize = 0;
7871 biggest_datasize = 0;
7873 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7875 for ( i=0; i<num_values; i++ )
7877 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7879 name_length = strlen(val->valuename);
7880 if ( strlen(val->valuename) > biggest_valuesize )
7881 biggest_valuesize = name_length;
7883 if ( val->size > biggest_datasize )
7884 biggest_datasize = val->size;
7886 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7887 biggest_datasize));
7890 /* the value is an UNICODE string but real_value_size is the length
7891 in bytes including the trailing 0 */
7893 *out_value_len = 2 * (1+biggest_valuesize);
7894 *out_data_len = biggest_datasize;
7896 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7898 goto done;
7902 * the value len is wrong in NT sp3
7903 * that's the number of bytes not the number of unicode chars
7906 if ( key_index != -1 )
7907 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7909 if ( !val )
7912 /* out_value should default to "" or else NT4 has
7913 problems unmarshalling the response */
7915 *out_max_value_len=(in_value_len/sizeof(uint16));
7917 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7919 result = WERR_NOMEM;
7920 goto done;
7923 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7925 /* the data is counted in bytes */
7927 *out_max_data_len = in_data_len;
7928 *out_data_len = in_data_len;
7930 /* only allocate when given a non-zero data_len */
7932 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7934 result = WERR_NOMEM;
7935 goto done;
7938 result = WERR_NO_MORE_ITEMS;
7940 else
7943 * the value is:
7944 * - counted in bytes in the request
7945 * - counted in UNICODE chars in the max reply
7946 * - counted in bytes in the real size
7948 * take a pause *before* coding not *during* coding
7951 /* name */
7952 *out_max_value_len=(in_value_len/sizeof(uint16));
7953 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7955 result = WERR_NOMEM;
7956 goto done;
7959 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7961 /* type */
7963 *out_type = regval_type( val );
7965 /* data - counted in bytes */
7967 *out_max_data_len = in_data_len;
7968 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7970 result = WERR_NOMEM;
7971 goto done;
7973 data_len = regval_size(val);
7974 if ( *data_out )
7975 memcpy( *data_out, regval_data_p(val), data_len );
7976 *out_data_len = data_len;
7979 done:
7980 free_a_printer(&printer, 2);
7981 return result;
7984 /****************************************************************************
7985 ****************************************************************************/
7987 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7989 POLICY_HND *handle = &q_u->handle;
7990 UNISTR2 *value = &q_u->value;
7991 uint32 type = q_u->type;
7992 uint8 *data = q_u->data;
7993 uint32 real_len = q_u->real_len;
7995 NT_PRINTER_INFO_LEVEL *printer = NULL;
7996 int snum=0;
7997 WERROR status = WERR_OK;
7998 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7999 fstring valuename;
8001 DEBUG(5,("spoolss_setprinterdata\n"));
8003 if (!Printer) {
8004 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8005 return WERR_BADFID;
8008 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8009 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8010 return WERR_INVALID_PARAM;
8013 if (!get_printer_snum(p,handle, &snum))
8014 return WERR_BADFID;
8017 * Access check : NT returns "access denied" if you make a
8018 * SetPrinterData call without the necessary privildge.
8019 * we were originally returning OK if nothing changed
8020 * which made Win2k issue **a lot** of SetPrinterData
8021 * when connecting to a printer --jerry
8024 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8026 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8027 status = WERR_ACCESS_DENIED;
8028 goto done;
8031 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8032 if (!W_ERROR_IS_OK(status))
8033 return status;
8035 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8038 * When client side code sets a magic printer data key, detect it and save
8039 * the current printer data and the magic key's data (its the DEVMODE) for
8040 * future printer/driver initializations.
8042 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8044 /* Set devmode and printer initialization info */
8045 status = save_driver_init( printer, 2, data, real_len );
8047 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8049 else
8051 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8052 type, data, real_len );
8053 if ( W_ERROR_IS_OK(status) )
8054 status = mod_a_printer(printer, 2);
8057 done:
8058 free_a_printer(&printer, 2);
8060 return status;
8063 /****************************************************************************
8064 ****************************************************************************/
8066 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8068 POLICY_HND *handle = &q_u->handle;
8069 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8070 int snum;
8072 DEBUG(5,("_spoolss_resetprinter\n"));
8075 * All we do is to check to see if the handle and queue is valid.
8076 * This call really doesn't mean anything to us because we only
8077 * support RAW printing. --jerry
8080 if (!Printer) {
8081 DEBUG(2,("_spoolss_resetprinter: 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;
8089 /* blindly return success */
8090 return WERR_OK;
8094 /****************************************************************************
8095 ****************************************************************************/
8097 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8099 POLICY_HND *handle = &q_u->handle;
8100 UNISTR2 *value = &q_u->valuename;
8102 NT_PRINTER_INFO_LEVEL *printer = NULL;
8103 int snum=0;
8104 WERROR status = WERR_OK;
8105 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8106 pstring valuename;
8108 DEBUG(5,("spoolss_deleteprinterdata\n"));
8110 if (!Printer) {
8111 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8112 return WERR_BADFID;
8115 if (!get_printer_snum(p, handle, &snum))
8116 return WERR_BADFID;
8118 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8119 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8120 return WERR_ACCESS_DENIED;
8123 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8124 if (!W_ERROR_IS_OK(status))
8125 return status;
8127 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8129 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8131 if ( W_ERROR_IS_OK(status) )
8132 mod_a_printer( printer, 2 );
8134 free_a_printer(&printer, 2);
8136 return status;
8139 /****************************************************************************
8140 ****************************************************************************/
8142 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8144 POLICY_HND *handle = &q_u->handle;
8145 FORM *form = &q_u->form;
8146 nt_forms_struct tmpForm;
8147 int snum;
8148 WERROR status = WERR_OK;
8149 NT_PRINTER_INFO_LEVEL *printer = NULL;
8151 int count=0;
8152 nt_forms_struct *list=NULL;
8153 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8155 DEBUG(5,("spoolss_addform\n"));
8157 if (!Printer) {
8158 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8159 return WERR_BADFID;
8163 /* forms can be added on printer of on the print server handle */
8165 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8167 if (!get_printer_snum(p,handle, &snum))
8168 return WERR_BADFID;
8170 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8171 if (!W_ERROR_IS_OK(status))
8172 goto done;
8175 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8176 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8177 status = WERR_ACCESS_DENIED;
8178 goto done;
8181 /* can't add if builtin */
8183 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8184 status = WERR_ALREADY_EXISTS;
8185 goto done;
8188 count = get_ntforms(&list);
8190 if(!add_a_form(&list, form, &count)) {
8191 status = WERR_NOMEM;
8192 goto done;
8195 write_ntforms(&list, count);
8198 * ChangeID must always be set if this is a printer
8201 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8202 status = mod_a_printer(printer, 2);
8204 done:
8205 if ( printer )
8206 free_a_printer(&printer, 2);
8207 SAFE_FREE(list);
8209 return status;
8212 /****************************************************************************
8213 ****************************************************************************/
8215 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8217 POLICY_HND *handle = &q_u->handle;
8218 UNISTR2 *form_name = &q_u->name;
8219 nt_forms_struct tmpForm;
8220 int count=0;
8221 nt_forms_struct *list=NULL;
8222 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8223 int snum;
8224 WERROR status = WERR_OK;
8225 NT_PRINTER_INFO_LEVEL *printer = NULL;
8227 DEBUG(5,("spoolss_deleteform\n"));
8229 if (!Printer) {
8230 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8231 return WERR_BADFID;
8234 /* forms can be deleted on printer of on the print server handle */
8236 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8238 if (!get_printer_snum(p,handle, &snum))
8239 return WERR_BADFID;
8241 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8242 if (!W_ERROR_IS_OK(status))
8243 goto done;
8246 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8247 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8248 status = WERR_ACCESS_DENIED;
8249 goto done;
8252 /* can't delete if builtin */
8254 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8255 status = WERR_INVALID_PARAM;
8256 goto done;
8259 count = get_ntforms(&list);
8261 if ( !delete_a_form(&list, form_name, &count, &status ))
8262 goto done;
8265 * ChangeID must always be set if this is a printer
8268 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8269 status = mod_a_printer(printer, 2);
8271 done:
8272 if ( printer )
8273 free_a_printer(&printer, 2);
8274 SAFE_FREE(list);
8276 return status;
8279 /****************************************************************************
8280 ****************************************************************************/
8282 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8284 POLICY_HND *handle = &q_u->handle;
8285 FORM *form = &q_u->form;
8286 nt_forms_struct tmpForm;
8287 int snum;
8288 WERROR status = WERR_OK;
8289 NT_PRINTER_INFO_LEVEL *printer = NULL;
8291 int count=0;
8292 nt_forms_struct *list=NULL;
8293 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8295 DEBUG(5,("spoolss_setform\n"));
8297 if (!Printer) {
8298 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8299 return WERR_BADFID;
8302 /* forms can be modified on printer of on the print server handle */
8304 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8306 if (!get_printer_snum(p,handle, &snum))
8307 return WERR_BADFID;
8309 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8310 if (!W_ERROR_IS_OK(status))
8311 goto done;
8314 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8315 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8316 status = WERR_ACCESS_DENIED;
8317 goto done;
8320 /* can't set if builtin */
8321 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8322 status = WERR_INVALID_PARAM;
8323 goto done;
8326 count = get_ntforms(&list);
8327 update_a_form(&list, form, count);
8328 write_ntforms(&list, count);
8331 * ChangeID must always be set if this is a printer
8334 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8335 status = mod_a_printer(printer, 2);
8338 done:
8339 if ( printer )
8340 free_a_printer(&printer, 2);
8341 SAFE_FREE(list);
8343 return status;
8346 /****************************************************************************
8347 enumprintprocessors level 1.
8348 ****************************************************************************/
8350 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8352 PRINTPROCESSOR_1 *info_1=NULL;
8353 WERROR result = WERR_OK;
8355 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8356 return WERR_NOMEM;
8358 (*returned) = 0x1;
8360 init_unistr(&info_1->name, "winprint");
8362 *needed += spoolss_size_printprocessor_info_1(info_1);
8364 if (*needed > offered) {
8365 result = WERR_INSUFFICIENT_BUFFER;
8366 goto out;
8369 if (!rpcbuf_alloc_size(buffer, *needed)) {
8370 result = WERR_NOMEM;
8371 goto out;
8374 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8376 out:
8377 SAFE_FREE(info_1);
8379 if ( !W_ERROR_IS_OK(result) )
8380 *returned = 0;
8382 return result;
8385 /****************************************************************************
8386 ****************************************************************************/
8388 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8390 uint32 level = q_u->level;
8391 RPC_BUFFER *buffer = NULL;
8392 uint32 offered = q_u->offered;
8393 uint32 *needed = &r_u->needed;
8394 uint32 *returned = &r_u->returned;
8396 /* that's an [in out] buffer */
8398 if ( q_u->buffer ) {
8399 rpcbuf_move(q_u->buffer, &r_u->buffer);
8400 buffer = r_u->buffer;
8403 DEBUG(5,("spoolss_enumprintprocessors\n"));
8406 * Enumerate the print processors ...
8408 * Just reply with "winprint", to keep NT happy
8409 * and I can use my nice printer checker.
8412 *returned=0;
8413 *needed=0;
8415 switch (level) {
8416 case 1:
8417 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8418 default:
8419 return WERR_UNKNOWN_LEVEL;
8423 /****************************************************************************
8424 enumprintprocdatatypes level 1.
8425 ****************************************************************************/
8427 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8429 PRINTPROCDATATYPE_1 *info_1=NULL;
8430 WERROR result = WERR_NOMEM;
8432 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8433 return WERR_NOMEM;
8435 (*returned) = 0x1;
8437 init_unistr(&info_1->name, "RAW");
8439 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8441 if (*needed > offered) {
8442 result = WERR_INSUFFICIENT_BUFFER;
8443 goto out;
8446 if (!rpcbuf_alloc_size(buffer, *needed)) {
8447 result = WERR_NOMEM;
8448 goto out;
8451 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8453 out:
8454 SAFE_FREE(info_1);
8456 if ( !W_ERROR_IS_OK(result) )
8457 *returned = 0;
8459 return result;
8462 /****************************************************************************
8463 ****************************************************************************/
8465 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8467 uint32 level = q_u->level;
8468 RPC_BUFFER *buffer = NULL;
8469 uint32 offered = q_u->offered;
8470 uint32 *needed = &r_u->needed;
8471 uint32 *returned = &r_u->returned;
8473 /* that's an [in out] buffer */
8475 if ( q_u->buffer ) {
8476 rpcbuf_move(q_u->buffer, &r_u->buffer);
8477 buffer = r_u->buffer;
8480 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8482 *returned=0;
8483 *needed=0;
8485 switch (level) {
8486 case 1:
8487 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8488 default:
8489 return WERR_UNKNOWN_LEVEL;
8493 /****************************************************************************
8494 enumprintmonitors level 1.
8495 ****************************************************************************/
8497 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8499 PRINTMONITOR_1 *info_1=NULL;
8500 WERROR result = WERR_OK;
8502 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8503 return WERR_NOMEM;
8505 (*returned) = 0x1;
8507 init_unistr(&info_1->name, "Local Port");
8509 *needed += spoolss_size_printmonitor_info_1(info_1);
8511 if (*needed > offered) {
8512 result = WERR_INSUFFICIENT_BUFFER;
8513 goto out;
8516 if (!rpcbuf_alloc_size(buffer, *needed)) {
8517 result = WERR_NOMEM;
8518 goto out;
8521 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8523 out:
8524 SAFE_FREE(info_1);
8526 if ( !W_ERROR_IS_OK(result) )
8527 *returned = 0;
8529 return result;
8532 /****************************************************************************
8533 enumprintmonitors level 2.
8534 ****************************************************************************/
8536 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8538 PRINTMONITOR_2 *info_2=NULL;
8539 WERROR result = WERR_OK;
8541 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8542 return WERR_NOMEM;
8544 (*returned) = 0x1;
8546 init_unistr(&info_2->name, "Local Port");
8547 init_unistr(&info_2->environment, "Windows NT X86");
8548 init_unistr(&info_2->dll_name, "localmon.dll");
8550 *needed += spoolss_size_printmonitor_info_2(info_2);
8552 if (*needed > offered) {
8553 result = WERR_INSUFFICIENT_BUFFER;
8554 goto out;
8557 if (!rpcbuf_alloc_size(buffer, *needed)) {
8558 result = WERR_NOMEM;
8559 goto out;
8562 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8564 out:
8565 SAFE_FREE(info_2);
8567 if ( !W_ERROR_IS_OK(result) )
8568 *returned = 0;
8570 return result;
8573 /****************************************************************************
8574 ****************************************************************************/
8576 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8578 uint32 level = q_u->level;
8579 RPC_BUFFER *buffer = NULL;
8580 uint32 offered = q_u->offered;
8581 uint32 *needed = &r_u->needed;
8582 uint32 *returned = &r_u->returned;
8584 /* that's an [in out] buffer */
8586 if ( q_u->buffer ) {
8587 rpcbuf_move(q_u->buffer, &r_u->buffer);
8588 buffer = r_u->buffer;
8591 DEBUG(5,("spoolss_enumprintmonitors\n"));
8594 * Enumerate the print monitors ...
8596 * Just reply with "Local Port", to keep NT happy
8597 * and I can use my nice printer checker.
8600 *returned=0;
8601 *needed=0;
8603 switch (level) {
8604 case 1:
8605 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8606 case 2:
8607 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8608 default:
8609 return WERR_UNKNOWN_LEVEL;
8613 /****************************************************************************
8614 ****************************************************************************/
8616 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8617 NT_PRINTER_INFO_LEVEL *ntprinter,
8618 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8619 uint32 *needed)
8621 int i=0;
8622 BOOL found=False;
8623 JOB_INFO_1 *info_1=NULL;
8624 WERROR result = WERR_OK;
8626 info_1=SMB_MALLOC_P(JOB_INFO_1);
8628 if (info_1 == NULL) {
8629 return WERR_NOMEM;
8632 for (i=0; i<count && found==False; i++) {
8633 if ((*queue)[i].job==(int)jobid)
8634 found=True;
8637 if (found==False) {
8638 SAFE_FREE(info_1);
8639 /* NT treats not found as bad param... yet another bad choice */
8640 return WERR_INVALID_PARAM;
8643 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8645 *needed += spoolss_size_job_info_1(info_1);
8647 if (*needed > offered) {
8648 result = WERR_INSUFFICIENT_BUFFER;
8649 goto out;
8652 if (!rpcbuf_alloc_size(buffer, *needed)) {
8653 result = WERR_NOMEM;
8654 goto out;
8657 smb_io_job_info_1("", buffer, info_1, 0);
8659 out:
8660 SAFE_FREE(info_1);
8662 return result;
8665 /****************************************************************************
8666 ****************************************************************************/
8668 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8669 NT_PRINTER_INFO_LEVEL *ntprinter,
8670 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8671 uint32 *needed)
8673 int i = 0;
8674 BOOL found = False;
8675 JOB_INFO_2 *info_2;
8676 WERROR result;
8677 DEVICEMODE *devmode = NULL;
8678 NT_DEVICEMODE *nt_devmode = NULL;
8680 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8681 return WERR_NOMEM;
8683 ZERO_STRUCTP(info_2);
8685 for ( i=0; i<count && found==False; i++ )
8687 if ((*queue)[i].job == (int)jobid)
8688 found = True;
8691 if ( !found ) {
8692 /* NT treats not found as bad param... yet another bad
8693 choice */
8694 result = WERR_INVALID_PARAM;
8695 goto done;
8699 * if the print job does not have a DEVMODE associated with it,
8700 * just use the one for the printer. A NULL devicemode is not
8701 * a failure condition
8704 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8705 devmode = construct_dev_mode(snum);
8706 else {
8707 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8708 ZERO_STRUCTP( devmode );
8709 convert_nt_devicemode( devmode, nt_devmode );
8713 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8715 *needed += spoolss_size_job_info_2(info_2);
8717 if (*needed > offered) {
8718 result = WERR_INSUFFICIENT_BUFFER;
8719 goto done;
8722 if (!rpcbuf_alloc_size(buffer, *needed)) {
8723 result = WERR_NOMEM;
8724 goto done;
8727 smb_io_job_info_2("", buffer, info_2, 0);
8729 result = WERR_OK;
8731 done:
8732 /* Cleanup allocated memory */
8734 free_job_info_2(info_2); /* Also frees devmode */
8735 SAFE_FREE(info_2);
8737 return result;
8740 /****************************************************************************
8741 ****************************************************************************/
8743 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8745 POLICY_HND *handle = &q_u->handle;
8746 uint32 jobid = q_u->jobid;
8747 uint32 level = q_u->level;
8748 RPC_BUFFER *buffer = NULL;
8749 uint32 offered = q_u->offered;
8750 uint32 *needed = &r_u->needed;
8751 WERROR wstatus = WERR_OK;
8752 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8753 int snum;
8754 int count;
8755 print_queue_struct *queue = NULL;
8756 print_status_struct prt_status;
8758 /* that's an [in out] buffer */
8760 if ( q_u->buffer ) {
8761 rpcbuf_move(q_u->buffer, &r_u->buffer);
8762 buffer = r_u->buffer;
8765 DEBUG(5,("spoolss_getjob\n"));
8767 *needed = 0;
8769 if (!get_printer_snum(p, handle, &snum))
8770 return WERR_BADFID;
8772 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8773 if ( !W_ERROR_IS_OK(wstatus) )
8774 return wstatus;
8776 count = print_queue_status(snum, &queue, &prt_status);
8778 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8779 count, prt_status.status, prt_status.message));
8781 switch ( level ) {
8782 case 1:
8783 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8784 buffer, offered, needed);
8785 break;
8786 case 2:
8787 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8788 buffer, offered, needed);
8789 break;
8790 default:
8791 wstatus = WERR_UNKNOWN_LEVEL;
8792 break;
8795 SAFE_FREE(queue);
8796 free_a_printer( &ntprinter, 2 );
8798 return wstatus;
8801 /********************************************************************
8802 spoolss_getprinterdataex
8804 From MSDN documentation of GetPrinterDataEx: pass request
8805 to GetPrinterData if key is "PrinterDriverData".
8806 ********************************************************************/
8808 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8810 POLICY_HND *handle = &q_u->handle;
8811 uint32 in_size = q_u->size;
8812 uint32 *type = &r_u->type;
8813 uint32 *out_size = &r_u->size;
8814 uint8 **data = &r_u->data;
8815 uint32 *needed = &r_u->needed;
8816 fstring keyname, valuename;
8818 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8820 NT_PRINTER_INFO_LEVEL *printer = NULL;
8821 int snum = 0;
8822 WERROR status = WERR_OK;
8824 DEBUG(4,("_spoolss_getprinterdataex\n"));
8826 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8827 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8829 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8830 keyname, valuename));
8832 /* in case of problem, return some default values */
8834 *needed = 0;
8835 *type = 0;
8836 *out_size = in_size;
8838 if (!Printer) {
8839 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8840 status = WERR_BADFID;
8841 goto done;
8844 /* Is the handle to a printer or to the server? */
8846 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8847 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8848 status = WERR_INVALID_PARAM;
8849 goto done;
8852 if ( !get_printer_snum(p,handle, &snum) )
8853 return WERR_BADFID;
8855 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8856 if ( !W_ERROR_IS_OK(status) )
8857 goto done;
8859 /* check to see if the keyname is valid */
8860 if ( !strlen(keyname) ) {
8861 status = WERR_INVALID_PARAM;
8862 goto done;
8865 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8866 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8867 free_a_printer( &printer, 2 );
8868 status = WERR_BADFILE;
8869 goto done;
8872 /* When given a new keyname, we should just create it */
8874 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8876 if (*needed > *out_size)
8877 status = WERR_MORE_DATA;
8879 done:
8880 if ( !W_ERROR_IS_OK(status) )
8882 DEBUG(5, ("error: allocating %d\n", *out_size));
8884 /* reply this param doesn't exist */
8886 if ( *out_size )
8888 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8889 status = WERR_NOMEM;
8890 goto done;
8893 else {
8894 *data = NULL;
8898 if ( printer )
8899 free_a_printer( &printer, 2 );
8901 return status;
8904 /********************************************************************
8905 * spoolss_setprinterdataex
8906 ********************************************************************/
8908 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8910 POLICY_HND *handle = &q_u->handle;
8911 uint32 type = q_u->type;
8912 uint8 *data = q_u->data;
8913 uint32 real_len = q_u->real_len;
8915 NT_PRINTER_INFO_LEVEL *printer = NULL;
8916 int snum = 0;
8917 WERROR status = WERR_OK;
8918 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8919 fstring valuename;
8920 fstring keyname;
8921 char *oid_string;
8923 DEBUG(4,("_spoolss_setprinterdataex\n"));
8925 /* From MSDN documentation of SetPrinterDataEx: pass request to
8926 SetPrinterData if key is "PrinterDriverData" */
8928 if (!Printer) {
8929 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8930 return WERR_BADFID;
8933 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8934 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8935 return WERR_INVALID_PARAM;
8938 if ( !get_printer_snum(p,handle, &snum) )
8939 return WERR_BADFID;
8942 * Access check : NT returns "access denied" if you make a
8943 * SetPrinterData call without the necessary privildge.
8944 * we were originally returning OK if nothing changed
8945 * which made Win2k issue **a lot** of SetPrinterData
8946 * when connecting to a printer --jerry
8949 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8951 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8952 return WERR_ACCESS_DENIED;
8955 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8956 if (!W_ERROR_IS_OK(status))
8957 return status;
8959 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8960 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8962 /* check for OID in valuename */
8964 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8966 *oid_string = '\0';
8967 oid_string++;
8970 /* save the registry data */
8972 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8974 if ( W_ERROR_IS_OK(status) )
8976 /* save the OID if one was specified */
8977 if ( oid_string ) {
8978 fstrcat( keyname, "\\" );
8979 fstrcat( keyname, SPOOL_OID_KEY );
8982 * I'm not checking the status here on purpose. Don't know
8983 * if this is right, but I'm returning the status from the
8984 * previous set_printer_dataex() call. I have no idea if
8985 * this is right. --jerry
8988 set_printer_dataex( printer, keyname, valuename,
8989 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8992 status = mod_a_printer(printer, 2);
8995 free_a_printer(&printer, 2);
8997 return status;
9001 /********************************************************************
9002 * spoolss_deleteprinterdataex
9003 ********************************************************************/
9005 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9007 POLICY_HND *handle = &q_u->handle;
9008 UNISTR2 *value = &q_u->valuename;
9009 UNISTR2 *key = &q_u->keyname;
9011 NT_PRINTER_INFO_LEVEL *printer = NULL;
9012 int snum=0;
9013 WERROR status = WERR_OK;
9014 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9015 pstring valuename, keyname;
9017 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9019 if (!Printer) {
9020 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9021 return WERR_BADFID;
9024 if (!get_printer_snum(p, handle, &snum))
9025 return WERR_BADFID;
9027 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9028 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9029 return WERR_ACCESS_DENIED;
9032 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9033 if (!W_ERROR_IS_OK(status))
9034 return status;
9036 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9037 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9039 status = delete_printer_dataex( printer, keyname, valuename );
9041 if ( W_ERROR_IS_OK(status) )
9042 mod_a_printer( printer, 2 );
9044 free_a_printer(&printer, 2);
9046 return status;
9049 /********************************************************************
9050 * spoolss_enumprinterkey
9051 ********************************************************************/
9054 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9056 fstring key;
9057 fstring *keynames = NULL;
9058 uint16 *enumkeys = NULL;
9059 int num_keys;
9060 int printerkey_len;
9061 POLICY_HND *handle = &q_u->handle;
9062 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9063 NT_PRINTER_DATA *data;
9064 NT_PRINTER_INFO_LEVEL *printer = NULL;
9065 int snum = 0;
9066 WERROR status = WERR_BADFILE;
9069 DEBUG(4,("_spoolss_enumprinterkey\n"));
9071 if (!Printer) {
9072 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9073 return WERR_BADFID;
9076 if ( !get_printer_snum(p,handle, &snum) )
9077 return WERR_BADFID;
9079 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9080 if (!W_ERROR_IS_OK(status))
9081 return status;
9083 /* get the list of subkey names */
9085 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9086 data = printer->info_2->data;
9088 num_keys = get_printer_subkeys( data, key, &keynames );
9090 if ( num_keys == -1 ) {
9091 status = WERR_BADFILE;
9092 goto done;
9095 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9097 r_u->needed = printerkey_len*2;
9099 if ( q_u->size < r_u->needed ) {
9100 status = WERR_MORE_DATA;
9101 goto done;
9104 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9105 status = WERR_NOMEM;
9106 goto done;
9109 status = WERR_OK;
9111 if ( q_u->size < r_u->needed )
9112 status = WERR_MORE_DATA;
9114 done:
9115 free_a_printer( &printer, 2 );
9116 SAFE_FREE( keynames );
9118 return status;
9121 /********************************************************************
9122 * spoolss_deleteprinterkey
9123 ********************************************************************/
9125 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9127 POLICY_HND *handle = &q_u->handle;
9128 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9129 fstring key;
9130 NT_PRINTER_INFO_LEVEL *printer = NULL;
9131 int snum=0;
9132 WERROR status;
9134 DEBUG(5,("spoolss_deleteprinterkey\n"));
9136 if (!Printer) {
9137 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9138 return WERR_BADFID;
9141 /* if keyname == NULL, return error */
9143 if ( !q_u->keyname.buffer )
9144 return WERR_INVALID_PARAM;
9146 if (!get_printer_snum(p, handle, &snum))
9147 return WERR_BADFID;
9149 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9150 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9151 return WERR_ACCESS_DENIED;
9154 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9155 if (!W_ERROR_IS_OK(status))
9156 return status;
9158 /* delete the key and all subneys */
9160 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9162 status = delete_all_printer_data( printer->info_2, key );
9164 if ( W_ERROR_IS_OK(status) )
9165 status = mod_a_printer(printer, 2);
9167 free_a_printer( &printer, 2 );
9169 return status;
9173 /********************************************************************
9174 * spoolss_enumprinterdataex
9175 ********************************************************************/
9177 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9179 POLICY_HND *handle = &q_u->handle;
9180 uint32 in_size = q_u->size;
9181 uint32 num_entries,
9182 needed;
9183 NT_PRINTER_INFO_LEVEL *printer = NULL;
9184 PRINTER_ENUM_VALUES *enum_values = NULL;
9185 NT_PRINTER_DATA *p_data;
9186 fstring key;
9187 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9188 int snum;
9189 WERROR result;
9190 int key_index;
9191 int i;
9192 REGISTRY_VALUE *val;
9193 char *value_name;
9194 uint32 data_len;
9197 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9199 if (!Printer) {
9200 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9201 return WERR_BADFID;
9205 * first check for a keyname of NULL or "". Win2k seems to send
9206 * this a lot and we should send back WERR_INVALID_PARAM
9207 * no need to spend time looking up the printer in this case.
9208 * --jerry
9211 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9212 if ( !strlen(key) ) {
9213 result = WERR_INVALID_PARAM;
9214 goto done;
9217 /* get the printer off of disk */
9219 if (!get_printer_snum(p,handle, &snum))
9220 return WERR_BADFID;
9222 ZERO_STRUCT(printer);
9223 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9224 if (!W_ERROR_IS_OK(result))
9225 return result;
9227 /* now look for a match on the key name */
9229 p_data = printer->info_2->data;
9231 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9232 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9234 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9235 result = WERR_INVALID_PARAM;
9236 goto done;
9239 result = WERR_OK;
9240 needed = 0;
9242 /* allocate the memory for the array of pointers -- if necessary */
9244 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9245 if ( num_entries )
9247 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9249 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9250 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9251 result = WERR_NOMEM;
9252 goto done;
9255 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9259 * loop through all params and build the array to pass
9260 * back to the client
9263 for ( i=0; i<num_entries; i++ )
9265 /* lookup the registry value */
9267 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9268 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9270 /* copy the data */
9272 value_name = regval_name( val );
9273 init_unistr( &enum_values[i].valuename, value_name );
9274 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9275 enum_values[i].type = regval_type( val );
9277 data_len = regval_size( val );
9278 if ( data_len ) {
9279 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9281 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9282 data_len ));
9283 result = WERR_NOMEM;
9284 goto done;
9287 enum_values[i].data_len = data_len;
9289 /* keep track of the size of the array in bytes */
9291 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9294 /* housekeeping information in the reply */
9296 r_u->needed = needed;
9297 r_u->returned = num_entries;
9299 if (needed > in_size) {
9300 result = WERR_MORE_DATA;
9301 goto done;
9304 /* copy data into the reply */
9306 r_u->ctr.size = r_u->needed;
9307 r_u->ctr.size_of_array = r_u->returned;
9308 r_u->ctr.values = enum_values;
9312 done:
9313 if ( printer )
9314 free_a_printer(&printer, 2);
9316 return result;
9319 /****************************************************************************
9320 ****************************************************************************/
9322 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9324 init_unistr(&info->name, name);
9327 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9328 UNISTR2 *environment,
9329 RPC_BUFFER *buffer,
9330 uint32 offered,
9331 uint32 *needed)
9333 pstring path;
9334 pstring long_archi;
9335 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9336 WERROR result = WERR_OK;
9338 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9340 if (!get_short_archi(long_archi))
9341 return WERR_INVALID_ENVIRONMENT;
9343 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9344 return WERR_NOMEM;
9346 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9348 fill_printprocessordirectory_1(info, path);
9350 *needed += spoolss_size_printprocessordirectory_info_1(info);
9352 if (*needed > offered) {
9353 result = WERR_INSUFFICIENT_BUFFER;
9354 goto out;
9357 if (!rpcbuf_alloc_size(buffer, *needed)) {
9358 result = WERR_INSUFFICIENT_BUFFER;
9359 goto out;
9362 smb_io_printprocessordirectory_1("", buffer, info, 0);
9364 out:
9365 SAFE_FREE(info);
9367 return result;
9370 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9372 uint32 level = q_u->level;
9373 RPC_BUFFER *buffer = NULL;
9374 uint32 offered = q_u->offered;
9375 uint32 *needed = &r_u->needed;
9376 WERROR result;
9378 /* that's an [in out] buffer */
9380 if ( q_u->buffer ) {
9381 rpcbuf_move(q_u->buffer, &r_u->buffer);
9382 buffer = r_u->buffer;
9385 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9387 *needed=0;
9389 switch(level) {
9390 case 1:
9391 result = getprintprocessordirectory_level_1
9392 (&q_u->name, &q_u->environment, buffer, offered, needed);
9393 break;
9394 default:
9395 result = WERR_UNKNOWN_LEVEL;
9398 return result;
9401 #if 0
9403 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9404 SPOOL_R_REPLYOPENPRINTER *r_u)
9406 DEBUG(5,("_spoolss_replyopenprinter\n"));
9408 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9410 return WERR_OK;
9413 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9414 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9416 DEBUG(5,("_spoolss_replycloseprinter\n"));
9417 return WERR_OK;
9420 #endif