Fix bug #5372. With a large CUPS installation with a remote server, contacting
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob40ad81a44952aba25de199a63d8ae8dce0268ef5
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_"
43 struct table_node {
44 const char *long_archi;
45 const char *short_archi;
46 int version;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
55 int snum;
56 uint32 counter;
57 } counter_printer_0;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table {
72 const char *name;
73 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v)
80 switch (v) {
81 case LPQ_QUEUED:
82 return 0;
83 case LPQ_PAUSED:
84 return JOB_STATUS_PAUSED;
85 case LPQ_SPOOLING:
86 return JOB_STATUS_SPOOLING;
87 case LPQ_PRINTING:
88 return JOB_STATUS_PRINTING;
89 case LPQ_ERROR:
90 return JOB_STATUS_ERROR;
91 case LPQ_DELETING:
92 return JOB_STATUS_DELETING;
93 case LPQ_OFFLINE:
94 return JOB_STATUS_OFFLINE;
95 case LPQ_PAPEROUT:
96 return JOB_STATUS_PAPEROUT;
97 case LPQ_PRINTED:
98 return JOB_STATUS_PRINTED;
99 case LPQ_DELETED:
100 return JOB_STATUS_DELETED;
101 case LPQ_BLOCKED:
102 return JOB_STATUS_BLOCKED;
103 case LPQ_USER_INTERVENTION:
104 return JOB_STATUS_USER_INTERVENTION;
106 return 0;
109 static int nt_printq_status(int v)
111 switch (v) {
112 case LPQ_PAUSED:
113 return PRINTER_STATUS_PAUSED;
114 case LPQ_QUEUED:
115 case LPQ_SPOOLING:
116 case LPQ_PRINTING:
117 return 0;
119 return 0;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
128 if (*pp == NULL)
129 return;
131 SAFE_FREE((*pp)->ctr.type);
132 SAFE_FREE(*pp);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
141 WERROR result;
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
154 return;
157 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
159 if (!W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( notify_cli_pipe->cli );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
177 smb_connections--;
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True) {
189 int snum = -1;
191 if ( Printer->printer_type == SPLHND_SERVER) {
192 snum = -1;
193 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
194 } else if (Printer->printer_type == SPLHND_PRINTER) {
195 snum = print_queue_snum(Printer->sharename);
196 if (snum != -1)
197 srv_spoolss_replycloseprinter(snum,
198 &Printer->notify.client_hnd);
202 Printer->notify.flags=0;
203 Printer->notify.options=0;
204 Printer->notify.localmachine[0]='\0';
205 Printer->notify.printerlocal=0;
206 free_spool_notify_option(&Printer->notify.option);
207 Printer->notify.option=NULL;
208 Printer->notify.client_connected=False;
210 free_nt_devicemode( &Printer->nt_devmode );
211 free_a_printer( &Printer->printer_info, 2 );
213 talloc_destroy( Printer->ctx );
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list, Printer);
218 SAFE_FREE(Printer);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
227 SPOOL_NOTIFY_OPTION *new_sp = NULL;
229 if (!sp)
230 return NULL;
232 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
233 if (!new_sp)
234 return NULL;
236 *new_sp = *sp;
238 if (sp->ctr.count) {
239 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
241 if (!new_sp->ctr.type) {
242 SAFE_FREE(new_sp);
243 return NULL;
247 return new_sp;
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
256 Printer_entry *find_printer = NULL;
258 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
260 return NULL;
263 return find_printer;
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
272 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
274 if (!Printer) {
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
276 return False;
279 close_policy_hnd(p, hnd);
281 return True;
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
289 char *cmd = lp_deleteprinter_cmd();
290 pstring command;
291 int ret;
292 SE_PRIV se_printop = SE_PRINT_OPERATOR;
293 BOOL is_print_op = False;
295 /* can't fail if we don't try */
297 if ( !*cmd )
298 return WERR_OK;
300 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
302 if ( token )
303 is_print_op = user_has_privileges( token, &se_printop );
305 DEBUG(10,("Running [%s]\n", command));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
309 if ( is_print_op )
310 become_root();
312 if ( (ret = smbrun(command, NULL)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
317 if ( is_print_op )
318 unbecome_root();
320 /********** END SePrintOperatorPrivlege BLOCK **********/
322 DEBUGADD(10,("returned [%d]\n", ret));
324 if (ret != 0)
325 return WERR_BADFID; /* What to return here? */
327 /* go ahead and re-read the services immediately */
328 reload_services( False );
330 if ( lp_servicenumber( sharename ) < 0 )
331 return WERR_ACCESS_DENIED;
333 return WERR_OK;
336 /****************************************************************************
337 Delete a printer given a handle.
338 ****************************************************************************/
340 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
342 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
344 if (!Printer) {
345 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
346 return WERR_BADFID;
350 * It turns out that Windows allows delete printer on a handle
351 * opened by an admin user, then used on a pipe handle created
352 * by an anonymous user..... but they're working on security.... riiight !
353 * JRA.
356 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
357 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
358 return WERR_ACCESS_DENIED;
361 /* this does not need a become root since the access check has been
362 done on the handle already */
364 if (del_a_printer( Printer->sharename ) != 0) {
365 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
366 return WERR_BADFID;
369 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
372 /****************************************************************************
373 Return the snum of a printer corresponding to an handle.
374 ****************************************************************************/
376 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
378 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
380 if (!Printer) {
381 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
382 return False;
385 switch (Printer->printer_type) {
386 case SPLHND_PRINTER:
387 DEBUG(4,("short name:%s\n", Printer->sharename));
388 *number = print_queue_snum(Printer->sharename);
389 return (*number != -1);
390 case SPLHND_SERVER:
391 return False;
392 default:
393 return False;
397 /****************************************************************************
398 Set printer handle type.
399 Check if it's \\server or \\server\printer
400 ****************************************************************************/
402 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
404 DEBUG(3,("Setting printer type=%s\n", handlename));
406 if ( strlen(handlename) < 3 ) {
407 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
408 return False;
411 /* it's a print server */
412 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
413 DEBUGADD(4,("Printer is a print server\n"));
414 Printer->printer_type = SPLHND_SERVER;
416 /* it's a printer (set_printer_hnd_name() will handle port monitors */
417 else {
418 DEBUGADD(4,("Printer is a printer\n"));
419 Printer->printer_type = SPLHND_PRINTER;
422 return True;
425 /****************************************************************************
426 Set printer handle name.. Accept names like \\server, \\server\printer,
427 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
428 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
429 XcvDataPort() interface.
430 ****************************************************************************/
432 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
434 int snum;
435 int n_services=lp_numservices();
436 char *aprinter, *printername;
437 const char *servername;
438 fstring sname;
439 BOOL found=False;
440 NT_PRINTER_INFO_LEVEL *printer = NULL;
441 WERROR result;
443 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
445 aprinter = handlename;
446 if ( *handlename == '\\' ) {
447 servername = handlename + 2;
448 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
449 *aprinter = '\0';
450 aprinter++;
453 else {
454 servername = "";
457 /* save the servername to fill in replies on this handle */
459 if ( !is_myname_or_ipaddr( servername ) )
460 return False;
462 fstrcpy( Printer->servername, servername );
464 if ( Printer->printer_type == SPLHND_SERVER )
465 return True;
467 if ( Printer->printer_type != SPLHND_PRINTER )
468 return False;
470 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
472 /* check for the Port Monitor Interface */
474 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
475 Printer->printer_type = SPLHND_PORTMON_TCP;
476 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
477 found = True;
479 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
480 Printer->printer_type = SPLHND_PORTMON_LOCAL;
481 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
482 found = True;
485 /* Search all sharenames first as this is easier than pulling
486 the printer_info_2 off of disk. Don't use find_service() since
487 that calls out to map_username() */
489 /* do another loop to look for printernames */
491 for (snum=0; !found && snum<n_services; snum++) {
493 /* no point going on if this is not a printer */
495 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
496 continue;
498 fstrcpy(sname, lp_servicename(snum));
499 if ( strequal( aprinter, sname ) ) {
500 found = True;
501 break;
504 /* no point looking up the printer object if
505 we aren't allowing printername != sharename */
507 if ( lp_force_printername(snum) )
508 continue;
510 fstrcpy(sname, lp_servicename(snum));
512 printer = NULL;
514 /* This call doesn't fill in the location or comment from
515 * a CUPS server for efficiency with large numbers of printers.
516 * JRA.
518 result = get_a_printer_search( NULL, &printer, 2, sname );
519 if ( !W_ERROR_IS_OK(result) ) {
520 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
521 sname, dos_errstr(result)));
522 continue;
525 /* printername is always returned as \\server\printername */
526 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
527 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
528 printer->info_2->printername));
529 free_a_printer( &printer, 2);
530 continue;
533 printername++;
535 if ( strequal(printername, aprinter) ) {
536 free_a_printer( &printer, 2);
537 found = True;
538 break;
541 DEBUGADD(10, ("printername: %s\n", printername));
543 free_a_printer( &printer, 2);
546 free_a_printer( &printer, 2);
548 if ( !found ) {
549 DEBUGADD(4,("Printer not found\n"));
550 return False;
553 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
555 fstrcpy(Printer->sharename, sname);
557 return True;
560 /****************************************************************************
561 Find first available printer slot. creates a printer handle for you.
562 ****************************************************************************/
564 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
566 Printer_entry *new_printer;
568 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
570 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
571 return False;
573 ZERO_STRUCTP(new_printer);
575 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
576 SAFE_FREE(new_printer);
577 return False;
580 /* Add to the internal list. */
581 DLIST_ADD(printers_list, new_printer);
583 new_printer->notify.option=NULL;
585 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
586 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
587 close_printer_handle(p, hnd);
588 return False;
591 if (!set_printer_hnd_printertype(new_printer, name)) {
592 close_printer_handle(p, hnd);
593 return False;
596 if (!set_printer_hnd_name(new_printer, name)) {
597 close_printer_handle(p, hnd);
598 return False;
601 new_printer->access_granted = access_granted;
603 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
605 return True;
608 /***************************************************************************
609 check to see if the client motify handle is monitoring the notification
610 given by (notify_type, notify_field).
611 **************************************************************************/
613 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
614 uint16 notify_field)
616 return True;
619 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
620 uint16 notify_field)
622 SPOOL_NOTIFY_OPTION *option = p->notify.option;
623 uint32 i, j;
626 * Flags should always be zero when the change notify
627 * is registered by the client's spooler. A user Win32 app
628 * might use the flags though instead of the NOTIFY_OPTION_INFO
629 * --jerry
632 if (!option) {
633 return False;
636 if (p->notify.flags)
637 return is_monitoring_event_flags(
638 p->notify.flags, notify_type, notify_field);
640 for (i = 0; i < option->count; i++) {
642 /* Check match for notify_type */
644 if (option->ctr.type[i].type != notify_type)
645 continue;
647 /* Check match for field */
649 for (j = 0; j < option->ctr.type[i].count; j++) {
650 if (option->ctr.type[i].fields[j] == notify_field) {
651 return True;
656 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
657 p->servername, p->sharename, notify_type, notify_field));
659 return False;
662 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
664 static void notify_one_value(struct spoolss_notify_msg *msg,
665 SPOOL_NOTIFY_INFO_DATA *data,
666 TALLOC_CTX *mem_ctx)
668 data->notify_data.value[0] = msg->notify.value[0];
669 data->notify_data.value[1] = 0;
672 static void notify_string(struct spoolss_notify_msg *msg,
673 SPOOL_NOTIFY_INFO_DATA *data,
674 TALLOC_CTX *mem_ctx)
676 UNISTR2 unistr;
678 /* The length of the message includes the trailing \0 */
680 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
682 data->notify_data.data.length = msg->len * 2;
683 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
685 if (!data->notify_data.data.string) {
686 data->notify_data.data.length = 0;
687 return;
690 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
693 static void notify_system_time(struct spoolss_notify_msg *msg,
694 SPOOL_NOTIFY_INFO_DATA *data,
695 TALLOC_CTX *mem_ctx)
697 SYSTEMTIME systime;
698 prs_struct ps;
700 if (msg->len != sizeof(time_t)) {
701 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
702 msg->len));
703 return;
706 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
707 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
708 return;
711 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
712 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
713 prs_mem_free(&ps);
714 return;
717 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
718 prs_mem_free(&ps);
719 return;
722 data->notify_data.data.length = prs_offset(&ps);
723 if (prs_offset(&ps)) {
724 data->notify_data.data.string = (uint16 *)
725 TALLOC(mem_ctx, prs_offset(&ps));
726 if (!data->notify_data.data.string) {
727 prs_mem_free(&ps);
728 return;
730 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
731 } else {
732 data->notify_data.data.string = NULL;
735 prs_mem_free(&ps);
738 struct notify2_message_table {
739 const char *name;
740 void (*fn)(struct spoolss_notify_msg *msg,
741 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
744 static struct notify2_message_table printer_notify_table[] = {
745 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
746 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
747 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
748 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
749 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
750 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
751 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
752 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
753 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
754 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
755 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
756 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
757 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
758 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
759 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
760 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
761 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
762 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
763 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
766 static struct notify2_message_table job_notify_table[] = {
767 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
768 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
769 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
770 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
771 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
772 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
773 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
774 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
775 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
776 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
777 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
778 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
779 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
780 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
781 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
782 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
783 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
784 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
785 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
786 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
787 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
788 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
789 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
790 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
794 /***********************************************************************
795 Allocate talloc context for container object
796 **********************************************************************/
798 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
800 if ( !ctr )
801 return;
803 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
805 return;
808 /***********************************************************************
809 release all allocated memory and zero out structure
810 **********************************************************************/
812 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 if ( !ctr )
815 return;
817 if ( ctr->ctx )
818 talloc_destroy(ctr->ctx);
820 ZERO_STRUCTP(ctr);
822 return;
825 /***********************************************************************
826 **********************************************************************/
828 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
830 if ( !ctr )
831 return NULL;
833 return ctr->ctx;
836 /***********************************************************************
837 **********************************************************************/
839 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
841 if ( !ctr || !ctr->msg_groups )
842 return NULL;
844 if ( idx >= ctr->num_groups )
845 return NULL;
847 return &ctr->msg_groups[idx];
851 /***********************************************************************
852 How many groups of change messages do we have ?
853 **********************************************************************/
855 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
857 if ( !ctr )
858 return 0;
860 return ctr->num_groups;
863 /***********************************************************************
864 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
865 **********************************************************************/
867 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
869 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
870 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
871 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
872 int i, new_slot;
874 if ( !ctr || !msg )
875 return 0;
877 /* loop over all groups looking for a matching printer name */
879 for ( i=0; i<ctr->num_groups; i++ ) {
880 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
881 break;
884 /* add a new group? */
886 if ( i == ctr->num_groups ) {
887 ctr->num_groups++;
889 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
890 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
891 return 0;
893 ctr->msg_groups = groups;
895 /* clear the new entry and set the printer name */
897 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
898 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
901 /* add the change messages; 'i' is the correct index now regardless */
903 msg_grp = &ctr->msg_groups[i];
905 msg_grp->num_msgs++;
907 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
908 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
909 return 0;
911 msg_grp->msgs = msg_list;
913 new_slot = msg_grp->num_msgs-1;
914 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
916 /* need to allocate own copy of data */
918 if ( msg->len != 0 )
919 msg_grp->msgs[new_slot].notify.data = (char *)
920 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
922 return ctr->num_groups;
925 /***********************************************************************
926 Send a change notication message on all handles which have a call
927 back registered
928 **********************************************************************/
930 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
932 Printer_entry *p;
933 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
934 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
935 SPOOLSS_NOTIFY_MSG *messages;
936 int sending_msg_count;
938 if ( !msg_group ) {
939 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
940 return;
943 messages = msg_group->msgs;
945 if ( !messages ) {
946 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
947 return;
950 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
952 /* loop over all printers */
954 for (p = printers_list; p; p = p->next) {
955 SPOOL_NOTIFY_INFO_DATA *data;
956 uint32 data_len = 0;
957 uint32 id;
958 int i;
960 /* Is there notification on this handle? */
962 if ( !p->notify.client_connected )
963 continue;
965 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
967 /* For this printer? Print servers always receive
968 notifications. */
970 if ( ( p->printer_type == SPLHND_PRINTER ) &&
971 ( !strequal(msg_group->printername, p->sharename) ) )
972 continue;
974 DEBUG(10,("Our printer\n"));
976 /* allocate the max entries possible */
978 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
979 if (!data) {
980 return;
983 ZERO_STRUCTP(data);
985 /* build the array of change notifications */
987 sending_msg_count = 0;
989 for ( i=0; i<msg_group->num_msgs; i++ ) {
990 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
992 /* Are we monitoring this event? */
994 if (!is_monitoring_event(p, msg->type, msg->field))
995 continue;
997 sending_msg_count++;
1000 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1001 msg->type, msg->field, p->sharename));
1004 * if the is a printer notification handle and not a job notification
1005 * type, then set the id to 0. Other wise just use what was specified
1006 * in the message.
1008 * When registering change notification on a print server handle
1009 * we always need to send back the id (snum) matching the printer
1010 * for which the change took place. For change notify registered
1011 * on a printer handle, this does not matter and the id should be 0.
1013 * --jerry
1016 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1017 id = 0;
1018 else
1019 id = msg->id;
1022 /* Convert unix jobid to smb jobid */
1024 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1025 id = sysjob_to_jobid(msg->id);
1027 if (id == -1) {
1028 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1029 goto done;
1033 construct_info_data( &data[data_len], msg->type, msg->field, id );
1035 switch(msg->type) {
1036 case PRINTER_NOTIFY_TYPE:
1037 if ( printer_notify_table[msg->field].fn )
1038 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1039 break;
1041 case JOB_NOTIFY_TYPE:
1042 if ( job_notify_table[msg->field].fn )
1043 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1044 break;
1046 default:
1047 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1048 goto done;
1051 data_len++;
1054 if ( sending_msg_count ) {
1055 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1056 data_len, data, p->notify.change, 0 );
1060 done:
1061 DEBUG(8,("send_notify2_changes: Exit...\n"));
1062 return;
1065 /***********************************************************************
1066 **********************************************************************/
1068 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1071 uint32 tv_sec, tv_usec;
1072 size_t offset = 0;
1074 /* Unpack message */
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1077 msg->printer);
1079 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1080 &tv_sec, &tv_usec,
1081 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1083 if (msg->len == 0)
1084 tdb_unpack((char *)buf + offset, len - offset, "dd",
1085 &msg->notify.value[0], &msg->notify.value[1]);
1086 else
1087 tdb_unpack((char *)buf + offset, len - offset, "B",
1088 &msg->len, &msg->notify.data);
1090 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1091 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1093 tv->tv_sec = tv_sec;
1094 tv->tv_usec = tv_usec;
1096 if (msg->len == 0)
1097 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1098 msg->notify.value[1]));
1099 else
1100 dump_data(3, msg->notify.data, msg->len);
1102 return True;
1105 /********************************************************************
1106 Receive a notify2 message list
1107 ********************************************************************/
1109 static void receive_notify2_message_list(int msg_type, struct process_id src,
1110 void *msg, size_t len,
1111 void *private_data)
1113 size_t msg_count, i;
1114 char *buf = (char *)msg;
1115 char *msg_ptr;
1116 size_t msg_len;
1117 SPOOLSS_NOTIFY_MSG notify;
1118 SPOOLSS_NOTIFY_MSG_CTR messages;
1119 int num_groups;
1121 if (len < 4) {
1122 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1123 return;
1126 msg_count = IVAL(buf, 0);
1127 msg_ptr = buf + 4;
1129 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1131 if (msg_count == 0) {
1132 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1133 return;
1136 /* initialize the container */
1138 ZERO_STRUCT( messages );
1139 notify_msg_ctr_init( &messages );
1142 * build message groups for each printer identified
1143 * in a change_notify msg. Remember that a PCN message
1144 * includes the handle returned for the srv_spoolss_replyopenprinter()
1145 * call. Therefore messages are grouped according to printer handle.
1148 for ( i=0; i<msg_count; i++ ) {
1149 struct timeval msg_tv;
1151 if (msg_ptr + 4 - buf > len) {
1152 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1153 return;
1156 msg_len = IVAL(msg_ptr,0);
1157 msg_ptr += 4;
1159 if (msg_ptr + msg_len - buf > len) {
1160 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1161 return;
1164 /* unpack messages */
1166 ZERO_STRUCT( notify );
1167 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1168 msg_ptr += msg_len;
1170 /* add to correct list in container */
1172 notify_msg_ctr_addmsg( &messages, &notify );
1174 /* free memory that might have been allocated by notify2_unpack_msg() */
1176 if ( notify.len != 0 )
1177 SAFE_FREE( notify.notify.data );
1180 /* process each group of messages */
1182 num_groups = notify_msg_ctr_numgroups( &messages );
1183 for ( i=0; i<num_groups; i++ )
1184 send_notify2_changes( &messages, i );
1187 /* cleanup */
1189 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1191 notify_msg_ctr_destroy( &messages );
1193 return;
1196 /********************************************************************
1197 Send a message to ourself about new driver being installed
1198 so we can upgrade the information for each printer bound to this
1199 driver
1200 ********************************************************************/
1202 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1204 int len = strlen(drivername);
1206 if (!len)
1207 return False;
1209 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1210 drivername));
1212 message_send_pid(pid_to_procid(sys_getpid()),
1213 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1215 return True;
1218 /**********************************************************************
1219 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1220 over all printers, upgrading ones as necessary
1221 **********************************************************************/
1223 void do_drv_upgrade_printer(int msg_type, struct process_id src,
1224 void *buf, size_t len, void *private_data)
1226 fstring drivername;
1227 int snum;
1228 int n_services = lp_numservices();
1230 len = MIN(len,sizeof(drivername)-1);
1231 strncpy(drivername, (const char *)buf, len);
1233 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1235 /* Iterate the printer list */
1237 for (snum=0; snum<n_services; snum++)
1239 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1241 WERROR result;
1242 NT_PRINTER_INFO_LEVEL *printer = NULL;
1244 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1245 if (!W_ERROR_IS_OK(result))
1246 continue;
1248 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1250 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1252 /* all we care about currently is the change_id */
1254 result = mod_a_printer(printer, 2);
1255 if (!W_ERROR_IS_OK(result)) {
1256 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1257 dos_errstr(result)));
1261 free_a_printer(&printer, 2);
1265 /* all done */
1268 /********************************************************************
1269 Update the cache for all printq's with a registered client
1270 connection
1271 ********************************************************************/
1273 void update_monitored_printq_cache( void )
1275 Printer_entry *printer = printers_list;
1276 int snum;
1278 /* loop through all printers and update the cache where
1279 client_connected == True */
1280 while ( printer )
1282 if ( (printer->printer_type == SPLHND_PRINTER)
1283 && printer->notify.client_connected )
1285 snum = print_queue_snum(printer->sharename);
1286 print_queue_status( snum, NULL, NULL );
1289 printer = printer->next;
1292 return;
1294 /********************************************************************
1295 Send a message to ourself about new driver being installed
1296 so we can upgrade the information for each printer bound to this
1297 driver
1298 ********************************************************************/
1300 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1302 int len = strlen(drivername);
1304 if (!len)
1305 return False;
1307 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1308 drivername));
1310 message_send_pid(pid_to_procid(sys_getpid()),
1311 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1313 return True;
1316 /**********************************************************************
1317 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1318 over all printers, resetting printer data as neessary
1319 **********************************************************************/
1321 void reset_all_printerdata(int msg_type, struct process_id src,
1322 void *buf, size_t len, void *private_data)
1324 fstring drivername;
1325 int snum;
1326 int n_services = lp_numservices();
1328 len = MIN( len, sizeof(drivername)-1 );
1329 strncpy( drivername, (const char *)buf, len );
1331 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1333 /* Iterate the printer list */
1335 for ( snum=0; snum<n_services; snum++ )
1337 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1339 WERROR result;
1340 NT_PRINTER_INFO_LEVEL *printer = NULL;
1342 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1343 if ( !W_ERROR_IS_OK(result) )
1344 continue;
1347 * if the printer is bound to the driver,
1348 * then reset to the new driver initdata
1351 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1353 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1355 if ( !set_driver_init(printer, 2) ) {
1356 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1357 printer->info_2->printername, printer->info_2->drivername));
1360 result = mod_a_printer( printer, 2 );
1361 if ( !W_ERROR_IS_OK(result) ) {
1362 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1363 get_dos_error_msg(result)));
1367 free_a_printer( &printer, 2 );
1371 /* all done */
1373 return;
1376 /********************************************************************
1377 Copy routines used by convert_to_openprinterex()
1378 *******************************************************************/
1380 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1382 DEVICEMODE *d;
1383 int len;
1385 if (!devmode)
1386 return NULL;
1388 DEBUG (8,("dup_devmode\n"));
1390 /* bulk copy first */
1392 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1393 if (!d)
1394 return NULL;
1396 /* dup the pointer members separately */
1398 len = unistrlen(devmode->devicename.buffer);
1399 if (len != -1) {
1400 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1401 if (!d->devicename.buffer) {
1402 return NULL;
1404 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1405 return NULL;
1409 len = unistrlen(devmode->formname.buffer);
1410 if (len != -1) {
1411 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1412 if (!d->formname.buffer) {
1413 return NULL;
1415 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1416 return NULL;
1419 if (devmode->driverextra) {
1420 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1421 devmode->driverextra);
1422 if (!d->dev_private) {
1423 return NULL;
1425 } else {
1426 d->dev_private = NULL;
1428 return d;
1431 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1433 if (!new_ctr || !ctr)
1434 return;
1436 DEBUG(8,("copy_devmode_ctr\n"));
1438 new_ctr->size = ctr->size;
1439 new_ctr->devmode_ptr = ctr->devmode_ptr;
1441 if(ctr->devmode_ptr)
1442 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1445 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1447 if (!new_def || !def)
1448 return;
1450 DEBUG(8,("copy_printer_defaults\n"));
1452 new_def->datatype_ptr = def->datatype_ptr;
1454 if (def->datatype_ptr)
1455 copy_unistr2(&new_def->datatype, &def->datatype);
1457 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1459 new_def->access_required = def->access_required;
1462 /********************************************************************
1463 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1464 * SPOOL_Q_OPEN_PRINTER_EX structure
1465 ********************************************************************/
1467 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1469 if (!q_u_ex || !q_u)
1470 return WERR_OK;
1472 DEBUG(8,("convert_to_openprinterex\n"));
1474 if ( q_u->printername ) {
1475 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1476 if (q_u_ex->printername == NULL)
1477 return WERR_NOMEM;
1478 copy_unistr2(q_u_ex->printername, q_u->printername);
1481 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1483 return WERR_OK;
1486 /********************************************************************
1487 * spoolss_open_printer
1489 * called from the spoolss dispatcher
1490 ********************************************************************/
1492 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1494 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1495 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1497 if (!q_u || !r_u)
1498 return WERR_NOMEM;
1500 ZERO_STRUCT(q_u_ex);
1501 ZERO_STRUCT(r_u_ex);
1503 /* convert the OpenPrinter() call to OpenPrinterEx() */
1505 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1506 if (!W_ERROR_IS_OK(r_u_ex.status))
1507 return r_u_ex.status;
1509 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1511 /* convert back to OpenPrinter() */
1513 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1515 return r_u->status;
1518 /********************************************************************
1519 ********************************************************************/
1521 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1523 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1524 POLICY_HND *handle = &r_u->handle;
1526 fstring name;
1527 int snum;
1528 struct current_user user;
1529 Printer_entry *Printer=NULL;
1531 if ( !q_u->printername )
1532 return WERR_INVALID_PRINTER_NAME;
1534 /* some sanity check because you can open a printer or a print server */
1535 /* aka: \\server\printer or \\server */
1537 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1539 DEBUGADD(3,("checking name: %s\n",name));
1541 if (!open_printer_hnd(p, handle, name, 0))
1542 return WERR_INVALID_PRINTER_NAME;
1544 Printer=find_printer_index_by_hnd(p, handle);
1545 if ( !Printer ) {
1546 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1547 "handle we created for printer %s\n", name ));
1548 close_printer_handle(p,handle);
1549 return WERR_INVALID_PRINTER_NAME;
1552 get_current_user(&user, p);
1555 * First case: the user is opening the print server:
1557 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1558 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1560 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1561 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1562 * or if the user is listed in the smb.conf printer admin parameter.
1564 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1565 * client view printer folder, but does not show the MSAPW.
1567 * Note: this test needs code to check access rights here too. Jeremy
1568 * could you look at this?
1570 * Second case: the user is opening a printer:
1571 * NT doesn't let us connect to a printer if the connecting user
1572 * doesn't have print permission.
1574 * Third case: user is opening a Port Monitor
1575 * access checks same as opening a handle to the print server.
1578 switch (Printer->printer_type )
1580 case SPLHND_SERVER:
1581 case SPLHND_PORTMON_TCP:
1582 case SPLHND_PORTMON_LOCAL:
1583 /* Printserver handles use global struct... */
1585 snum = -1;
1587 /* Map standard access rights to object specific access rights */
1589 se_map_standard(&printer_default->access_required,
1590 &printserver_std_mapping);
1592 /* Deny any object specific bits that don't apply to print
1593 servers (i.e printer and job specific bits) */
1595 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1597 if (printer_default->access_required &
1598 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1599 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1600 close_printer_handle(p, handle);
1601 return WERR_ACCESS_DENIED;
1604 /* Allow admin access */
1606 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1608 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1610 if (!lp_ms_add_printer_wizard()) {
1611 close_printer_handle(p, handle);
1612 return WERR_ACCESS_DENIED;
1615 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1616 and not a printer admin, then fail */
1618 if ((user.ut.uid != 0) &&
1619 !user_has_privileges(user.nt_user_token,
1620 &se_printop ) &&
1621 !token_contains_name_in_list(
1622 uidtoname(user.ut.uid), NULL,
1623 user.nt_user_token,
1624 lp_printer_admin(snum))) {
1625 close_printer_handle(p, handle);
1626 return WERR_ACCESS_DENIED;
1629 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1631 else
1633 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1636 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1637 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1639 /* We fall through to return WERR_OK */
1640 break;
1642 case SPLHND_PRINTER:
1643 /* NT doesn't let us connect to a printer if the connecting user
1644 doesn't have print permission. */
1646 if (!get_printer_snum(p, handle, &snum)) {
1647 close_printer_handle(p, handle);
1648 return WERR_BADFID;
1651 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1653 /* map an empty access mask to the minimum access mask */
1654 if (printer_default->access_required == 0x0)
1655 printer_default->access_required = PRINTER_ACCESS_USE;
1658 * If we are not serving the printer driver for this printer,
1659 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1660 * will keep NT clients happy --jerry
1663 if (lp_use_client_driver(snum)
1664 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1666 printer_default->access_required = PRINTER_ACCESS_USE;
1669 /* check smb.conf parameters and the the sec_desc */
1671 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1672 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1673 return WERR_ACCESS_DENIED;
1676 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1677 snum) ||
1678 !print_access_check(&user, snum,
1679 printer_default->access_required)) {
1680 DEBUG(3, ("access DENIED for printer open\n"));
1681 close_printer_handle(p, handle);
1682 return WERR_ACCESS_DENIED;
1685 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1686 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1692 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1693 else
1694 printer_default->access_required = PRINTER_ACCESS_USE;
1696 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1697 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1699 break;
1701 default:
1702 /* sanity check to prevent programmer error */
1703 return WERR_BADFID;
1706 Printer->access_granted = printer_default->access_required;
1709 * If the client sent a devmode in the OpenPrinter() call, then
1710 * save it here in case we get a job submission on this handle
1713 if ( (Printer->printer_type != SPLHND_SERVER)
1714 && q_u->printer_default.devmode_cont.devmode_ptr )
1716 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1717 &Printer->nt_devmode );
1720 #if 0 /* JERRY -- I'm doubtful this is really effective */
1721 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1722 optimization in Windows 2000 clients --jerry */
1724 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1725 && (RA_WIN2K == get_remote_arch()) )
1727 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1728 sys_usleep( 500000 );
1730 #endif
1732 return WERR_OK;
1735 /****************************************************************************
1736 ****************************************************************************/
1738 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1739 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1741 BOOL ret;
1743 switch (level) {
1744 case 2:
1745 /* allocate memory if needed. Messy because
1746 convert_printer_info is used to update an existing
1747 printer or build a new one */
1749 if ( !printer->info_2 ) {
1750 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1751 if ( !printer->info_2 ) {
1752 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1753 return False;
1757 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1758 printer->info_2->setuptime = time(NULL);
1760 return ret;
1763 return False;
1766 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1767 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1769 BOOL result = True;
1771 switch (level) {
1772 case 3:
1773 printer->info_3=NULL;
1774 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1775 result = False;
1776 break;
1777 case 6:
1778 printer->info_6=NULL;
1779 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1780 result = False;
1781 break;
1782 default:
1783 break;
1786 return result;
1789 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1790 NT_DEVICEMODE **pp_nt_devmode)
1792 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1795 * Ensure nt_devmode is a valid pointer
1796 * as we will be overwriting it.
1799 if (nt_devmode == NULL) {
1800 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1801 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1802 return False;
1805 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1806 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1808 nt_devmode->specversion=devmode->specversion;
1809 nt_devmode->driverversion=devmode->driverversion;
1810 nt_devmode->size=devmode->size;
1811 nt_devmode->fields=devmode->fields;
1812 nt_devmode->orientation=devmode->orientation;
1813 nt_devmode->papersize=devmode->papersize;
1814 nt_devmode->paperlength=devmode->paperlength;
1815 nt_devmode->paperwidth=devmode->paperwidth;
1816 nt_devmode->scale=devmode->scale;
1817 nt_devmode->copies=devmode->copies;
1818 nt_devmode->defaultsource=devmode->defaultsource;
1819 nt_devmode->printquality=devmode->printquality;
1820 nt_devmode->color=devmode->color;
1821 nt_devmode->duplex=devmode->duplex;
1822 nt_devmode->yresolution=devmode->yresolution;
1823 nt_devmode->ttoption=devmode->ttoption;
1824 nt_devmode->collate=devmode->collate;
1826 nt_devmode->logpixels=devmode->logpixels;
1827 nt_devmode->bitsperpel=devmode->bitsperpel;
1828 nt_devmode->pelswidth=devmode->pelswidth;
1829 nt_devmode->pelsheight=devmode->pelsheight;
1830 nt_devmode->displayflags=devmode->displayflags;
1831 nt_devmode->displayfrequency=devmode->displayfrequency;
1832 nt_devmode->icmmethod=devmode->icmmethod;
1833 nt_devmode->icmintent=devmode->icmintent;
1834 nt_devmode->mediatype=devmode->mediatype;
1835 nt_devmode->dithertype=devmode->dithertype;
1836 nt_devmode->reserved1=devmode->reserved1;
1837 nt_devmode->reserved2=devmode->reserved2;
1838 nt_devmode->panningwidth=devmode->panningwidth;
1839 nt_devmode->panningheight=devmode->panningheight;
1842 * Only change private and driverextra if the incoming devmode
1843 * has a new one. JRA.
1846 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1847 SAFE_FREE(nt_devmode->nt_dev_private);
1848 nt_devmode->driverextra=devmode->driverextra;
1849 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1850 return False;
1851 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1854 *pp_nt_devmode = nt_devmode;
1856 return True;
1859 /********************************************************************
1860 * _spoolss_enddocprinter_internal.
1861 ********************************************************************/
1863 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1865 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1866 int snum;
1868 if (!Printer) {
1869 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1870 return WERR_BADFID;
1873 if (!get_printer_snum(p, handle, &snum))
1874 return WERR_BADFID;
1876 Printer->document_started=False;
1877 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1878 /* error codes unhandled so far ... */
1880 return WERR_OK;
1883 /********************************************************************
1884 * api_spoolss_closeprinter
1885 ********************************************************************/
1887 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1889 POLICY_HND *handle = &q_u->handle;
1891 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1893 if (Printer && Printer->document_started)
1894 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1896 if (!close_printer_handle(p, handle))
1897 return WERR_BADFID;
1899 /* clear the returned printer handle. Observed behavior
1900 from Win2k server. Don't think this really matters.
1901 Previous code just copied the value of the closed
1902 handle. --jerry */
1904 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1906 return WERR_OK;
1909 /********************************************************************
1910 * api_spoolss_deleteprinter
1912 ********************************************************************/
1914 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1916 POLICY_HND *handle = &q_u->handle;
1917 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1918 WERROR result;
1920 if (Printer && Printer->document_started)
1921 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1923 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1925 result = delete_printer_handle(p, handle);
1927 update_c_setprinter(False);
1929 return result;
1932 /*******************************************************************
1933 * static function to lookup the version id corresponding to an
1934 * long architecture string
1935 ******************************************************************/
1937 static int get_version_id (char * arch)
1939 int i;
1940 struct table_node archi_table[]= {
1942 {"Windows 4.0", "WIN40", 0 },
1943 {"Windows NT x86", "W32X86", 2 },
1944 {"Windows NT R4000", "W32MIPS", 2 },
1945 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1946 {"Windows NT PowerPC", "W32PPC", 2 },
1947 {"Windows IA64", "IA64", 3 },
1948 {"Windows x64", "x64", 3 },
1949 {NULL, "", -1 }
1952 for (i=0; archi_table[i].long_archi != NULL; i++)
1954 if (strcmp(arch, archi_table[i].long_archi) == 0)
1955 return (archi_table[i].version);
1958 return -1;
1961 /********************************************************************
1962 * _spoolss_deleteprinterdriver
1963 ********************************************************************/
1965 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1967 fstring driver;
1968 fstring arch;
1969 NT_PRINTER_DRIVER_INFO_LEVEL info;
1970 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1971 int version;
1972 struct current_user user;
1973 WERROR status;
1974 WERROR status_win2k = WERR_ACCESS_DENIED;
1975 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1977 get_current_user(&user, p);
1979 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1980 and not a printer admin, then fail */
1982 if ( (user.ut.uid != 0)
1983 && !user_has_privileges(user.nt_user_token, &se_printop )
1984 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1985 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1987 return WERR_ACCESS_DENIED;
1990 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1991 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1993 /* check that we have a valid driver name first */
1995 if ((version=get_version_id(arch)) == -1)
1996 return WERR_INVALID_ENVIRONMENT;
1998 ZERO_STRUCT(info);
1999 ZERO_STRUCT(info_win2k);
2001 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2003 /* try for Win2k driver if "Windows NT x86" */
2005 if ( version == 2 ) {
2006 version = 3;
2007 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2008 status = WERR_UNKNOWN_PRINTER_DRIVER;
2009 goto done;
2012 /* otherwise it was a failure */
2013 else {
2014 status = WERR_UNKNOWN_PRINTER_DRIVER;
2015 goto done;
2020 if (printer_driver_in_use(info.info_3)) {
2021 status = WERR_PRINTER_DRIVER_IN_USE;
2022 goto done;
2025 if ( version == 2 )
2027 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2029 /* if we get to here, we now have 2 driver info structures to remove */
2030 /* remove the Win2k driver first*/
2032 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2033 free_a_printer_driver( info_win2k, 3 );
2035 /* this should not have failed---if it did, report to client */
2036 if ( !W_ERROR_IS_OK(status_win2k) )
2038 status = status_win2k;
2039 goto done;
2044 status = delete_printer_driver(info.info_3, &user, version, False);
2046 /* if at least one of the deletes succeeded return OK */
2048 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2049 status = WERR_OK;
2051 done:
2052 free_a_printer_driver( info, 3 );
2054 return status;
2057 /********************************************************************
2058 * spoolss_deleteprinterdriverex
2059 ********************************************************************/
2061 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2063 fstring driver;
2064 fstring arch;
2065 NT_PRINTER_DRIVER_INFO_LEVEL info;
2066 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2067 int version;
2068 uint32 flags = q_u->delete_flags;
2069 BOOL delete_files;
2070 struct current_user user;
2071 WERROR status;
2072 WERROR status_win2k = WERR_ACCESS_DENIED;
2073 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2075 get_current_user(&user, p);
2077 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078 and not a printer admin, then fail */
2080 if ( (user.ut.uid != 0)
2081 && !user_has_privileges(user.nt_user_token, &se_printop )
2082 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2083 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2085 return WERR_ACCESS_DENIED;
2088 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2089 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2091 /* check that we have a valid driver name first */
2092 if ((version=get_version_id(arch)) == -1) {
2093 /* this is what NT returns */
2094 return WERR_INVALID_ENVIRONMENT;
2097 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2098 version = q_u->version;
2100 ZERO_STRUCT(info);
2101 ZERO_STRUCT(info_win2k);
2103 status = get_a_printer_driver(&info, 3, driver, arch, version);
2105 if ( !W_ERROR_IS_OK(status) )
2108 * if the client asked for a specific version,
2109 * or this is something other than Windows NT x86,
2110 * then we've failed
2113 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2114 goto done;
2116 /* try for Win2k driver if "Windows NT x86" */
2118 version = 3;
2119 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2120 status = WERR_UNKNOWN_PRINTER_DRIVER;
2121 goto done;
2125 if ( printer_driver_in_use(info.info_3) ) {
2126 status = WERR_PRINTER_DRIVER_IN_USE;
2127 goto done;
2131 * we have a couple of cases to consider.
2132 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2133 * then the delete should fail if **any** files overlap with
2134 * other drivers
2135 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2136 * non-overlapping files
2137 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2138 * is set, the do not delete any files
2139 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2142 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2144 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2146 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2147 /* no idea of the correct error here */
2148 status = WERR_ACCESS_DENIED;
2149 goto done;
2153 /* also check for W32X86/3 if necessary; maybe we already have? */
2155 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2156 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2159 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2160 /* no idea of the correct error here */
2161 free_a_printer_driver( info_win2k, 3 );
2162 status = WERR_ACCESS_DENIED;
2163 goto done;
2166 /* if we get to here, we now have 2 driver info structures to remove */
2167 /* remove the Win2k driver first*/
2169 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2170 free_a_printer_driver( info_win2k, 3 );
2172 /* this should not have failed---if it did, report to client */
2174 if ( !W_ERROR_IS_OK(status_win2k) )
2175 goto done;
2179 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2181 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2182 status = WERR_OK;
2183 done:
2184 free_a_printer_driver( info, 3 );
2186 return status;
2190 /****************************************************************************
2191 Internal routine for retreiving printerdata
2192 ***************************************************************************/
2194 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2195 const char *key, const char *value, uint32 *type, uint8 **data,
2196 uint32 *needed, uint32 in_size )
2198 REGISTRY_VALUE *val;
2199 uint32 size;
2200 int data_len;
2202 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2203 return WERR_BADFILE;
2205 *type = regval_type( val );
2207 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2209 size = regval_size( val );
2211 /* copy the min(in_size, len) */
2213 if ( in_size ) {
2214 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2216 /* special case for 0 length values */
2217 if ( data_len ) {
2218 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2219 return WERR_NOMEM;
2221 else {
2222 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2223 return WERR_NOMEM;
2226 else
2227 *data = NULL;
2229 *needed = size;
2231 DEBUG(5,("get_printer_dataex: copy done\n"));
2233 return WERR_OK;
2236 /****************************************************************************
2237 Internal routine for removing printerdata
2238 ***************************************************************************/
2240 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2242 return delete_printer_data( printer->info_2, key, value );
2245 /****************************************************************************
2246 Internal routine for storing printerdata
2247 ***************************************************************************/
2249 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2250 uint32 type, uint8 *data, int real_len )
2252 /* the registry objects enforce uniqueness based on value name */
2254 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2257 /********************************************************************
2258 GetPrinterData on a printer server Handle.
2259 ********************************************************************/
2261 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2263 int i;
2265 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2267 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2268 *type = REG_DWORD;
2269 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2270 return WERR_NOMEM;
2271 SIVAL(*data, 0, 0x00);
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 == SPLHND_SERVER )
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;
2513 } else {
2514 *data = NULL;
2518 /* cleanup & exit */
2520 if ( printer )
2521 free_a_printer( &printer, 2 );
2523 return status;
2526 /*********************************************************
2527 Connect to the client machine.
2528 **********************************************************/
2530 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2531 struct in_addr *client_ip, const char *remote_machine)
2533 NTSTATUS ret;
2534 struct cli_state *the_cli;
2535 struct in_addr rm_addr;
2537 if ( is_zero_ip(*client_ip) ) {
2538 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2539 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2540 return False;
2543 if ( ismyip( rm_addr )) {
2544 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2545 return False;
2547 } else {
2548 rm_addr.s_addr = client_ip->s_addr;
2549 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2550 inet_ntoa(*client_ip) ));
2553 /* setup the connection */
2555 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2556 &rm_addr, 0, "IPC$", "IPC",
2557 "", /* username */
2558 "", /* domain */
2559 "", /* password */
2560 0, lp_client_signing(), NULL );
2562 if ( !NT_STATUS_IS_OK( ret ) ) {
2563 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2564 remote_machine ));
2565 return False;
2568 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2569 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2570 cli_shutdown(the_cli);
2571 return False;
2575 * Ok - we have an anonymous connection to the IPC$ share.
2576 * Now start the NT Domain stuff :-).
2579 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2580 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2581 remote_machine, nt_errstr(ret)));
2582 cli_shutdown(the_cli);
2583 return False;
2586 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2588 (*pp_pipe)->cli = the_cli;
2590 return True;
2593 /***************************************************************************
2594 Connect to the client.
2595 ****************************************************************************/
2597 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2598 uint32 localprinter, uint32 type,
2599 POLICY_HND *handle, struct in_addr *client_ip)
2601 WERROR result;
2604 * If it's the first connection, contact the client
2605 * and connect to the IPC$ share anonymously
2607 if (smb_connections==0) {
2608 fstring unix_printer;
2610 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2612 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2613 return False;
2615 message_register(MSG_PRINTER_NOTIFY2,
2616 receive_notify2_message_list, NULL);
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 == SPLHND_SERVER)
2688 snum = -1;
2689 else if ( (Printer->printer_type == SPLHND_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 if (len) {
2722 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);
2729 } else {
2730 data->notify_data.data.string = NULL;
2734 /*******************************************************************
2735 * fill a notify_info_data with the printername (not including the servername).
2736 ********************************************************************/
2738 void spoolss_notify_printer_name(int snum,
2739 SPOOL_NOTIFY_INFO_DATA *data,
2740 print_queue_struct *queue,
2741 NT_PRINTER_INFO_LEVEL *printer,
2742 TALLOC_CTX *mem_ctx)
2744 pstring temp;
2745 uint32 len;
2747 /* the notify name should not contain the \\server\ part */
2748 char *p = strrchr(printer->info_2->printername, '\\');
2750 if (!p) {
2751 p = printer->info_2->printername;
2752 } else {
2753 p++;
2756 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2758 data->notify_data.data.length = len;
2759 if (len) {
2760 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2761 if (!data->notify_data.data.string) {
2762 data->notify_data.data.length = 0;
2763 return;
2765 memcpy(data->notify_data.data.string, temp, len);
2766 } else {
2767 data->notify_data.data.string = NULL;
2771 /*******************************************************************
2772 * fill a notify_info_data with the servicename
2773 ********************************************************************/
2775 void spoolss_notify_share_name(int snum,
2776 SPOOL_NOTIFY_INFO_DATA *data,
2777 print_queue_struct *queue,
2778 NT_PRINTER_INFO_LEVEL *printer,
2779 TALLOC_CTX *mem_ctx)
2781 pstring temp;
2782 uint32 len;
2784 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2786 data->notify_data.data.length = len;
2787 if (len) {
2788 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2789 if (!data->notify_data.data.string) {
2790 data->notify_data.data.length = 0;
2791 return;
2793 memcpy(data->notify_data.data.string, temp, len);
2794 } else {
2795 data->notify_data.data.string = NULL;
2800 /*******************************************************************
2801 * fill a notify_info_data with the port name
2802 ********************************************************************/
2804 void spoolss_notify_port_name(int snum,
2805 SPOOL_NOTIFY_INFO_DATA *data,
2806 print_queue_struct *queue,
2807 NT_PRINTER_INFO_LEVEL *printer,
2808 TALLOC_CTX *mem_ctx)
2810 pstring temp;
2811 uint32 len;
2813 /* even if it's strange, that's consistant in all the code */
2815 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2817 data->notify_data.data.length = len;
2818 if (len) {
2819 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2821 if (!data->notify_data.data.string) {
2822 data->notify_data.data.length = 0;
2823 return;
2826 memcpy(data->notify_data.data.string, temp, len);
2827 } else {
2828 data->notify_data.data.string = NULL;
2832 /*******************************************************************
2833 * fill a notify_info_data with the printername
2834 * but it doesn't exist, have to see what to do
2835 ********************************************************************/
2837 void spoolss_notify_driver_name(int snum,
2838 SPOOL_NOTIFY_INFO_DATA *data,
2839 print_queue_struct *queue,
2840 NT_PRINTER_INFO_LEVEL *printer,
2841 TALLOC_CTX *mem_ctx)
2843 pstring temp;
2844 uint32 len;
2846 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2848 data->notify_data.data.length = len;
2849 if (len) {
2850 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2852 if (!data->notify_data.data.string) {
2853 data->notify_data.data.length = 0;
2854 return;
2857 memcpy(data->notify_data.data.string, temp, len);
2858 } else {
2859 data->notify_data.data.string = NULL;
2863 /*******************************************************************
2864 * fill a notify_info_data with the comment
2865 ********************************************************************/
2867 void spoolss_notify_comment(int snum,
2868 SPOOL_NOTIFY_INFO_DATA *data,
2869 print_queue_struct *queue,
2870 NT_PRINTER_INFO_LEVEL *printer,
2871 TALLOC_CTX *mem_ctx)
2873 pstring temp;
2874 uint32 len;
2876 if (*printer->info_2->comment == '\0')
2877 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2878 else
2879 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2881 data->notify_data.data.length = len;
2882 if (len) {
2883 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2885 if (!data->notify_data.data.string) {
2886 data->notify_data.data.length = 0;
2887 return;
2890 memcpy(data->notify_data.data.string, temp, len);
2891 } else {
2892 data->notify_data.data.string = NULL;
2896 /*******************************************************************
2897 * fill a notify_info_data with the comment
2898 * location = "Room 1, floor 2, building 3"
2899 ********************************************************************/
2901 void spoolss_notify_location(int snum,
2902 SPOOL_NOTIFY_INFO_DATA *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2907 pstring temp;
2908 uint32 len;
2910 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2912 data->notify_data.data.length = len;
2913 if (len) {
2914 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2916 if (!data->notify_data.data.string) {
2917 data->notify_data.data.length = 0;
2918 return;
2921 memcpy(data->notify_data.data.string, temp, len);
2922 } else {
2923 data->notify_data.data.string = NULL;
2927 /*******************************************************************
2928 * fill a notify_info_data with the device mode
2929 * jfm:xxxx don't to it for know but that's a real problem !!!
2930 ********************************************************************/
2932 static void spoolss_notify_devmode(int snum,
2933 SPOOL_NOTIFY_INFO_DATA *data,
2934 print_queue_struct *queue,
2935 NT_PRINTER_INFO_LEVEL *printer,
2936 TALLOC_CTX *mem_ctx)
2938 /* for a dummy implementation we have to zero the fields */
2939 data->notify_data.data.length = 0;
2940 data->notify_data.data.string = NULL;
2943 /*******************************************************************
2944 * fill a notify_info_data with the separator file name
2945 ********************************************************************/
2947 void spoolss_notify_sepfile(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->sepfile, sizeof(temp)-2, STR_TERMINATE);
2958 data->notify_data.data.length = len;
2959 if (len) {
2960 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2962 if (!data->notify_data.data.string) {
2963 data->notify_data.data.length = 0;
2964 return;
2967 memcpy(data->notify_data.data.string, temp, len);
2968 } else {
2969 data->notify_data.data.string = NULL;
2973 /*******************************************************************
2974 * fill a notify_info_data with the print processor
2975 * jfm:xxxx return always winprint to indicate we don't do anything to it
2976 ********************************************************************/
2978 void spoolss_notify_print_processor(int snum,
2979 SPOOL_NOTIFY_INFO_DATA *data,
2980 print_queue_struct *queue,
2981 NT_PRINTER_INFO_LEVEL *printer,
2982 TALLOC_CTX *mem_ctx)
2984 pstring temp;
2985 uint32 len;
2987 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2989 data->notify_data.data.length = len;
2990 if (len) {
2991 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2993 if (!data->notify_data.data.string) {
2994 data->notify_data.data.length = 0;
2995 return;
2998 memcpy(data->notify_data.data.string, temp, len);
2999 } else {
3000 data->notify_data.data.string = NULL;
3004 /*******************************************************************
3005 * fill a notify_info_data with the print processor options
3006 * jfm:xxxx send an empty string
3007 ********************************************************************/
3009 void spoolss_notify_parameters(int snum,
3010 SPOOL_NOTIFY_INFO_DATA *data,
3011 print_queue_struct *queue,
3012 NT_PRINTER_INFO_LEVEL *printer,
3013 TALLOC_CTX *mem_ctx)
3015 pstring temp;
3016 uint32 len;
3018 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3020 data->notify_data.data.length = len;
3021 if (len) {
3022 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3024 if (!data->notify_data.data.string) {
3025 data->notify_data.data.length = 0;
3026 return;
3029 memcpy(data->notify_data.data.string, temp, len);
3030 } else {
3031 data->notify_data.data.string = NULL;
3035 /*******************************************************************
3036 * fill a notify_info_data with the data type
3037 * jfm:xxxx always send RAW as data type
3038 ********************************************************************/
3040 void spoolss_notify_datatype(int snum,
3041 SPOOL_NOTIFY_INFO_DATA *data,
3042 print_queue_struct *queue,
3043 NT_PRINTER_INFO_LEVEL *printer,
3044 TALLOC_CTX *mem_ctx)
3046 pstring temp;
3047 uint32 len;
3049 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3051 data->notify_data.data.length = len;
3052 if (len) {
3053 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3055 if (!data->notify_data.data.string) {
3056 data->notify_data.data.length = 0;
3057 return;
3060 memcpy(data->notify_data.data.string, temp, len);
3061 } else {
3062 data->notify_data.data.string = NULL;
3066 /*******************************************************************
3067 * fill a notify_info_data with the security descriptor
3068 * jfm:xxxx send an null pointer to say no security desc
3069 * have to implement security before !
3070 ********************************************************************/
3072 static void spoolss_notify_security_desc(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.sd.size = printer->info_2->secdesc_buf->len;
3079 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3082 /*******************************************************************
3083 * fill a notify_info_data with the attributes
3084 * jfm:xxxx a samba printer is always shared
3085 ********************************************************************/
3087 void spoolss_notify_attributes(int snum,
3088 SPOOL_NOTIFY_INFO_DATA *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3093 data->notify_data.value[0] = printer->info_2->attributes;
3094 data->notify_data.value[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the priority
3099 ********************************************************************/
3101 static void spoolss_notify_priority(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 data->notify_data.value[0] = printer->info_2->priority;
3108 data->notify_data.value[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the default priority
3113 ********************************************************************/
3115 static void spoolss_notify_default_priority(int snum,
3116 SPOOL_NOTIFY_INFO_DATA *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 data->notify_data.value[0] = printer->info_2->default_priority;
3122 data->notify_data.value[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the start time
3127 ********************************************************************/
3129 static void spoolss_notify_start_time(int snum,
3130 SPOOL_NOTIFY_INFO_DATA *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 data->notify_data.value[0] = printer->info_2->starttime;
3136 data->notify_data.value[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the until time
3141 ********************************************************************/
3143 static void spoolss_notify_until_time(int snum,
3144 SPOOL_NOTIFY_INFO_DATA *data,
3145 print_queue_struct *queue,
3146 NT_PRINTER_INFO_LEVEL *printer,
3147 TALLOC_CTX *mem_ctx)
3149 data->notify_data.value[0] = printer->info_2->untiltime;
3150 data->notify_data.value[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the status
3155 ********************************************************************/
3157 static void spoolss_notify_status(int snum,
3158 SPOOL_NOTIFY_INFO_DATA *data,
3159 print_queue_struct *queue,
3160 NT_PRINTER_INFO_LEVEL *printer,
3161 TALLOC_CTX *mem_ctx)
3163 print_status_struct status;
3165 print_queue_length(snum, &status);
3166 data->notify_data.value[0]=(uint32) status.status;
3167 data->notify_data.value[1] = 0;
3170 /*******************************************************************
3171 * fill a notify_info_data with the number of jobs queued
3172 ********************************************************************/
3174 void spoolss_notify_cjobs(int snum,
3175 SPOOL_NOTIFY_INFO_DATA *data,
3176 print_queue_struct *queue,
3177 NT_PRINTER_INFO_LEVEL *printer,
3178 TALLOC_CTX *mem_ctx)
3180 data->notify_data.value[0] = print_queue_length(snum, NULL);
3181 data->notify_data.value[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with the average ppm
3186 ********************************************************************/
3188 static void spoolss_notify_average_ppm(int snum,
3189 SPOOL_NOTIFY_INFO_DATA *data,
3190 print_queue_struct *queue,
3191 NT_PRINTER_INFO_LEVEL *printer,
3192 TALLOC_CTX *mem_ctx)
3194 /* always respond 8 pages per minutes */
3195 /* a little hard ! */
3196 data->notify_data.value[0] = printer->info_2->averageppm;
3197 data->notify_data.value[1] = 0;
3200 /*******************************************************************
3201 * fill a notify_info_data with username
3202 ********************************************************************/
3204 static void spoolss_notify_username(int snum,
3205 SPOOL_NOTIFY_INFO_DATA *data,
3206 print_queue_struct *queue,
3207 NT_PRINTER_INFO_LEVEL *printer,
3208 TALLOC_CTX *mem_ctx)
3210 pstring temp;
3211 uint32 len;
3213 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3215 data->notify_data.data.length = len;
3216 if (len) {
3217 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3219 if (!data->notify_data.data.string) {
3220 data->notify_data.data.length = 0;
3221 return;
3224 memcpy(data->notify_data.data.string, temp, len);
3225 } else {
3226 data->notify_data.data.string = NULL;
3230 /*******************************************************************
3231 * fill a notify_info_data with job status
3232 ********************************************************************/
3234 static void spoolss_notify_job_status(int snum,
3235 SPOOL_NOTIFY_INFO_DATA *data,
3236 print_queue_struct *queue,
3237 NT_PRINTER_INFO_LEVEL *printer,
3238 TALLOC_CTX *mem_ctx)
3240 data->notify_data.value[0]=nt_printj_status(queue->status);
3241 data->notify_data.value[1] = 0;
3244 /*******************************************************************
3245 * fill a notify_info_data with job name
3246 ********************************************************************/
3248 static void spoolss_notify_job_name(int snum,
3249 SPOOL_NOTIFY_INFO_DATA *data,
3250 print_queue_struct *queue,
3251 NT_PRINTER_INFO_LEVEL *printer,
3252 TALLOC_CTX *mem_ctx)
3254 pstring temp;
3255 uint32 len;
3257 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3259 data->notify_data.data.length = len;
3260 if (len) {
3261 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3263 if (!data->notify_data.data.string) {
3264 data->notify_data.data.length = 0;
3265 return;
3268 memcpy(data->notify_data.data.string, temp, len);
3269 } else {
3270 data->notify_data.data.string = NULL;
3274 /*******************************************************************
3275 * fill a notify_info_data with job status
3276 ********************************************************************/
3278 static void spoolss_notify_job_status_string(int snum,
3279 SPOOL_NOTIFY_INFO_DATA *data,
3280 print_queue_struct *queue,
3281 NT_PRINTER_INFO_LEVEL *printer,
3282 TALLOC_CTX *mem_ctx)
3285 * Now we're returning job status codes we just return a "" here. JRA.
3288 const char *p = "";
3289 pstring temp;
3290 uint32 len;
3292 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3293 p = "unknown";
3295 switch (queue->status) {
3296 case LPQ_QUEUED:
3297 p = "Queued";
3298 break;
3299 case LPQ_PAUSED:
3300 p = ""; /* NT provides the paused string */
3301 break;
3302 case LPQ_SPOOLING:
3303 p = "Spooling";
3304 break;
3305 case LPQ_PRINTING:
3306 p = "Printing";
3307 break;
3309 #endif /* NO LONGER NEEDED. */
3311 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3313 data->notify_data.data.length = len;
3314 if (len) {
3315 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3317 if (!data->notify_data.data.string) {
3318 data->notify_data.data.length = 0;
3319 return;
3322 memcpy(data->notify_data.data.string, temp, len);
3323 } else {
3324 data->notify_data.data.string = NULL;
3328 /*******************************************************************
3329 * fill a notify_info_data with job time
3330 ********************************************************************/
3332 static void spoolss_notify_job_time(int snum,
3333 SPOOL_NOTIFY_INFO_DATA *data,
3334 print_queue_struct *queue,
3335 NT_PRINTER_INFO_LEVEL *printer,
3336 TALLOC_CTX *mem_ctx)
3338 data->notify_data.value[0]=0x0;
3339 data->notify_data.value[1]=0;
3342 /*******************************************************************
3343 * fill a notify_info_data with job size
3344 ********************************************************************/
3346 static void spoolss_notify_job_size(int snum,
3347 SPOOL_NOTIFY_INFO_DATA *data,
3348 print_queue_struct *queue,
3349 NT_PRINTER_INFO_LEVEL *printer,
3350 TALLOC_CTX *mem_ctx)
3352 data->notify_data.value[0]=queue->size;
3353 data->notify_data.value[1]=0;
3356 /*******************************************************************
3357 * fill a notify_info_data with page info
3358 ********************************************************************/
3359 static void spoolss_notify_total_pages(int snum,
3360 SPOOL_NOTIFY_INFO_DATA *data,
3361 print_queue_struct *queue,
3362 NT_PRINTER_INFO_LEVEL *printer,
3363 TALLOC_CTX *mem_ctx)
3365 data->notify_data.value[0]=queue->page_count;
3366 data->notify_data.value[1]=0;
3369 /*******************************************************************
3370 * fill a notify_info_data with pages printed info.
3371 ********************************************************************/
3372 static void spoolss_notify_pages_printed(int snum,
3373 SPOOL_NOTIFY_INFO_DATA *data,
3374 print_queue_struct *queue,
3375 NT_PRINTER_INFO_LEVEL *printer,
3376 TALLOC_CTX *mem_ctx)
3378 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3379 data->notify_data.value[1]=0;
3382 /*******************************************************************
3383 Fill a notify_info_data with job position.
3384 ********************************************************************/
3386 static void spoolss_notify_job_position(int snum,
3387 SPOOL_NOTIFY_INFO_DATA *data,
3388 print_queue_struct *queue,
3389 NT_PRINTER_INFO_LEVEL *printer,
3390 TALLOC_CTX *mem_ctx)
3392 data->notify_data.value[0]=queue->job;
3393 data->notify_data.value[1]=0;
3396 /*******************************************************************
3397 Fill a notify_info_data with submitted time.
3398 ********************************************************************/
3400 static void spoolss_notify_submitted_time(int snum,
3401 SPOOL_NOTIFY_INFO_DATA *data,
3402 print_queue_struct *queue,
3403 NT_PRINTER_INFO_LEVEL *printer,
3404 TALLOC_CTX *mem_ctx)
3406 struct tm *t;
3407 uint32 len;
3408 SYSTEMTIME st;
3409 char *p;
3411 t=gmtime(&queue->time);
3413 len = sizeof(SYSTEMTIME);
3415 data->notify_data.data.length = len;
3416 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3418 if (!data->notify_data.data.string) {
3419 data->notify_data.data.length = 0;
3420 return;
3423 make_systemtime(&st, t);
3426 * Systemtime must be linearized as a set of UINT16's.
3427 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3430 p = (char *)data->notify_data.data.string;
3431 SSVAL(p, 0, st.year);
3432 SSVAL(p, 2, st.month);
3433 SSVAL(p, 4, st.dayofweek);
3434 SSVAL(p, 6, st.day);
3435 SSVAL(p, 8, st.hour);
3436 SSVAL(p, 10, st.minute);
3437 SSVAL(p, 12, st.second);
3438 SSVAL(p, 14, st.milliseconds);
3441 struct s_notify_info_data_table
3443 uint16 type;
3444 uint16 field;
3445 const char *name;
3446 uint32 size;
3447 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3448 print_queue_struct *queue,
3449 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3452 /* A table describing the various print notification constants and
3453 whether the notification data is a pointer to a variable sized
3454 buffer, a one value uint32 or a two value uint32. */
3456 static const struct s_notify_info_data_table notify_info_data_table[] =
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3507 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3510 /*******************************************************************
3511 Return the size of info_data structure.
3512 ********************************************************************/
3514 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3516 int i=0;
3518 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3519 if ( (notify_info_data_table[i].type == type)
3520 && (notify_info_data_table[i].field == field) ) {
3521 switch(notify_info_data_table[i].size) {
3522 case NOTIFY_ONE_VALUE:
3523 case NOTIFY_TWO_VALUE:
3524 return 1;
3525 case NOTIFY_STRING:
3526 return 2;
3528 /* The only pointer notify data I have seen on
3529 the wire is the submitted time and this has
3530 the notify size set to 4. -tpot */
3532 case NOTIFY_POINTER:
3533 return 4;
3535 case NOTIFY_SECDESC:
3536 return 5;
3541 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3543 return 0;
3546 /*******************************************************************
3547 Return the type of notify_info_data.
3548 ********************************************************************/
3550 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3552 uint32 i=0;
3554 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3555 if (notify_info_data_table[i].type == type &&
3556 notify_info_data_table[i].field == field)
3557 return notify_info_data_table[i].size;
3560 return 0;
3563 /****************************************************************************
3564 ****************************************************************************/
3566 static BOOL search_notify(uint16 type, uint16 field, int *value)
3568 int i;
3570 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3571 if (notify_info_data_table[i].type == type &&
3572 notify_info_data_table[i].field == field &&
3573 notify_info_data_table[i].fn != NULL) {
3574 *value = i;
3575 return True;
3579 return False;
3582 /****************************************************************************
3583 ****************************************************************************/
3585 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3587 info_data->type = type;
3588 info_data->field = field;
3589 info_data->reserved = 0;
3591 info_data->size = size_of_notify_info_data(type, field);
3592 info_data->enc_type = type_of_notify_info_data(type, field);
3594 info_data->id = id;
3597 /*******************************************************************
3599 * fill a notify_info struct with info asked
3601 ********************************************************************/
3603 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3604 snum, SPOOL_NOTIFY_OPTION_TYPE
3605 *option_type, uint32 id,
3606 TALLOC_CTX *mem_ctx)
3608 int field_num,j;
3609 uint16 type;
3610 uint16 field;
3612 SPOOL_NOTIFY_INFO_DATA *current_data;
3613 NT_PRINTER_INFO_LEVEL *printer = NULL;
3614 print_queue_struct *queue=NULL;
3616 type=option_type->type;
3618 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3619 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3620 option_type->count, lp_servicename(snum)));
3622 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3623 return False;
3625 for(field_num=0; field_num<option_type->count; field_num++) {
3626 field = option_type->fields[field_num];
3628 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3630 if (!search_notify(type, field, &j) )
3631 continue;
3633 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3634 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3635 free_a_printer(&printer, 2);
3636 return False;
3639 current_data = &info->data[info->count];
3641 construct_info_data(current_data, type, field, id);
3643 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3644 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3646 notify_info_data_table[j].fn(snum, current_data, queue,
3647 printer, mem_ctx);
3649 info->count++;
3652 free_a_printer(&printer, 2);
3653 return True;
3656 /*******************************************************************
3658 * fill a notify_info struct with info asked
3660 ********************************************************************/
3662 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3663 SPOOL_NOTIFY_INFO *info,
3664 NT_PRINTER_INFO_LEVEL *printer,
3665 int snum, SPOOL_NOTIFY_OPTION_TYPE
3666 *option_type, uint32 id,
3667 TALLOC_CTX *mem_ctx)
3669 int field_num,j;
3670 uint16 type;
3671 uint16 field;
3673 SPOOL_NOTIFY_INFO_DATA *current_data;
3675 DEBUG(4,("construct_notify_jobs_info\n"));
3677 type = option_type->type;
3679 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3680 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3681 option_type->count));
3683 for(field_num=0; field_num<option_type->count; field_num++) {
3684 field = option_type->fields[field_num];
3686 if (!search_notify(type, field, &j) )
3687 continue;
3689 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3690 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3691 return False;
3694 current_data=&(info->data[info->count]);
3696 construct_info_data(current_data, type, field, id);
3697 notify_info_data_table[j].fn(snum, current_data, queue,
3698 printer, mem_ctx);
3699 info->count++;
3702 return True;
3706 * JFM: The enumeration is not that simple, it's even non obvious.
3708 * let's take an example: I want to monitor the PRINTER SERVER for
3709 * the printer's name and the number of jobs currently queued.
3710 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3711 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3713 * I have 3 printers on the back of my server.
3715 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3716 * structures.
3717 * Number Data Id
3718 * 1 printer 1 name 1
3719 * 2 printer 1 cjob 1
3720 * 3 printer 2 name 2
3721 * 4 printer 2 cjob 2
3722 * 5 printer 3 name 3
3723 * 6 printer 3 name 3
3725 * that's the print server case, the printer case is even worse.
3728 /*******************************************************************
3730 * enumerate all printers on the printserver
3731 * fill a notify_info struct with info asked
3733 ********************************************************************/
3735 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3736 SPOOL_NOTIFY_INFO *info,
3737 TALLOC_CTX *mem_ctx)
3739 int snum;
3740 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3741 int n_services=lp_numservices();
3742 int i;
3743 SPOOL_NOTIFY_OPTION *option;
3744 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3746 DEBUG(4,("printserver_notify_info\n"));
3748 if (!Printer)
3749 return WERR_BADFID;
3751 option=Printer->notify.option;
3752 info->version=2;
3753 info->data=NULL;
3754 info->count=0;
3756 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3757 sending a ffpcn() request first */
3759 if ( !option )
3760 return WERR_BADFID;
3762 for (i=0; i<option->count; i++) {
3763 option_type=&(option->ctr.type[i]);
3765 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3766 continue;
3768 for (snum=0; snum<n_services; snum++)
3770 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3771 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3775 #if 0
3777 * Debugging information, don't delete.
3780 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3781 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3782 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3784 for (i=0; i<info->count; i++) {
3785 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3786 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3787 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3789 #endif
3791 return WERR_OK;
3794 /*******************************************************************
3796 * fill a notify_info struct with info asked
3798 ********************************************************************/
3800 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3801 TALLOC_CTX *mem_ctx)
3803 int snum;
3804 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3805 int i;
3806 uint32 id;
3807 SPOOL_NOTIFY_OPTION *option;
3808 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3809 int count,j;
3810 print_queue_struct *queue=NULL;
3811 print_status_struct status;
3813 DEBUG(4,("printer_notify_info\n"));
3815 if (!Printer)
3816 return WERR_BADFID;
3818 option=Printer->notify.option;
3819 id = 0x0;
3820 info->version=2;
3821 info->data=NULL;
3822 info->count=0;
3824 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3825 sending a ffpcn() request first */
3827 if ( !option )
3828 return WERR_BADFID;
3830 get_printer_snum(p, hnd, &snum);
3832 for (i=0; i<option->count; i++) {
3833 option_type=&option->ctr.type[i];
3835 switch ( option_type->type ) {
3836 case PRINTER_NOTIFY_TYPE:
3837 if(construct_notify_printer_info(Printer, info, snum,
3838 option_type, id,
3839 mem_ctx))
3840 id--;
3841 break;
3843 case JOB_NOTIFY_TYPE: {
3844 NT_PRINTER_INFO_LEVEL *printer = NULL;
3846 count = print_queue_status(snum, &queue, &status);
3848 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3849 goto done;
3851 for (j=0; j<count; j++) {
3852 construct_notify_jobs_info(&queue[j], info,
3853 printer, snum,
3854 option_type,
3855 queue[j].job,
3856 mem_ctx);
3859 free_a_printer(&printer, 2);
3861 done:
3862 SAFE_FREE(queue);
3863 break;
3869 * Debugging information, don't delete.
3872 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3873 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3874 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3876 for (i=0; i<info->count; i++) {
3877 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3878 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3879 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3882 return WERR_OK;
3885 /********************************************************************
3886 * spoolss_rfnpcnex
3887 ********************************************************************/
3889 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3891 POLICY_HND *handle = &q_u->handle;
3892 SPOOL_NOTIFY_INFO *info = &r_u->info;
3894 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3895 WERROR result = WERR_BADFID;
3897 /* we always have a NOTIFY_INFO struct */
3898 r_u->info_ptr=0x1;
3900 if (!Printer) {
3901 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3902 OUR_HANDLE(handle)));
3903 goto done;
3906 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3909 * We are now using the change value, and
3910 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3911 * I don't have a global notification system, I'm sending back all the
3912 * informations even when _NOTHING_ has changed.
3915 /* We need to keep track of the change value to send back in
3916 RRPCN replies otherwise our updates are ignored. */
3918 Printer->notify.fnpcn = True;
3920 if (Printer->notify.client_connected) {
3921 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3922 Printer->notify.change = q_u->change;
3925 /* just ignore the SPOOL_NOTIFY_OPTION */
3927 switch (Printer->printer_type) {
3928 case SPLHND_SERVER:
3929 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3930 break;
3932 case SPLHND_PRINTER:
3933 result = printer_notify_info(p, handle, info, p->mem_ctx);
3934 break;
3937 Printer->notify.fnpcn = False;
3939 done:
3940 return result;
3943 /********************************************************************
3944 * construct_printer_info_0
3945 * fill a printer_info_0 struct
3946 ********************************************************************/
3948 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3950 pstring chaine;
3951 int count;
3952 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3953 counter_printer_0 *session_counter;
3954 uint32 global_counter;
3955 struct tm *t;
3956 time_t setuptime;
3957 print_status_struct status;
3959 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3960 return False;
3962 count = print_queue_length(snum, &status);
3964 /* check if we already have a counter for this printer */
3965 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3966 if (session_counter->snum == snum)
3967 break;
3970 /* it's the first time, add it to the list */
3971 if (session_counter==NULL) {
3972 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3973 free_a_printer(&ntprinter, 2);
3974 return False;
3976 ZERO_STRUCTP(session_counter);
3977 session_counter->snum=snum;
3978 session_counter->counter=0;
3979 DLIST_ADD(counter_list, session_counter);
3982 /* increment it */
3983 session_counter->counter++;
3985 /* JFM:
3986 * the global_counter should be stored in a TDB as it's common to all the clients
3987 * and should be zeroed on samba startup
3989 global_counter=session_counter->counter;
3991 pstrcpy(chaine,ntprinter->info_2->printername);
3993 init_unistr(&printer->printername, chaine);
3995 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3996 init_unistr(&printer->servername, chaine);
3998 printer->cjobs = count;
3999 printer->total_jobs = 0;
4000 printer->total_bytes = 0;
4002 setuptime = (time_t)ntprinter->info_2->setuptime;
4003 t=gmtime(&setuptime);
4005 printer->year = t->tm_year+1900;
4006 printer->month = t->tm_mon+1;
4007 printer->dayofweek = t->tm_wday;
4008 printer->day = t->tm_mday;
4009 printer->hour = t->tm_hour;
4010 printer->minute = t->tm_min;
4011 printer->second = t->tm_sec;
4012 printer->milliseconds = 0;
4014 printer->global_counter = global_counter;
4015 printer->total_pages = 0;
4017 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4018 printer->major_version = 0x0005; /* NT 5 */
4019 printer->build_version = 0x0893; /* build 2195 */
4021 printer->unknown7 = 0x1;
4022 printer->unknown8 = 0x0;
4023 printer->unknown9 = 0x0;
4024 printer->session_counter = session_counter->counter;
4025 printer->unknown11 = 0x0;
4026 printer->printer_errors = 0x0; /* number of print failure */
4027 printer->unknown13 = 0x0;
4028 printer->unknown14 = 0x1;
4029 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4030 printer->unknown16 = 0x0;
4031 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4032 printer->unknown18 = 0x0;
4033 printer->status = nt_printq_status(status.status);
4034 printer->unknown20 = 0x0;
4035 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4036 printer->unknown22 = 0x0;
4037 printer->unknown23 = 0x6; /* 6 ???*/
4038 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4039 printer->unknown25 = 0;
4040 printer->unknown26 = 0;
4041 printer->unknown27 = 0;
4042 printer->unknown28 = 0;
4043 printer->unknown29 = 0;
4045 free_a_printer(&ntprinter,2);
4046 return (True);
4049 /********************************************************************
4050 * construct_printer_info_1
4051 * fill a printer_info_1 struct
4052 ********************************************************************/
4053 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4055 pstring chaine;
4056 pstring chaine2;
4057 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4059 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4060 return False;
4062 printer->flags=flags;
4064 if (*ntprinter->info_2->comment == '\0') {
4065 init_unistr(&printer->comment, lp_comment(snum));
4066 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4067 ntprinter->info_2->drivername, lp_comment(snum));
4069 else {
4070 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4071 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4072 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4075 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4077 init_unistr(&printer->description, chaine);
4078 init_unistr(&printer->name, chaine2);
4080 free_a_printer(&ntprinter,2);
4082 return True;
4085 /****************************************************************************
4086 Free a DEVMODE struct.
4087 ****************************************************************************/
4089 static void free_dev_mode(DEVICEMODE *dev)
4091 if (dev == NULL)
4092 return;
4094 SAFE_FREE(dev->dev_private);
4095 SAFE_FREE(dev);
4099 /****************************************************************************
4100 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4101 should be valid upon entry
4102 ****************************************************************************/
4104 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4106 if ( !devmode || !ntdevmode )
4107 return False;
4109 init_unistr(&devmode->devicename, ntdevmode->devicename);
4111 init_unistr(&devmode->formname, ntdevmode->formname);
4113 devmode->specversion = ntdevmode->specversion;
4114 devmode->driverversion = ntdevmode->driverversion;
4115 devmode->size = ntdevmode->size;
4116 devmode->driverextra = ntdevmode->driverextra;
4117 devmode->fields = ntdevmode->fields;
4119 devmode->orientation = ntdevmode->orientation;
4120 devmode->papersize = ntdevmode->papersize;
4121 devmode->paperlength = ntdevmode->paperlength;
4122 devmode->paperwidth = ntdevmode->paperwidth;
4123 devmode->scale = ntdevmode->scale;
4124 devmode->copies = ntdevmode->copies;
4125 devmode->defaultsource = ntdevmode->defaultsource;
4126 devmode->printquality = ntdevmode->printquality;
4127 devmode->color = ntdevmode->color;
4128 devmode->duplex = ntdevmode->duplex;
4129 devmode->yresolution = ntdevmode->yresolution;
4130 devmode->ttoption = ntdevmode->ttoption;
4131 devmode->collate = ntdevmode->collate;
4132 devmode->icmmethod = ntdevmode->icmmethod;
4133 devmode->icmintent = ntdevmode->icmintent;
4134 devmode->mediatype = ntdevmode->mediatype;
4135 devmode->dithertype = ntdevmode->dithertype;
4137 if (ntdevmode->nt_dev_private != NULL) {
4138 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4139 return False;
4142 return True;
4145 /****************************************************************************
4146 Create a DEVMODE struct. Returns malloced memory.
4147 ****************************************************************************/
4149 DEVICEMODE *construct_dev_mode(const char *servicename)
4151 NT_PRINTER_INFO_LEVEL *printer = NULL;
4152 DEVICEMODE *devmode = NULL;
4154 DEBUG(7,("construct_dev_mode\n"));
4156 DEBUGADD(8,("getting printer characteristics\n"));
4158 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4159 return NULL;
4161 if ( !printer->info_2->devmode ) {
4162 DEBUG(5, ("BONG! There was no device mode!\n"));
4163 goto done;
4166 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4167 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4168 goto done;
4171 ZERO_STRUCTP(devmode);
4173 DEBUGADD(8,("loading DEVICEMODE\n"));
4175 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4176 free_dev_mode( devmode );
4177 devmode = NULL;
4180 done:
4181 free_a_printer(&printer,2);
4183 return devmode;
4186 /********************************************************************
4187 * construct_printer_info_2
4188 * fill a printer_info_2 struct
4189 ********************************************************************/
4191 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4193 int count;
4194 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4196 print_status_struct status;
4198 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4199 return False;
4201 count = print_queue_length(snum, &status);
4203 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4204 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4205 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4206 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4207 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4209 if (*ntprinter->info_2->comment == '\0')
4210 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4211 else
4212 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4214 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4215 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4216 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4217 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4218 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4220 printer->attributes = ntprinter->info_2->attributes;
4222 printer->priority = ntprinter->info_2->priority; /* priority */
4223 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4224 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4225 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4226 printer->status = nt_printq_status(status.status); /* status */
4227 printer->cjobs = count; /* jobs */
4228 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4230 if ( !(printer->devmode = construct_dev_mode(
4231 lp_const_servicename(snum))) )
4232 DEBUG(8, ("Returning NULL Devicemode!\n"));
4234 printer->secdesc = NULL;
4236 if ( ntprinter->info_2->secdesc_buf
4237 && ntprinter->info_2->secdesc_buf->len != 0 )
4239 /* don't use talloc_steal() here unless you do a deep steal of all
4240 the SEC_DESC members */
4242 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4243 ntprinter->info_2->secdesc_buf->sec );
4246 free_a_printer(&ntprinter, 2);
4248 return True;
4251 /********************************************************************
4252 * construct_printer_info_3
4253 * fill a printer_info_3 struct
4254 ********************************************************************/
4256 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4258 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4259 PRINTER_INFO_3 *printer = NULL;
4261 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4262 return False;
4264 *pp_printer = NULL;
4265 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4266 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4267 free_a_printer(&ntprinter, 2);
4268 return False;
4271 ZERO_STRUCTP(printer);
4273 /* These are the components of the SD we are returning. */
4275 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4276 /* don't use talloc_steal() here unless you do a deep steal of all
4277 the SEC_DESC members */
4279 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4280 ntprinter->info_2->secdesc_buf->sec );
4283 free_a_printer(&ntprinter, 2);
4285 *pp_printer = printer;
4286 return True;
4289 /********************************************************************
4290 * construct_printer_info_4
4291 * fill a printer_info_4 struct
4292 ********************************************************************/
4294 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4296 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4298 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4299 return False;
4301 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4302 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4303 printer->attributes = ntprinter->info_2->attributes;
4305 free_a_printer(&ntprinter, 2);
4306 return True;
4309 /********************************************************************
4310 * construct_printer_info_5
4311 * fill a printer_info_5 struct
4312 ********************************************************************/
4314 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4316 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4318 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4319 return False;
4321 init_unistr(&printer->printername, ntprinter->info_2->printername);
4322 init_unistr(&printer->portname, ntprinter->info_2->portname);
4323 printer->attributes = ntprinter->info_2->attributes;
4325 /* these two are not used by NT+ according to MSDN */
4327 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4328 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4330 free_a_printer(&ntprinter, 2);
4332 return True;
4335 /********************************************************************
4336 * construct_printer_info_7
4337 * fill a printer_info_7 struct
4338 ********************************************************************/
4340 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4342 char *guid_str = NULL;
4343 struct GUID guid;
4345 if (is_printer_published(print_hnd, snum, &guid)) {
4346 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4347 strupper_m(guid_str);
4348 init_unistr(&printer->guid, guid_str);
4349 printer->action = SPOOL_DS_PUBLISH;
4350 } else {
4351 init_unistr(&printer->guid, "");
4352 printer->action = SPOOL_DS_UNPUBLISH;
4355 return True;
4358 /********************************************************************
4359 Spoolss_enumprinters.
4360 ********************************************************************/
4362 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4364 int snum;
4365 int i;
4366 int n_services=lp_numservices();
4367 PRINTER_INFO_1 *printers=NULL;
4368 PRINTER_INFO_1 current_prt;
4369 WERROR result = WERR_OK;
4371 DEBUG(4,("enum_all_printers_info_1\n"));
4373 for (snum=0; snum<n_services; snum++) {
4374 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4375 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4377 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4378 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4379 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4380 *returned=0;
4381 return WERR_NOMEM;
4383 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4385 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4386 (*returned)++;
4391 /* check the required size. */
4392 for (i=0; i<*returned; i++)
4393 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4395 if (*needed > offered) {
4396 result = WERR_INSUFFICIENT_BUFFER;
4397 goto out;
4400 if (!rpcbuf_alloc_size(buffer, *needed)) {
4401 result = WERR_NOMEM;
4402 goto out;
4405 /* fill the buffer with the structures */
4406 for (i=0; i<*returned; i++)
4407 smb_io_printer_info_1("", buffer, &printers[i], 0);
4409 out:
4410 /* clear memory */
4412 SAFE_FREE(printers);
4414 if ( !W_ERROR_IS_OK(result) )
4415 *returned = 0;
4417 return result;
4420 /********************************************************************
4421 enum_all_printers_info_1_local.
4422 *********************************************************************/
4424 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4426 DEBUG(4,("enum_all_printers_info_1_local\n"));
4428 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4431 /********************************************************************
4432 enum_all_printers_info_1_name.
4433 *********************************************************************/
4435 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4437 char *s = name;
4439 DEBUG(4,("enum_all_printers_info_1_name\n"));
4441 if ((name[0] == '\\') && (name[1] == '\\'))
4442 s = name + 2;
4444 if (is_myname_or_ipaddr(s)) {
4445 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4447 else
4448 return WERR_INVALID_NAME;
4451 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4452 /********************************************************************
4453 enum_all_printers_info_1_remote.
4454 *********************************************************************/
4456 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4458 PRINTER_INFO_1 *printer;
4459 fstring printername;
4460 fstring desc;
4461 fstring comment;
4462 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4463 WERROR result = WERR_OK;
4465 /* JFM: currently it's more a place holder than anything else.
4466 * In the spooler world there is a notion of server registration.
4467 * the print servers are registered on the PDC (in the same domain)
4469 * We should have a TDB here. The registration is done thru an
4470 * undocumented RPC call.
4473 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4474 return WERR_NOMEM;
4476 *returned=1;
4478 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4479 slprintf(desc, sizeof(desc)-1,"%s", name);
4480 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4482 init_unistr(&printer->description, desc);
4483 init_unistr(&printer->name, printername);
4484 init_unistr(&printer->comment, comment);
4485 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4487 /* check the required size. */
4488 *needed += spoolss_size_printer_info_1(printer);
4490 if (*needed > offered) {
4491 result = WERR_INSUFFICIENT_BUFFER;
4492 goto out;
4495 if (!rpcbuf_alloc_size(buffer, *needed)) {
4496 result = WERR_NOMEM;
4497 goto out;
4500 /* fill the buffer with the structures */
4501 smb_io_printer_info_1("", buffer, printer, 0);
4503 out:
4504 /* clear memory */
4505 SAFE_FREE(printer);
4507 if ( !W_ERROR_IS_OK(result) )
4508 *returned = 0;
4510 return result;
4513 #endif
4515 /********************************************************************
4516 enum_all_printers_info_1_network.
4517 *********************************************************************/
4519 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4521 char *s = name;
4523 DEBUG(4,("enum_all_printers_info_1_network\n"));
4525 /* If we respond to a enum_printers level 1 on our name with flags
4526 set to PRINTER_ENUM_REMOTE with a list of printers then these
4527 printers incorrectly appear in the APW browse list.
4528 Specifically the printers for the server appear at the workgroup
4529 level where all the other servers in the domain are
4530 listed. Windows responds to this call with a
4531 WERR_CAN_NOT_COMPLETE so we should do the same. */
4533 if (name[0] == '\\' && name[1] == '\\')
4534 s = name + 2;
4536 if (is_myname_or_ipaddr(s))
4537 return WERR_CAN_NOT_COMPLETE;
4539 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4542 /********************************************************************
4543 * api_spoolss_enumprinters
4545 * called from api_spoolss_enumprinters (see this to understand)
4546 ********************************************************************/
4548 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4550 int snum;
4551 int i;
4552 int n_services=lp_numservices();
4553 PRINTER_INFO_2 *printers=NULL;
4554 PRINTER_INFO_2 current_prt;
4555 WERROR result = WERR_OK;
4557 *returned = 0;
4559 for (snum=0; snum<n_services; snum++) {
4560 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4561 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4563 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4564 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4565 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4566 *returned = 0;
4567 return WERR_NOMEM;
4570 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4572 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4574 (*returned)++;
4579 /* check the required size. */
4580 for (i=0; i<*returned; i++)
4581 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4583 if (*needed > offered) {
4584 result = WERR_INSUFFICIENT_BUFFER;
4585 goto out;
4588 if (!rpcbuf_alloc_size(buffer, *needed)) {
4589 result = WERR_NOMEM;
4590 goto out;
4593 /* fill the buffer with the structures */
4594 for (i=0; i<*returned; i++)
4595 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4597 out:
4598 /* clear memory */
4600 for (i=0; i<*returned; i++)
4601 free_devmode(printers[i].devmode);
4603 SAFE_FREE(printers);
4605 if ( !W_ERROR_IS_OK(result) )
4606 *returned = 0;
4608 return result;
4611 /********************************************************************
4612 * handle enumeration of printers at level 1
4613 ********************************************************************/
4615 static WERROR enumprinters_level1( uint32 flags, fstring name,
4616 RPC_BUFFER *buffer, uint32 offered,
4617 uint32 *needed, uint32 *returned)
4619 /* Not all the flags are equals */
4621 if (flags & PRINTER_ENUM_LOCAL)
4622 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4624 if (flags & PRINTER_ENUM_NAME)
4625 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4627 #if 0 /* JERRY - disabled for now */
4628 if (flags & PRINTER_ENUM_REMOTE)
4629 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4630 #endif
4632 if (flags & PRINTER_ENUM_NETWORK)
4633 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4635 return WERR_OK; /* NT4sp5 does that */
4638 /********************************************************************
4639 * handle enumeration of printers at level 2
4640 ********************************************************************/
4642 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4643 RPC_BUFFER *buffer, uint32 offered,
4644 uint32 *needed, uint32 *returned)
4646 char *s = servername;
4648 if (flags & PRINTER_ENUM_LOCAL) {
4649 return enum_all_printers_info_2(buffer, offered, needed, returned);
4652 if (flags & PRINTER_ENUM_NAME) {
4653 if ((servername[0] == '\\') && (servername[1] == '\\'))
4654 s = servername + 2;
4655 if (is_myname_or_ipaddr(s))
4656 return enum_all_printers_info_2(buffer, offered, needed, returned);
4657 else
4658 return WERR_INVALID_NAME;
4661 if (flags & PRINTER_ENUM_REMOTE)
4662 return WERR_UNKNOWN_LEVEL;
4664 return WERR_OK;
4667 /********************************************************************
4668 * handle enumeration of printers at level 5
4669 ********************************************************************/
4671 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4672 RPC_BUFFER *buffer, uint32 offered,
4673 uint32 *needed, uint32 *returned)
4675 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4676 return WERR_OK;
4679 /********************************************************************
4680 * api_spoolss_enumprinters
4682 * called from api_spoolss_enumprinters (see this to understand)
4683 ********************************************************************/
4685 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4687 uint32 flags = q_u->flags;
4688 UNISTR2 *servername = &q_u->servername;
4689 uint32 level = q_u->level;
4690 RPC_BUFFER *buffer = NULL;
4691 uint32 offered = q_u->offered;
4692 uint32 *needed = &r_u->needed;
4693 uint32 *returned = &r_u->returned;
4695 fstring name;
4697 /* that's an [in out] buffer */
4699 if (!q_u->buffer && (offered!=0)) {
4700 return WERR_INVALID_PARAM;
4703 rpcbuf_move(q_u->buffer, &r_u->buffer);
4704 buffer = r_u->buffer;
4706 DEBUG(4,("_spoolss_enumprinters\n"));
4708 *needed=0;
4709 *returned=0;
4712 * Level 1:
4713 * flags==PRINTER_ENUM_NAME
4714 * if name=="" then enumerates all printers
4715 * if name!="" then enumerate the printer
4716 * flags==PRINTER_ENUM_REMOTE
4717 * name is NULL, enumerate printers
4718 * Level 2: name!="" enumerates printers, name can't be NULL
4719 * Level 3: doesn't exist
4720 * Level 4: does a local registry lookup
4721 * Level 5: same as Level 2
4724 unistr2_to_ascii(name, servername, sizeof(name)-1);
4725 strupper_m(name);
4727 switch (level) {
4728 case 1:
4729 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4730 case 2:
4731 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4732 case 5:
4733 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4734 case 3:
4735 case 4:
4736 break;
4738 return WERR_UNKNOWN_LEVEL;
4741 /****************************************************************************
4742 ****************************************************************************/
4744 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4746 PRINTER_INFO_0 *printer=NULL;
4747 WERROR result = WERR_OK;
4749 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4750 return WERR_NOMEM;
4752 construct_printer_info_0(print_hnd, printer, snum);
4754 /* check the required size. */
4755 *needed += spoolss_size_printer_info_0(printer);
4757 if (*needed > offered) {
4758 result = WERR_INSUFFICIENT_BUFFER;
4759 goto out;
4762 if (!rpcbuf_alloc_size(buffer, *needed)) {
4763 result = WERR_NOMEM;
4764 goto out;
4767 /* fill the buffer with the structures */
4768 smb_io_printer_info_0("", buffer, printer, 0);
4770 out:
4771 /* clear memory */
4773 SAFE_FREE(printer);
4775 return result;
4778 /****************************************************************************
4779 ****************************************************************************/
4781 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4783 PRINTER_INFO_1 *printer=NULL;
4784 WERROR result = WERR_OK;
4786 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4787 return WERR_NOMEM;
4789 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4791 /* check the required size. */
4792 *needed += spoolss_size_printer_info_1(printer);
4794 if (*needed > offered) {
4795 result = WERR_INSUFFICIENT_BUFFER;
4796 goto out;
4799 if (!rpcbuf_alloc_size(buffer, *needed)) {
4800 result = WERR_NOMEM;
4801 goto out;
4804 /* fill the buffer with the structures */
4805 smb_io_printer_info_1("", buffer, printer, 0);
4807 out:
4808 /* clear memory */
4809 SAFE_FREE(printer);
4811 return result;
4814 /****************************************************************************
4815 ****************************************************************************/
4817 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4819 PRINTER_INFO_2 *printer=NULL;
4820 WERROR result = WERR_OK;
4822 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4823 return WERR_NOMEM;
4825 construct_printer_info_2(print_hnd, printer, snum);
4827 /* check the required size. */
4828 *needed += spoolss_size_printer_info_2(printer);
4830 if (*needed > offered) {
4831 result = WERR_INSUFFICIENT_BUFFER;
4832 goto out;
4835 if (!rpcbuf_alloc_size(buffer, *needed)) {
4836 result = WERR_NOMEM;
4837 goto out;
4840 /* fill the buffer with the structures */
4841 if (!smb_io_printer_info_2("", buffer, printer, 0))
4842 result = WERR_NOMEM;
4844 out:
4845 /* clear memory */
4846 free_printer_info_2(printer);
4848 return result;
4851 /****************************************************************************
4852 ****************************************************************************/
4854 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4856 PRINTER_INFO_3 *printer=NULL;
4857 WERROR result = WERR_OK;
4859 if (!construct_printer_info_3(print_hnd, &printer, snum))
4860 return WERR_NOMEM;
4862 /* check the required size. */
4863 *needed += spoolss_size_printer_info_3(printer);
4865 if (*needed > offered) {
4866 result = WERR_INSUFFICIENT_BUFFER;
4867 goto out;
4870 if (!rpcbuf_alloc_size(buffer, *needed)) {
4871 result = WERR_NOMEM;
4872 goto out;
4875 /* fill the buffer with the structures */
4876 smb_io_printer_info_3("", buffer, printer, 0);
4878 out:
4879 /* clear memory */
4880 free_printer_info_3(printer);
4882 return result;
4885 /****************************************************************************
4886 ****************************************************************************/
4888 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4890 PRINTER_INFO_4 *printer=NULL;
4891 WERROR result = WERR_OK;
4893 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4894 return WERR_NOMEM;
4896 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4897 SAFE_FREE(printer);
4898 return WERR_NOMEM;
4901 /* check the required size. */
4902 *needed += spoolss_size_printer_info_4(printer);
4904 if (*needed > offered) {
4905 result = WERR_INSUFFICIENT_BUFFER;
4906 goto out;
4909 if (!rpcbuf_alloc_size(buffer, *needed)) {
4910 result = WERR_NOMEM;
4911 goto out;
4914 /* fill the buffer with the structures */
4915 smb_io_printer_info_4("", buffer, printer, 0);
4917 out:
4918 /* clear memory */
4919 free_printer_info_4(printer);
4921 return result;
4924 /****************************************************************************
4925 ****************************************************************************/
4927 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4929 PRINTER_INFO_5 *printer=NULL;
4930 WERROR result = WERR_OK;
4932 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4933 return WERR_NOMEM;
4935 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4936 free_printer_info_5(printer);
4937 return WERR_NOMEM;
4940 /* check the required size. */
4941 *needed += spoolss_size_printer_info_5(printer);
4943 if (*needed > offered) {
4944 result = WERR_INSUFFICIENT_BUFFER;
4945 goto out;
4948 if (!rpcbuf_alloc_size(buffer, *needed)) {
4949 result = WERR_NOMEM;
4950 goto out;
4953 /* fill the buffer with the structures */
4954 smb_io_printer_info_5("", buffer, printer, 0);
4956 out:
4957 /* clear memory */
4958 free_printer_info_5(printer);
4960 return result;
4963 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4965 PRINTER_INFO_7 *printer=NULL;
4966 WERROR result = WERR_OK;
4968 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4969 return WERR_NOMEM;
4971 if (!construct_printer_info_7(print_hnd, printer, snum))
4972 return WERR_NOMEM;
4974 /* check the required size. */
4975 *needed += spoolss_size_printer_info_7(printer);
4977 if (*needed > offered) {
4978 result = WERR_INSUFFICIENT_BUFFER;
4979 goto out;
4982 if (!rpcbuf_alloc_size(buffer, *needed)) {
4983 result = WERR_NOMEM;
4984 goto out;
4988 /* fill the buffer with the structures */
4989 smb_io_printer_info_7("", buffer, printer, 0);
4991 out:
4992 /* clear memory */
4993 free_printer_info_7(printer);
4995 return result;
4998 /****************************************************************************
4999 ****************************************************************************/
5001 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5003 POLICY_HND *handle = &q_u->handle;
5004 uint32 level = q_u->level;
5005 RPC_BUFFER *buffer = NULL;
5006 uint32 offered = q_u->offered;
5007 uint32 *needed = &r_u->needed;
5008 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5010 int snum;
5012 /* that's an [in out] buffer */
5014 if (!q_u->buffer && (offered!=0)) {
5015 return WERR_INVALID_PARAM;
5018 rpcbuf_move(q_u->buffer, &r_u->buffer);
5019 buffer = r_u->buffer;
5021 *needed=0;
5023 if (!get_printer_snum(p, handle, &snum))
5024 return WERR_BADFID;
5026 switch (level) {
5027 case 0:
5028 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5029 case 1:
5030 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5031 case 2:
5032 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5033 case 3:
5034 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5035 case 4:
5036 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5037 case 5:
5038 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5039 case 7:
5040 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5042 return WERR_UNKNOWN_LEVEL;
5045 /********************************************************************
5046 * fill a DRIVER_INFO_1 struct
5047 ********************************************************************/
5049 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5051 init_unistr( &info->name, driver.info_3->name);
5054 /********************************************************************
5055 * construct_printer_driver_info_1
5056 ********************************************************************/
5058 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5060 NT_PRINTER_INFO_LEVEL *printer = NULL;
5061 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5063 ZERO_STRUCT(driver);
5065 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5066 return WERR_INVALID_PRINTER_NAME;
5068 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5069 free_a_printer(&printer, 2);
5070 return WERR_UNKNOWN_PRINTER_DRIVER;
5073 fill_printer_driver_info_1(info, driver, servername, architecture);
5075 free_a_printer(&printer,2);
5077 return WERR_OK;
5080 /********************************************************************
5081 * construct_printer_driver_info_2
5082 * fill a printer_info_2 struct
5083 ********************************************************************/
5085 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5087 pstring temp;
5089 info->version=driver.info_3->cversion;
5091 init_unistr( &info->name, driver.info_3->name );
5092 init_unistr( &info->architecture, driver.info_3->environment );
5095 if (strlen(driver.info_3->driverpath)) {
5096 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5097 init_unistr( &info->driverpath, temp );
5098 } else
5099 init_unistr( &info->driverpath, "" );
5101 if (strlen(driver.info_3->datafile)) {
5102 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5103 init_unistr( &info->datafile, temp );
5104 } else
5105 init_unistr( &info->datafile, "" );
5107 if (strlen(driver.info_3->configfile)) {
5108 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5109 init_unistr( &info->configfile, temp );
5110 } else
5111 init_unistr( &info->configfile, "" );
5114 /********************************************************************
5115 * construct_printer_driver_info_2
5116 * fill a printer_info_2 struct
5117 ********************************************************************/
5119 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5121 NT_PRINTER_INFO_LEVEL *printer = NULL;
5122 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5124 ZERO_STRUCT(printer);
5125 ZERO_STRUCT(driver);
5127 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5128 return WERR_INVALID_PRINTER_NAME;
5130 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5131 free_a_printer(&printer, 2);
5132 return WERR_UNKNOWN_PRINTER_DRIVER;
5135 fill_printer_driver_info_2(info, driver, servername);
5137 free_a_printer(&printer,2);
5139 return WERR_OK;
5142 /********************************************************************
5143 * copy a strings array and convert to UNICODE
5145 * convert an array of ascii string to a UNICODE string
5146 ********************************************************************/
5148 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5150 int i=0;
5151 int j=0;
5152 const char *v;
5153 pstring line;
5155 DEBUG(6,("init_unistr_array\n"));
5156 *uni_array=NULL;
5158 while (True)
5160 if ( !char_array )
5161 v = "";
5162 else
5164 v = char_array[i];
5165 if (!v)
5166 v = ""; /* hack to handle null lists */
5169 /* hack to allow this to be used in places other than when generating
5170 the list of dependent files */
5172 if ( servername )
5173 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5174 else
5175 pstrcpy( line, v );
5177 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5179 /* add one extra unit16 for the second terminating NULL */
5181 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5182 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5183 return 0;
5186 if ( !strlen(v) )
5187 break;
5189 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5190 i++;
5193 if (*uni_array) {
5194 /* special case for ""; we need to add both NULL's here */
5195 if (!j)
5196 (*uni_array)[j++]=0x0000;
5197 (*uni_array)[j]=0x0000;
5200 DEBUGADD(6,("last one:done\n"));
5202 /* return size of array in uint16's */
5204 return j+1;
5207 /********************************************************************
5208 * construct_printer_info_3
5209 * fill a printer_info_3 struct
5210 ********************************************************************/
5212 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5214 pstring temp;
5216 ZERO_STRUCTP(info);
5218 info->version=driver.info_3->cversion;
5220 init_unistr( &info->name, driver.info_3->name );
5221 init_unistr( &info->architecture, driver.info_3->environment );
5223 if (strlen(driver.info_3->driverpath)) {
5224 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5225 init_unistr( &info->driverpath, temp );
5226 } else
5227 init_unistr( &info->driverpath, "" );
5229 if (strlen(driver.info_3->datafile)) {
5230 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5231 init_unistr( &info->datafile, temp );
5232 } else
5233 init_unistr( &info->datafile, "" );
5235 if (strlen(driver.info_3->configfile)) {
5236 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5237 init_unistr( &info->configfile, temp );
5238 } else
5239 init_unistr( &info->configfile, "" );
5241 if (strlen(driver.info_3->helpfile)) {
5242 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5243 init_unistr( &info->helpfile, temp );
5244 } else
5245 init_unistr( &info->helpfile, "" );
5247 init_unistr( &info->monitorname, driver.info_3->monitorname );
5248 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5250 info->dependentfiles=NULL;
5251 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5254 /********************************************************************
5255 * construct_printer_info_3
5256 * fill a printer_info_3 struct
5257 ********************************************************************/
5259 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5261 NT_PRINTER_INFO_LEVEL *printer = NULL;
5262 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5263 WERROR status;
5264 ZERO_STRUCT(driver);
5266 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5267 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5268 if (!W_ERROR_IS_OK(status))
5269 return WERR_INVALID_PRINTER_NAME;
5271 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5272 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5274 #if 0 /* JERRY */
5277 * I put this code in during testing. Helpful when commenting out the
5278 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5279 * as win2k always queries the driver using an infor level of 6.
5280 * I've left it in (but ifdef'd out) because I'll probably
5281 * use it in experimentation again in the future. --jerry 22/01/2002
5284 if (!W_ERROR_IS_OK(status)) {
5286 * Is this a W2k client ?
5288 if (version == 3) {
5289 /* Yes - try again with a WinNT driver. */
5290 version = 2;
5291 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5292 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5294 #endif
5296 if (!W_ERROR_IS_OK(status)) {
5297 free_a_printer(&printer,2);
5298 return WERR_UNKNOWN_PRINTER_DRIVER;
5301 #if 0 /* JERRY */
5303 #endif
5306 fill_printer_driver_info_3(info, driver, servername);
5308 free_a_printer(&printer,2);
5310 return WERR_OK;
5313 /********************************************************************
5314 * construct_printer_info_6
5315 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5316 ********************************************************************/
5318 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5320 pstring temp;
5321 fstring nullstr;
5323 ZERO_STRUCTP(info);
5324 memset(&nullstr, '\0', sizeof(fstring));
5326 info->version=driver.info_3->cversion;
5328 init_unistr( &info->name, driver.info_3->name );
5329 init_unistr( &info->architecture, driver.info_3->environment );
5331 if (strlen(driver.info_3->driverpath)) {
5332 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5333 init_unistr( &info->driverpath, temp );
5334 } else
5335 init_unistr( &info->driverpath, "" );
5337 if (strlen(driver.info_3->datafile)) {
5338 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5339 init_unistr( &info->datafile, temp );
5340 } else
5341 init_unistr( &info->datafile, "" );
5343 if (strlen(driver.info_3->configfile)) {
5344 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5345 init_unistr( &info->configfile, temp );
5346 } else
5347 init_unistr( &info->configfile, "" );
5349 if (strlen(driver.info_3->helpfile)) {
5350 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5351 init_unistr( &info->helpfile, temp );
5352 } else
5353 init_unistr( &info->helpfile, "" );
5355 init_unistr( &info->monitorname, driver.info_3->monitorname );
5356 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5358 info->dependentfiles = NULL;
5359 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5361 info->previousdrivernames=NULL;
5362 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5364 info->driver_date=0;
5366 info->padding=0;
5367 info->driver_version_low=0;
5368 info->driver_version_high=0;
5370 init_unistr( &info->mfgname, "");
5371 init_unistr( &info->oem_url, "");
5372 init_unistr( &info->hardware_id, "");
5373 init_unistr( &info->provider, "");
5376 /********************************************************************
5377 * construct_printer_info_6
5378 * fill a printer_info_6 struct
5379 ********************************************************************/
5381 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5382 fstring servername, fstring architecture, uint32 version)
5384 NT_PRINTER_INFO_LEVEL *printer = NULL;
5385 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5386 WERROR status;
5388 ZERO_STRUCT(driver);
5390 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5392 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5394 if (!W_ERROR_IS_OK(status))
5395 return WERR_INVALID_PRINTER_NAME;
5397 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5399 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5401 if (!W_ERROR_IS_OK(status))
5404 * Is this a W2k client ?
5407 if (version < 3) {
5408 free_a_printer(&printer,2);
5409 return WERR_UNKNOWN_PRINTER_DRIVER;
5412 /* Yes - try again with a WinNT driver. */
5413 version = 2;
5414 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5415 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5416 if (!W_ERROR_IS_OK(status)) {
5417 free_a_printer(&printer,2);
5418 return WERR_UNKNOWN_PRINTER_DRIVER;
5422 fill_printer_driver_info_6(info, driver, servername);
5424 free_a_printer(&printer,2);
5425 free_a_printer_driver(driver, 3);
5427 return WERR_OK;
5430 /****************************************************************************
5431 ****************************************************************************/
5433 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5435 SAFE_FREE(info->dependentfiles);
5438 /****************************************************************************
5439 ****************************************************************************/
5441 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5443 SAFE_FREE(info->dependentfiles);
5446 /****************************************************************************
5447 ****************************************************************************/
5449 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5451 DRIVER_INFO_1 *info=NULL;
5452 WERROR result;
5454 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5455 return WERR_NOMEM;
5457 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5458 if (!W_ERROR_IS_OK(result))
5459 goto out;
5461 /* check the required size. */
5462 *needed += spoolss_size_printer_driver_info_1(info);
5464 if (*needed > offered) {
5465 result = WERR_INSUFFICIENT_BUFFER;
5466 goto out;
5469 if (!rpcbuf_alloc_size(buffer, *needed)) {
5470 result = WERR_NOMEM;
5471 goto out;
5474 /* fill the buffer with the structures */
5475 smb_io_printer_driver_info_1("", buffer, info, 0);
5477 out:
5478 /* clear memory */
5479 SAFE_FREE(info);
5481 return result;
5484 /****************************************************************************
5485 ****************************************************************************/
5487 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5489 DRIVER_INFO_2 *info=NULL;
5490 WERROR result;
5492 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5493 return WERR_NOMEM;
5495 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5496 if (!W_ERROR_IS_OK(result))
5497 goto out;
5499 /* check the required size. */
5500 *needed += spoolss_size_printer_driver_info_2(info);
5502 if (*needed > offered) {
5503 result = WERR_INSUFFICIENT_BUFFER;
5504 goto out;
5507 if (!rpcbuf_alloc_size(buffer, *needed)) {
5508 result = WERR_NOMEM;
5509 goto out;
5512 /* fill the buffer with the structures */
5513 smb_io_printer_driver_info_2("", buffer, info, 0);
5515 out:
5516 /* clear memory */
5517 SAFE_FREE(info);
5519 return result;
5522 /****************************************************************************
5523 ****************************************************************************/
5525 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5527 DRIVER_INFO_3 info;
5528 WERROR result;
5530 ZERO_STRUCT(info);
5532 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5533 if (!W_ERROR_IS_OK(result))
5534 goto out;
5536 /* check the required size. */
5537 *needed += spoolss_size_printer_driver_info_3(&info);
5539 if (*needed > offered) {
5540 result = WERR_INSUFFICIENT_BUFFER;
5541 goto out;
5544 if (!rpcbuf_alloc_size(buffer, *needed)) {
5545 result = WERR_NOMEM;
5546 goto out;
5549 /* fill the buffer with the structures */
5550 smb_io_printer_driver_info_3("", buffer, &info, 0);
5552 out:
5553 free_printer_driver_info_3(&info);
5555 return result;
5558 /****************************************************************************
5559 ****************************************************************************/
5561 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5563 DRIVER_INFO_6 info;
5564 WERROR result;
5566 ZERO_STRUCT(info);
5568 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5569 if (!W_ERROR_IS_OK(result))
5570 goto out;
5572 /* check the required size. */
5573 *needed += spoolss_size_printer_driver_info_6(&info);
5575 if (*needed > offered) {
5576 result = WERR_INSUFFICIENT_BUFFER;
5577 goto out;
5580 if (!rpcbuf_alloc_size(buffer, *needed)) {
5581 result = WERR_NOMEM;
5582 goto out;
5585 /* fill the buffer with the structures */
5586 smb_io_printer_driver_info_6("", buffer, &info, 0);
5588 out:
5589 free_printer_driver_info_6(&info);
5591 return result;
5594 /****************************************************************************
5595 ****************************************************************************/
5597 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5599 POLICY_HND *handle = &q_u->handle;
5600 UNISTR2 *uni_arch = &q_u->architecture;
5601 uint32 level = q_u->level;
5602 uint32 clientmajorversion = q_u->clientmajorversion;
5603 RPC_BUFFER *buffer = NULL;
5604 uint32 offered = q_u->offered;
5605 uint32 *needed = &r_u->needed;
5606 uint32 *servermajorversion = &r_u->servermajorversion;
5607 uint32 *serverminorversion = &r_u->serverminorversion;
5608 Printer_entry *printer;
5610 fstring servername;
5611 fstring architecture;
5612 int snum;
5614 /* that's an [in out] buffer */
5616 if (!q_u->buffer && (offered!=0)) {
5617 return WERR_INVALID_PARAM;
5620 rpcbuf_move(q_u->buffer, &r_u->buffer);
5621 buffer = r_u->buffer;
5623 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5625 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5626 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5627 return WERR_INVALID_PRINTER_NAME;
5630 *needed = 0;
5631 *servermajorversion = 0;
5632 *serverminorversion = 0;
5634 fstrcpy(servername, get_server_name( printer ));
5635 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5637 if (!get_printer_snum(p, handle, &snum))
5638 return WERR_BADFID;
5640 switch (level) {
5641 case 1:
5642 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5643 case 2:
5644 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5645 case 3:
5646 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5647 case 6:
5648 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5649 #if 0 /* JERRY */
5650 case 101:
5651 /* apparently this call is the equivalent of
5652 EnumPrinterDataEx() for the DsDriver key */
5653 break;
5654 #endif
5657 return WERR_UNKNOWN_LEVEL;
5660 /****************************************************************************
5661 ****************************************************************************/
5663 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5665 POLICY_HND *handle = &q_u->handle;
5667 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5669 if (!Printer) {
5670 DEBUG(3,("Error in startpageprinter printer handle\n"));
5671 return WERR_BADFID;
5674 Printer->page_started=True;
5675 return WERR_OK;
5678 /****************************************************************************
5679 ****************************************************************************/
5681 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5683 POLICY_HND *handle = &q_u->handle;
5684 int snum;
5686 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5688 if (!Printer) {
5689 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5690 return WERR_BADFID;
5693 if (!get_printer_snum(p, handle, &snum))
5694 return WERR_BADFID;
5696 Printer->page_started=False;
5697 print_job_endpage(snum, Printer->jobid);
5699 return WERR_OK;
5702 /********************************************************************
5703 * api_spoolss_getprinter
5704 * called from the spoolss dispatcher
5706 ********************************************************************/
5708 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5710 POLICY_HND *handle = &q_u->handle;
5711 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5712 uint32 *jobid = &r_u->jobid;
5714 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5715 int snum;
5716 pstring jobname;
5717 fstring datatype;
5718 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5719 struct current_user user;
5721 if (!Printer) {
5722 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5723 return WERR_BADFID;
5726 get_current_user(&user, p);
5729 * a nice thing with NT is it doesn't listen to what you tell it.
5730 * when asked to send _only_ RAW datas, it tries to send datas
5731 * in EMF format.
5733 * So I add checks like in NT Server ...
5736 if (info_1->p_datatype != 0) {
5737 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5738 if (strcmp(datatype, "RAW") != 0) {
5739 (*jobid)=0;
5740 return WERR_INVALID_DATATYPE;
5744 /* get the share number of the printer */
5745 if (!get_printer_snum(p, handle, &snum)) {
5746 return WERR_BADFID;
5749 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5751 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5753 /* An error occured in print_job_start() so return an appropriate
5754 NT error code. */
5756 if (Printer->jobid == -1) {
5757 return map_werror_from_unix(errno);
5760 Printer->document_started=True;
5761 (*jobid) = Printer->jobid;
5763 return WERR_OK;
5766 /********************************************************************
5767 * api_spoolss_getprinter
5768 * called from the spoolss dispatcher
5770 ********************************************************************/
5772 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5774 POLICY_HND *handle = &q_u->handle;
5776 return _spoolss_enddocprinter_internal(p, handle);
5779 /****************************************************************************
5780 ****************************************************************************/
5782 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5784 POLICY_HND *handle = &q_u->handle;
5785 uint32 buffer_size = q_u->buffer_size;
5786 uint8 *buffer = q_u->buffer;
5787 uint32 *buffer_written = &q_u->buffer_size2;
5788 int snum;
5789 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5791 if (!Printer) {
5792 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5793 r_u->buffer_written = q_u->buffer_size2;
5794 return WERR_BADFID;
5797 if (!get_printer_snum(p, handle, &snum))
5798 return WERR_BADFID;
5800 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5801 (SMB_OFF_T)-1, (size_t)buffer_size);
5802 if (*buffer_written == (uint32)-1) {
5803 r_u->buffer_written = 0;
5804 if (errno == ENOSPC)
5805 return WERR_NO_SPOOL_SPACE;
5806 else
5807 return WERR_ACCESS_DENIED;
5810 r_u->buffer_written = q_u->buffer_size2;
5812 return WERR_OK;
5815 /********************************************************************
5816 * api_spoolss_getprinter
5817 * called from the spoolss dispatcher
5819 ********************************************************************/
5821 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5822 pipes_struct *p)
5824 struct current_user user;
5825 int snum;
5826 WERROR errcode = WERR_BADFUNC;
5827 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5829 get_current_user(&user, p);
5831 if (!Printer) {
5832 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5833 return WERR_BADFID;
5836 if (!get_printer_snum(p, handle, &snum))
5837 return WERR_BADFID;
5839 switch (command) {
5840 case PRINTER_CONTROL_PAUSE:
5841 if (print_queue_pause(&user, snum, &errcode)) {
5842 errcode = WERR_OK;
5844 break;
5845 case PRINTER_CONTROL_RESUME:
5846 case PRINTER_CONTROL_UNPAUSE:
5847 if (print_queue_resume(&user, snum, &errcode)) {
5848 errcode = WERR_OK;
5850 break;
5851 case PRINTER_CONTROL_PURGE:
5852 if (print_queue_purge(&user, snum, &errcode)) {
5853 errcode = WERR_OK;
5855 break;
5856 default:
5857 return WERR_UNKNOWN_LEVEL;
5860 return errcode;
5863 /********************************************************************
5864 * api_spoolss_abortprinter
5865 * From MSDN: "Deletes printer's spool file if printer is configured
5866 * for spooling"
5867 ********************************************************************/
5869 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5871 POLICY_HND *handle = &q_u->handle;
5872 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5873 int snum;
5874 struct current_user user;
5875 WERROR errcode = WERR_OK;
5877 if (!Printer) {
5878 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5879 return WERR_BADFID;
5882 if (!get_printer_snum(p, handle, &snum))
5883 return WERR_BADFID;
5885 get_current_user( &user, p );
5887 print_job_delete( &user, snum, Printer->jobid, &errcode );
5889 return errcode;
5892 /********************************************************************
5893 * called by spoolss_api_setprinter
5894 * when updating a printer description
5895 ********************************************************************/
5897 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5898 const SPOOL_PRINTER_INFO_LEVEL *info,
5899 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5901 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5902 WERROR result;
5903 int snum;
5905 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5907 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5908 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5909 OUR_HANDLE(handle)));
5911 result = WERR_BADFID;
5912 goto done;
5915 if (!secdesc_ctr) {
5916 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5917 result = WERR_INVALID_PARAM;
5918 goto done;
5921 /* Check the user has permissions to change the security
5922 descriptor. By experimentation with two NT machines, the user
5923 requires Full Access to the printer to change security
5924 information. */
5926 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5927 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5928 result = WERR_ACCESS_DENIED;
5929 goto done;
5932 /* NT seems to like setting the security descriptor even though
5933 nothing may have actually changed. */
5935 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5937 if (DEBUGLEVEL >= 10) {
5938 SEC_ACL *the_acl;
5939 int i;
5941 the_acl = old_secdesc_ctr->sec->dacl;
5942 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5943 PRINTERNAME(snum), the_acl->num_aces));
5945 for (i = 0; i < the_acl->num_aces; i++) {
5946 fstring sid_str;
5948 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5950 DEBUG(10, ("%s 0x%08x\n", sid_str,
5951 the_acl->aces[i].access_mask));
5954 the_acl = secdesc_ctr->sec->dacl;
5956 if (the_acl) {
5957 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5958 PRINTERNAME(snum), the_acl->num_aces));
5960 for (i = 0; i < the_acl->num_aces; i++) {
5961 fstring sid_str;
5963 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5965 DEBUG(10, ("%s 0x%08x\n", sid_str,
5966 the_acl->aces[i].access_mask));
5968 } else {
5969 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5973 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5974 if (!new_secdesc_ctr) {
5975 result = WERR_NOMEM;
5976 goto done;
5979 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5980 result = WERR_OK;
5981 goto done;
5984 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5986 done:
5988 return result;
5991 /********************************************************************
5992 Canonicalize printer info from a client
5994 ATTN: It does not matter what we set the servername to hear
5995 since we do the necessary work in get_a_printer() to set it to
5996 the correct value based on what the client sent in the
5997 _spoolss_open_printer_ex().
5998 ********************************************************************/
6000 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6002 fstring printername;
6003 const char *p;
6005 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6006 "portname=%s drivername=%s comment=%s location=%s\n",
6007 info->servername, info->printername, info->sharename,
6008 info->portname, info->drivername, info->comment, info->location));
6010 /* we force some elements to "correct" values */
6011 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6012 fstrcpy(info->sharename, lp_servicename(snum));
6014 /* check to see if we allow printername != sharename */
6016 if ( lp_force_printername(snum) ) {
6017 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6018 global_myname(), info->sharename );
6019 } else {
6021 /* make sure printername is in \\server\printername format */
6023 fstrcpy( printername, info->printername );
6024 p = printername;
6025 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6026 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6027 p++;
6030 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6031 global_myname(), p );
6034 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6035 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6039 return True;
6042 /****************************************************************************
6043 ****************************************************************************/
6045 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6047 char *cmd = lp_addport_cmd();
6048 pstring command;
6049 int ret;
6050 int fd;
6051 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6052 BOOL is_print_op = False;
6054 if ( !*cmd ) {
6055 return WERR_ACCESS_DENIED;
6058 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6060 if ( token )
6061 is_print_op = user_has_privileges( token, &se_printop );
6063 DEBUG(10,("Running [%s]\n", command));
6065 /********* BEGIN SePrintOperatorPrivilege **********/
6067 if ( is_print_op )
6068 become_root();
6070 ret = smbrun(command, &fd);
6072 if ( is_print_op )
6073 unbecome_root();
6075 /********* END SePrintOperatorPrivilege **********/
6077 DEBUGADD(10,("returned [%d]\n", ret));
6079 if ( ret != 0 ) {
6080 if (fd != -1)
6081 close(fd);
6082 return WERR_ACCESS_DENIED;
6085 return WERR_OK;
6088 /****************************************************************************
6089 ****************************************************************************/
6091 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6093 char *cmd = lp_addprinter_cmd();
6094 char **qlines;
6095 pstring command;
6096 int numlines;
6097 int ret;
6098 int fd;
6099 fstring remote_machine = "%m";
6100 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6101 BOOL is_print_op = False;
6103 standard_sub_basic(current_user_info.smb_name,
6104 current_user_info.domain,
6105 remote_machine,sizeof(remote_machine));
6107 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6108 cmd, printer->info_2->printername, printer->info_2->sharename,
6109 printer->info_2->portname, printer->info_2->drivername,
6110 printer->info_2->location, printer->info_2->comment, remote_machine);
6112 if ( token )
6113 is_print_op = user_has_privileges( token, &se_printop );
6115 DEBUG(10,("Running [%s]\n", command));
6117 /********* BEGIN SePrintOperatorPrivilege **********/
6119 if ( is_print_op )
6120 become_root();
6122 if ( (ret = smbrun(command, &fd)) == 0 ) {
6123 /* Tell everyone we updated smb.conf. */
6124 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6127 if ( is_print_op )
6128 unbecome_root();
6130 /********* END SePrintOperatorPrivilege **********/
6132 DEBUGADD(10,("returned [%d]\n", ret));
6134 if ( ret != 0 ) {
6135 if (fd != -1)
6136 close(fd);
6137 return False;
6140 /* reload our services immediately */
6141 reload_services( False );
6143 numlines = 0;
6144 /* Get lines and convert them back to dos-codepage */
6145 qlines = fd_lines_load(fd, &numlines, 0);
6146 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6147 close(fd);
6149 /* Set the portname to what the script says the portname should be. */
6150 /* but don't require anything to be return from the script exit a good error code */
6152 if (numlines) {
6153 /* Set the portname to what the script says the portname should be. */
6154 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6155 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6158 file_lines_free(qlines);
6159 return True;
6163 /********************************************************************
6164 * Called by spoolss_api_setprinter
6165 * when updating a printer description.
6166 ********************************************************************/
6168 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6169 const SPOOL_PRINTER_INFO_LEVEL *info,
6170 DEVICEMODE *devmode)
6172 int snum;
6173 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6174 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6175 WERROR result;
6176 UNISTR2 buffer;
6177 fstring asc_buffer;
6179 DEBUG(8,("update_printer\n"));
6181 result = WERR_OK;
6183 if (!Printer) {
6184 result = WERR_BADFID;
6185 goto done;
6188 if (!get_printer_snum(p, handle, &snum)) {
6189 result = WERR_BADFID;
6190 goto done;
6193 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6194 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6195 result = WERR_BADFID;
6196 goto done;
6199 DEBUGADD(8,("Converting info_2 struct\n"));
6202 * convert_printer_info converts the incoming
6203 * info from the client and overwrites the info
6204 * just read from the tdb in the pointer 'printer'.
6207 if (!convert_printer_info(info, printer, level)) {
6208 result = WERR_NOMEM;
6209 goto done;
6212 if (devmode) {
6213 /* we have a valid devmode
6214 convert it and link it*/
6216 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6217 if (!convert_devicemode(printer->info_2->printername, devmode,
6218 &printer->info_2->devmode)) {
6219 result = WERR_NOMEM;
6220 goto done;
6224 /* Do sanity check on the requested changes for Samba */
6226 if (!check_printer_ok(printer->info_2, snum)) {
6227 result = WERR_INVALID_PARAM;
6228 goto done;
6231 /* FIXME!!! If the driver has changed we really should verify that
6232 it is installed before doing much else --jerry */
6234 /* Check calling user has permission to update printer description */
6236 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6237 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6238 result = WERR_ACCESS_DENIED;
6239 goto done;
6242 /* Call addprinter hook */
6243 /* Check changes to see if this is really needed */
6245 if ( *lp_addprinter_cmd()
6246 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6247 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6248 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6249 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6251 /* add_printer_hook() will call reload_services() */
6253 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6254 result = WERR_ACCESS_DENIED;
6255 goto done;
6260 * When a *new* driver is bound to a printer, the drivername is used to
6261 * lookup previously saved driver initialization info, which is then
6262 * bound to the printer, simulating what happens in the Windows arch.
6264 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6266 if (!set_driver_init(printer, 2))
6268 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6269 printer->info_2->drivername));
6272 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6273 printer->info_2->drivername));
6275 notify_printer_driver(snum, printer->info_2->drivername);
6279 * flag which changes actually occured. This is a small subset of
6280 * all the possible changes. We also have to update things in the
6281 * DsSpooler key.
6284 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6285 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6286 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6287 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6289 notify_printer_comment(snum, printer->info_2->comment);
6292 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6293 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6294 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6295 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6297 notify_printer_sharename(snum, printer->info_2->sharename);
6300 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6301 char *pname;
6303 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6304 pname++;
6305 else
6306 pname = printer->info_2->printername;
6309 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6310 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6311 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6313 notify_printer_printername( snum, pname );
6316 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6317 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6318 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6319 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6321 notify_printer_port(snum, printer->info_2->portname);
6324 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6325 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6326 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6327 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6329 notify_printer_location(snum, printer->info_2->location);
6332 /* here we need to update some more DsSpooler keys */
6333 /* uNCName, serverName, shortServerName */
6335 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6336 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6337 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6338 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6339 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6341 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6342 global_myname(), printer->info_2->sharename );
6343 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6344 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6345 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6347 /* Update printer info */
6348 result = mod_a_printer(printer, 2);
6350 done:
6351 free_a_printer(&printer, 2);
6352 free_a_printer(&old_printer, 2);
6355 return result;
6358 /****************************************************************************
6359 ****************************************************************************/
6360 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6361 const SPOOL_PRINTER_INFO_LEVEL *info)
6363 #ifdef HAVE_ADS
6364 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6365 int snum;
6366 Printer_entry *Printer;
6368 if ( lp_security() != SEC_ADS ) {
6369 return WERR_UNKNOWN_LEVEL;
6372 Printer = find_printer_index_by_hnd(p, handle);
6374 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6376 if (!Printer)
6377 return WERR_BADFID;
6379 if (!get_printer_snum(p, handle, &snum))
6380 return WERR_BADFID;
6382 nt_printer_publish(Printer, snum, info7->action);
6384 return WERR_OK;
6385 #else
6386 return WERR_UNKNOWN_LEVEL;
6387 #endif
6389 /****************************************************************************
6390 ****************************************************************************/
6392 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6394 POLICY_HND *handle = &q_u->handle;
6395 uint32 level = q_u->level;
6396 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6397 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6398 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6399 uint32 command = q_u->command;
6400 WERROR result;
6402 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6404 if (!Printer) {
6405 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6406 return WERR_BADFID;
6409 /* check the level */
6410 switch (level) {
6411 case 0:
6412 return control_printer(handle, command, p);
6413 case 2:
6414 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6415 if (!W_ERROR_IS_OK(result))
6416 return result;
6417 if (secdesc_ctr)
6418 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6419 return result;
6420 case 3:
6421 return update_printer_sec(handle, level, info, p,
6422 secdesc_ctr);
6423 case 7:
6424 return publish_or_unpublish_printer(p, handle, info);
6425 default:
6426 return WERR_UNKNOWN_LEVEL;
6430 /****************************************************************************
6431 ****************************************************************************/
6433 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6435 POLICY_HND *handle = &q_u->handle;
6436 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6438 if (!Printer) {
6439 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6440 return WERR_BADFID;
6443 if (Printer->notify.client_connected==True) {
6444 int snum = -1;
6446 if ( Printer->printer_type == SPLHND_SERVER)
6447 snum = -1;
6448 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6449 !get_printer_snum(p, handle, &snum) )
6450 return WERR_BADFID;
6452 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6455 Printer->notify.flags=0;
6456 Printer->notify.options=0;
6457 Printer->notify.localmachine[0]='\0';
6458 Printer->notify.printerlocal=0;
6459 if (Printer->notify.option)
6460 free_spool_notify_option(&Printer->notify.option);
6461 Printer->notify.client_connected=False;
6463 return WERR_OK;
6466 /****************************************************************************
6467 ****************************************************************************/
6469 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6471 /* that's an [in out] buffer */
6473 if (!q_u->buffer && (q_u->offered!=0)) {
6474 return WERR_INVALID_PARAM;
6477 rpcbuf_move(q_u->buffer, &r_u->buffer);
6479 r_u->needed = 0;
6480 return WERR_INVALID_PARAM; /* this is what a NT server
6481 returns for AddJob. AddJob
6482 must fail on non-local
6483 printers */
6486 /****************************************************************************
6487 ****************************************************************************/
6489 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6490 int position, int snum,
6491 const NT_PRINTER_INFO_LEVEL *ntprinter)
6493 struct tm *t;
6495 t=gmtime(&queue->time);
6497 job_info->jobid=queue->job;
6498 init_unistr(&job_info->printername, lp_servicename(snum));
6499 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6500 init_unistr(&job_info->username, queue->fs_user);
6501 init_unistr(&job_info->document, queue->fs_file);
6502 init_unistr(&job_info->datatype, "RAW");
6503 init_unistr(&job_info->text_status, "");
6504 job_info->status=nt_printj_status(queue->status);
6505 job_info->priority=queue->priority;
6506 job_info->position=position;
6507 job_info->totalpages=queue->page_count;
6508 job_info->pagesprinted=0;
6510 make_systemtime(&job_info->submitted, t);
6513 /****************************************************************************
6514 ****************************************************************************/
6516 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6517 int position, int snum,
6518 const NT_PRINTER_INFO_LEVEL *ntprinter,
6519 DEVICEMODE *devmode)
6521 struct tm *t;
6523 t=gmtime(&queue->time);
6525 job_info->jobid=queue->job;
6527 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6529 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6530 init_unistr(&job_info->username, queue->fs_user);
6531 init_unistr(&job_info->document, queue->fs_file);
6532 init_unistr(&job_info->notifyname, queue->fs_user);
6533 init_unistr(&job_info->datatype, "RAW");
6534 init_unistr(&job_info->printprocessor, "winprint");
6535 init_unistr(&job_info->parameters, "");
6536 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6537 init_unistr(&job_info->text_status, "");
6539 /* and here the security descriptor */
6541 job_info->status=nt_printj_status(queue->status);
6542 job_info->priority=queue->priority;
6543 job_info->position=position;
6544 job_info->starttime=0;
6545 job_info->untiltime=0;
6546 job_info->totalpages=queue->page_count;
6547 job_info->size=queue->size;
6548 make_systemtime(&(job_info->submitted), t);
6549 job_info->timeelapsed=0;
6550 job_info->pagesprinted=0;
6552 job_info->devmode = devmode;
6554 return (True);
6557 /****************************************************************************
6558 Enumjobs at level 1.
6559 ****************************************************************************/
6561 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6562 const NT_PRINTER_INFO_LEVEL *ntprinter,
6563 RPC_BUFFER *buffer, uint32 offered,
6564 uint32 *needed, uint32 *returned)
6566 JOB_INFO_1 *info;
6567 int i;
6568 WERROR result = WERR_OK;
6570 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6571 if (info==NULL) {
6572 *returned=0;
6573 return WERR_NOMEM;
6576 for (i=0; i<*returned; i++)
6577 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6579 /* check the required size. */
6580 for (i=0; i<*returned; i++)
6581 (*needed) += spoolss_size_job_info_1(&info[i]);
6583 if (*needed > offered) {
6584 result = WERR_INSUFFICIENT_BUFFER;
6585 goto out;
6588 if (!rpcbuf_alloc_size(buffer, *needed)) {
6589 result = WERR_NOMEM;
6590 goto out;
6593 /* fill the buffer with the structures */
6594 for (i=0; i<*returned; i++)
6595 smb_io_job_info_1("", buffer, &info[i], 0);
6597 out:
6598 /* clear memory */
6599 SAFE_FREE(info);
6601 if ( !W_ERROR_IS_OK(result) )
6602 *returned = 0;
6604 return result;
6607 /****************************************************************************
6608 Enumjobs at level 2.
6609 ****************************************************************************/
6611 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6612 const NT_PRINTER_INFO_LEVEL *ntprinter,
6613 RPC_BUFFER *buffer, uint32 offered,
6614 uint32 *needed, uint32 *returned)
6616 JOB_INFO_2 *info = NULL;
6617 int i;
6618 WERROR result = WERR_OK;
6619 DEVICEMODE *devmode = NULL;
6621 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6622 *returned=0;
6623 return WERR_NOMEM;
6626 /* this should not be a failure condition if the devmode is NULL */
6628 devmode = construct_dev_mode(lp_const_servicename(snum));
6630 for (i=0; i<*returned; i++)
6631 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6633 /* check the required size. */
6634 for (i=0; i<*returned; i++)
6635 (*needed) += spoolss_size_job_info_2(&info[i]);
6637 if (*needed > offered) {
6638 result = WERR_INSUFFICIENT_BUFFER;
6639 goto out;
6642 if (!rpcbuf_alloc_size(buffer, *needed)) {
6643 result = WERR_NOMEM;
6644 goto out;
6647 /* fill the buffer with the structures */
6648 for (i=0; i<*returned; i++)
6649 smb_io_job_info_2("", buffer, &info[i], 0);
6651 out:
6652 free_devmode(devmode);
6653 SAFE_FREE(info);
6655 if ( !W_ERROR_IS_OK(result) )
6656 *returned = 0;
6658 return result;
6662 /****************************************************************************
6663 Enumjobs.
6664 ****************************************************************************/
6666 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6668 POLICY_HND *handle = &q_u->handle;
6669 uint32 level = q_u->level;
6670 RPC_BUFFER *buffer = NULL;
6671 uint32 offered = q_u->offered;
6672 uint32 *needed = &r_u->needed;
6673 uint32 *returned = &r_u->returned;
6674 WERROR wret;
6675 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6676 int snum;
6677 print_status_struct prt_status;
6678 print_queue_struct *queue=NULL;
6680 /* that's an [in out] buffer */
6682 if (!q_u->buffer && (offered!=0)) {
6683 return WERR_INVALID_PARAM;
6686 rpcbuf_move(q_u->buffer, &r_u->buffer);
6687 buffer = r_u->buffer;
6689 DEBUG(4,("_spoolss_enumjobs\n"));
6691 *needed=0;
6692 *returned=0;
6694 /* lookup the printer snum and tdb entry */
6696 if (!get_printer_snum(p, handle, &snum))
6697 return WERR_BADFID;
6699 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6700 if ( !W_ERROR_IS_OK(wret) )
6701 return wret;
6703 *returned = print_queue_status(snum, &queue, &prt_status);
6704 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6706 if (*returned == 0) {
6707 SAFE_FREE(queue);
6708 free_a_printer(&ntprinter, 2);
6709 return WERR_OK;
6712 switch (level) {
6713 case 1:
6714 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6715 break;
6716 case 2:
6717 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6718 break;
6719 default:
6720 *returned=0;
6721 wret = WERR_UNKNOWN_LEVEL;
6722 break;
6725 SAFE_FREE(queue);
6726 free_a_printer( &ntprinter, 2 );
6727 return wret;
6730 /****************************************************************************
6731 ****************************************************************************/
6733 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6735 return WERR_OK;
6738 /****************************************************************************
6739 ****************************************************************************/
6741 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6743 POLICY_HND *handle = &q_u->handle;
6744 uint32 jobid = q_u->jobid;
6745 uint32 command = q_u->command;
6747 struct current_user user;
6748 int snum;
6749 WERROR errcode = WERR_BADFUNC;
6751 if (!get_printer_snum(p, handle, &snum)) {
6752 return WERR_BADFID;
6755 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6756 return WERR_INVALID_PRINTER_NAME;
6759 get_current_user(&user, p);
6761 switch (command) {
6762 case JOB_CONTROL_CANCEL:
6763 case JOB_CONTROL_DELETE:
6764 if (print_job_delete(&user, snum, jobid, &errcode)) {
6765 errcode = WERR_OK;
6767 break;
6768 case JOB_CONTROL_PAUSE:
6769 if (print_job_pause(&user, snum, jobid, &errcode)) {
6770 errcode = WERR_OK;
6772 break;
6773 case JOB_CONTROL_RESTART:
6774 case JOB_CONTROL_RESUME:
6775 if (print_job_resume(&user, snum, jobid, &errcode)) {
6776 errcode = WERR_OK;
6778 break;
6779 default:
6780 return WERR_UNKNOWN_LEVEL;
6783 return errcode;
6786 /****************************************************************************
6787 Enumerates all printer drivers at level 1.
6788 ****************************************************************************/
6790 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6792 int i;
6793 int ndrivers;
6794 uint32 version;
6795 fstring *list = NULL;
6796 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6797 DRIVER_INFO_1 *driver_info_1=NULL;
6798 WERROR result = WERR_OK;
6800 *returned=0;
6802 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6803 list=NULL;
6804 ndrivers=get_ntdrivers(&list, architecture, version);
6805 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6807 if(ndrivers == -1) {
6808 SAFE_FREE(driver_info_1);
6809 return WERR_NOMEM;
6812 if(ndrivers != 0) {
6813 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6814 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6815 SAFE_FREE(list);
6816 return WERR_NOMEM;
6820 for (i=0; i<ndrivers; i++) {
6821 WERROR status;
6822 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6823 ZERO_STRUCT(driver);
6824 status = get_a_printer_driver(&driver, 3, list[i],
6825 architecture, version);
6826 if (!W_ERROR_IS_OK(status)) {
6827 SAFE_FREE(list);
6828 SAFE_FREE(driver_info_1);
6829 return status;
6831 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6832 free_a_printer_driver(driver, 3);
6835 *returned+=ndrivers;
6836 SAFE_FREE(list);
6839 /* check the required size. */
6840 for (i=0; i<*returned; i++) {
6841 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6842 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6845 if (*needed > offered) {
6846 result = WERR_INSUFFICIENT_BUFFER;
6847 goto out;
6850 if (!rpcbuf_alloc_size(buffer, *needed)) {
6851 result = WERR_NOMEM;
6852 goto out;
6855 /* fill the buffer with the driver structures */
6856 for (i=0; i<*returned; i++) {
6857 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6858 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6861 out:
6862 SAFE_FREE(driver_info_1);
6864 if ( !W_ERROR_IS_OK(result) )
6865 *returned = 0;
6867 return result;
6870 /****************************************************************************
6871 Enumerates all printer drivers at level 2.
6872 ****************************************************************************/
6874 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6876 int i;
6877 int ndrivers;
6878 uint32 version;
6879 fstring *list = NULL;
6880 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6881 DRIVER_INFO_2 *driver_info_2=NULL;
6882 WERROR result = WERR_OK;
6884 *returned=0;
6886 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6887 list=NULL;
6888 ndrivers=get_ntdrivers(&list, architecture, version);
6889 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6891 if(ndrivers == -1) {
6892 SAFE_FREE(driver_info_2);
6893 return WERR_NOMEM;
6896 if(ndrivers != 0) {
6897 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6898 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6899 SAFE_FREE(list);
6900 return WERR_NOMEM;
6904 for (i=0; i<ndrivers; i++) {
6905 WERROR status;
6907 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6908 ZERO_STRUCT(driver);
6909 status = get_a_printer_driver(&driver, 3, list[i],
6910 architecture, version);
6911 if (!W_ERROR_IS_OK(status)) {
6912 SAFE_FREE(list);
6913 SAFE_FREE(driver_info_2);
6914 return status;
6916 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6917 free_a_printer_driver(driver, 3);
6920 *returned+=ndrivers;
6921 SAFE_FREE(list);
6924 /* check the required size. */
6925 for (i=0; i<*returned; i++) {
6926 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6927 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6930 if (*needed > offered) {
6931 result = WERR_INSUFFICIENT_BUFFER;
6932 goto out;
6935 if (!rpcbuf_alloc_size(buffer, *needed)) {
6936 result = WERR_NOMEM;
6937 goto out;
6940 /* fill the buffer with the form structures */
6941 for (i=0; i<*returned; i++) {
6942 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6943 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6946 out:
6947 SAFE_FREE(driver_info_2);
6949 if ( !W_ERROR_IS_OK(result) )
6950 *returned = 0;
6952 return result;
6955 /****************************************************************************
6956 Enumerates all printer drivers at level 3.
6957 ****************************************************************************/
6959 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6961 int i;
6962 int ndrivers;
6963 uint32 version;
6964 fstring *list = NULL;
6965 DRIVER_INFO_3 *driver_info_3=NULL;
6966 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6967 WERROR result = WERR_OK;
6969 *returned=0;
6971 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6972 list=NULL;
6973 ndrivers=get_ntdrivers(&list, architecture, version);
6974 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6976 if(ndrivers == -1) {
6977 SAFE_FREE(driver_info_3);
6978 return WERR_NOMEM;
6981 if(ndrivers != 0) {
6982 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6983 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6984 SAFE_FREE(list);
6985 return WERR_NOMEM;
6989 for (i=0; i<ndrivers; i++) {
6990 WERROR status;
6992 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6993 ZERO_STRUCT(driver);
6994 status = get_a_printer_driver(&driver, 3, list[i],
6995 architecture, version);
6996 if (!W_ERROR_IS_OK(status)) {
6997 SAFE_FREE(list);
6998 SAFE_FREE(driver_info_3);
6999 return status;
7001 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7002 free_a_printer_driver(driver, 3);
7005 *returned+=ndrivers;
7006 SAFE_FREE(list);
7009 /* check the required size. */
7010 for (i=0; i<*returned; i++) {
7011 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7012 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7015 if (*needed > offered) {
7016 result = WERR_INSUFFICIENT_BUFFER;
7017 goto out;
7020 if (!rpcbuf_alloc_size(buffer, *needed)) {
7021 result = WERR_NOMEM;
7022 goto out;
7025 /* fill the buffer with the driver structures */
7026 for (i=0; i<*returned; i++) {
7027 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7028 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7031 out:
7032 for (i=0; i<*returned; i++) {
7033 SAFE_FREE(driver_info_3[i].dependentfiles);
7036 SAFE_FREE(driver_info_3);
7038 if ( !W_ERROR_IS_OK(result) )
7039 *returned = 0;
7041 return result;
7044 /****************************************************************************
7045 Enumerates all printer drivers.
7046 ****************************************************************************/
7048 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7050 uint32 level = q_u->level;
7051 RPC_BUFFER *buffer = NULL;
7052 uint32 offered = q_u->offered;
7053 uint32 *needed = &r_u->needed;
7054 uint32 *returned = &r_u->returned;
7056 fstring servername;
7057 fstring architecture;
7059 /* that's an [in out] buffer */
7061 if (!q_u->buffer && (offered!=0)) {
7062 return WERR_INVALID_PARAM;
7065 rpcbuf_move(q_u->buffer, &r_u->buffer);
7066 buffer = r_u->buffer;
7068 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7070 *needed = 0;
7071 *returned = 0;
7073 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7074 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7076 if ( !is_myname_or_ipaddr( servername ) )
7077 return WERR_UNKNOWN_PRINTER_DRIVER;
7079 switch (level) {
7080 case 1:
7081 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7082 case 2:
7083 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7084 case 3:
7085 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7086 default:
7087 return WERR_UNKNOWN_LEVEL;
7091 /****************************************************************************
7092 ****************************************************************************/
7094 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7096 form->flag=list->flag;
7097 init_unistr(&form->name, list->name);
7098 form->width=list->width;
7099 form->length=list->length;
7100 form->left=list->left;
7101 form->top=list->top;
7102 form->right=list->right;
7103 form->bottom=list->bottom;
7106 /****************************************************************************
7107 ****************************************************************************/
7109 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7111 uint32 level = q_u->level;
7112 RPC_BUFFER *buffer = NULL;
7113 uint32 offered = q_u->offered;
7114 uint32 *needed = &r_u->needed;
7115 uint32 *numofforms = &r_u->numofforms;
7116 uint32 numbuiltinforms;
7118 nt_forms_struct *list=NULL;
7119 nt_forms_struct *builtinlist=NULL;
7120 FORM_1 *forms_1;
7121 int buffer_size=0;
7122 int i;
7124 /* that's an [in out] buffer */
7126 if (!q_u->buffer && (offered!=0) ) {
7127 return WERR_INVALID_PARAM;
7130 rpcbuf_move(q_u->buffer, &r_u->buffer);
7131 buffer = r_u->buffer;
7133 DEBUG(4,("_spoolss_enumforms\n"));
7134 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7135 DEBUGADD(5,("Info level [%d]\n", level));
7137 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7138 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7139 *numofforms = get_ntforms(&list);
7140 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7141 *numofforms += numbuiltinforms;
7143 if (*numofforms == 0) {
7144 SAFE_FREE(builtinlist);
7145 SAFE_FREE(list);
7146 return WERR_NO_MORE_ITEMS;
7149 switch (level) {
7150 case 1:
7151 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7152 SAFE_FREE(builtinlist);
7153 SAFE_FREE(list);
7154 *numofforms=0;
7155 return WERR_NOMEM;
7158 /* construct the list of form structures */
7159 for (i=0; i<numbuiltinforms; i++) {
7160 DEBUGADD(6,("Filling form number [%d]\n",i));
7161 fill_form_1(&forms_1[i], &builtinlist[i]);
7164 SAFE_FREE(builtinlist);
7166 for (; i<*numofforms; i++) {
7167 DEBUGADD(6,("Filling form number [%d]\n",i));
7168 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7171 SAFE_FREE(list);
7173 /* check the required size. */
7174 for (i=0; i<numbuiltinforms; i++) {
7175 DEBUGADD(6,("adding form [%d]'s size\n",i));
7176 buffer_size += spoolss_size_form_1(&forms_1[i]);
7178 for (; i<*numofforms; i++) {
7179 DEBUGADD(6,("adding form [%d]'s size\n",i));
7180 buffer_size += spoolss_size_form_1(&forms_1[i]);
7183 *needed=buffer_size;
7185 if (*needed > offered) {
7186 SAFE_FREE(forms_1);
7187 *numofforms=0;
7188 return WERR_INSUFFICIENT_BUFFER;
7191 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7192 SAFE_FREE(forms_1);
7193 *numofforms=0;
7194 return WERR_NOMEM;
7197 /* fill the buffer with the form structures */
7198 for (i=0; i<numbuiltinforms; i++) {
7199 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7200 smb_io_form_1("", buffer, &forms_1[i], 0);
7202 for (; i<*numofforms; i++) {
7203 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7204 smb_io_form_1("", buffer, &forms_1[i], 0);
7207 SAFE_FREE(forms_1);
7209 return WERR_OK;
7211 default:
7212 SAFE_FREE(list);
7213 SAFE_FREE(builtinlist);
7214 return WERR_UNKNOWN_LEVEL;
7218 /****************************************************************************
7219 ****************************************************************************/
7221 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7223 uint32 level = q_u->level;
7224 UNISTR2 *uni_formname = &q_u->formname;
7225 RPC_BUFFER *buffer = NULL;
7226 uint32 offered = q_u->offered;
7227 uint32 *needed = &r_u->needed;
7229 nt_forms_struct *list=NULL;
7230 nt_forms_struct builtin_form;
7231 BOOL foundBuiltin;
7232 FORM_1 form_1;
7233 fstring form_name;
7234 int buffer_size=0;
7235 int numofforms=0, i=0;
7237 /* that's an [in out] buffer */
7239 if (!q_u->buffer && (offered!=0)) {
7240 return WERR_INVALID_PARAM;
7243 rpcbuf_move(q_u->buffer, &r_u->buffer);
7244 buffer = r_u->buffer;
7246 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7248 DEBUG(4,("_spoolss_getform\n"));
7249 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7250 DEBUGADD(5,("Info level [%d]\n", level));
7252 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7253 if (!foundBuiltin) {
7254 numofforms = get_ntforms(&list);
7255 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7257 if (numofforms == 0)
7258 return WERR_BADFID;
7261 switch (level) {
7262 case 1:
7263 if (foundBuiltin) {
7264 fill_form_1(&form_1, &builtin_form);
7265 } else {
7267 /* Check if the requested name is in the list of form structures */
7268 for (i=0; i<numofforms; i++) {
7270 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7272 if (strequal(form_name, list[i].name)) {
7273 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7274 fill_form_1(&form_1, &list[i]);
7275 break;
7279 SAFE_FREE(list);
7280 if (i == numofforms) {
7281 return WERR_BADFID;
7284 /* check the required size. */
7286 *needed=spoolss_size_form_1(&form_1);
7288 if (*needed > offered)
7289 return WERR_INSUFFICIENT_BUFFER;
7291 if (!rpcbuf_alloc_size(buffer, buffer_size))
7292 return WERR_NOMEM;
7294 /* fill the buffer with the form structures */
7295 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7296 smb_io_form_1("", buffer, &form_1, 0);
7298 return WERR_OK;
7300 default:
7301 SAFE_FREE(list);
7302 return WERR_UNKNOWN_LEVEL;
7306 /****************************************************************************
7307 ****************************************************************************/
7309 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7311 init_unistr(&port->port_name, name);
7314 /****************************************************************************
7315 TODO: This probably needs distinguish between TCP/IP and Local ports
7316 somehow.
7317 ****************************************************************************/
7319 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7321 init_unistr(&port->port_name, name);
7322 init_unistr(&port->monitor_name, "Local Monitor");
7323 init_unistr(&port->description, SPL_LOCAL_PORT );
7324 port->port_type=PORT_TYPE_WRITE;
7325 port->reserved=0x0;
7329 /****************************************************************************
7330 wrapper around the enumer ports command
7331 ****************************************************************************/
7333 WERROR enumports_hook( int *count, char ***lines )
7335 char *cmd = lp_enumports_cmd();
7336 char **qlines;
7337 pstring command;
7338 int numlines;
7339 int ret;
7340 int fd;
7342 *count = 0;
7343 *lines = NULL;
7345 /* if no hook then just fill in the default port */
7347 if ( !*cmd ) {
7348 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7349 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7350 qlines[1] = NULL;
7351 numlines = 1;
7353 else {
7354 /* we have a valid enumport command */
7356 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7358 DEBUG(10,("Running [%s]\n", command));
7359 ret = smbrun(command, &fd);
7360 DEBUG(10,("Returned [%d]\n", ret));
7361 if (ret != 0) {
7362 if (fd != -1) {
7363 close(fd);
7365 return WERR_ACCESS_DENIED;
7368 numlines = 0;
7369 qlines = fd_lines_load(fd, &numlines, 0);
7370 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7371 close(fd);
7374 *count = numlines;
7375 *lines = qlines;
7377 return WERR_OK;
7380 /****************************************************************************
7381 enumports level 1.
7382 ****************************************************************************/
7384 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7386 PORT_INFO_1 *ports=NULL;
7387 int i=0;
7388 WERROR result = WERR_OK;
7389 char **qlines = NULL;
7390 int numlines = 0;
7392 result = enumports_hook( &numlines, &qlines );
7393 if (!W_ERROR_IS_OK(result)) {
7394 file_lines_free(qlines);
7395 return result;
7398 if(numlines) {
7399 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7400 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7401 dos_errstr(WERR_NOMEM)));
7402 file_lines_free(qlines);
7403 return WERR_NOMEM;
7406 for (i=0; i<numlines; i++) {
7407 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7408 fill_port_1(&ports[i], qlines[i]);
7411 file_lines_free(qlines);
7413 *returned = numlines;
7415 /* check the required size. */
7416 for (i=0; i<*returned; i++) {
7417 DEBUGADD(6,("adding port [%d]'s size\n", i));
7418 *needed += spoolss_size_port_info_1(&ports[i]);
7421 if (*needed > offered) {
7422 result = WERR_INSUFFICIENT_BUFFER;
7423 goto out;
7426 if (!rpcbuf_alloc_size(buffer, *needed)) {
7427 result = WERR_NOMEM;
7428 goto out;
7431 /* fill the buffer with the ports structures */
7432 for (i=0; i<*returned; i++) {
7433 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7434 smb_io_port_1("", buffer, &ports[i], 0);
7437 out:
7438 SAFE_FREE(ports);
7440 if ( !W_ERROR_IS_OK(result) )
7441 *returned = 0;
7443 return result;
7446 /****************************************************************************
7447 enumports level 2.
7448 ****************************************************************************/
7450 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7452 PORT_INFO_2 *ports=NULL;
7453 int i=0;
7454 WERROR result = WERR_OK;
7455 char **qlines = NULL;
7456 int numlines = 0;
7458 result = enumports_hook( &numlines, &qlines );
7459 if ( !W_ERROR_IS_OK(result)) {
7460 file_lines_free(qlines);
7461 return result;
7464 if(numlines) {
7465 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7466 file_lines_free(qlines);
7467 return WERR_NOMEM;
7470 for (i=0; i<numlines; i++) {
7471 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7472 fill_port_2(&(ports[i]), qlines[i]);
7476 file_lines_free(qlines);
7478 *returned = numlines;
7480 /* check the required size. */
7481 for (i=0; i<*returned; i++) {
7482 DEBUGADD(6,("adding port [%d]'s size\n", i));
7483 *needed += spoolss_size_port_info_2(&ports[i]);
7486 if (*needed > offered) {
7487 result = WERR_INSUFFICIENT_BUFFER;
7488 goto out;
7491 if (!rpcbuf_alloc_size(buffer, *needed)) {
7492 result = WERR_NOMEM;
7493 goto out;
7496 /* fill the buffer with the ports structures */
7497 for (i=0; i<*returned; i++) {
7498 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7499 smb_io_port_2("", buffer, &ports[i], 0);
7502 out:
7503 SAFE_FREE(ports);
7505 if ( !W_ERROR_IS_OK(result) )
7506 *returned = 0;
7508 return result;
7511 /****************************************************************************
7512 enumports.
7513 ****************************************************************************/
7515 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7517 uint32 level = q_u->level;
7518 RPC_BUFFER *buffer = NULL;
7519 uint32 offered = q_u->offered;
7520 uint32 *needed = &r_u->needed;
7521 uint32 *returned = &r_u->returned;
7523 /* that's an [in out] buffer */
7525 if (!q_u->buffer && (offered!=0)) {
7526 return WERR_INVALID_PARAM;
7529 rpcbuf_move(q_u->buffer, &r_u->buffer);
7530 buffer = r_u->buffer;
7532 DEBUG(4,("_spoolss_enumports\n"));
7534 *returned=0;
7535 *needed=0;
7537 switch (level) {
7538 case 1:
7539 return enumports_level_1(buffer, offered, needed, returned);
7540 case 2:
7541 return enumports_level_2(buffer, offered, needed, returned);
7542 default:
7543 return WERR_UNKNOWN_LEVEL;
7547 /****************************************************************************
7548 ****************************************************************************/
7550 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7551 const SPOOL_PRINTER_INFO_LEVEL *info,
7552 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7553 uint32 user_switch, const SPOOL_USER_CTR *user,
7554 POLICY_HND *handle)
7556 NT_PRINTER_INFO_LEVEL *printer = NULL;
7557 fstring name;
7558 int snum;
7559 WERROR err = WERR_OK;
7561 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7562 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7563 return WERR_NOMEM;
7566 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7567 if (!convert_printer_info(info, printer, 2)) {
7568 free_a_printer(&printer, 2);
7569 return WERR_NOMEM;
7572 /* check to see if the printer already exists */
7574 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7575 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7576 printer->info_2->sharename));
7577 free_a_printer(&printer, 2);
7578 return WERR_PRINTER_ALREADY_EXISTS;
7581 /* FIXME!!! smbd should check to see if the driver is installed before
7582 trying to add a printer like this --jerry */
7584 if (*lp_addprinter_cmd() ) {
7585 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7586 free_a_printer(&printer,2);
7587 return WERR_ACCESS_DENIED;
7589 } else {
7590 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7591 "smb.conf parameter \"addprinter command\" is defined. This"
7592 "parameter must exist for this call to succeed\n",
7593 printer->info_2->sharename ));
7596 /* use our primary netbios name since get_a_printer() will convert
7597 it to what the client expects on a case by case basis */
7599 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7600 printer->info_2->sharename);
7603 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7604 free_a_printer(&printer,2);
7605 return WERR_ACCESS_DENIED;
7608 /* you must be a printer admin to add a new printer */
7609 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7610 free_a_printer(&printer,2);
7611 return WERR_ACCESS_DENIED;
7615 * Do sanity check on the requested changes for Samba.
7618 if (!check_printer_ok(printer->info_2, snum)) {
7619 free_a_printer(&printer,2);
7620 return WERR_INVALID_PARAM;
7624 * When a printer is created, the drivername bound to the printer is used
7625 * to lookup previously saved driver initialization info, which is then
7626 * bound to the new printer, simulating what happens in the Windows arch.
7629 if (!devmode)
7631 set_driver_init(printer, 2);
7633 else
7635 /* A valid devmode was included, convert and link it
7637 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7639 if (!convert_devicemode(printer->info_2->printername, devmode,
7640 &printer->info_2->devmode))
7641 return WERR_NOMEM;
7644 /* write the ASCII on disk */
7645 err = mod_a_printer(printer, 2);
7646 if (!W_ERROR_IS_OK(err)) {
7647 free_a_printer(&printer,2);
7648 return err;
7651 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7652 /* Handle open failed - remove addition. */
7653 del_a_printer(printer->info_2->sharename);
7654 free_a_printer(&printer,2);
7655 return WERR_ACCESS_DENIED;
7658 update_c_setprinter(False);
7659 free_a_printer(&printer,2);
7661 return WERR_OK;
7664 /****************************************************************************
7665 ****************************************************************************/
7667 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7669 UNISTR2 *uni_srv_name = q_u->server_name;
7670 uint32 level = q_u->level;
7671 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7672 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7673 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7674 uint32 user_switch = q_u->user_switch;
7675 SPOOL_USER_CTR *user = &q_u->user_ctr;
7676 POLICY_HND *handle = &r_u->handle;
7678 switch (level) {
7679 case 1:
7680 /* we don't handle yet */
7681 /* but I know what to do ... */
7682 return WERR_UNKNOWN_LEVEL;
7683 case 2:
7684 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7685 devmode, sdb,
7686 user_switch, user, handle);
7687 default:
7688 return WERR_UNKNOWN_LEVEL;
7692 /****************************************************************************
7693 ****************************************************************************/
7695 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7697 uint32 level = q_u->level;
7698 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7699 WERROR err = WERR_OK;
7700 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7701 struct current_user user;
7702 fstring driver_name;
7703 uint32 version;
7705 ZERO_STRUCT(driver);
7707 get_current_user(&user, p);
7709 if (!convert_printer_driver_info(info, &driver, level)) {
7710 err = WERR_NOMEM;
7711 goto done;
7714 DEBUG(5,("Cleaning driver's information\n"));
7715 err = clean_up_driver_struct(driver, level, &user);
7716 if (!W_ERROR_IS_OK(err))
7717 goto done;
7719 DEBUG(5,("Moving driver to final destination\n"));
7720 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7721 goto done;
7724 if (add_a_printer_driver(driver, level)!=0) {
7725 err = WERR_ACCESS_DENIED;
7726 goto done;
7730 * I think this is where he DrvUpgradePrinter() hook would be
7731 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7732 * server. Right now, we just need to send ourselves a message
7733 * to update each printer bound to this driver. --jerry
7736 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7737 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7738 driver_name));
7742 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7743 * decide if the driver init data should be deleted. The rules are:
7744 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7745 * 2) delete init data only if there is no 2k/Xp driver
7746 * 3) always delete init data
7747 * The generalized rule is always use init data from the highest order driver.
7748 * It is necessary to follow the driver install by an initialization step to
7749 * finish off this process.
7751 if (level == 3)
7752 version = driver.info_3->cversion;
7753 else if (level == 6)
7754 version = driver.info_6->version;
7755 else
7756 version = -1;
7757 switch (version) {
7759 * 9x printer driver - never delete init data
7761 case 0:
7762 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7763 driver_name));
7764 break;
7767 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7768 * there is no 2k/Xp driver init data for this driver name.
7770 case 2:
7772 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7774 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7776 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7778 if (!del_driver_init(driver_name))
7779 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7780 } else {
7782 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7784 free_a_printer_driver(driver1,3);
7785 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7786 driver_name));
7789 break;
7792 * 2k or Xp printer driver - always delete init data
7794 case 3:
7795 if (!del_driver_init(driver_name))
7796 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7797 break;
7799 default:
7800 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7801 break;
7805 done:
7806 free_a_printer_driver(driver, level);
7807 return err;
7810 /********************************************************************
7811 * spoolss_addprinterdriverex
7812 ********************************************************************/
7814 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7816 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7817 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7820 * we only support the semantics of AddPrinterDriver()
7821 * i.e. only copy files that are newer than existing ones
7824 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7825 return WERR_ACCESS_DENIED;
7827 ZERO_STRUCT(q_u_local);
7828 ZERO_STRUCT(r_u_local);
7830 /* just pass the information off to _spoolss_addprinterdriver() */
7831 q_u_local.server_name_ptr = q_u->server_name_ptr;
7832 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7833 q_u_local.level = q_u->level;
7834 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7836 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7839 /****************************************************************************
7840 ****************************************************************************/
7842 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7844 init_unistr(&info->name, name);
7847 /****************************************************************************
7848 ****************************************************************************/
7850 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7852 pstring path;
7853 pstring long_archi;
7854 fstring servername;
7855 char *pservername;
7856 const char *short_archi;
7857 DRIVER_DIRECTORY_1 *info=NULL;
7858 WERROR result = WERR_OK;
7860 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7861 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7863 /* check for beginning double '\'s and that the server
7864 long enough */
7866 pservername = servername;
7867 if ( *pservername == '\\' && strlen(servername)>2 ) {
7868 pservername += 2;
7871 if ( !is_myname_or_ipaddr( pservername ) )
7872 return WERR_INVALID_PARAM;
7874 if (!(short_archi = get_short_archi(long_archi)))
7875 return WERR_INVALID_ENVIRONMENT;
7877 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7878 return WERR_NOMEM;
7880 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7882 DEBUG(4,("printer driver directory: [%s]\n", path));
7884 fill_driverdir_1(info, path);
7886 *needed += spoolss_size_driverdir_info_1(info);
7888 if (*needed > offered) {
7889 result = WERR_INSUFFICIENT_BUFFER;
7890 goto out;
7893 if (!rpcbuf_alloc_size(buffer, *needed)) {
7894 result = WERR_NOMEM;
7895 goto out;
7898 smb_io_driverdir_1("", buffer, info, 0);
7900 out:
7901 SAFE_FREE(info);
7903 return result;
7906 /****************************************************************************
7907 ****************************************************************************/
7909 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7911 UNISTR2 *name = &q_u->name;
7912 UNISTR2 *uni_environment = &q_u->environment;
7913 uint32 level = q_u->level;
7914 RPC_BUFFER *buffer = NULL;
7915 uint32 offered = q_u->offered;
7916 uint32 *needed = &r_u->needed;
7918 /* that's an [in out] buffer */
7920 if (!q_u->buffer && (offered!=0)) {
7921 return WERR_INVALID_PARAM;
7924 rpcbuf_move(q_u->buffer, &r_u->buffer);
7925 buffer = r_u->buffer;
7927 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7929 *needed=0;
7931 switch(level) {
7932 case 1:
7933 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7934 default:
7935 return WERR_UNKNOWN_LEVEL;
7939 /****************************************************************************
7940 ****************************************************************************/
7942 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7944 POLICY_HND *handle = &q_u->handle;
7945 uint32 idx = q_u->index;
7946 uint32 in_value_len = q_u->valuesize;
7947 uint32 in_data_len = q_u->datasize;
7948 uint32 *out_max_value_len = &r_u->valuesize;
7949 uint16 **out_value = &r_u->value;
7950 uint32 *out_value_len = &r_u->realvaluesize;
7951 uint32 *out_type = &r_u->type;
7952 uint32 *out_max_data_len = &r_u->datasize;
7953 uint8 **data_out = &r_u->data;
7954 uint32 *out_data_len = &r_u->realdatasize;
7956 NT_PRINTER_INFO_LEVEL *printer = NULL;
7958 uint32 biggest_valuesize;
7959 uint32 biggest_datasize;
7960 uint32 data_len;
7961 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7962 int snum;
7963 WERROR result;
7964 REGISTRY_VALUE *val = NULL;
7965 NT_PRINTER_DATA *p_data;
7966 int i, key_index, num_values;
7967 int name_length;
7969 *out_type = 0;
7971 *out_max_data_len = 0;
7972 *data_out = NULL;
7973 *out_data_len = 0;
7975 DEBUG(5,("spoolss_enumprinterdata\n"));
7977 if (!Printer) {
7978 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7979 return WERR_BADFID;
7982 if (!get_printer_snum(p,handle, &snum))
7983 return WERR_BADFID;
7985 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7986 if (!W_ERROR_IS_OK(result))
7987 return result;
7989 p_data = printer->info_2->data;
7990 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7992 result = WERR_OK;
7995 * The NT machine wants to know the biggest size of value and data
7997 * cf: MSDN EnumPrinterData remark section
8000 if ( !in_value_len && !in_data_len && (key_index != -1) )
8002 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8004 biggest_valuesize = 0;
8005 biggest_datasize = 0;
8007 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8009 for ( i=0; i<num_values; i++ )
8011 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8013 name_length = strlen(val->valuename);
8014 if ( strlen(val->valuename) > biggest_valuesize )
8015 biggest_valuesize = name_length;
8017 if ( val->size > biggest_datasize )
8018 biggest_datasize = val->size;
8020 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8021 biggest_datasize));
8024 /* the value is an UNICODE string but real_value_size is the length
8025 in bytes including the trailing 0 */
8027 *out_value_len = 2 * (1+biggest_valuesize);
8028 *out_data_len = biggest_datasize;
8030 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8032 goto done;
8036 * the value len is wrong in NT sp3
8037 * that's the number of bytes not the number of unicode chars
8040 if ( key_index != -1 )
8041 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8043 if ( !val )
8046 /* out_value should default to "" or else NT4 has
8047 problems unmarshalling the response */
8049 *out_max_value_len=(in_value_len/sizeof(uint16));
8051 if (in_value_len) {
8052 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8054 result = WERR_NOMEM;
8055 goto done;
8057 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8058 } else {
8059 *out_value=NULL;
8060 *out_value_len = 0;
8063 /* the data is counted in bytes */
8065 *out_max_data_len = in_data_len;
8066 *out_data_len = in_data_len;
8068 /* only allocate when given a non-zero data_len */
8070 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8072 result = WERR_NOMEM;
8073 goto done;
8076 result = WERR_NO_MORE_ITEMS;
8078 else
8081 * the value is:
8082 * - counted in bytes in the request
8083 * - counted in UNICODE chars in the max reply
8084 * - counted in bytes in the real size
8086 * take a pause *before* coding not *during* coding
8089 /* name */
8090 *out_max_value_len=(in_value_len/sizeof(uint16));
8091 if (in_value_len) {
8092 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8094 result = WERR_NOMEM;
8095 goto done;
8098 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8099 } else {
8100 *out_value = NULL;
8101 *out_value_len = 0;
8104 /* type */
8106 *out_type = regval_type( val );
8108 /* data - counted in bytes */
8110 *out_max_data_len = in_data_len;
8111 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8113 result = WERR_NOMEM;
8114 goto done;
8116 data_len = regval_size(val);
8117 if ( *data_out && data_len )
8118 memcpy( *data_out, regval_data_p(val), data_len );
8119 *out_data_len = data_len;
8122 done:
8123 free_a_printer(&printer, 2);
8124 return result;
8127 /****************************************************************************
8128 ****************************************************************************/
8130 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8132 POLICY_HND *handle = &q_u->handle;
8133 UNISTR2 *value = &q_u->value;
8134 uint32 type = q_u->type;
8135 uint8 *data = q_u->data;
8136 uint32 real_len = q_u->real_len;
8138 NT_PRINTER_INFO_LEVEL *printer = NULL;
8139 int snum=0;
8140 WERROR status = WERR_OK;
8141 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8142 fstring valuename;
8144 DEBUG(5,("spoolss_setprinterdata\n"));
8146 if (!Printer) {
8147 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8148 return WERR_BADFID;
8151 if ( Printer->printer_type == SPLHND_SERVER ) {
8152 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8153 return WERR_INVALID_PARAM;
8156 if (!get_printer_snum(p,handle, &snum))
8157 return WERR_BADFID;
8160 * Access check : NT returns "access denied" if you make a
8161 * SetPrinterData call without the necessary privildge.
8162 * we were originally returning OK if nothing changed
8163 * which made Win2k issue **a lot** of SetPrinterData
8164 * when connecting to a printer --jerry
8167 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8169 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8170 status = WERR_ACCESS_DENIED;
8171 goto done;
8174 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8175 if (!W_ERROR_IS_OK(status))
8176 return status;
8178 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8181 * When client side code sets a magic printer data key, detect it and save
8182 * the current printer data and the magic key's data (its the DEVMODE) for
8183 * future printer/driver initializations.
8185 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8187 /* Set devmode and printer initialization info */
8188 status = save_driver_init( printer, 2, data, real_len );
8190 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8192 else
8194 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8195 type, data, real_len );
8196 if ( W_ERROR_IS_OK(status) )
8197 status = mod_a_printer(printer, 2);
8200 done:
8201 free_a_printer(&printer, 2);
8203 return status;
8206 /****************************************************************************
8207 ****************************************************************************/
8209 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8211 POLICY_HND *handle = &q_u->handle;
8212 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8213 int snum;
8215 DEBUG(5,("_spoolss_resetprinter\n"));
8218 * All we do is to check to see if the handle and queue is valid.
8219 * This call really doesn't mean anything to us because we only
8220 * support RAW printing. --jerry
8223 if (!Printer) {
8224 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8225 return WERR_BADFID;
8228 if (!get_printer_snum(p,handle, &snum))
8229 return WERR_BADFID;
8232 /* blindly return success */
8233 return WERR_OK;
8237 /****************************************************************************
8238 ****************************************************************************/
8240 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8242 POLICY_HND *handle = &q_u->handle;
8243 UNISTR2 *value = &q_u->valuename;
8245 NT_PRINTER_INFO_LEVEL *printer = NULL;
8246 int snum=0;
8247 WERROR status = WERR_OK;
8248 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8249 pstring valuename;
8251 DEBUG(5,("spoolss_deleteprinterdata\n"));
8253 if (!Printer) {
8254 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8255 return WERR_BADFID;
8258 if (!get_printer_snum(p, handle, &snum))
8259 return WERR_BADFID;
8261 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8262 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8263 return WERR_ACCESS_DENIED;
8266 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8267 if (!W_ERROR_IS_OK(status))
8268 return status;
8270 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8272 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8274 if ( W_ERROR_IS_OK(status) )
8275 mod_a_printer( printer, 2 );
8277 free_a_printer(&printer, 2);
8279 return status;
8282 /****************************************************************************
8283 ****************************************************************************/
8285 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8287 POLICY_HND *handle = &q_u->handle;
8288 FORM *form = &q_u->form;
8289 nt_forms_struct tmpForm;
8290 int snum;
8291 WERROR status = WERR_OK;
8292 NT_PRINTER_INFO_LEVEL *printer = NULL;
8294 int count=0;
8295 nt_forms_struct *list=NULL;
8296 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8298 DEBUG(5,("spoolss_addform\n"));
8300 if (!Printer) {
8301 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8302 return WERR_BADFID;
8306 /* forms can be added on printer of on the print server handle */
8308 if ( Printer->printer_type == SPLHND_PRINTER )
8310 if (!get_printer_snum(p,handle, &snum))
8311 return WERR_BADFID;
8313 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8314 if (!W_ERROR_IS_OK(status))
8315 goto done;
8318 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8319 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8320 status = WERR_ACCESS_DENIED;
8321 goto done;
8324 /* can't add if builtin */
8326 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8327 status = WERR_ALREADY_EXISTS;
8328 goto done;
8331 count = get_ntforms(&list);
8333 if(!add_a_form(&list, form, &count)) {
8334 status = WERR_NOMEM;
8335 goto done;
8338 write_ntforms(&list, count);
8341 * ChangeID must always be set if this is a printer
8344 if ( Printer->printer_type == SPLHND_PRINTER )
8345 status = mod_a_printer(printer, 2);
8347 done:
8348 if ( printer )
8349 free_a_printer(&printer, 2);
8350 SAFE_FREE(list);
8352 return status;
8355 /****************************************************************************
8356 ****************************************************************************/
8358 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8360 POLICY_HND *handle = &q_u->handle;
8361 UNISTR2 *form_name = &q_u->name;
8362 nt_forms_struct tmpForm;
8363 int count=0;
8364 nt_forms_struct *list=NULL;
8365 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8366 int snum;
8367 WERROR status = WERR_OK;
8368 NT_PRINTER_INFO_LEVEL *printer = NULL;
8370 DEBUG(5,("spoolss_deleteform\n"));
8372 if (!Printer) {
8373 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8374 return WERR_BADFID;
8377 /* forms can be deleted on printer of on the print server handle */
8379 if ( Printer->printer_type == SPLHND_PRINTER )
8381 if (!get_printer_snum(p,handle, &snum))
8382 return WERR_BADFID;
8384 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8385 if (!W_ERROR_IS_OK(status))
8386 goto done;
8389 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8390 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8391 status = WERR_ACCESS_DENIED;
8392 goto done;
8395 /* can't delete if builtin */
8397 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8398 status = WERR_INVALID_PARAM;
8399 goto done;
8402 count = get_ntforms(&list);
8404 if ( !delete_a_form(&list, form_name, &count, &status ))
8405 goto done;
8408 * ChangeID must always be set if this is a printer
8411 if ( Printer->printer_type == SPLHND_PRINTER )
8412 status = mod_a_printer(printer, 2);
8414 done:
8415 if ( printer )
8416 free_a_printer(&printer, 2);
8417 SAFE_FREE(list);
8419 return status;
8422 /****************************************************************************
8423 ****************************************************************************/
8425 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8427 POLICY_HND *handle = &q_u->handle;
8428 FORM *form = &q_u->form;
8429 nt_forms_struct tmpForm;
8430 int snum;
8431 WERROR status = WERR_OK;
8432 NT_PRINTER_INFO_LEVEL *printer = NULL;
8434 int count=0;
8435 nt_forms_struct *list=NULL;
8436 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8438 DEBUG(5,("spoolss_setform\n"));
8440 if (!Printer) {
8441 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8442 return WERR_BADFID;
8445 /* forms can be modified on printer of on the print server handle */
8447 if ( Printer->printer_type == SPLHND_PRINTER )
8449 if (!get_printer_snum(p,handle, &snum))
8450 return WERR_BADFID;
8452 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8453 if (!W_ERROR_IS_OK(status))
8454 goto done;
8457 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8458 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8459 status = WERR_ACCESS_DENIED;
8460 goto done;
8463 /* can't set if builtin */
8464 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8465 status = WERR_INVALID_PARAM;
8466 goto done;
8469 count = get_ntforms(&list);
8470 update_a_form(&list, form, count);
8471 write_ntforms(&list, count);
8474 * ChangeID must always be set if this is a printer
8477 if ( Printer->printer_type == SPLHND_PRINTER )
8478 status = mod_a_printer(printer, 2);
8481 done:
8482 if ( printer )
8483 free_a_printer(&printer, 2);
8484 SAFE_FREE(list);
8486 return status;
8489 /****************************************************************************
8490 enumprintprocessors level 1.
8491 ****************************************************************************/
8493 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8495 PRINTPROCESSOR_1 *info_1=NULL;
8496 WERROR result = WERR_OK;
8498 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8499 return WERR_NOMEM;
8501 (*returned) = 0x1;
8503 init_unistr(&info_1->name, "winprint");
8505 *needed += spoolss_size_printprocessor_info_1(info_1);
8507 if (*needed > offered) {
8508 result = WERR_INSUFFICIENT_BUFFER;
8509 goto out;
8512 if (!rpcbuf_alloc_size(buffer, *needed)) {
8513 result = WERR_NOMEM;
8514 goto out;
8517 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8519 out:
8520 SAFE_FREE(info_1);
8522 if ( !W_ERROR_IS_OK(result) )
8523 *returned = 0;
8525 return result;
8528 /****************************************************************************
8529 ****************************************************************************/
8531 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8533 uint32 level = q_u->level;
8534 RPC_BUFFER *buffer = NULL;
8535 uint32 offered = q_u->offered;
8536 uint32 *needed = &r_u->needed;
8537 uint32 *returned = &r_u->returned;
8539 /* that's an [in out] buffer */
8541 if (!q_u->buffer && (offered!=0)) {
8542 return WERR_INVALID_PARAM;
8545 rpcbuf_move(q_u->buffer, &r_u->buffer);
8546 buffer = r_u->buffer;
8548 DEBUG(5,("spoolss_enumprintprocessors\n"));
8551 * Enumerate the print processors ...
8553 * Just reply with "winprint", to keep NT happy
8554 * and I can use my nice printer checker.
8557 *returned=0;
8558 *needed=0;
8560 switch (level) {
8561 case 1:
8562 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8563 default:
8564 return WERR_UNKNOWN_LEVEL;
8568 /****************************************************************************
8569 enumprintprocdatatypes level 1.
8570 ****************************************************************************/
8572 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8574 PRINTPROCDATATYPE_1 *info_1=NULL;
8575 WERROR result = WERR_OK;
8577 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8578 return WERR_NOMEM;
8580 (*returned) = 0x1;
8582 init_unistr(&info_1->name, "RAW");
8584 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8586 if (*needed > offered) {
8587 result = WERR_INSUFFICIENT_BUFFER;
8588 goto out;
8591 if (!rpcbuf_alloc_size(buffer, *needed)) {
8592 result = WERR_NOMEM;
8593 goto out;
8596 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8598 out:
8599 SAFE_FREE(info_1);
8601 if ( !W_ERROR_IS_OK(result) )
8602 *returned = 0;
8604 return result;
8607 /****************************************************************************
8608 ****************************************************************************/
8610 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8612 uint32 level = q_u->level;
8613 RPC_BUFFER *buffer = NULL;
8614 uint32 offered = q_u->offered;
8615 uint32 *needed = &r_u->needed;
8616 uint32 *returned = &r_u->returned;
8618 /* that's an [in out] buffer */
8620 if (!q_u->buffer && (offered!=0)) {
8621 return WERR_INVALID_PARAM;
8624 rpcbuf_move(q_u->buffer, &r_u->buffer);
8625 buffer = r_u->buffer;
8627 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8629 *returned=0;
8630 *needed=0;
8632 switch (level) {
8633 case 1:
8634 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8635 default:
8636 return WERR_UNKNOWN_LEVEL;
8640 /****************************************************************************
8641 enumprintmonitors level 1.
8642 ****************************************************************************/
8644 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8646 PRINTMONITOR_1 *info_1;
8647 WERROR result = WERR_OK;
8648 int i;
8650 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8651 return WERR_NOMEM;
8653 *returned = 2;
8655 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8656 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8658 for ( i=0; i<*returned; i++ ) {
8659 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8662 if (*needed > offered) {
8663 result = WERR_INSUFFICIENT_BUFFER;
8664 goto out;
8667 if (!rpcbuf_alloc_size(buffer, *needed)) {
8668 result = WERR_NOMEM;
8669 goto out;
8672 for ( i=0; i<*returned; i++ ) {
8673 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8676 out:
8677 SAFE_FREE(info_1);
8679 if ( !W_ERROR_IS_OK(result) )
8680 *returned = 0;
8682 return result;
8685 /****************************************************************************
8686 enumprintmonitors level 2.
8687 ****************************************************************************/
8689 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8691 PRINTMONITOR_2 *info_2;
8692 WERROR result = WERR_OK;
8693 int i;
8695 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8696 return WERR_NOMEM;
8698 *returned = 2;
8700 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8701 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8702 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8704 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8705 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8706 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8708 for ( i=0; i<*returned; i++ ) {
8709 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8712 if (*needed > offered) {
8713 result = WERR_INSUFFICIENT_BUFFER;
8714 goto out;
8717 if (!rpcbuf_alloc_size(buffer, *needed)) {
8718 result = WERR_NOMEM;
8719 goto out;
8722 for ( i=0; i<*returned; i++ ) {
8723 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8726 out:
8727 SAFE_FREE(info_2);
8729 if ( !W_ERROR_IS_OK(result) )
8730 *returned = 0;
8732 return result;
8735 /****************************************************************************
8736 ****************************************************************************/
8738 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8740 uint32 level = q_u->level;
8741 RPC_BUFFER *buffer = NULL;
8742 uint32 offered = q_u->offered;
8743 uint32 *needed = &r_u->needed;
8744 uint32 *returned = &r_u->returned;
8746 /* that's an [in out] buffer */
8748 if (!q_u->buffer && (offered!=0)) {
8749 return WERR_INVALID_PARAM;
8752 rpcbuf_move(q_u->buffer, &r_u->buffer);
8753 buffer = r_u->buffer;
8755 DEBUG(5,("spoolss_enumprintmonitors\n"));
8758 * Enumerate the print monitors ...
8760 * Just reply with "Local Port", to keep NT happy
8761 * and I can use my nice printer checker.
8764 *returned=0;
8765 *needed=0;
8767 switch (level) {
8768 case 1:
8769 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8770 case 2:
8771 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8772 default:
8773 return WERR_UNKNOWN_LEVEL;
8777 /****************************************************************************
8778 ****************************************************************************/
8780 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8781 NT_PRINTER_INFO_LEVEL *ntprinter,
8782 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8783 uint32 *needed)
8785 int i=0;
8786 BOOL found=False;
8787 JOB_INFO_1 *info_1=NULL;
8788 WERROR result = WERR_OK;
8790 info_1=SMB_MALLOC_P(JOB_INFO_1);
8792 if (info_1 == NULL) {
8793 return WERR_NOMEM;
8796 for (i=0; i<count && found==False; i++) {
8797 if ((*queue)[i].job==(int)jobid)
8798 found=True;
8801 if (found==False) {
8802 SAFE_FREE(info_1);
8803 /* NT treats not found as bad param... yet another bad choice */
8804 return WERR_INVALID_PARAM;
8807 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8809 *needed += spoolss_size_job_info_1(info_1);
8811 if (*needed > offered) {
8812 result = WERR_INSUFFICIENT_BUFFER;
8813 goto out;
8816 if (!rpcbuf_alloc_size(buffer, *needed)) {
8817 result = WERR_NOMEM;
8818 goto out;
8821 smb_io_job_info_1("", buffer, info_1, 0);
8823 out:
8824 SAFE_FREE(info_1);
8826 return result;
8829 /****************************************************************************
8830 ****************************************************************************/
8832 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8833 NT_PRINTER_INFO_LEVEL *ntprinter,
8834 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8835 uint32 *needed)
8837 int i = 0;
8838 BOOL found = False;
8839 JOB_INFO_2 *info_2;
8840 WERROR result;
8841 DEVICEMODE *devmode = NULL;
8842 NT_DEVICEMODE *nt_devmode = NULL;
8844 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8845 return WERR_NOMEM;
8847 ZERO_STRUCTP(info_2);
8849 for ( i=0; i<count && found==False; i++ )
8851 if ((*queue)[i].job == (int)jobid)
8852 found = True;
8855 if ( !found ) {
8856 /* NT treats not found as bad param... yet another bad
8857 choice */
8858 result = WERR_INVALID_PARAM;
8859 goto done;
8863 * if the print job does not have a DEVMODE associated with it,
8864 * just use the one for the printer. A NULL devicemode is not
8865 * a failure condition
8868 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8869 devmode = construct_dev_mode(lp_const_servicename(snum));
8870 else {
8871 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8872 ZERO_STRUCTP( devmode );
8873 convert_nt_devicemode( devmode, nt_devmode );
8877 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8879 *needed += spoolss_size_job_info_2(info_2);
8881 if (*needed > offered) {
8882 result = WERR_INSUFFICIENT_BUFFER;
8883 goto done;
8886 if (!rpcbuf_alloc_size(buffer, *needed)) {
8887 result = WERR_NOMEM;
8888 goto done;
8891 smb_io_job_info_2("", buffer, info_2, 0);
8893 result = WERR_OK;
8895 done:
8896 /* Cleanup allocated memory */
8898 free_job_info_2(info_2); /* Also frees devmode */
8899 SAFE_FREE(info_2);
8901 return result;
8904 /****************************************************************************
8905 ****************************************************************************/
8907 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8909 POLICY_HND *handle = &q_u->handle;
8910 uint32 jobid = q_u->jobid;
8911 uint32 level = q_u->level;
8912 RPC_BUFFER *buffer = NULL;
8913 uint32 offered = q_u->offered;
8914 uint32 *needed = &r_u->needed;
8915 WERROR wstatus = WERR_OK;
8916 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8917 int snum;
8918 int count;
8919 print_queue_struct *queue = NULL;
8920 print_status_struct prt_status;
8922 /* that's an [in out] buffer */
8924 if (!q_u->buffer && (offered!=0)) {
8925 return WERR_INVALID_PARAM;
8928 rpcbuf_move(q_u->buffer, &r_u->buffer);
8929 buffer = r_u->buffer;
8931 DEBUG(5,("spoolss_getjob\n"));
8933 *needed = 0;
8935 if (!get_printer_snum(p, handle, &snum))
8936 return WERR_BADFID;
8938 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8939 if ( !W_ERROR_IS_OK(wstatus) )
8940 return wstatus;
8942 count = print_queue_status(snum, &queue, &prt_status);
8944 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8945 count, prt_status.status, prt_status.message));
8947 switch ( level ) {
8948 case 1:
8949 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8950 buffer, offered, needed);
8951 break;
8952 case 2:
8953 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8954 buffer, offered, needed);
8955 break;
8956 default:
8957 wstatus = WERR_UNKNOWN_LEVEL;
8958 break;
8961 SAFE_FREE(queue);
8962 free_a_printer( &ntprinter, 2 );
8964 return wstatus;
8967 /********************************************************************
8968 spoolss_getprinterdataex
8970 From MSDN documentation of GetPrinterDataEx: pass request
8971 to GetPrinterData if key is "PrinterDriverData".
8972 ********************************************************************/
8974 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8976 POLICY_HND *handle = &q_u->handle;
8977 uint32 in_size = q_u->size;
8978 uint32 *type = &r_u->type;
8979 uint32 *out_size = &r_u->size;
8980 uint8 **data = &r_u->data;
8981 uint32 *needed = &r_u->needed;
8982 fstring keyname, valuename;
8984 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8986 NT_PRINTER_INFO_LEVEL *printer = NULL;
8987 int snum = 0;
8988 WERROR status = WERR_OK;
8990 DEBUG(4,("_spoolss_getprinterdataex\n"));
8992 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8993 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8995 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8996 keyname, valuename));
8998 /* in case of problem, return some default values */
9000 *needed = 0;
9001 *type = 0;
9002 *out_size = in_size;
9004 if (!Printer) {
9005 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9006 status = WERR_BADFID;
9007 goto done;
9010 /* Is the handle to a printer or to the server? */
9012 if (Printer->printer_type == SPLHND_SERVER) {
9013 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9014 status = WERR_INVALID_PARAM;
9015 goto done;
9018 if ( !get_printer_snum(p,handle, &snum) )
9019 return WERR_BADFID;
9021 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9022 if ( !W_ERROR_IS_OK(status) )
9023 goto done;
9025 /* check to see if the keyname is valid */
9026 if ( !strlen(keyname) ) {
9027 status = WERR_INVALID_PARAM;
9028 goto done;
9031 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9032 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9033 free_a_printer( &printer, 2 );
9034 status = WERR_BADFILE;
9035 goto done;
9038 /* When given a new keyname, we should just create it */
9040 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9042 if (*needed > *out_size)
9043 status = WERR_MORE_DATA;
9045 done:
9046 if ( !W_ERROR_IS_OK(status) )
9048 DEBUG(5, ("error: allocating %d\n", *out_size));
9050 /* reply this param doesn't exist */
9052 if ( *out_size )
9054 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9055 status = WERR_NOMEM;
9056 goto done;
9058 } else {
9059 *data = NULL;
9063 if ( printer )
9064 free_a_printer( &printer, 2 );
9066 return status;
9069 /********************************************************************
9070 * spoolss_setprinterdataex
9071 ********************************************************************/
9073 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9075 POLICY_HND *handle = &q_u->handle;
9076 uint32 type = q_u->type;
9077 uint8 *data = q_u->data;
9078 uint32 real_len = q_u->real_len;
9080 NT_PRINTER_INFO_LEVEL *printer = NULL;
9081 int snum = 0;
9082 WERROR status = WERR_OK;
9083 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9084 fstring valuename;
9085 fstring keyname;
9086 char *oid_string;
9088 DEBUG(4,("_spoolss_setprinterdataex\n"));
9090 /* From MSDN documentation of SetPrinterDataEx: pass request to
9091 SetPrinterData if key is "PrinterDriverData" */
9093 if (!Printer) {
9094 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9095 return WERR_BADFID;
9098 if ( Printer->printer_type == SPLHND_SERVER ) {
9099 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9100 return WERR_INVALID_PARAM;
9103 if ( !get_printer_snum(p,handle, &snum) )
9104 return WERR_BADFID;
9107 * Access check : NT returns "access denied" if you make a
9108 * SetPrinterData call without the necessary privildge.
9109 * we were originally returning OK if nothing changed
9110 * which made Win2k issue **a lot** of SetPrinterData
9111 * when connecting to a printer --jerry
9114 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9116 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9117 return WERR_ACCESS_DENIED;
9120 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9121 if (!W_ERROR_IS_OK(status))
9122 return status;
9124 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9125 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9127 /* check for OID in valuename */
9129 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9131 *oid_string = '\0';
9132 oid_string++;
9135 /* save the registry data */
9137 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9139 if ( W_ERROR_IS_OK(status) )
9141 /* save the OID if one was specified */
9142 if ( oid_string ) {
9143 fstrcat( keyname, "\\" );
9144 fstrcat( keyname, SPOOL_OID_KEY );
9147 * I'm not checking the status here on purpose. Don't know
9148 * if this is right, but I'm returning the status from the
9149 * previous set_printer_dataex() call. I have no idea if
9150 * this is right. --jerry
9153 set_printer_dataex( printer, keyname, valuename,
9154 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9157 status = mod_a_printer(printer, 2);
9160 free_a_printer(&printer, 2);
9162 return status;
9166 /********************************************************************
9167 * spoolss_deleteprinterdataex
9168 ********************************************************************/
9170 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9172 POLICY_HND *handle = &q_u->handle;
9173 UNISTR2 *value = &q_u->valuename;
9174 UNISTR2 *key = &q_u->keyname;
9176 NT_PRINTER_INFO_LEVEL *printer = NULL;
9177 int snum=0;
9178 WERROR status = WERR_OK;
9179 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9180 pstring valuename, keyname;
9182 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9184 if (!Printer) {
9185 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9186 return WERR_BADFID;
9189 if (!get_printer_snum(p, handle, &snum))
9190 return WERR_BADFID;
9192 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9193 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9194 return WERR_ACCESS_DENIED;
9197 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9198 if (!W_ERROR_IS_OK(status))
9199 return status;
9201 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9202 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9204 status = delete_printer_dataex( printer, keyname, valuename );
9206 if ( W_ERROR_IS_OK(status) )
9207 mod_a_printer( printer, 2 );
9209 free_a_printer(&printer, 2);
9211 return status;
9214 /********************************************************************
9215 * spoolss_enumprinterkey
9216 ********************************************************************/
9219 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9221 fstring key;
9222 fstring *keynames = NULL;
9223 uint16 *enumkeys = NULL;
9224 int num_keys;
9225 int printerkey_len;
9226 POLICY_HND *handle = &q_u->handle;
9227 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9228 NT_PRINTER_DATA *data;
9229 NT_PRINTER_INFO_LEVEL *printer = NULL;
9230 int snum = 0;
9231 WERROR status = WERR_BADFILE;
9234 DEBUG(4,("_spoolss_enumprinterkey\n"));
9236 if (!Printer) {
9237 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9238 return WERR_BADFID;
9241 if ( !get_printer_snum(p,handle, &snum) )
9242 return WERR_BADFID;
9244 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9245 if (!W_ERROR_IS_OK(status))
9246 return status;
9248 /* get the list of subkey names */
9250 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9251 data = printer->info_2->data;
9253 num_keys = get_printer_subkeys( data, key, &keynames );
9255 if ( num_keys == -1 ) {
9256 status = WERR_BADFILE;
9257 goto done;
9260 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9262 r_u->needed = printerkey_len*2;
9264 if ( q_u->size < r_u->needed ) {
9265 status = WERR_MORE_DATA;
9266 goto done;
9269 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9270 status = WERR_NOMEM;
9271 goto done;
9274 status = WERR_OK;
9276 if ( q_u->size < r_u->needed )
9277 status = WERR_MORE_DATA;
9279 done:
9280 free_a_printer( &printer, 2 );
9281 SAFE_FREE( keynames );
9283 return status;
9286 /********************************************************************
9287 * spoolss_deleteprinterkey
9288 ********************************************************************/
9290 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9292 POLICY_HND *handle = &q_u->handle;
9293 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9294 fstring key;
9295 NT_PRINTER_INFO_LEVEL *printer = NULL;
9296 int snum=0;
9297 WERROR status;
9299 DEBUG(5,("spoolss_deleteprinterkey\n"));
9301 if (!Printer) {
9302 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9303 return WERR_BADFID;
9306 /* if keyname == NULL, return error */
9308 if ( !q_u->keyname.buffer )
9309 return WERR_INVALID_PARAM;
9311 if (!get_printer_snum(p, handle, &snum))
9312 return WERR_BADFID;
9314 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9315 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9316 return WERR_ACCESS_DENIED;
9319 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9320 if (!W_ERROR_IS_OK(status))
9321 return status;
9323 /* delete the key and all subneys */
9325 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9327 status = delete_all_printer_data( printer->info_2, key );
9329 if ( W_ERROR_IS_OK(status) )
9330 status = mod_a_printer(printer, 2);
9332 free_a_printer( &printer, 2 );
9334 return status;
9338 /********************************************************************
9339 * spoolss_enumprinterdataex
9340 ********************************************************************/
9342 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9344 POLICY_HND *handle = &q_u->handle;
9345 uint32 in_size = q_u->size;
9346 uint32 num_entries,
9347 needed;
9348 NT_PRINTER_INFO_LEVEL *printer = NULL;
9349 PRINTER_ENUM_VALUES *enum_values = NULL;
9350 NT_PRINTER_DATA *p_data;
9351 fstring key;
9352 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9353 int snum;
9354 WERROR result;
9355 int key_index;
9356 int i;
9357 REGISTRY_VALUE *val;
9358 char *value_name;
9359 uint32 data_len;
9362 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9364 if (!Printer) {
9365 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9366 return WERR_BADFID;
9370 * first check for a keyname of NULL or "". Win2k seems to send
9371 * this a lot and we should send back WERR_INVALID_PARAM
9372 * no need to spend time looking up the printer in this case.
9373 * --jerry
9376 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9377 if ( !strlen(key) ) {
9378 result = WERR_INVALID_PARAM;
9379 goto done;
9382 /* get the printer off of disk */
9384 if (!get_printer_snum(p,handle, &snum))
9385 return WERR_BADFID;
9387 ZERO_STRUCT(printer);
9388 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9389 if (!W_ERROR_IS_OK(result))
9390 return result;
9392 /* now look for a match on the key name */
9394 p_data = printer->info_2->data;
9396 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9397 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9399 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9400 result = WERR_INVALID_PARAM;
9401 goto done;
9404 result = WERR_OK;
9405 needed = 0;
9407 /* allocate the memory for the array of pointers -- if necessary */
9409 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9410 if ( num_entries )
9412 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9414 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9415 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9416 result = WERR_NOMEM;
9417 goto done;
9420 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9424 * loop through all params and build the array to pass
9425 * back to the client
9428 for ( i=0; i<num_entries; i++ )
9430 /* lookup the registry value */
9432 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9433 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9435 /* copy the data */
9437 value_name = regval_name( val );
9438 init_unistr( &enum_values[i].valuename, value_name );
9439 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9440 enum_values[i].type = regval_type( val );
9442 data_len = regval_size( val );
9443 if ( data_len ) {
9444 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9446 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9447 data_len ));
9448 result = WERR_NOMEM;
9449 goto done;
9452 enum_values[i].data_len = data_len;
9454 /* keep track of the size of the array in bytes */
9456 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9459 /* housekeeping information in the reply */
9461 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9462 * the hand marshalled container size is a multiple
9463 * of 4 bytes for RPC alignment.
9466 if (needed % 4) {
9467 needed += 4-(needed % 4);
9470 r_u->needed = needed;
9471 r_u->returned = num_entries;
9473 if (needed > in_size) {
9474 result = WERR_MORE_DATA;
9475 goto done;
9478 /* copy data into the reply */
9480 r_u->ctr.size = r_u->needed;
9482 r_u->ctr.size_of_array = r_u->returned;
9483 r_u->ctr.values = enum_values;
9487 done:
9488 if ( printer )
9489 free_a_printer(&printer, 2);
9491 return result;
9494 /****************************************************************************
9495 ****************************************************************************/
9497 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9499 init_unistr(&info->name, name);
9502 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9503 UNISTR2 *environment,
9504 RPC_BUFFER *buffer,
9505 uint32 offered,
9506 uint32 *needed)
9508 pstring path;
9509 pstring long_archi;
9510 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9511 WERROR result = WERR_OK;
9513 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9515 if (!get_short_archi(long_archi))
9516 return WERR_INVALID_ENVIRONMENT;
9518 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9519 return WERR_NOMEM;
9521 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9523 fill_printprocessordirectory_1(info, path);
9525 *needed += spoolss_size_printprocessordirectory_info_1(info);
9527 if (*needed > offered) {
9528 result = WERR_INSUFFICIENT_BUFFER;
9529 goto out;
9532 if (!rpcbuf_alloc_size(buffer, *needed)) {
9533 result = WERR_INSUFFICIENT_BUFFER;
9534 goto out;
9537 smb_io_printprocessordirectory_1("", buffer, info, 0);
9539 out:
9540 SAFE_FREE(info);
9542 return result;
9545 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9547 uint32 level = q_u->level;
9548 RPC_BUFFER *buffer = NULL;
9549 uint32 offered = q_u->offered;
9550 uint32 *needed = &r_u->needed;
9551 WERROR result;
9553 /* that's an [in out] buffer */
9555 if (!q_u->buffer && (offered!=0)) {
9556 return WERR_INVALID_PARAM;
9559 rpcbuf_move(q_u->buffer, &r_u->buffer);
9560 buffer = r_u->buffer;
9562 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9564 *needed=0;
9566 switch(level) {
9567 case 1:
9568 result = getprintprocessordirectory_level_1
9569 (&q_u->name, &q_u->environment, buffer, offered, needed);
9570 break;
9571 default:
9572 result = WERR_UNKNOWN_LEVEL;
9575 return result;
9578 /*******************************************************************
9579 Streams the monitor UI DLL name in UNICODE
9580 *******************************************************************/
9582 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9583 RPC_BUFFER *out, uint32 *needed )
9585 const char *dllname = "tcpmonui.dll";
9587 *needed = (strlen(dllname)+1) * 2;
9589 if ( rpcbuf_get_size(out) < *needed ) {
9590 return WERR_INSUFFICIENT_BUFFER;
9593 if ( !make_monitorui_buf( out, dllname ) ) {
9594 return WERR_NOMEM;
9597 return WERR_OK;
9600 /*******************************************************************
9601 Create a new TCP/IP port
9602 *******************************************************************/
9604 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9605 RPC_BUFFER *out, uint32 *needed )
9607 NT_PORT_DATA_1 port1;
9608 pstring device_uri;
9610 ZERO_STRUCT( port1 );
9612 /* convert to our internal port data structure */
9614 if ( !convert_port_data_1( &port1, in ) ) {
9615 return WERR_NOMEM;
9618 /* create the device URI and call the add_port_hook() */
9620 switch ( port1.protocol ) {
9621 case PORT_PROTOCOL_DIRECT:
9622 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9623 break;
9625 case PORT_PROTOCOL_LPR:
9626 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9627 break;
9629 default:
9630 return WERR_UNKNOWN_PORT;
9633 return add_port_hook( token, port1.name, device_uri );
9636 /*******************************************************************
9637 *******************************************************************/
9639 struct xcv_api_table xcvtcp_cmds[] = {
9640 { "MonitorUI", xcvtcp_monitorui },
9641 { "AddPort", xcvtcp_addport},
9642 { NULL, NULL }
9645 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9646 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9647 uint32 *needed )
9649 int i;
9651 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9653 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9654 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9655 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9658 return WERR_BADFUNC;
9661 /*******************************************************************
9662 *******************************************************************/
9663 #if 0 /* don't support management using the "Local Port" monitor */
9665 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9666 RPC_BUFFER *out, uint32 *needed )
9668 const char *dllname = "localui.dll";
9670 *needed = (strlen(dllname)+1) * 2;
9672 if ( rpcbuf_get_size(out) < *needed ) {
9673 return WERR_INSUFFICIENT_BUFFER;
9676 if ( !make_monitorui_buf( out, dllname )) {
9677 return WERR_NOMEM;
9680 return WERR_OK;
9683 /*******************************************************************
9684 *******************************************************************/
9686 struct xcv_api_table xcvlocal_cmds[] = {
9687 { "MonitorUI", xcvlocal_monitorui },
9688 { NULL, NULL }
9690 #else
9691 struct xcv_api_table xcvlocal_cmds[] = {
9692 { NULL, NULL }
9694 #endif
9698 /*******************************************************************
9699 *******************************************************************/
9701 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9702 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9703 uint32 *needed )
9705 int i;
9707 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9709 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9710 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9711 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9713 return WERR_BADFUNC;
9716 /*******************************************************************
9717 *******************************************************************/
9719 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9721 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9722 fstring command;
9724 if (!Printer) {
9725 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9726 return WERR_BADFID;
9729 /* Has to be a handle to the TCP/IP port monitor */
9731 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9732 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9733 return WERR_BADFID;
9736 /* requires administrative access to the server */
9738 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9739 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9740 return WERR_ACCESS_DENIED;
9743 /* Get the command name. There's numerous commands supported by the
9744 TCPMON interface. */
9746 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9747 q_u->dataname.uni_str_len*2, 0);
9749 /* Allocate the outgoing buffer */
9751 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9753 switch ( Printer->printer_type ) {
9754 case SPLHND_PORTMON_TCP:
9755 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9756 &q_u->indata, &r_u->outdata, &r_u->needed );
9757 case SPLHND_PORTMON_LOCAL:
9758 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9759 &q_u->indata, &r_u->outdata, &r_u->needed );
9762 return WERR_INVALID_PRINT_MONITOR;