Add some missing whitespaces.
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob4c5fcf53418bf5f16e77ee14c8e2d57992fb6793
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 3 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, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 extern userdom_struct current_user_info;
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 struct table_node {
43 const char *long_archi;
44 const char *short_archi;
45 int version;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
54 int snum;
55 uint32 counter;
56 } counter_printer_0;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
71 const char *name;
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
76 /* translate between internal status numbers and NT status numbers */
77 static int nt_printj_status(int v)
79 switch (v) {
80 case LPQ_QUEUED:
81 return 0;
82 case LPQ_PAUSED:
83 return JOB_STATUS_PAUSED;
84 case LPQ_SPOOLING:
85 return JOB_STATUS_SPOOLING;
86 case LPQ_PRINTING:
87 return JOB_STATUS_PRINTING;
88 case LPQ_ERROR:
89 return JOB_STATUS_ERROR;
90 case LPQ_DELETING:
91 return JOB_STATUS_DELETING;
92 case LPQ_OFFLINE:
93 return JOB_STATUS_OFFLINE;
94 case LPQ_PAPEROUT:
95 return JOB_STATUS_PAPEROUT;
96 case LPQ_PRINTED:
97 return JOB_STATUS_PRINTED;
98 case LPQ_DELETED:
99 return JOB_STATUS_DELETED;
100 case LPQ_BLOCKED:
101 return JOB_STATUS_BLOCKED;
102 case LPQ_USER_INTERVENTION:
103 return JOB_STATUS_USER_INTERVENTION;
105 return 0;
108 static int nt_printq_status(int v)
110 switch (v) {
111 case LPQ_PAUSED:
112 return PRINTER_STATUS_PAUSED;
113 case LPQ_QUEUED:
114 case LPQ_SPOOLING:
115 case LPQ_PRINTING:
116 return 0;
118 return 0;
121 /****************************************************************************
122 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
123 ****************************************************************************/
125 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
127 if (*pp == NULL)
128 return;
130 SAFE_FREE((*pp)->ctr.type);
131 SAFE_FREE(*pp);
134 /***************************************************************************
135 Disconnect from the client
136 ****************************************************************************/
138 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
140 WERROR result;
143 * Tell the specific printing tdb we no longer want messages for this printer
144 * by deregistering our PID.
147 if (!print_notify_deregister_pid(snum))
148 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
150 /* weird if the test succeds !!! */
151 if (smb_connections==0) {
152 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
153 return;
156 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe,
157 talloc_tos(),
158 handle);
160 if (!W_ERROR_IS_OK(result))
161 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
162 dos_errstr(result)));
164 /* if it's the last connection, deconnect the IPC$ share */
165 if (smb_connections==1) {
167 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
168 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
170 messaging_deregister(smbd_messaging_context(),
171 MSG_PRINTER_NOTIFY2, NULL);
173 /* Tell the connections db we're no longer interested in
174 * printer notify messages. */
176 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
179 smb_connections--;
182 /****************************************************************************
183 Functions to free a printer entry datastruct.
184 ****************************************************************************/
186 static void free_printer_entry(void *ptr)
188 Printer_entry *Printer = (Printer_entry *)ptr;
190 if (Printer->notify.client_connected==True) {
191 int snum = -1;
193 if ( Printer->printer_type == SPLHND_SERVER) {
194 snum = -1;
195 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
196 } else if (Printer->printer_type == SPLHND_PRINTER) {
197 snum = print_queue_snum(Printer->sharename);
198 if (snum != -1)
199 srv_spoolss_replycloseprinter(snum,
200 &Printer->notify.client_hnd);
204 Printer->notify.flags=0;
205 Printer->notify.options=0;
206 Printer->notify.localmachine[0]='\0';
207 Printer->notify.printerlocal=0;
208 free_spool_notify_option(&Printer->notify.option);
209 Printer->notify.option=NULL;
210 Printer->notify.client_connected=False;
212 free_nt_devicemode( &Printer->nt_devmode );
213 free_a_printer( &Printer->printer_info, 2 );
215 talloc_destroy( Printer->ctx );
217 /* Remove from the internal list. */
218 DLIST_REMOVE(printers_list, Printer);
220 SAFE_FREE(Printer);
223 /****************************************************************************
224 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
225 ****************************************************************************/
227 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
229 SPOOL_NOTIFY_OPTION *new_sp = NULL;
231 if (!sp)
232 return NULL;
234 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
235 if (!new_sp)
236 return NULL;
238 *new_sp = *sp;
240 if (sp->ctr.count) {
241 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
243 if (!new_sp->ctr.type) {
244 SAFE_FREE(new_sp);
245 return NULL;
249 return new_sp;
252 /****************************************************************************
253 find printer index by handle
254 ****************************************************************************/
256 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *find_printer = NULL;
260 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
261 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
262 return NULL;
265 return find_printer;
268 /****************************************************************************
269 Close printer index by handle.
270 ****************************************************************************/
272 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
274 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
276 if (!Printer) {
277 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
278 return False;
281 close_policy_hnd(p, hnd);
283 return True;
286 /****************************************************************************
287 Delete a printer given a handle.
288 ****************************************************************************/
290 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
292 char *cmd = lp_deleteprinter_cmd();
293 char *command = NULL;
294 int ret;
295 SE_PRIV se_printop = SE_PRINT_OPERATOR;
296 bool is_print_op = False;
298 /* can't fail if we don't try */
300 if ( !*cmd )
301 return WERR_OK;
303 command = talloc_asprintf(ctx,
304 "%s \"%s\"",
305 cmd, sharename);
306 if (!command) {
307 return WERR_NOMEM;
309 if ( token )
310 is_print_op = user_has_privileges( token, &se_printop );
312 DEBUG(10,("Running [%s]\n", command));
314 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
316 if ( is_print_op )
317 become_root();
319 if ( (ret = smbrun(command, NULL)) == 0 ) {
320 /* Tell everyone we updated smb.conf. */
321 message_send_all(smbd_messaging_context(),
322 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
325 if ( is_print_op )
326 unbecome_root();
328 /********** END SePrintOperatorPrivlege BLOCK **********/
330 DEBUGADD(10,("returned [%d]\n", ret));
332 TALLOC_FREE(command);
334 if (ret != 0)
335 return WERR_BADFID; /* What to return here? */
337 /* go ahead and re-read the services immediately */
338 reload_services( False );
340 if ( lp_servicenumber( sharename ) < 0 )
341 return WERR_ACCESS_DENIED;
343 return WERR_OK;
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
354 if (!Printer) {
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
356 return WERR_BADFID;
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
363 * JRA.
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
371 /* this does not need a become root since the access check has been
372 done on the handle already */
374 if (del_a_printer( Printer->sharename ) != 0) {
375 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
376 return WERR_BADFID;
379 return delete_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, Printer->sharename );
382 /****************************************************************************
383 Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
386 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
387 struct share_params **params)
389 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
391 if (!Printer) {
392 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
393 return False;
396 switch (Printer->printer_type) {
397 case SPLHND_PRINTER:
398 DEBUG(4,("short name:%s\n", Printer->sharename));
399 *number = print_queue_snum(Printer->sharename);
400 return (*number != -1);
401 case SPLHND_SERVER:
402 return False;
403 default:
404 return False;
408 /****************************************************************************
409 Set printer handle type.
410 Check if it's \\server or \\server\printer
411 ****************************************************************************/
413 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
415 DEBUG(3,("Setting printer type=%s\n", handlename));
417 if ( strlen(handlename) < 3 ) {
418 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
419 return False;
422 /* it's a print server */
423 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
424 DEBUGADD(4,("Printer is a print server\n"));
425 Printer->printer_type = SPLHND_SERVER;
427 /* it's a printer (set_printer_hnd_name() will handle port monitors */
428 else {
429 DEBUGADD(4,("Printer is a printer\n"));
430 Printer->printer_type = SPLHND_PRINTER;
433 return True;
436 /****************************************************************************
437 Set printer handle name.. Accept names like \\server, \\server\printer,
438 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
439 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
440 XcvDataPort() interface.
441 ****************************************************************************/
443 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
445 int snum;
446 int n_services=lp_numservices();
447 char *aprinter, *printername;
448 const char *servername;
449 fstring sname;
450 bool found=False;
451 NT_PRINTER_INFO_LEVEL *printer = NULL;
452 WERROR result;
454 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
456 aprinter = handlename;
457 if ( *handlename == '\\' ) {
458 servername = handlename + 2;
459 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
460 *aprinter = '\0';
461 aprinter++;
464 else {
465 servername = "";
468 /* save the servername to fill in replies on this handle */
470 if ( !is_myname_or_ipaddr( servername ) )
471 return False;
473 fstrcpy( Printer->servername, servername );
475 if ( Printer->printer_type == SPLHND_SERVER )
476 return True;
478 if ( Printer->printer_type != SPLHND_PRINTER )
479 return False;
481 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
483 /* check for the Port Monitor Interface */
485 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
486 Printer->printer_type = SPLHND_PORTMON_TCP;
487 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
488 found = True;
490 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
491 Printer->printer_type = SPLHND_PORTMON_LOCAL;
492 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
493 found = True;
496 /* Search all sharenames first as this is easier than pulling
497 the printer_info_2 off of disk. Don't use find_service() since
498 that calls out to map_username() */
500 /* do another loop to look for printernames */
502 for (snum=0; !found && snum<n_services; snum++) {
504 /* no point going on if this is not a printer */
506 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
507 continue;
509 fstrcpy(sname, lp_servicename(snum));
510 if ( strequal( aprinter, sname ) ) {
511 found = True;
512 break;
515 /* no point looking up the printer object if
516 we aren't allowing printername != sharename */
518 if ( lp_force_printername(snum) )
519 continue;
521 fstrcpy(sname, lp_servicename(snum));
523 printer = NULL;
525 /* This call doesn't fill in the location or comment from
526 * a CUPS server for efficiency with large numbers of printers.
527 * JRA.
530 result = get_a_printer_search( NULL, &printer, 2, sname );
531 if ( !W_ERROR_IS_OK(result) ) {
532 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
533 sname, dos_errstr(result)));
534 continue;
537 /* printername is always returned as \\server\printername */
538 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
539 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
540 printer->info_2->printername));
541 free_a_printer( &printer, 2);
542 continue;
545 printername++;
547 if ( strequal(printername, aprinter) ) {
548 free_a_printer( &printer, 2);
549 found = True;
550 break;
553 DEBUGADD(10, ("printername: %s\n", printername));
555 free_a_printer( &printer, 2);
558 free_a_printer( &printer, 2);
560 if ( !found ) {
561 DEBUGADD(4,("Printer not found\n"));
562 return False;
565 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
567 fstrcpy(Printer->sharename, sname);
569 return True;
572 /****************************************************************************
573 Find first available printer slot. creates a printer handle for you.
574 ****************************************************************************/
576 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
578 Printer_entry *new_printer;
580 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
582 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
583 return False;
585 ZERO_STRUCTP(new_printer);
587 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
588 SAFE_FREE(new_printer);
589 return False;
592 /* Add to the internal list. */
593 DLIST_ADD(printers_list, new_printer);
595 new_printer->notify.option=NULL;
597 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
598 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
599 close_printer_handle(p, hnd);
600 return False;
603 if (!set_printer_hnd_printertype(new_printer, name)) {
604 close_printer_handle(p, hnd);
605 return False;
608 if (!set_printer_hnd_name(new_printer, name)) {
609 close_printer_handle(p, hnd);
610 return False;
613 new_printer->access_granted = access_granted;
615 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
617 return True;
620 /***************************************************************************
621 check to see if the client motify handle is monitoring the notification
622 given by (notify_type, notify_field).
623 **************************************************************************/
625 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
626 uint16 notify_field)
628 return True;
631 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
632 uint16 notify_field)
634 SPOOL_NOTIFY_OPTION *option = p->notify.option;
635 uint32 i, j;
638 * Flags should always be zero when the change notify
639 * is registered by the client's spooler. A user Win32 app
640 * might use the flags though instead of the NOTIFY_OPTION_INFO
641 * --jerry
644 if (!option) {
645 return False;
648 if (p->notify.flags)
649 return is_monitoring_event_flags(
650 p->notify.flags, notify_type, notify_field);
652 for (i = 0; i < option->count; i++) {
654 /* Check match for notify_type */
656 if (option->ctr.type[i].type != notify_type)
657 continue;
659 /* Check match for field */
661 for (j = 0; j < option->ctr.type[i].count; j++) {
662 if (option->ctr.type[i].fields[j] == notify_field) {
663 return True;
668 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
669 p->servername, p->sharename, notify_type, notify_field));
671 return False;
674 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
676 static void notify_one_value(struct spoolss_notify_msg *msg,
677 SPOOL_NOTIFY_INFO_DATA *data,
678 TALLOC_CTX *mem_ctx)
680 data->notify_data.value[0] = msg->notify.value[0];
681 data->notify_data.value[1] = 0;
684 static void notify_string(struct spoolss_notify_msg *msg,
685 SPOOL_NOTIFY_INFO_DATA *data,
686 TALLOC_CTX *mem_ctx)
688 UNISTR2 unistr;
690 /* The length of the message includes the trailing \0 */
692 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
694 data->notify_data.data.length = msg->len * 2;
695 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
697 if (!data->notify_data.data.string) {
698 data->notify_data.data.length = 0;
699 return;
702 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
705 static void notify_system_time(struct spoolss_notify_msg *msg,
706 SPOOL_NOTIFY_INFO_DATA *data,
707 TALLOC_CTX *mem_ctx)
709 SYSTEMTIME systime;
710 prs_struct ps;
712 if (msg->len != sizeof(time_t)) {
713 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
714 msg->len));
715 return;
718 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
719 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
720 return;
723 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
724 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
725 prs_mem_free(&ps);
726 return;
729 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
730 prs_mem_free(&ps);
731 return;
734 data->notify_data.data.length = prs_offset(&ps);
735 if (prs_offset(&ps)) {
736 data->notify_data.data.string = (uint16 *)
737 TALLOC(mem_ctx, prs_offset(&ps));
738 if (!data->notify_data.data.string) {
739 prs_mem_free(&ps);
740 return;
742 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
743 } else {
744 data->notify_data.data.string = NULL;
747 prs_mem_free(&ps);
750 struct notify2_message_table {
751 const char *name;
752 void (*fn)(struct spoolss_notify_msg *msg,
753 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
756 static struct notify2_message_table printer_notify_table[] = {
757 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
758 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
759 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
760 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
761 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
762 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
763 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
764 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
765 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
766 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
767 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
768 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
769 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
770 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
771 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
772 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
773 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
774 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
775 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
778 static struct notify2_message_table job_notify_table[] = {
779 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
780 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
781 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
782 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
783 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
784 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
785 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
786 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
787 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
788 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
789 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
790 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
791 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
792 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
793 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
794 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
795 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
796 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
797 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
798 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
799 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
800 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
801 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
802 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
806 /***********************************************************************
807 Allocate talloc context for container object
808 **********************************************************************/
810 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 if ( !ctr )
813 return;
815 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817 return;
820 /***********************************************************************
821 release all allocated memory and zero out structure
822 **********************************************************************/
824 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 if ( !ctr )
827 return;
829 if ( ctr->ctx )
830 talloc_destroy(ctr->ctx);
832 ZERO_STRUCTP(ctr);
834 return;
837 /***********************************************************************
838 **********************************************************************/
840 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 if ( !ctr )
843 return NULL;
845 return ctr->ctx;
848 /***********************************************************************
849 **********************************************************************/
851 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
853 if ( !ctr || !ctr->msg_groups )
854 return NULL;
856 if ( idx >= ctr->num_groups )
857 return NULL;
859 return &ctr->msg_groups[idx];
863 /***********************************************************************
864 How many groups of change messages do we have ?
865 **********************************************************************/
867 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 if ( !ctr )
870 return 0;
872 return ctr->num_groups;
875 /***********************************************************************
876 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
877 **********************************************************************/
879 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
882 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
883 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
884 int i, new_slot;
886 if ( !ctr || !msg )
887 return 0;
889 /* loop over all groups looking for a matching printer name */
891 for ( i=0; i<ctr->num_groups; i++ ) {
892 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
893 break;
896 /* add a new group? */
898 if ( i == ctr->num_groups ) {
899 ctr->num_groups++;
901 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
902 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
903 return 0;
905 ctr->msg_groups = groups;
907 /* clear the new entry and set the printer name */
909 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
910 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
913 /* add the change messages; 'i' is the correct index now regardless */
915 msg_grp = &ctr->msg_groups[i];
917 msg_grp->num_msgs++;
919 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
921 return 0;
923 msg_grp->msgs = msg_list;
925 new_slot = msg_grp->num_msgs-1;
926 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928 /* need to allocate own copy of data */
930 if ( msg->len != 0 )
931 msg_grp->msgs[new_slot].notify.data = (char *)
932 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934 return ctr->num_groups;
937 /***********************************************************************
938 Send a change notication message on all handles which have a call
939 back registered
940 **********************************************************************/
942 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
944 Printer_entry *p;
945 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
946 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
947 SPOOLSS_NOTIFY_MSG *messages;
948 int sending_msg_count;
950 if ( !msg_group ) {
951 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
952 return;
955 messages = msg_group->msgs;
957 if ( !messages ) {
958 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
959 return;
962 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964 /* loop over all printers */
966 for (p = printers_list; p; p = p->next) {
967 SPOOL_NOTIFY_INFO_DATA *data;
968 uint32 data_len = 0;
969 uint32 id;
970 int i;
972 /* Is there notification on this handle? */
974 if ( !p->notify.client_connected )
975 continue;
977 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979 /* For this printer? Print servers always receive
980 notifications. */
982 if ( ( p->printer_type == SPLHND_PRINTER ) &&
983 ( !strequal(msg_group->printername, p->sharename) ) )
984 continue;
986 DEBUG(10,("Our printer\n"));
988 /* allocate the max entries possible */
990 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
991 if (!data) {
992 return;
995 ZERO_STRUCTP(data);
997 /* build the array of change notifications */
999 sending_msg_count = 0;
1001 for ( i=0; i<msg_group->num_msgs; i++ ) {
1002 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1004 /* Are we monitoring this event? */
1006 if (!is_monitoring_event(p, msg->type, msg->field))
1007 continue;
1009 sending_msg_count++;
1012 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1013 msg->type, msg->field, p->sharename));
1016 * if the is a printer notification handle and not a job notification
1017 * type, then set the id to 0. Other wise just use what was specified
1018 * in the message.
1020 * When registering change notification on a print server handle
1021 * we always need to send back the id (snum) matching the printer
1022 * for which the change took place. For change notify registered
1023 * on a printer handle, this does not matter and the id should be 0.
1025 * --jerry
1028 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1029 id = 0;
1030 else
1031 id = msg->id;
1034 /* Convert unix jobid to smb jobid */
1036 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1037 id = sysjob_to_jobid(msg->id);
1039 if (id == -1) {
1040 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1041 goto done;
1045 construct_info_data( &data[data_len], msg->type, msg->field, id );
1047 switch(msg->type) {
1048 case PRINTER_NOTIFY_TYPE:
1049 if ( printer_notify_table[msg->field].fn )
1050 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1051 break;
1053 case JOB_NOTIFY_TYPE:
1054 if ( job_notify_table[msg->field].fn )
1055 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1056 break;
1058 default:
1059 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1060 goto done;
1063 data_len++;
1066 if ( sending_msg_count ) {
1067 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1068 data_len, data, p->notify.change, 0 );
1072 done:
1073 DEBUG(8,("send_notify2_changes: Exit...\n"));
1074 return;
1077 /***********************************************************************
1078 **********************************************************************/
1080 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1083 uint32 tv_sec, tv_usec;
1084 size_t offset = 0;
1086 /* Unpack message */
1088 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1089 msg->printer);
1091 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1092 &tv_sec, &tv_usec,
1093 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1095 if (msg->len == 0)
1096 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1097 &msg->notify.value[0], &msg->notify.value[1]);
1098 else
1099 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1100 &msg->len, &msg->notify.data);
1102 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1103 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1105 tv->tv_sec = tv_sec;
1106 tv->tv_usec = tv_usec;
1108 if (msg->len == 0)
1109 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1110 msg->notify.value[1]));
1111 else
1112 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1114 return True;
1117 /********************************************************************
1118 Receive a notify2 message list
1119 ********************************************************************/
1121 static void receive_notify2_message_list(struct messaging_context *msg,
1122 void *private_data,
1123 uint32_t msg_type,
1124 struct server_id server_id,
1125 DATA_BLOB *data)
1127 size_t msg_count, i;
1128 char *buf = (char *)data->data;
1129 char *msg_ptr;
1130 size_t msg_len;
1131 SPOOLSS_NOTIFY_MSG notify;
1132 SPOOLSS_NOTIFY_MSG_CTR messages;
1133 int num_groups;
1135 if (data->length < 4) {
1136 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1137 return;
1140 msg_count = IVAL(buf, 0);
1141 msg_ptr = buf + 4;
1143 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1145 if (msg_count == 0) {
1146 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1147 return;
1150 /* initialize the container */
1152 ZERO_STRUCT( messages );
1153 notify_msg_ctr_init( &messages );
1156 * build message groups for each printer identified
1157 * in a change_notify msg. Remember that a PCN message
1158 * includes the handle returned for the srv_spoolss_replyopenprinter()
1159 * call. Therefore messages are grouped according to printer handle.
1162 for ( i=0; i<msg_count; i++ ) {
1163 struct timeval msg_tv;
1165 if (msg_ptr + 4 - buf > data->length) {
1166 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1167 return;
1170 msg_len = IVAL(msg_ptr,0);
1171 msg_ptr += 4;
1173 if (msg_ptr + msg_len - buf > data->length) {
1174 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1175 return;
1178 /* unpack messages */
1180 ZERO_STRUCT( notify );
1181 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1182 msg_ptr += msg_len;
1184 /* add to correct list in container */
1186 notify_msg_ctr_addmsg( &messages, &notify );
1188 /* free memory that might have been allocated by notify2_unpack_msg() */
1190 if ( notify.len != 0 )
1191 SAFE_FREE( notify.notify.data );
1194 /* process each group of messages */
1196 num_groups = notify_msg_ctr_numgroups( &messages );
1197 for ( i=0; i<num_groups; i++ )
1198 send_notify2_changes( &messages, i );
1201 /* cleanup */
1203 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1205 notify_msg_ctr_destroy( &messages );
1207 return;
1210 /********************************************************************
1211 Send a message to ourself about new driver being installed
1212 so we can upgrade the information for each printer bound to this
1213 driver
1214 ********************************************************************/
1216 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1218 int len = strlen(drivername);
1220 if (!len)
1221 return False;
1223 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1224 drivername));
1226 messaging_send_buf(smbd_messaging_context(), procid_self(),
1227 MSG_PRINTER_DRVUPGRADE,
1228 (uint8 *)drivername, len+1);
1230 return True;
1233 /**********************************************************************
1234 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1235 over all printers, upgrading ones as necessary
1236 **********************************************************************/
1238 void do_drv_upgrade_printer(struct messaging_context *msg,
1239 void *private_data,
1240 uint32_t msg_type,
1241 struct server_id server_id,
1242 DATA_BLOB *data)
1244 fstring drivername;
1245 int snum;
1246 int n_services = lp_numservices();
1247 size_t len;
1249 len = MIN(data->length,sizeof(drivername)-1);
1250 strncpy(drivername, (const char *)data->data, len);
1252 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1254 /* Iterate the printer list */
1256 for (snum=0; snum<n_services; snum++)
1258 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1260 WERROR result;
1261 NT_PRINTER_INFO_LEVEL *printer = NULL;
1263 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1264 if (!W_ERROR_IS_OK(result))
1265 continue;
1267 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1269 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1271 /* all we care about currently is the change_id */
1273 result = mod_a_printer(printer, 2);
1274 if (!W_ERROR_IS_OK(result)) {
1275 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1276 dos_errstr(result)));
1280 free_a_printer(&printer, 2);
1284 /* all done */
1287 /********************************************************************
1288 Update the cache for all printq's with a registered client
1289 connection
1290 ********************************************************************/
1292 void update_monitored_printq_cache( void )
1294 Printer_entry *printer = printers_list;
1295 int snum;
1297 /* loop through all printers and update the cache where
1298 client_connected == True */
1299 while ( printer )
1301 if ( (printer->printer_type == SPLHND_PRINTER)
1302 && printer->notify.client_connected )
1304 snum = print_queue_snum(printer->sharename);
1305 print_queue_status( snum, NULL, NULL );
1308 printer = printer->next;
1311 return;
1313 /********************************************************************
1314 Send a message to ourself about new driver being installed
1315 so we can upgrade the information for each printer bound to this
1316 driver
1317 ********************************************************************/
1319 static bool srv_spoolss_reset_printerdata(char* drivername)
1321 int len = strlen(drivername);
1323 if (!len)
1324 return False;
1326 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1327 drivername));
1329 messaging_send_buf(smbd_messaging_context(), procid_self(),
1330 MSG_PRINTERDATA_INIT_RESET,
1331 (uint8 *)drivername, len+1);
1333 return True;
1336 /**********************************************************************
1337 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1338 over all printers, resetting printer data as neessary
1339 **********************************************************************/
1341 void reset_all_printerdata(struct messaging_context *msg,
1342 void *private_data,
1343 uint32_t msg_type,
1344 struct server_id server_id,
1345 DATA_BLOB *data)
1347 fstring drivername;
1348 int snum;
1349 int n_services = lp_numservices();
1350 size_t len;
1352 len = MIN( data->length, sizeof(drivername)-1 );
1353 strncpy( drivername, (const char *)data->data, len );
1355 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1357 /* Iterate the printer list */
1359 for ( snum=0; snum<n_services; snum++ )
1361 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1363 WERROR result;
1364 NT_PRINTER_INFO_LEVEL *printer = NULL;
1366 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1367 if ( !W_ERROR_IS_OK(result) )
1368 continue;
1371 * if the printer is bound to the driver,
1372 * then reset to the new driver initdata
1375 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1377 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1379 if ( !set_driver_init(printer, 2) ) {
1380 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1381 printer->info_2->printername, printer->info_2->drivername));
1384 result = mod_a_printer( printer, 2 );
1385 if ( !W_ERROR_IS_OK(result) ) {
1386 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1387 get_dos_error_msg(result)));
1391 free_a_printer( &printer, 2 );
1395 /* all done */
1397 return;
1400 /********************************************************************
1401 Copy routines used by convert_to_openprinterex()
1402 *******************************************************************/
1404 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1406 DEVICEMODE *d;
1407 int len;
1409 if (!devmode)
1410 return NULL;
1412 DEBUG (8,("dup_devmode\n"));
1414 /* bulk copy first */
1416 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1417 if (!d)
1418 return NULL;
1420 /* dup the pointer members separately */
1422 len = unistrlen(devmode->devicename.buffer);
1423 if (len != -1) {
1424 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1425 if (!d->devicename.buffer) {
1426 return NULL;
1428 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1429 return NULL;
1433 len = unistrlen(devmode->formname.buffer);
1434 if (len != -1) {
1435 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1436 if (!d->formname.buffer) {
1437 return NULL;
1439 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1440 return NULL;
1443 if (devmode->driverextra) {
1444 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1445 devmode->driverextra);
1446 if (!d->dev_private) {
1447 return NULL;
1449 } else {
1450 d->dev_private = NULL;
1452 return d;
1455 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1457 if (!new_ctr || !ctr)
1458 return;
1460 DEBUG(8,("copy_devmode_ctr\n"));
1462 new_ctr->size = ctr->size;
1463 new_ctr->devmode_ptr = ctr->devmode_ptr;
1465 if(ctr->devmode_ptr)
1466 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1469 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1471 if (!new_def || !def)
1472 return;
1474 DEBUG(8,("copy_printer_defaults\n"));
1476 new_def->datatype_ptr = def->datatype_ptr;
1478 if (def->datatype_ptr)
1479 copy_unistr2(&new_def->datatype, &def->datatype);
1481 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1483 new_def->access_required = def->access_required;
1486 /********************************************************************
1487 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1488 * SPOOL_Q_OPEN_PRINTER_EX structure
1489 ********************************************************************/
1491 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1493 if (!q_u_ex || !q_u)
1494 return WERR_OK;
1496 DEBUG(8,("convert_to_openprinterex\n"));
1498 if ( q_u->printername ) {
1499 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1500 if (q_u_ex->printername == NULL)
1501 return WERR_NOMEM;
1502 copy_unistr2(q_u_ex->printername, q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1507 return WERR_OK;
1510 /********************************************************************
1511 * spoolss_open_printer
1513 * called from the spoolss dispatcher
1514 ********************************************************************/
1516 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1518 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1519 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1521 if (!q_u || !r_u)
1522 return WERR_NOMEM;
1524 ZERO_STRUCT(q_u_ex);
1525 ZERO_STRUCT(r_u_ex);
1527 /* convert the OpenPrinter() call to OpenPrinterEx() */
1529 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1530 if (!W_ERROR_IS_OK(r_u_ex.status))
1531 return r_u_ex.status;
1533 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1535 /* convert back to OpenPrinter() */
1537 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1539 if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1540 /* OpenPrinterEx returns this for a bad
1541 * printer name. We must return WERR_INVALID_PRINTER_NAME
1542 * instead.
1544 r_u->status = WERR_INVALID_PRINTER_NAME;
1546 return r_u->status;
1549 /********************************************************************
1550 ********************************************************************/
1552 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1554 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1555 POLICY_HND *handle = &r_u->handle;
1557 fstring name;
1558 int snum;
1559 Printer_entry *Printer=NULL;
1561 if (!q_u->printername) {
1562 return WERR_INVALID_PARAM;
1565 /* some sanity check because you can open a printer or a print server */
1566 /* aka: \\server\printer or \\server */
1568 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1570 DEBUGADD(3,("checking name: %s\n",name));
1572 if (!open_printer_hnd(p, handle, name, 0)) {
1573 return WERR_INVALID_PARAM;
1576 Printer=find_printer_index_by_hnd(p, handle);
1577 if ( !Printer ) {
1578 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1579 "handle we created for printer %s\n", name ));
1580 close_printer_handle(p,handle);
1581 return WERR_INVALID_PARAM;
1585 * First case: the user is opening the print server:
1587 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1588 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1590 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1591 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1592 * or if the user is listed in the smb.conf printer admin parameter.
1594 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1595 * client view printer folder, but does not show the MSAPW.
1597 * Note: this test needs code to check access rights here too. Jeremy
1598 * could you look at this?
1600 * Second case: the user is opening a printer:
1601 * NT doesn't let us connect to a printer if the connecting user
1602 * doesn't have print permission.
1604 * Third case: user is opening a Port Monitor
1605 * access checks same as opening a handle to the print server.
1608 switch (Printer->printer_type )
1610 case SPLHND_SERVER:
1611 case SPLHND_PORTMON_TCP:
1612 case SPLHND_PORTMON_LOCAL:
1613 /* Printserver handles use global struct... */
1615 snum = -1;
1617 /* Map standard access rights to object specific access rights */
1619 se_map_standard(&printer_default->access_required,
1620 &printserver_std_mapping);
1622 /* Deny any object specific bits that don't apply to print
1623 servers (i.e printer and job specific bits) */
1625 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1627 if (printer_default->access_required &
1628 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1629 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1630 close_printer_handle(p, handle);
1631 return WERR_ACCESS_DENIED;
1634 /* Allow admin access */
1636 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1638 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1640 if (!lp_ms_add_printer_wizard()) {
1641 close_printer_handle(p, handle);
1642 return WERR_ACCESS_DENIED;
1645 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1646 and not a printer admin, then fail */
1648 if ((p->pipe_user.ut.uid != 0) &&
1649 !user_has_privileges(p->pipe_user.nt_user_token,
1650 &se_printop ) &&
1651 !token_contains_name_in_list(
1652 uidtoname(p->pipe_user.ut.uid), NULL,
1653 p->pipe_user.nt_user_token,
1654 lp_printer_admin(snum))) {
1655 close_printer_handle(p, handle);
1656 return WERR_ACCESS_DENIED;
1659 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1661 else
1663 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1666 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1667 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1669 /* We fall through to return WERR_OK */
1670 break;
1672 case SPLHND_PRINTER:
1673 /* NT doesn't let us connect to a printer if the connecting user
1674 doesn't have print permission. */
1676 if (!get_printer_snum(p, handle, &snum, NULL)) {
1677 close_printer_handle(p, handle);
1678 return WERR_BADFID;
1681 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1683 /* map an empty access mask to the minimum access mask */
1684 if (printer_default->access_required == 0x0)
1685 printer_default->access_required = PRINTER_ACCESS_USE;
1688 * If we are not serving the printer driver for this printer,
1689 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1690 * will keep NT clients happy --jerry
1693 if (lp_use_client_driver(snum)
1694 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1696 printer_default->access_required = PRINTER_ACCESS_USE;
1699 /* check smb.conf parameters and the the sec_desc */
1701 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1702 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1703 return WERR_ACCESS_DENIED;
1706 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1707 p->pipe_user.nt_user_token, snum) ||
1708 !print_access_check(&p->pipe_user, snum,
1709 printer_default->access_required)) {
1710 DEBUG(3, ("access DENIED for printer open\n"));
1711 close_printer_handle(p, handle);
1712 return WERR_ACCESS_DENIED;
1715 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1716 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1717 close_printer_handle(p, handle);
1718 return WERR_ACCESS_DENIED;
1721 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1722 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1723 else
1724 printer_default->access_required = PRINTER_ACCESS_USE;
1726 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1727 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1729 break;
1731 default:
1732 /* sanity check to prevent programmer error */
1733 return WERR_BADFID;
1736 Printer->access_granted = printer_default->access_required;
1739 * If the client sent a devmode in the OpenPrinter() call, then
1740 * save it here in case we get a job submission on this handle
1743 if ( (Printer->printer_type != SPLHND_SERVER)
1744 && q_u->printer_default.devmode_cont.devmode_ptr )
1746 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1747 &Printer->nt_devmode );
1750 #if 0 /* JERRY -- I'm doubtful this is really effective */
1751 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1752 optimization in Windows 2000 clients --jerry */
1754 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1755 && (RA_WIN2K == get_remote_arch()) )
1757 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1758 sys_usleep( 500000 );
1760 #endif
1762 return WERR_OK;
1765 /****************************************************************************
1766 ****************************************************************************/
1768 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1769 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1771 bool ret;
1773 switch (level) {
1774 case 2:
1775 /* allocate memory if needed. Messy because
1776 convert_printer_info is used to update an existing
1777 printer or build a new one */
1779 if ( !printer->info_2 ) {
1780 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1781 if ( !printer->info_2 ) {
1782 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1783 return False;
1787 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1788 printer->info_2->setuptime = time(NULL);
1790 return ret;
1793 return False;
1796 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1797 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1799 bool result = True;
1801 switch (level) {
1802 case 3:
1803 printer->info_3=NULL;
1804 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1805 result = False;
1806 break;
1807 case 6:
1808 printer->info_6=NULL;
1809 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1810 result = False;
1811 break;
1812 default:
1813 break;
1816 return result;
1819 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1820 NT_DEVICEMODE **pp_nt_devmode)
1822 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1825 * Ensure nt_devmode is a valid pointer
1826 * as we will be overwriting it.
1829 if (nt_devmode == NULL) {
1830 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1831 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1832 return False;
1835 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1836 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1838 nt_devmode->specversion=devmode->specversion;
1839 nt_devmode->driverversion=devmode->driverversion;
1840 nt_devmode->size=devmode->size;
1841 nt_devmode->fields=devmode->fields;
1842 nt_devmode->orientation=devmode->orientation;
1843 nt_devmode->papersize=devmode->papersize;
1844 nt_devmode->paperlength=devmode->paperlength;
1845 nt_devmode->paperwidth=devmode->paperwidth;
1846 nt_devmode->scale=devmode->scale;
1847 nt_devmode->copies=devmode->copies;
1848 nt_devmode->defaultsource=devmode->defaultsource;
1849 nt_devmode->printquality=devmode->printquality;
1850 nt_devmode->color=devmode->color;
1851 nt_devmode->duplex=devmode->duplex;
1852 nt_devmode->yresolution=devmode->yresolution;
1853 nt_devmode->ttoption=devmode->ttoption;
1854 nt_devmode->collate=devmode->collate;
1856 nt_devmode->logpixels=devmode->logpixels;
1857 nt_devmode->bitsperpel=devmode->bitsperpel;
1858 nt_devmode->pelswidth=devmode->pelswidth;
1859 nt_devmode->pelsheight=devmode->pelsheight;
1860 nt_devmode->displayflags=devmode->displayflags;
1861 nt_devmode->displayfrequency=devmode->displayfrequency;
1862 nt_devmode->icmmethod=devmode->icmmethod;
1863 nt_devmode->icmintent=devmode->icmintent;
1864 nt_devmode->mediatype=devmode->mediatype;
1865 nt_devmode->dithertype=devmode->dithertype;
1866 nt_devmode->reserved1=devmode->reserved1;
1867 nt_devmode->reserved2=devmode->reserved2;
1868 nt_devmode->panningwidth=devmode->panningwidth;
1869 nt_devmode->panningheight=devmode->panningheight;
1872 * Only change private and driverextra if the incoming devmode
1873 * has a new one. JRA.
1876 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1877 SAFE_FREE(nt_devmode->nt_dev_private);
1878 nt_devmode->driverextra=devmode->driverextra;
1879 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1880 return False;
1881 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1884 *pp_nt_devmode = nt_devmode;
1886 return True;
1889 /********************************************************************
1890 * _spoolss_enddocprinter_internal.
1891 ********************************************************************/
1893 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1896 int snum;
1898 if (!Printer) {
1899 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1900 return WERR_BADFID;
1903 if (!get_printer_snum(p, handle, &snum, NULL))
1904 return WERR_BADFID;
1906 Printer->document_started=False;
1907 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1908 /* error codes unhandled so far ... */
1910 return WERR_OK;
1913 /********************************************************************
1914 * api_spoolss_closeprinter
1915 ********************************************************************/
1917 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1919 POLICY_HND *handle = &q_u->handle;
1921 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1923 if (Printer && Printer->document_started)
1924 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1926 if (!close_printer_handle(p, handle))
1927 return WERR_BADFID;
1929 /* clear the returned printer handle. Observed behavior
1930 from Win2k server. Don't think this really matters.
1931 Previous code just copied the value of the closed
1932 handle. --jerry */
1934 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1936 return WERR_OK;
1939 /********************************************************************
1940 * api_spoolss_deleteprinter
1942 ********************************************************************/
1944 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1946 POLICY_HND *handle = &q_u->handle;
1947 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1948 WERROR result;
1950 if (Printer && Printer->document_started)
1951 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1953 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1955 result = delete_printer_handle(p, handle);
1957 update_c_setprinter(False);
1959 return result;
1962 /*******************************************************************
1963 * static function to lookup the version id corresponding to an
1964 * long architecture string
1965 ******************************************************************/
1967 static int get_version_id (char * arch)
1969 int i;
1970 struct table_node archi_table[]= {
1972 {"Windows 4.0", "WIN40", 0 },
1973 {"Windows NT x86", "W32X86", 2 },
1974 {"Windows NT R4000", "W32MIPS", 2 },
1975 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1976 {"Windows NT PowerPC", "W32PPC", 2 },
1977 {"Windows IA64", "IA64", 3 },
1978 {"Windows x64", "x64", 3 },
1979 {NULL, "", -1 }
1982 for (i=0; archi_table[i].long_archi != NULL; i++)
1984 if (strcmp(arch, archi_table[i].long_archi) == 0)
1985 return (archi_table[i].version);
1988 return -1;
1991 /********************************************************************
1992 * _spoolss_deleteprinterdriver
1993 ********************************************************************/
1995 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1997 fstring driver;
1998 fstring arch;
1999 NT_PRINTER_DRIVER_INFO_LEVEL info;
2000 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2001 int version;
2002 WERROR status;
2003 WERROR status_win2k = WERR_ACCESS_DENIED;
2004 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2006 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2007 and not a printer admin, then fail */
2009 if ( (p->pipe_user.ut.uid != 0)
2010 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2011 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2012 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2014 return WERR_ACCESS_DENIED;
2017 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2018 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2020 /* check that we have a valid driver name first */
2022 if ((version=get_version_id(arch)) == -1)
2023 return WERR_INVALID_ENVIRONMENT;
2025 ZERO_STRUCT(info);
2026 ZERO_STRUCT(info_win2k);
2028 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2030 /* try for Win2k driver if "Windows NT x86" */
2032 if ( version == 2 ) {
2033 version = 3;
2034 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2035 status = WERR_UNKNOWN_PRINTER_DRIVER;
2036 goto done;
2039 /* otherwise it was a failure */
2040 else {
2041 status = WERR_UNKNOWN_PRINTER_DRIVER;
2042 goto done;
2047 if (printer_driver_in_use(info.info_3)) {
2048 status = WERR_PRINTER_DRIVER_IN_USE;
2049 goto done;
2052 if ( version == 2 )
2054 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2056 /* if we get to here, we now have 2 driver info structures to remove */
2057 /* remove the Win2k driver first*/
2059 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2060 free_a_printer_driver( info_win2k, 3 );
2062 /* this should not have failed---if it did, report to client */
2063 if ( !W_ERROR_IS_OK(status_win2k) )
2065 status = status_win2k;
2066 goto done;
2071 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2073 /* if at least one of the deletes succeeded return OK */
2075 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2076 status = WERR_OK;
2078 done:
2079 free_a_printer_driver( info, 3 );
2081 return status;
2084 /********************************************************************
2085 * spoolss_deleteprinterdriverex
2086 ********************************************************************/
2088 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2090 fstring driver;
2091 fstring arch;
2092 NT_PRINTER_DRIVER_INFO_LEVEL info;
2093 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2094 int version;
2095 uint32 flags = q_u->delete_flags;
2096 bool delete_files;
2097 WERROR status;
2098 WERROR status_win2k = WERR_ACCESS_DENIED;
2099 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2101 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2102 and not a printer admin, then fail */
2104 if ( (p->pipe_user.ut.uid != 0)
2105 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2106 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2107 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2109 return WERR_ACCESS_DENIED;
2112 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2113 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2115 /* check that we have a valid driver name first */
2116 if ((version=get_version_id(arch)) == -1) {
2117 /* this is what NT returns */
2118 return WERR_INVALID_ENVIRONMENT;
2121 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2122 version = q_u->version;
2124 ZERO_STRUCT(info);
2125 ZERO_STRUCT(info_win2k);
2127 status = get_a_printer_driver(&info, 3, driver, arch, version);
2129 if ( !W_ERROR_IS_OK(status) )
2132 * if the client asked for a specific version,
2133 * or this is something other than Windows NT x86,
2134 * then we've failed
2137 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2138 goto done;
2140 /* try for Win2k driver if "Windows NT x86" */
2142 version = 3;
2143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2144 status = WERR_UNKNOWN_PRINTER_DRIVER;
2145 goto done;
2149 if ( printer_driver_in_use(info.info_3) ) {
2150 status = WERR_PRINTER_DRIVER_IN_USE;
2151 goto done;
2155 * we have a couple of cases to consider.
2156 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2157 * then the delete should fail if **any** files overlap with
2158 * other drivers
2159 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2160 * non-overlapping files
2161 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2162 * is set, the do not delete any files
2163 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2166 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2168 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2170 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2171 /* no idea of the correct error here */
2172 status = WERR_ACCESS_DENIED;
2173 goto done;
2177 /* also check for W32X86/3 if necessary; maybe we already have? */
2179 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2180 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2183 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2184 /* no idea of the correct error here */
2185 free_a_printer_driver( info_win2k, 3 );
2186 status = WERR_ACCESS_DENIED;
2187 goto done;
2190 /* if we get to here, we now have 2 driver info structures to remove */
2191 /* remove the Win2k driver first*/
2193 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2194 free_a_printer_driver( info_win2k, 3 );
2196 /* this should not have failed---if it did, report to client */
2198 if ( !W_ERROR_IS_OK(status_win2k) )
2199 goto done;
2203 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2205 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2206 status = WERR_OK;
2207 done:
2208 free_a_printer_driver( info, 3 );
2210 return status;
2214 /****************************************************************************
2215 Internal routine for retreiving printerdata
2216 ***************************************************************************/
2218 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2219 const char *key, const char *value, uint32 *type, uint8 **data,
2220 uint32 *needed, uint32 in_size )
2222 REGISTRY_VALUE *val;
2223 uint32 size;
2224 int data_len;
2226 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2227 return WERR_BADFILE;
2229 *type = regval_type( val );
2231 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2233 size = regval_size( val );
2235 /* copy the min(in_size, len) */
2237 if ( in_size ) {
2238 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2240 /* special case for 0 length values */
2241 if ( data_len ) {
2242 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2243 return WERR_NOMEM;
2245 else {
2246 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2247 return WERR_NOMEM;
2250 else
2251 *data = NULL;
2253 *needed = size;
2255 DEBUG(5,("get_printer_dataex: copy done\n"));
2257 return WERR_OK;
2260 /****************************************************************************
2261 Internal routine for removing printerdata
2262 ***************************************************************************/
2264 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2266 return delete_printer_data( printer->info_2, key, value );
2269 /****************************************************************************
2270 Internal routine for storing printerdata
2271 ***************************************************************************/
2273 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2274 uint32 type, uint8 *data, int real_len )
2276 /* the registry objects enforce uniqueness based on value name */
2278 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2281 /********************************************************************
2282 GetPrinterData on a printer server Handle.
2283 ********************************************************************/
2285 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2287 int i;
2289 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2291 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2292 *type = REG_DWORD;
2293 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2294 return WERR_NOMEM;
2295 SIVAL(*data, 0, 0x00);
2296 *needed = 0x4;
2297 return WERR_OK;
2300 if (!StrCaseCmp(value, "BeepEnabled")) {
2301 *type = REG_DWORD;
2302 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2303 return WERR_NOMEM;
2304 SIVAL(*data, 0, 0x00);
2305 *needed = 0x4;
2306 return WERR_OK;
2309 if (!StrCaseCmp(value, "EventLog")) {
2310 *type = REG_DWORD;
2311 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2312 return WERR_NOMEM;
2313 /* formally was 0x1b */
2314 SIVAL(*data, 0, 0x0);
2315 *needed = 0x4;
2316 return WERR_OK;
2319 if (!StrCaseCmp(value, "NetPopup")) {
2320 *type = REG_DWORD;
2321 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2322 return WERR_NOMEM;
2323 SIVAL(*data, 0, 0x00);
2324 *needed = 0x4;
2325 return WERR_OK;
2328 if (!StrCaseCmp(value, "MajorVersion")) {
2329 *type = REG_DWORD;
2330 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2331 return WERR_NOMEM;
2333 /* Windows NT 4.0 seems to not allow uploading of drivers
2334 to a server that reports 0x3 as the MajorVersion.
2335 need to investigate more how Win2k gets around this .
2336 -- jerry */
2338 if ( RA_WINNT == get_remote_arch() )
2339 SIVAL(*data, 0, 2);
2340 else
2341 SIVAL(*data, 0, 3);
2343 *needed = 0x4;
2344 return WERR_OK;
2347 if (!StrCaseCmp(value, "MinorVersion")) {
2348 *type = REG_DWORD;
2349 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2350 return WERR_NOMEM;
2351 SIVAL(*data, 0, 0);
2352 *needed = 0x4;
2353 return WERR_OK;
2356 /* REG_BINARY
2357 * uint32 size = 0x114
2358 * uint32 major = 5
2359 * uint32 minor = [0|1]
2360 * uint32 build = [2195|2600]
2361 * extra unicode string = e.g. "Service Pack 3"
2363 if (!StrCaseCmp(value, "OSVersion")) {
2364 *type = REG_BINARY;
2365 *needed = 0x114;
2367 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2368 return WERR_NOMEM;
2370 SIVAL(*data, 0, *needed); /* size */
2371 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2372 SIVAL(*data, 8, 0);
2373 SIVAL(*data, 12, 2195); /* build */
2375 /* leave extra string empty */
2377 return WERR_OK;
2381 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2382 const char *string="C:\\PRINTERS";
2383 *type = REG_SZ;
2384 *needed = 2*(strlen(string)+1);
2385 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2386 return WERR_NOMEM;
2387 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 /* it's done by hand ready to go on the wire */
2390 for (i=0; i<strlen(string); i++) {
2391 (*data)[2*i]=string[i];
2392 (*data)[2*i+1]='\0';
2394 return WERR_OK;
2397 if (!StrCaseCmp(value, "Architecture")) {
2398 const char *string="Windows NT x86";
2399 *type = REG_SZ;
2400 *needed = 2*(strlen(string)+1);
2401 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2402 return WERR_NOMEM;
2403 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 for (i=0; i<strlen(string); i++) {
2405 (*data)[2*i]=string[i];
2406 (*data)[2*i+1]='\0';
2408 return WERR_OK;
2411 if (!StrCaseCmp(value, "DsPresent")) {
2412 *type = REG_DWORD;
2413 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2414 return WERR_NOMEM;
2416 /* only show the publish check box if we are a
2417 memeber of a AD domain */
2419 if ( lp_security() == SEC_ADS )
2420 SIVAL(*data, 0, 0x01);
2421 else
2422 SIVAL(*data, 0, 0x00);
2424 *needed = 0x4;
2425 return WERR_OK;
2428 if (!StrCaseCmp(value, "DNSMachineName")) {
2429 const char *hostname = get_mydnsfullname();
2431 if (!hostname)
2432 return WERR_BADFILE;
2433 *type = REG_SZ;
2434 *needed = 2*(strlen(hostname)+1);
2435 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2436 return WERR_NOMEM;
2437 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2438 for (i=0; i<strlen(hostname); i++) {
2439 (*data)[2*i]=hostname[i];
2440 (*data)[2*i+1]='\0';
2442 return WERR_OK;
2446 return WERR_BADFILE;
2449 /********************************************************************
2450 * spoolss_getprinterdata
2451 ********************************************************************/
2453 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2455 POLICY_HND *handle = &q_u->handle;
2456 UNISTR2 *valuename = &q_u->valuename;
2457 uint32 in_size = q_u->size;
2458 uint32 *type = &r_u->type;
2459 uint32 *out_size = &r_u->size;
2460 uint8 **data = &r_u->data;
2461 uint32 *needed = &r_u->needed;
2462 WERROR status;
2463 fstring value;
2464 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2465 NT_PRINTER_INFO_LEVEL *printer = NULL;
2466 int snum = 0;
2469 * Reminder: when it's a string, the length is in BYTES
2470 * even if UNICODE is negociated.
2472 * JFM, 4/19/1999
2475 *out_size = in_size;
2477 /* in case of problem, return some default values */
2479 *needed = 0;
2480 *type = 0;
2482 DEBUG(4,("_spoolss_getprinterdata\n"));
2484 if ( !Printer ) {
2485 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2486 status = WERR_BADFID;
2487 goto done;
2490 unistr2_to_ascii(value, valuename, sizeof(value));
2492 if ( Printer->printer_type == SPLHND_SERVER )
2493 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2494 else
2496 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2497 status = WERR_BADFID;
2498 goto done;
2501 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2502 if ( !W_ERROR_IS_OK(status) )
2503 goto done;
2505 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2507 if ( strequal(value, "ChangeId") ) {
2508 *type = REG_DWORD;
2509 *needed = sizeof(uint32);
2510 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2511 status = WERR_NOMEM;
2512 goto done;
2514 SIVAL( *data, 0, printer->info_2->changeid );
2515 status = WERR_OK;
2517 else
2518 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2521 if (*needed > *out_size)
2522 status = WERR_MORE_DATA;
2524 done:
2525 if ( !W_ERROR_IS_OK(status) )
2527 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2529 /* reply this param doesn't exist */
2531 if ( *out_size ) {
2532 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2533 if ( printer )
2534 free_a_printer( &printer, 2 );
2535 return WERR_NOMEM;
2537 } else {
2538 *data = NULL;
2542 /* cleanup & exit */
2544 if ( printer )
2545 free_a_printer( &printer, 2 );
2547 return status;
2550 /*********************************************************
2551 Connect to the client machine.
2552 **********************************************************/
2554 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2555 struct sockaddr_storage *client_ss, const char *remote_machine)
2557 NTSTATUS ret;
2558 struct cli_state *the_cli;
2559 struct sockaddr_storage rm_addr;
2561 if ( is_zero_addr(client_ss) ) {
2562 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2563 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2564 return False;
2567 if (ismyaddr(&rm_addr)) {
2568 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2569 return False;
2571 } else {
2572 char addr[INET6_ADDRSTRLEN];
2573 rm_addr = *client_ss;
2574 print_sockaddr(addr, sizeof(addr), &rm_addr);
2575 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2576 addr));
2579 /* setup the connection */
2581 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2582 &rm_addr, 0, "IPC$", "IPC",
2583 "", /* username */
2584 "", /* domain */
2585 "", /* password */
2586 0, lp_client_signing(), NULL );
2588 if ( !NT_STATUS_IS_OK( ret ) ) {
2589 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2590 remote_machine ));
2591 return False;
2594 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2595 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2596 cli_shutdown(the_cli);
2597 return False;
2601 * Ok - we have an anonymous connection to the IPC$ share.
2602 * Now start the NT Domain stuff :-).
2605 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2606 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2607 remote_machine, nt_errstr(ret)));
2608 cli_shutdown(the_cli);
2609 return False;
2612 return True;
2615 /***************************************************************************
2616 Connect to the client.
2617 ****************************************************************************/
2619 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2620 uint32 localprinter, uint32 type,
2621 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2623 WERROR result;
2626 * If it's the first connection, contact the client
2627 * and connect to the IPC$ share anonymously
2629 if (smb_connections==0) {
2630 fstring unix_printer;
2632 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2634 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2635 return False;
2637 messaging_register(smbd_messaging_context(), NULL,
2638 MSG_PRINTER_NOTIFY2,
2639 receive_notify2_message_list);
2640 /* Tell the connections db we're now interested in printer
2641 * notify messages. */
2642 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2646 * Tell the specific printing tdb we want messages for this printer
2647 * by registering our PID.
2650 if (!print_notify_register_pid(snum))
2651 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2653 smb_connections++;
2655 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2656 talloc_tos(),
2657 printer,
2658 localprinter,
2659 type,
2660 handle);
2662 if (!W_ERROR_IS_OK(result))
2663 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2664 dos_errstr(result)));
2666 return (W_ERROR_IS_OK(result));
2669 /********************************************************************
2670 * _spoolss_rffpcnex
2671 * ReplyFindFirstPrinterChangeNotifyEx
2673 * before replying OK: status=0 a rpc call is made to the workstation
2674 * asking ReplyOpenPrinter
2676 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2677 * called from api_spoolss_rffpcnex
2678 ********************************************************************/
2680 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2682 POLICY_HND *handle = &q_u->handle;
2683 uint32 flags = q_u->flags;
2684 uint32 options = q_u->options;
2685 UNISTR2 *localmachine = &q_u->localmachine;
2686 uint32 printerlocal = q_u->printerlocal;
2687 int snum = -1;
2688 SPOOL_NOTIFY_OPTION *option = q_u->option;
2689 struct sockaddr_storage client_ss;
2691 /* store the notify value in the printer struct */
2693 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2695 if (!Printer) {
2696 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2697 return WERR_BADFID;
2700 Printer->notify.flags=flags;
2701 Printer->notify.options=options;
2702 Printer->notify.printerlocal=printerlocal;
2704 if (Printer->notify.option)
2705 free_spool_notify_option(&Printer->notify.option);
2707 Printer->notify.option=dup_spool_notify_option(option);
2709 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2710 sizeof(Printer->notify.localmachine));
2712 /* Connect to the client machine and send a ReplyOpenPrinter */
2714 if ( Printer->printer_type == SPLHND_SERVER)
2715 snum = -1;
2716 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2717 !get_printer_snum(p, handle, &snum, NULL) )
2718 return WERR_BADFID;
2720 if (!interpret_string_addr(&client_ss,
2721 p->conn->client_address,
2722 AI_NUMERICHOST)) {
2723 return WERR_SERVER_UNAVAILABLE;
2726 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2727 Printer->notify.printerlocal, 1,
2728 &Printer->notify.client_hnd, &client_ss))
2729 return WERR_SERVER_UNAVAILABLE;
2731 Printer->notify.client_connected=True;
2733 return WERR_OK;
2736 /*******************************************************************
2737 * fill a notify_info_data with the servername
2738 ********************************************************************/
2740 void spoolss_notify_server_name(int snum,
2741 SPOOL_NOTIFY_INFO_DATA *data,
2742 print_queue_struct *queue,
2743 NT_PRINTER_INFO_LEVEL *printer,
2744 TALLOC_CTX *mem_ctx)
2746 smb_ucs2_t *temp = NULL;
2747 uint32 len;
2749 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2750 if (len == (uint32)-1) {
2751 len = 0;
2754 data->notify_data.data.length = len;
2755 if (len) {
2756 data->notify_data.data.string = (uint16 *)temp;
2757 } else {
2758 data->notify_data.data.string = NULL;
2762 /*******************************************************************
2763 * fill a notify_info_data with the printername (not including the servername).
2764 ********************************************************************/
2766 void spoolss_notify_printer_name(int snum,
2767 SPOOL_NOTIFY_INFO_DATA *data,
2768 print_queue_struct *queue,
2769 NT_PRINTER_INFO_LEVEL *printer,
2770 TALLOC_CTX *mem_ctx)
2772 smb_ucs2_t *temp = NULL;
2773 uint32 len;
2775 /* the notify name should not contain the \\server\ part */
2776 char *p = strrchr(printer->info_2->printername, '\\');
2778 if (!p) {
2779 p = printer->info_2->printername;
2780 } else {
2781 p++;
2784 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2785 if (len == (uint32)-1) {
2786 len = 0;
2789 data->notify_data.data.length = len;
2790 if (len) {
2791 data->notify_data.data.string = (uint16 *)temp;
2792 } else {
2793 data->notify_data.data.string = NULL;
2797 /*******************************************************************
2798 * fill a notify_info_data with the servicename
2799 ********************************************************************/
2801 void spoolss_notify_share_name(int snum,
2802 SPOOL_NOTIFY_INFO_DATA *data,
2803 print_queue_struct *queue,
2804 NT_PRINTER_INFO_LEVEL *printer,
2805 TALLOC_CTX *mem_ctx)
2807 smb_ucs2_t *temp = NULL;
2808 uint32 len;
2810 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2811 if (len == (uint32)-1) {
2812 len = 0;
2815 data->notify_data.data.length = len;
2816 if (len) {
2817 data->notify_data.data.string = (uint16 *)temp;
2818 } else {
2819 data->notify_data.data.string = NULL;
2824 /*******************************************************************
2825 * fill a notify_info_data with the port name
2826 ********************************************************************/
2828 void spoolss_notify_port_name(int snum,
2829 SPOOL_NOTIFY_INFO_DATA *data,
2830 print_queue_struct *queue,
2831 NT_PRINTER_INFO_LEVEL *printer,
2832 TALLOC_CTX *mem_ctx)
2834 smb_ucs2_t *temp = NULL;
2835 uint32 len;
2837 /* even if it's strange, that's consistant in all the code */
2839 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2840 if (len == (uint32)-1) {
2841 len = 0;
2844 data->notify_data.data.length = len;
2845 if (len) {
2846 data->notify_data.data.string = (uint16 *)temp;
2847 } else {
2848 data->notify_data.data.string = NULL;
2852 /*******************************************************************
2853 * fill a notify_info_data with the printername
2854 * but it doesn't exist, have to see what to do
2855 ********************************************************************/
2857 void spoolss_notify_driver_name(int snum,
2858 SPOOL_NOTIFY_INFO_DATA *data,
2859 print_queue_struct *queue,
2860 NT_PRINTER_INFO_LEVEL *printer,
2861 TALLOC_CTX *mem_ctx)
2863 smb_ucs2_t *temp = NULL;
2864 uint32 len;
2866 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2867 if (len == (uint32)-1) {
2868 len = 0;
2871 data->notify_data.data.length = len;
2872 if (len) {
2873 data->notify_data.data.string = (uint16 *)temp;
2874 } else {
2875 data->notify_data.data.string = NULL;
2879 /*******************************************************************
2880 * fill a notify_info_data with the comment
2881 ********************************************************************/
2883 void spoolss_notify_comment(int snum,
2884 SPOOL_NOTIFY_INFO_DATA *data,
2885 print_queue_struct *queue,
2886 NT_PRINTER_INFO_LEVEL *printer,
2887 TALLOC_CTX *mem_ctx)
2889 smb_ucs2_t *temp = NULL;
2890 uint32 len;
2892 if (*printer->info_2->comment == '\0')
2893 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2894 else
2895 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2897 if (len == (uint32)-1) {
2898 len = 0;
2900 data->notify_data.data.length = len;
2901 if (len) {
2902 data->notify_data.data.string = (uint16 *)temp;
2903 } else {
2904 data->notify_data.data.string = NULL;
2908 /*******************************************************************
2909 * fill a notify_info_data with the comment
2910 * location = "Room 1, floor 2, building 3"
2911 ********************************************************************/
2913 void spoolss_notify_location(int snum,
2914 SPOOL_NOTIFY_INFO_DATA *data,
2915 print_queue_struct *queue,
2916 NT_PRINTER_INFO_LEVEL *printer,
2917 TALLOC_CTX *mem_ctx)
2919 smb_ucs2_t *temp = NULL;
2920 uint32 len;
2922 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2923 if (len == (uint32)-1) {
2924 len = 0;
2927 data->notify_data.data.length = len;
2928 if (len) {
2929 data->notify_data.data.string = (uint16 *)temp;
2930 } else {
2931 data->notify_data.data.string = NULL;
2935 /*******************************************************************
2936 * fill a notify_info_data with the device mode
2937 * jfm:xxxx don't to it for know but that's a real problem !!!
2938 ********************************************************************/
2940 static void spoolss_notify_devmode(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2946 /* for a dummy implementation we have to zero the fields */
2947 data->notify_data.data.length = 0;
2948 data->notify_data.data.string = NULL;
2951 /*******************************************************************
2952 * fill a notify_info_data with the separator file name
2953 ********************************************************************/
2955 void spoolss_notify_sepfile(int snum,
2956 SPOOL_NOTIFY_INFO_DATA *data,
2957 print_queue_struct *queue,
2958 NT_PRINTER_INFO_LEVEL *printer,
2959 TALLOC_CTX *mem_ctx)
2961 smb_ucs2_t *temp = NULL;
2962 uint32 len;
2964 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2965 if (len == (uint32)-1) {
2966 len = 0;
2969 data->notify_data.data.length = len;
2970 if (len) {
2971 data->notify_data.data.string = (uint16 *)temp;
2972 } else {
2973 data->notify_data.data.string = NULL;
2977 /*******************************************************************
2978 * fill a notify_info_data with the print processor
2979 * jfm:xxxx return always winprint to indicate we don't do anything to it
2980 ********************************************************************/
2982 void spoolss_notify_print_processor(int snum,
2983 SPOOL_NOTIFY_INFO_DATA *data,
2984 print_queue_struct *queue,
2985 NT_PRINTER_INFO_LEVEL *printer,
2986 TALLOC_CTX *mem_ctx)
2988 smb_ucs2_t *temp = NULL;
2989 uint32 len;
2991 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2992 if (len == (uint32)-1) {
2993 len = 0;
2996 data->notify_data.data.length = len;
2997 if (len) {
2998 data->notify_data.data.string = (uint16 *)temp;
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 smb_ucs2_t *temp = NULL;
3016 uint32 len;
3018 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3019 if (len == (uint32)-1) {
3020 len = 0;
3023 data->notify_data.data.length = len;
3024 if (len) {
3025 data->notify_data.data.string = (uint16 *)temp;
3026 } else {
3027 data->notify_data.data.string = NULL;
3031 /*******************************************************************
3032 * fill a notify_info_data with the data type
3033 * jfm:xxxx always send RAW as data type
3034 ********************************************************************/
3036 void spoolss_notify_datatype(int snum,
3037 SPOOL_NOTIFY_INFO_DATA *data,
3038 print_queue_struct *queue,
3039 NT_PRINTER_INFO_LEVEL *printer,
3040 TALLOC_CTX *mem_ctx)
3042 smb_ucs2_t *temp = NULL;
3043 uint32 len;
3045 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3046 if (len == (uint32)-1) {
3047 len = 0;
3050 data->notify_data.data.length = len;
3051 if (len) {
3052 data->notify_data.data.string = (uint16 *)temp;
3053 } else {
3054 data->notify_data.data.string = NULL;
3058 /*******************************************************************
3059 * fill a notify_info_data with the security descriptor
3060 * jfm:xxxx send an null pointer to say no security desc
3061 * have to implement security before !
3062 ********************************************************************/
3064 static void spoolss_notify_security_desc(int snum,
3065 SPOOL_NOTIFY_INFO_DATA *data,
3066 print_queue_struct *queue,
3067 NT_PRINTER_INFO_LEVEL *printer,
3068 TALLOC_CTX *mem_ctx)
3070 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3071 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3074 /*******************************************************************
3075 * fill a notify_info_data with the attributes
3076 * jfm:xxxx a samba printer is always shared
3077 ********************************************************************/
3079 void spoolss_notify_attributes(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.value[0] = printer->info_2->attributes;
3086 data->notify_data.value[1] = 0;
3089 /*******************************************************************
3090 * fill a notify_info_data with the priority
3091 ********************************************************************/
3093 static void spoolss_notify_priority(int snum,
3094 SPOOL_NOTIFY_INFO_DATA *data,
3095 print_queue_struct *queue,
3096 NT_PRINTER_INFO_LEVEL *printer,
3097 TALLOC_CTX *mem_ctx)
3099 data->notify_data.value[0] = printer->info_2->priority;
3100 data->notify_data.value[1] = 0;
3103 /*******************************************************************
3104 * fill a notify_info_data with the default priority
3105 ********************************************************************/
3107 static void spoolss_notify_default_priority(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 data->notify_data.value[0] = printer->info_2->default_priority;
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the start time
3119 ********************************************************************/
3121 static void spoolss_notify_start_time(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0] = printer->info_2->starttime;
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the until time
3133 ********************************************************************/
3135 static void spoolss_notify_until_time(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 data->notify_data.value[0] = printer->info_2->untiltime;
3142 data->notify_data.value[1] = 0;
3145 /*******************************************************************
3146 * fill a notify_info_data with the status
3147 ********************************************************************/
3149 static void spoolss_notify_status(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3155 print_status_struct status;
3157 print_queue_length(snum, &status);
3158 data->notify_data.value[0]=(uint32) status.status;
3159 data->notify_data.value[1] = 0;
3162 /*******************************************************************
3163 * fill a notify_info_data with the number of jobs queued
3164 ********************************************************************/
3166 void spoolss_notify_cjobs(int snum,
3167 SPOOL_NOTIFY_INFO_DATA *data,
3168 print_queue_struct *queue,
3169 NT_PRINTER_INFO_LEVEL *printer,
3170 TALLOC_CTX *mem_ctx)
3172 data->notify_data.value[0] = print_queue_length(snum, NULL);
3173 data->notify_data.value[1] = 0;
3176 /*******************************************************************
3177 * fill a notify_info_data with the average ppm
3178 ********************************************************************/
3180 static void spoolss_notify_average_ppm(int snum,
3181 SPOOL_NOTIFY_INFO_DATA *data,
3182 print_queue_struct *queue,
3183 NT_PRINTER_INFO_LEVEL *printer,
3184 TALLOC_CTX *mem_ctx)
3186 /* always respond 8 pages per minutes */
3187 /* a little hard ! */
3188 data->notify_data.value[0] = printer->info_2->averageppm;
3189 data->notify_data.value[1] = 0;
3192 /*******************************************************************
3193 * fill a notify_info_data with username
3194 ********************************************************************/
3196 static void spoolss_notify_username(int snum,
3197 SPOOL_NOTIFY_INFO_DATA *data,
3198 print_queue_struct *queue,
3199 NT_PRINTER_INFO_LEVEL *printer,
3200 TALLOC_CTX *mem_ctx)
3202 smb_ucs2_t *temp = NULL;
3203 uint32 len;
3205 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3206 if (len == (uint32)-1) {
3207 len = 0;
3210 data->notify_data.data.length = len;
3211 if (len) {
3212 data->notify_data.data.string = (uint16 *)temp;
3213 } else {
3214 data->notify_data.data.string = NULL;
3218 /*******************************************************************
3219 * fill a notify_info_data with job status
3220 ********************************************************************/
3222 static void spoolss_notify_job_status(int snum,
3223 SPOOL_NOTIFY_INFO_DATA *data,
3224 print_queue_struct *queue,
3225 NT_PRINTER_INFO_LEVEL *printer,
3226 TALLOC_CTX *mem_ctx)
3228 data->notify_data.value[0]=nt_printj_status(queue->status);
3229 data->notify_data.value[1] = 0;
3232 /*******************************************************************
3233 * fill a notify_info_data with job name
3234 ********************************************************************/
3236 static void spoolss_notify_job_name(int snum,
3237 SPOOL_NOTIFY_INFO_DATA *data,
3238 print_queue_struct *queue,
3239 NT_PRINTER_INFO_LEVEL *printer,
3240 TALLOC_CTX *mem_ctx)
3242 smb_ucs2_t *temp = NULL;
3243 uint32 len;
3245 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3246 if (len == (uint32)-1) {
3247 len = 0;
3250 data->notify_data.data.length = len;
3251 if (len) {
3252 data->notify_data.data.string = (uint16 *)temp;
3253 } else {
3254 data->notify_data.data.string = NULL;
3258 /*******************************************************************
3259 * fill a notify_info_data with job status
3260 ********************************************************************/
3262 static void spoolss_notify_job_status_string(int snum,
3263 SPOOL_NOTIFY_INFO_DATA *data,
3264 print_queue_struct *queue,
3265 NT_PRINTER_INFO_LEVEL *printer,
3266 TALLOC_CTX *mem_ctx)
3269 * Now we're returning job status codes we just return a "" here. JRA.
3272 const char *p = "";
3273 smb_ucs2_t *temp = NULL;
3274 uint32 len;
3276 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3277 p = "unknown";
3279 switch (queue->status) {
3280 case LPQ_QUEUED:
3281 p = "Queued";
3282 break;
3283 case LPQ_PAUSED:
3284 p = ""; /* NT provides the paused string */
3285 break;
3286 case LPQ_SPOOLING:
3287 p = "Spooling";
3288 break;
3289 case LPQ_PRINTING:
3290 p = "Printing";
3291 break;
3293 #endif /* NO LONGER NEEDED. */
3295 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3296 if (len == (uint32)-1) {
3297 len = 0;
3300 data->notify_data.data.length = len;
3301 if (len) {
3302 data->notify_data.data.string = (uint16 *)temp;
3303 } else {
3304 data->notify_data.data.string = NULL;
3308 /*******************************************************************
3309 * fill a notify_info_data with job time
3310 ********************************************************************/
3312 static void spoolss_notify_job_time(int snum,
3313 SPOOL_NOTIFY_INFO_DATA *data,
3314 print_queue_struct *queue,
3315 NT_PRINTER_INFO_LEVEL *printer,
3316 TALLOC_CTX *mem_ctx)
3318 data->notify_data.value[0]=0x0;
3319 data->notify_data.value[1]=0;
3322 /*******************************************************************
3323 * fill a notify_info_data with job size
3324 ********************************************************************/
3326 static void spoolss_notify_job_size(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3332 data->notify_data.value[0]=queue->size;
3333 data->notify_data.value[1]=0;
3336 /*******************************************************************
3337 * fill a notify_info_data with page info
3338 ********************************************************************/
3339 static void spoolss_notify_total_pages(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=queue->page_count;
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 * fill a notify_info_data with pages printed info.
3351 ********************************************************************/
3352 static void spoolss_notify_pages_printed(int snum,
3353 SPOOL_NOTIFY_INFO_DATA *data,
3354 print_queue_struct *queue,
3355 NT_PRINTER_INFO_LEVEL *printer,
3356 TALLOC_CTX *mem_ctx)
3358 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3359 data->notify_data.value[1]=0;
3362 /*******************************************************************
3363 Fill a notify_info_data with job position.
3364 ********************************************************************/
3366 static void spoolss_notify_job_position(int snum,
3367 SPOOL_NOTIFY_INFO_DATA *data,
3368 print_queue_struct *queue,
3369 NT_PRINTER_INFO_LEVEL *printer,
3370 TALLOC_CTX *mem_ctx)
3372 data->notify_data.value[0]=queue->job;
3373 data->notify_data.value[1]=0;
3376 /*******************************************************************
3377 Fill a notify_info_data with submitted time.
3378 ********************************************************************/
3380 static void spoolss_notify_submitted_time(int snum,
3381 SPOOL_NOTIFY_INFO_DATA *data,
3382 print_queue_struct *queue,
3383 NT_PRINTER_INFO_LEVEL *printer,
3384 TALLOC_CTX *mem_ctx)
3386 struct tm *t;
3387 uint32 len;
3388 SYSTEMTIME st;
3389 char *p;
3391 t=gmtime(&queue->time);
3393 len = sizeof(SYSTEMTIME);
3395 data->notify_data.data.length = len;
3396 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3398 if (!data->notify_data.data.string) {
3399 data->notify_data.data.length = 0;
3400 return;
3403 make_systemtime(&st, t);
3406 * Systemtime must be linearized as a set of UINT16's.
3407 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3410 p = (char *)data->notify_data.data.string;
3411 SSVAL(p, 0, st.year);
3412 SSVAL(p, 2, st.month);
3413 SSVAL(p, 4, st.dayofweek);
3414 SSVAL(p, 6, st.day);
3415 SSVAL(p, 8, st.hour);
3416 SSVAL(p, 10, st.minute);
3417 SSVAL(p, 12, st.second);
3418 SSVAL(p, 14, st.milliseconds);
3421 struct s_notify_info_data_table
3423 uint16 type;
3424 uint16 field;
3425 const char *name;
3426 uint32 size;
3427 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3428 print_queue_struct *queue,
3429 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3432 /* A table describing the various print notification constants and
3433 whether the notification data is a pointer to a variable sized
3434 buffer, a one value uint32 or a two value uint32. */
3436 static const struct s_notify_info_data_table notify_info_data_table[] =
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3487 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3490 /*******************************************************************
3491 Return the size of info_data structure.
3492 ********************************************************************/
3494 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3496 int i=0;
3498 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3499 if ( (notify_info_data_table[i].type == type)
3500 && (notify_info_data_table[i].field == field) ) {
3501 switch(notify_info_data_table[i].size) {
3502 case NOTIFY_ONE_VALUE:
3503 case NOTIFY_TWO_VALUE:
3504 return 1;
3505 case NOTIFY_STRING:
3506 return 2;
3508 /* The only pointer notify data I have seen on
3509 the wire is the submitted time and this has
3510 the notify size set to 4. -tpot */
3512 case NOTIFY_POINTER:
3513 return 4;
3515 case NOTIFY_SECDESC:
3516 return 5;
3521 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3523 return 0;
3526 /*******************************************************************
3527 Return the type of notify_info_data.
3528 ********************************************************************/
3530 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3532 uint32 i=0;
3534 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3535 if (notify_info_data_table[i].type == type &&
3536 notify_info_data_table[i].field == field)
3537 return notify_info_data_table[i].size;
3540 return 0;
3543 /****************************************************************************
3544 ****************************************************************************/
3546 static bool search_notify(uint16 type, uint16 field, int *value)
3548 int i;
3550 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3551 if (notify_info_data_table[i].type == type &&
3552 notify_info_data_table[i].field == field &&
3553 notify_info_data_table[i].fn != NULL) {
3554 *value = i;
3555 return True;
3559 return False;
3562 /****************************************************************************
3563 ****************************************************************************/
3565 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3567 info_data->type = type;
3568 info_data->field = field;
3569 info_data->reserved = 0;
3571 info_data->size = size_of_notify_info_data(type, field);
3572 info_data->enc_type = type_of_notify_info_data(type, field);
3574 info_data->id = id;
3577 /*******************************************************************
3579 * fill a notify_info struct with info asked
3581 ********************************************************************/
3583 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3584 snum, SPOOL_NOTIFY_OPTION_TYPE
3585 *option_type, uint32 id,
3586 TALLOC_CTX *mem_ctx)
3588 int field_num,j;
3589 uint16 type;
3590 uint16 field;
3592 SPOOL_NOTIFY_INFO_DATA *current_data;
3593 NT_PRINTER_INFO_LEVEL *printer = NULL;
3594 print_queue_struct *queue=NULL;
3596 type=option_type->type;
3598 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3599 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3600 option_type->count, lp_servicename(snum)));
3602 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3603 return False;
3605 for(field_num=0; field_num<option_type->count; field_num++) {
3606 field = option_type->fields[field_num];
3608 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3610 if (!search_notify(type, field, &j) )
3611 continue;
3613 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3614 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3615 free_a_printer(&printer, 2);
3616 return False;
3619 current_data = &info->data[info->count];
3621 construct_info_data(current_data, type, field, id);
3623 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3624 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3626 notify_info_data_table[j].fn(snum, current_data, queue,
3627 printer, mem_ctx);
3629 info->count++;
3632 free_a_printer(&printer, 2);
3633 return True;
3636 /*******************************************************************
3638 * fill a notify_info struct with info asked
3640 ********************************************************************/
3642 static bool construct_notify_jobs_info(print_queue_struct *queue,
3643 SPOOL_NOTIFY_INFO *info,
3644 NT_PRINTER_INFO_LEVEL *printer,
3645 int snum, SPOOL_NOTIFY_OPTION_TYPE
3646 *option_type, uint32 id,
3647 TALLOC_CTX *mem_ctx)
3649 int field_num,j;
3650 uint16 type;
3651 uint16 field;
3653 SPOOL_NOTIFY_INFO_DATA *current_data;
3655 DEBUG(4,("construct_notify_jobs_info\n"));
3657 type = option_type->type;
3659 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3660 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3661 option_type->count));
3663 for(field_num=0; field_num<option_type->count; field_num++) {
3664 field = option_type->fields[field_num];
3666 if (!search_notify(type, field, &j) )
3667 continue;
3669 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3670 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3671 return False;
3674 current_data=&(info->data[info->count]);
3676 construct_info_data(current_data, type, field, id);
3677 notify_info_data_table[j].fn(snum, current_data, queue,
3678 printer, mem_ctx);
3679 info->count++;
3682 return True;
3686 * JFM: The enumeration is not that simple, it's even non obvious.
3688 * let's take an example: I want to monitor the PRINTER SERVER for
3689 * the printer's name and the number of jobs currently queued.
3690 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3691 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3693 * I have 3 printers on the back of my server.
3695 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3696 * structures.
3697 * Number Data Id
3698 * 1 printer 1 name 1
3699 * 2 printer 1 cjob 1
3700 * 3 printer 2 name 2
3701 * 4 printer 2 cjob 2
3702 * 5 printer 3 name 3
3703 * 6 printer 3 name 3
3705 * that's the print server case, the printer case is even worse.
3708 /*******************************************************************
3710 * enumerate all printers on the printserver
3711 * fill a notify_info struct with info asked
3713 ********************************************************************/
3715 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3716 SPOOL_NOTIFY_INFO *info,
3717 TALLOC_CTX *mem_ctx)
3719 int snum;
3720 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3721 int n_services=lp_numservices();
3722 int i;
3723 SPOOL_NOTIFY_OPTION *option;
3724 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3726 DEBUG(4,("printserver_notify_info\n"));
3728 if (!Printer)
3729 return WERR_BADFID;
3731 option=Printer->notify.option;
3732 info->version=2;
3733 info->data=NULL;
3734 info->count=0;
3736 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3737 sending a ffpcn() request first */
3739 if ( !option )
3740 return WERR_BADFID;
3742 for (i=0; i<option->count; i++) {
3743 option_type=&(option->ctr.type[i]);
3745 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3746 continue;
3748 for (snum=0; snum<n_services; snum++)
3750 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3751 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3755 #if 0
3757 * Debugging information, don't delete.
3760 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3761 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3762 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3764 for (i=0; i<info->count; i++) {
3765 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3766 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3767 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3769 #endif
3771 return WERR_OK;
3774 /*******************************************************************
3776 * fill a notify_info struct with info asked
3778 ********************************************************************/
3780 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3781 TALLOC_CTX *mem_ctx)
3783 int snum;
3784 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3785 int i;
3786 uint32 id;
3787 SPOOL_NOTIFY_OPTION *option;
3788 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3789 int count,j;
3790 print_queue_struct *queue=NULL;
3791 print_status_struct status;
3793 DEBUG(4,("printer_notify_info\n"));
3795 if (!Printer)
3796 return WERR_BADFID;
3798 option=Printer->notify.option;
3799 id = 0x0;
3800 info->version=2;
3801 info->data=NULL;
3802 info->count=0;
3804 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3805 sending a ffpcn() request first */
3807 if ( !option )
3808 return WERR_BADFID;
3810 get_printer_snum(p, hnd, &snum, NULL);
3812 for (i=0; i<option->count; i++) {
3813 option_type=&option->ctr.type[i];
3815 switch ( option_type->type ) {
3816 case PRINTER_NOTIFY_TYPE:
3817 if(construct_notify_printer_info(Printer, info, snum,
3818 option_type, id,
3819 mem_ctx))
3820 id--;
3821 break;
3823 case JOB_NOTIFY_TYPE: {
3824 NT_PRINTER_INFO_LEVEL *printer = NULL;
3826 count = print_queue_status(snum, &queue, &status);
3828 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3829 goto done;
3831 for (j=0; j<count; j++) {
3832 construct_notify_jobs_info(&queue[j], info,
3833 printer, snum,
3834 option_type,
3835 queue[j].job,
3836 mem_ctx);
3839 free_a_printer(&printer, 2);
3841 done:
3842 SAFE_FREE(queue);
3843 break;
3849 * Debugging information, don't delete.
3852 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3853 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3854 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3856 for (i=0; i<info->count; i++) {
3857 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3858 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3859 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3862 return WERR_OK;
3865 /********************************************************************
3866 * spoolss_rfnpcnex
3867 ********************************************************************/
3869 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3871 POLICY_HND *handle = &q_u->handle;
3872 SPOOL_NOTIFY_INFO *info = &r_u->info;
3874 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3875 WERROR result = WERR_BADFID;
3877 /* we always have a NOTIFY_INFO struct */
3878 r_u->info_ptr=0x1;
3880 if (!Printer) {
3881 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3882 OUR_HANDLE(handle)));
3883 goto done;
3886 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3889 * We are now using the change value, and
3890 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3891 * I don't have a global notification system, I'm sending back all the
3892 * informations even when _NOTHING_ has changed.
3895 /* We need to keep track of the change value to send back in
3896 RRPCN replies otherwise our updates are ignored. */
3898 Printer->notify.fnpcn = True;
3900 if (Printer->notify.client_connected) {
3901 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3902 Printer->notify.change = q_u->change;
3905 /* just ignore the SPOOL_NOTIFY_OPTION */
3907 switch (Printer->printer_type) {
3908 case SPLHND_SERVER:
3909 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3910 break;
3912 case SPLHND_PRINTER:
3913 result = printer_notify_info(p, handle, info, p->mem_ctx);
3914 break;
3917 Printer->notify.fnpcn = False;
3919 done:
3920 return result;
3923 /********************************************************************
3924 * construct_printer_info_0
3925 * fill a printer_info_0 struct
3926 ********************************************************************/
3928 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3930 char *chaine = NULL;
3931 int count;
3932 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3933 counter_printer_0 *session_counter;
3934 uint32 global_counter;
3935 struct tm *t;
3936 time_t setuptime;
3937 print_status_struct status;
3938 TALLOC_CTX *ctx = talloc_tos();
3940 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3941 return False;
3943 init_unistr(&printer->printername, ntprinter->info_2->printername);
3945 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3946 if (!chaine) {
3947 free_a_printer(&ntprinter,2);
3948 return false;
3951 count = print_queue_length(snum, &status);
3953 /* check if we already have a counter for this printer */
3954 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3955 if (session_counter->snum == snum)
3956 break;
3959 init_unistr(&printer->servername, chaine);
3961 /* it's the first time, add it to the list */
3962 if (session_counter==NULL) {
3963 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3964 free_a_printer(&ntprinter, 2);
3965 return False;
3967 ZERO_STRUCTP(session_counter);
3968 session_counter->snum=snum;
3969 session_counter->counter=0;
3970 DLIST_ADD(counter_list, session_counter);
3973 /* increment it */
3974 session_counter->counter++;
3976 /* JFM:
3977 * the global_counter should be stored in a TDB as it's common to all the clients
3978 * and should be zeroed on samba startup
3980 global_counter=session_counter->counter;
3981 printer->cjobs = count;
3982 printer->total_jobs = 0;
3983 printer->total_bytes = 0;
3985 setuptime = (time_t)ntprinter->info_2->setuptime;
3986 t=gmtime(&setuptime);
3988 printer->year = t->tm_year+1900;
3989 printer->month = t->tm_mon+1;
3990 printer->dayofweek = t->tm_wday;
3991 printer->day = t->tm_mday;
3992 printer->hour = t->tm_hour;
3993 printer->minute = t->tm_min;
3994 printer->second = t->tm_sec;
3995 printer->milliseconds = 0;
3997 printer->global_counter = global_counter;
3998 printer->total_pages = 0;
4000 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4001 printer->major_version = 0x0005; /* NT 5 */
4002 printer->build_version = 0x0893; /* build 2195 */
4004 printer->unknown7 = 0x1;
4005 printer->unknown8 = 0x0;
4006 printer->unknown9 = 0x0;
4007 printer->session_counter = session_counter->counter;
4008 printer->unknown11 = 0x0;
4009 printer->printer_errors = 0x0; /* number of print failure */
4010 printer->unknown13 = 0x0;
4011 printer->unknown14 = 0x1;
4012 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4013 printer->unknown16 = 0x0;
4014 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4015 printer->unknown18 = 0x0;
4016 printer->status = nt_printq_status(status.status);
4017 printer->unknown20 = 0x0;
4018 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4019 printer->unknown22 = 0x0;
4020 printer->unknown23 = 0x6; /* 6 ???*/
4021 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4022 printer->unknown25 = 0;
4023 printer->unknown26 = 0;
4024 printer->unknown27 = 0;
4025 printer->unknown28 = 0;
4026 printer->unknown29 = 0;
4028 free_a_printer(&ntprinter,2);
4029 return (True);
4032 /********************************************************************
4033 * construct_printer_info_1
4034 * fill a printer_info_1 struct
4035 ********************************************************************/
4036 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4038 char *chaine = NULL;
4039 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4040 TALLOC_CTX *ctx = talloc_tos();
4042 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4043 return false;
4045 printer->flags=flags;
4047 if (*ntprinter->info_2->comment == '\0') {
4048 init_unistr(&printer->comment, lp_comment(snum));
4049 chaine = talloc_asprintf(ctx,
4050 "%s,%s,%s", ntprinter->info_2->printername,
4051 ntprinter->info_2->drivername, lp_comment(snum));
4053 else {
4054 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4055 chaine = talloc_asprintf(ctx,
4056 "%s,%s,%s", ntprinter->info_2->printername,
4057 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4060 if (!chaine) {
4061 free_a_printer(&ntprinter,2);
4062 return false;
4065 init_unistr(&printer->description, chaine);
4066 init_unistr(&printer->name, ntprinter->info_2->printername);
4068 free_a_printer(&ntprinter,2);
4070 return True;
4073 /****************************************************************************
4074 Free a DEVMODE struct.
4075 ****************************************************************************/
4077 static void free_dev_mode(DEVICEMODE *dev)
4079 if (dev == NULL)
4080 return;
4082 SAFE_FREE(dev->dev_private);
4083 SAFE_FREE(dev);
4087 /****************************************************************************
4088 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4089 should be valid upon entry
4090 ****************************************************************************/
4092 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4094 if ( !devmode || !ntdevmode )
4095 return False;
4097 init_unistr(&devmode->devicename, ntdevmode->devicename);
4099 init_unistr(&devmode->formname, ntdevmode->formname);
4101 devmode->specversion = ntdevmode->specversion;
4102 devmode->driverversion = ntdevmode->driverversion;
4103 devmode->size = ntdevmode->size;
4104 devmode->driverextra = ntdevmode->driverextra;
4105 devmode->fields = ntdevmode->fields;
4107 devmode->orientation = ntdevmode->orientation;
4108 devmode->papersize = ntdevmode->papersize;
4109 devmode->paperlength = ntdevmode->paperlength;
4110 devmode->paperwidth = ntdevmode->paperwidth;
4111 devmode->scale = ntdevmode->scale;
4112 devmode->copies = ntdevmode->copies;
4113 devmode->defaultsource = ntdevmode->defaultsource;
4114 devmode->printquality = ntdevmode->printquality;
4115 devmode->color = ntdevmode->color;
4116 devmode->duplex = ntdevmode->duplex;
4117 devmode->yresolution = ntdevmode->yresolution;
4118 devmode->ttoption = ntdevmode->ttoption;
4119 devmode->collate = ntdevmode->collate;
4120 devmode->icmmethod = ntdevmode->icmmethod;
4121 devmode->icmintent = ntdevmode->icmintent;
4122 devmode->mediatype = ntdevmode->mediatype;
4123 devmode->dithertype = ntdevmode->dithertype;
4125 if (ntdevmode->nt_dev_private != NULL) {
4126 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4127 return False;
4130 return True;
4133 /****************************************************************************
4134 Create a DEVMODE struct. Returns malloced memory.
4135 ****************************************************************************/
4137 DEVICEMODE *construct_dev_mode(const char *servicename)
4139 NT_PRINTER_INFO_LEVEL *printer = NULL;
4140 DEVICEMODE *devmode = NULL;
4142 DEBUG(7,("construct_dev_mode\n"));
4144 DEBUGADD(8,("getting printer characteristics\n"));
4146 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4147 return NULL;
4149 if ( !printer->info_2->devmode ) {
4150 DEBUG(5, ("BONG! There was no device mode!\n"));
4151 goto done;
4154 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4155 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4156 goto done;
4159 ZERO_STRUCTP(devmode);
4161 DEBUGADD(8,("loading DEVICEMODE\n"));
4163 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4164 free_dev_mode( devmode );
4165 devmode = NULL;
4168 done:
4169 free_a_printer(&printer,2);
4171 return devmode;
4174 /********************************************************************
4175 * construct_printer_info_2
4176 * fill a printer_info_2 struct
4177 ********************************************************************/
4179 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4181 int count;
4182 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4184 print_status_struct status;
4186 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4187 return False;
4189 count = print_queue_length(snum, &status);
4191 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4192 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4193 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4194 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4195 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4197 if (*ntprinter->info_2->comment == '\0')
4198 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4199 else
4200 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4202 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4203 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4204 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4205 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4206 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4208 printer->attributes = ntprinter->info_2->attributes;
4210 printer->priority = ntprinter->info_2->priority; /* priority */
4211 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4212 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4213 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4214 printer->status = nt_printq_status(status.status); /* status */
4215 printer->cjobs = count; /* jobs */
4216 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4218 if ( !(printer->devmode = construct_dev_mode(
4219 lp_const_servicename(snum))) )
4220 DEBUG(8, ("Returning NULL Devicemode!\n"));
4222 printer->secdesc = NULL;
4224 if ( ntprinter->info_2->secdesc_buf
4225 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4227 /* don't use talloc_steal() here unless you do a deep steal of all
4228 the SEC_DESC members */
4230 printer->secdesc = dup_sec_desc( talloc_tos(),
4231 ntprinter->info_2->secdesc_buf->sd );
4234 free_a_printer(&ntprinter, 2);
4236 return True;
4239 /********************************************************************
4240 * construct_printer_info_3
4241 * fill a printer_info_3 struct
4242 ********************************************************************/
4244 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4246 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4247 PRINTER_INFO_3 *printer = NULL;
4249 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4250 return False;
4252 *pp_printer = NULL;
4253 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4254 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4255 free_a_printer(&ntprinter, 2);
4256 return False;
4259 ZERO_STRUCTP(printer);
4261 /* These are the components of the SD we are returning. */
4263 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4264 /* don't use talloc_steal() here unless you do a deep steal of all
4265 the SEC_DESC members */
4267 printer->secdesc = dup_sec_desc( talloc_tos(),
4268 ntprinter->info_2->secdesc_buf->sd );
4271 free_a_printer(&ntprinter, 2);
4273 *pp_printer = printer;
4274 return True;
4277 /********************************************************************
4278 * construct_printer_info_4
4279 * fill a printer_info_4 struct
4280 ********************************************************************/
4282 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4284 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4286 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4287 return False;
4289 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4290 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4291 printer->attributes = ntprinter->info_2->attributes;
4293 free_a_printer(&ntprinter, 2);
4294 return True;
4297 /********************************************************************
4298 * construct_printer_info_5
4299 * fill a printer_info_5 struct
4300 ********************************************************************/
4302 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4304 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4306 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4307 return False;
4309 init_unistr(&printer->printername, ntprinter->info_2->printername);
4310 init_unistr(&printer->portname, ntprinter->info_2->portname);
4311 printer->attributes = ntprinter->info_2->attributes;
4313 /* these two are not used by NT+ according to MSDN */
4315 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4316 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4318 free_a_printer(&ntprinter, 2);
4320 return True;
4323 /********************************************************************
4324 * construct_printer_info_6
4325 * fill a printer_info_6 struct
4326 ********************************************************************/
4328 static bool construct_printer_info_6(Printer_entry *print_hnd,
4329 PRINTER_INFO_6 *printer,
4330 int snum)
4332 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4333 int count;
4334 print_status_struct status;
4336 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4337 lp_const_servicename(snum))))
4338 return False;
4340 count = print_queue_length(snum, &status);
4342 printer->status = nt_printq_status(status.status);
4344 free_a_printer(&ntprinter, 2);
4346 return True;
4349 /********************************************************************
4350 * construct_printer_info_7
4351 * fill a printer_info_7 struct
4352 ********************************************************************/
4354 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4356 char *guid_str = NULL;
4357 struct GUID guid;
4359 if (is_printer_published(print_hnd, snum, &guid)) {
4360 asprintf(&guid_str, "{%s}",
4361 smb_uuid_string(talloc_tos(), guid));
4362 strupper_m(guid_str);
4363 init_unistr(&printer->guid, guid_str);
4364 printer->action = SPOOL_DS_PUBLISH;
4365 } else {
4366 init_unistr(&printer->guid, "");
4367 printer->action = SPOOL_DS_UNPUBLISH;
4370 return True;
4373 /********************************************************************
4374 Spoolss_enumprinters.
4375 ********************************************************************/
4377 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4379 int snum;
4380 int i;
4381 int n_services=lp_numservices();
4382 PRINTER_INFO_1 *printers=NULL;
4383 PRINTER_INFO_1 current_prt;
4384 WERROR result = WERR_OK;
4386 DEBUG(4,("enum_all_printers_info_1\n"));
4388 for (snum=0; snum<n_services; snum++) {
4389 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4390 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4392 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4393 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4394 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4395 *returned=0;
4396 return WERR_NOMEM;
4398 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4400 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4401 (*returned)++;
4406 /* check the required size. */
4407 for (i=0; i<*returned; i++)
4408 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4410 if (*needed > offered) {
4411 result = WERR_INSUFFICIENT_BUFFER;
4412 goto out;
4415 if (!rpcbuf_alloc_size(buffer, *needed)) {
4416 result = WERR_NOMEM;
4417 goto out;
4420 /* fill the buffer with the structures */
4421 for (i=0; i<*returned; i++)
4422 smb_io_printer_info_1("", buffer, &printers[i], 0);
4424 out:
4425 /* clear memory */
4427 SAFE_FREE(printers);
4429 if ( !W_ERROR_IS_OK(result) )
4430 *returned = 0;
4432 return result;
4435 /********************************************************************
4436 enum_all_printers_info_1_local.
4437 *********************************************************************/
4439 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4441 DEBUG(4,("enum_all_printers_info_1_local\n"));
4443 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4446 /********************************************************************
4447 enum_all_printers_info_1_name.
4448 *********************************************************************/
4450 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4452 char *s = name;
4454 DEBUG(4,("enum_all_printers_info_1_name\n"));
4456 if ((name[0] == '\\') && (name[1] == '\\'))
4457 s = name + 2;
4459 if (is_myname_or_ipaddr(s)) {
4460 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4462 else
4463 return WERR_INVALID_NAME;
4466 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4467 /********************************************************************
4468 enum_all_printers_info_1_remote.
4469 *********************************************************************/
4471 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 PRINTER_INFO_1 *printer;
4474 fstring printername;
4475 fstring desc;
4476 fstring comment;
4477 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4478 WERROR result = WERR_OK;
4480 /* JFM: currently it's more a place holder than anything else.
4481 * In the spooler world there is a notion of server registration.
4482 * the print servers are registered on the PDC (in the same domain)
4484 * We should have a TDB here. The registration is done thru an
4485 * undocumented RPC call.
4488 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4489 return WERR_NOMEM;
4491 *returned=1;
4493 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4494 slprintf(desc, sizeof(desc)-1,"%s", name);
4495 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4497 init_unistr(&printer->description, desc);
4498 init_unistr(&printer->name, printername);
4499 init_unistr(&printer->comment, comment);
4500 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4502 /* check the required size. */
4503 *needed += spoolss_size_printer_info_1(printer);
4505 if (*needed > offered) {
4506 result = WERR_INSUFFICIENT_BUFFER;
4507 goto out;
4510 if (!rpcbuf_alloc_size(buffer, *needed)) {
4511 result = WERR_NOMEM;
4512 goto out;
4515 /* fill the buffer with the structures */
4516 smb_io_printer_info_1("", buffer, printer, 0);
4518 out:
4519 /* clear memory */
4520 SAFE_FREE(printer);
4522 if ( !W_ERROR_IS_OK(result) )
4523 *returned = 0;
4525 return result;
4528 #endif
4530 /********************************************************************
4531 enum_all_printers_info_1_network.
4532 *********************************************************************/
4534 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4536 char *s = name;
4538 DEBUG(4,("enum_all_printers_info_1_network\n"));
4540 /* If we respond to a enum_printers level 1 on our name with flags
4541 set to PRINTER_ENUM_REMOTE with a list of printers then these
4542 printers incorrectly appear in the APW browse list.
4543 Specifically the printers for the server appear at the workgroup
4544 level where all the other servers in the domain are
4545 listed. Windows responds to this call with a
4546 WERR_CAN_NOT_COMPLETE so we should do the same. */
4548 if (name[0] == '\\' && name[1] == '\\')
4549 s = name + 2;
4551 if (is_myname_or_ipaddr(s))
4552 return WERR_CAN_NOT_COMPLETE;
4554 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4557 /********************************************************************
4558 * api_spoolss_enumprinters
4560 * called from api_spoolss_enumprinters (see this to understand)
4561 ********************************************************************/
4563 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4565 int snum;
4566 int i;
4567 int n_services=lp_numservices();
4568 PRINTER_INFO_2 *printers=NULL;
4569 PRINTER_INFO_2 current_prt;
4570 WERROR result = WERR_OK;
4572 *returned = 0;
4574 for (snum=0; snum<n_services; snum++) {
4575 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4576 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4578 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4579 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4580 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4581 *returned = 0;
4582 return WERR_NOMEM;
4585 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4587 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4589 (*returned)++;
4594 /* check the required size. */
4595 for (i=0; i<*returned; i++)
4596 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4598 if (*needed > offered) {
4599 result = WERR_INSUFFICIENT_BUFFER;
4600 goto out;
4603 if (!rpcbuf_alloc_size(buffer, *needed)) {
4604 result = WERR_NOMEM;
4605 goto out;
4608 /* fill the buffer with the structures */
4609 for (i=0; i<*returned; i++)
4610 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4612 out:
4613 /* clear memory */
4615 for (i=0; i<*returned; i++)
4616 free_devmode(printers[i].devmode);
4618 SAFE_FREE(printers);
4620 if ( !W_ERROR_IS_OK(result) )
4621 *returned = 0;
4623 return result;
4626 /********************************************************************
4627 * handle enumeration of printers at level 1
4628 ********************************************************************/
4630 static WERROR enumprinters_level1( uint32 flags, fstring name,
4631 RPC_BUFFER *buffer, uint32 offered,
4632 uint32 *needed, uint32 *returned)
4634 /* Not all the flags are equals */
4636 if (flags & PRINTER_ENUM_LOCAL)
4637 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4639 if (flags & PRINTER_ENUM_NAME)
4640 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4642 #if 0 /* JERRY - disabled for now */
4643 if (flags & PRINTER_ENUM_REMOTE)
4644 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4645 #endif
4647 if (flags & PRINTER_ENUM_NETWORK)
4648 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4650 return WERR_OK; /* NT4sp5 does that */
4653 /********************************************************************
4654 * handle enumeration of printers at level 2
4655 ********************************************************************/
4657 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4658 RPC_BUFFER *buffer, uint32 offered,
4659 uint32 *needed, uint32 *returned)
4661 char *s = servername;
4663 if (flags & PRINTER_ENUM_LOCAL) {
4664 return enum_all_printers_info_2(buffer, offered, needed, returned);
4667 if (flags & PRINTER_ENUM_NAME) {
4668 if ((servername[0] == '\\') && (servername[1] == '\\'))
4669 s = servername + 2;
4670 if (is_myname_or_ipaddr(s))
4671 return enum_all_printers_info_2(buffer, offered, needed, returned);
4672 else
4673 return WERR_INVALID_NAME;
4676 if (flags & PRINTER_ENUM_REMOTE)
4677 return WERR_UNKNOWN_LEVEL;
4679 return WERR_OK;
4682 /********************************************************************
4683 * handle enumeration of printers at level 5
4684 ********************************************************************/
4686 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4687 RPC_BUFFER *buffer, uint32 offered,
4688 uint32 *needed, uint32 *returned)
4690 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4691 return WERR_OK;
4694 /********************************************************************
4695 * api_spoolss_enumprinters
4697 * called from api_spoolss_enumprinters (see this to understand)
4698 ********************************************************************/
4700 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4702 uint32 flags = q_u->flags;
4703 UNISTR2 *servername = &q_u->servername;
4704 uint32 level = q_u->level;
4705 RPC_BUFFER *buffer = NULL;
4706 uint32 offered = q_u->offered;
4707 uint32 *needed = &r_u->needed;
4708 uint32 *returned = &r_u->returned;
4710 fstring name;
4712 /* that's an [in out] buffer */
4714 if (!q_u->buffer && (offered!=0)) {
4715 return WERR_INVALID_PARAM;
4718 rpcbuf_move(q_u->buffer, &r_u->buffer);
4719 buffer = r_u->buffer;
4721 DEBUG(4,("_spoolss_enumprinters\n"));
4723 *needed=0;
4724 *returned=0;
4727 * Level 1:
4728 * flags==PRINTER_ENUM_NAME
4729 * if name=="" then enumerates all printers
4730 * if name!="" then enumerate the printer
4731 * flags==PRINTER_ENUM_REMOTE
4732 * name is NULL, enumerate printers
4733 * Level 2: name!="" enumerates printers, name can't be NULL
4734 * Level 3: doesn't exist
4735 * Level 4: does a local registry lookup
4736 * Level 5: same as Level 2
4739 unistr2_to_ascii(name, servername, sizeof(name));
4740 strupper_m(name);
4742 switch (level) {
4743 case 1:
4744 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4745 case 2:
4746 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4747 case 5:
4748 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4749 case 3:
4750 case 4:
4751 break;
4753 return WERR_UNKNOWN_LEVEL;
4756 /****************************************************************************
4757 ****************************************************************************/
4759 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4761 PRINTER_INFO_0 *printer=NULL;
4762 WERROR result = WERR_OK;
4764 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4765 return WERR_NOMEM;
4767 construct_printer_info_0(print_hnd, printer, snum);
4769 /* check the required size. */
4770 *needed += spoolss_size_printer_info_0(printer);
4772 if (*needed > offered) {
4773 result = WERR_INSUFFICIENT_BUFFER;
4774 goto out;
4777 if (!rpcbuf_alloc_size(buffer, *needed)) {
4778 result = WERR_NOMEM;
4779 goto out;
4782 /* fill the buffer with the structures */
4783 smb_io_printer_info_0("", buffer, printer, 0);
4785 out:
4786 /* clear memory */
4788 SAFE_FREE(printer);
4790 return result;
4793 /****************************************************************************
4794 ****************************************************************************/
4796 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4798 PRINTER_INFO_1 *printer=NULL;
4799 WERROR result = WERR_OK;
4801 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4802 return WERR_NOMEM;
4804 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4806 /* check the required size. */
4807 *needed += spoolss_size_printer_info_1(printer);
4809 if (*needed > offered) {
4810 result = WERR_INSUFFICIENT_BUFFER;
4811 goto out;
4814 if (!rpcbuf_alloc_size(buffer, *needed)) {
4815 result = WERR_NOMEM;
4816 goto out;
4819 /* fill the buffer with the structures */
4820 smb_io_printer_info_1("", buffer, printer, 0);
4822 out:
4823 /* clear memory */
4824 SAFE_FREE(printer);
4826 return result;
4829 /****************************************************************************
4830 ****************************************************************************/
4832 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4834 PRINTER_INFO_2 *printer=NULL;
4835 WERROR result = WERR_OK;
4837 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4838 return WERR_NOMEM;
4840 construct_printer_info_2(print_hnd, printer, snum);
4842 /* check the required size. */
4843 *needed += spoolss_size_printer_info_2(printer);
4845 if (*needed > offered) {
4846 result = WERR_INSUFFICIENT_BUFFER;
4847 goto out;
4850 if (!rpcbuf_alloc_size(buffer, *needed)) {
4851 result = WERR_NOMEM;
4852 goto out;
4855 /* fill the buffer with the structures */
4856 if (!smb_io_printer_info_2("", buffer, printer, 0))
4857 result = WERR_NOMEM;
4859 out:
4860 /* clear memory */
4861 free_printer_info_2(printer);
4863 return result;
4866 /****************************************************************************
4867 ****************************************************************************/
4869 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 PRINTER_INFO_3 *printer=NULL;
4872 WERROR result = WERR_OK;
4874 if (!construct_printer_info_3(print_hnd, &printer, snum))
4875 return WERR_NOMEM;
4877 /* check the required size. */
4878 *needed += spoolss_size_printer_info_3(printer);
4880 if (*needed > offered) {
4881 result = WERR_INSUFFICIENT_BUFFER;
4882 goto out;
4885 if (!rpcbuf_alloc_size(buffer, *needed)) {
4886 result = WERR_NOMEM;
4887 goto out;
4890 /* fill the buffer with the structures */
4891 smb_io_printer_info_3("", buffer, printer, 0);
4893 out:
4894 /* clear memory */
4895 free_printer_info_3(printer);
4897 return result;
4900 /****************************************************************************
4901 ****************************************************************************/
4903 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4905 PRINTER_INFO_4 *printer=NULL;
4906 WERROR result = WERR_OK;
4908 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4909 return WERR_NOMEM;
4911 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4912 SAFE_FREE(printer);
4913 return WERR_NOMEM;
4916 /* check the required size. */
4917 *needed += spoolss_size_printer_info_4(printer);
4919 if (*needed > offered) {
4920 result = WERR_INSUFFICIENT_BUFFER;
4921 goto out;
4924 if (!rpcbuf_alloc_size(buffer, *needed)) {
4925 result = WERR_NOMEM;
4926 goto out;
4929 /* fill the buffer with the structures */
4930 smb_io_printer_info_4("", buffer, printer, 0);
4932 out:
4933 /* clear memory */
4934 free_printer_info_4(printer);
4936 return result;
4939 /****************************************************************************
4940 ****************************************************************************/
4942 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4944 PRINTER_INFO_5 *printer=NULL;
4945 WERROR result = WERR_OK;
4947 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4948 return WERR_NOMEM;
4950 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4951 free_printer_info_5(printer);
4952 return WERR_NOMEM;
4955 /* check the required size. */
4956 *needed += spoolss_size_printer_info_5(printer);
4958 if (*needed > offered) {
4959 result = WERR_INSUFFICIENT_BUFFER;
4960 goto out;
4963 if (!rpcbuf_alloc_size(buffer, *needed)) {
4964 result = WERR_NOMEM;
4965 goto out;
4968 /* fill the buffer with the structures */
4969 smb_io_printer_info_5("", buffer, printer, 0);
4971 out:
4972 /* clear memory */
4973 free_printer_info_5(printer);
4975 return result;
4978 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4979 int snum,
4980 RPC_BUFFER *buffer, uint32 offered,
4981 uint32 *needed)
4983 PRINTER_INFO_6 *printer;
4984 WERROR result = WERR_OK;
4986 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4987 return WERR_NOMEM;
4990 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4991 free_printer_info_6(printer);
4992 return WERR_NOMEM;
4995 /* check the required size. */
4996 *needed += spoolss_size_printer_info_6(printer);
4998 if (*needed > offered) {
4999 result = WERR_INSUFFICIENT_BUFFER;
5000 goto out;
5003 if (!rpcbuf_alloc_size(buffer, *needed)) {
5004 result = WERR_NOMEM;
5005 goto out;
5008 /* fill the buffer with the structures */
5009 smb_io_printer_info_6("", buffer, printer, 0);
5011 out:
5012 /* clear memory */
5013 free_printer_info_6(printer);
5015 return result;
5018 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5020 PRINTER_INFO_7 *printer=NULL;
5021 WERROR result = WERR_OK;
5023 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5024 return WERR_NOMEM;
5026 if (!construct_printer_info_7(print_hnd, printer, snum))
5027 return WERR_NOMEM;
5029 /* check the required size. */
5030 *needed += spoolss_size_printer_info_7(printer);
5032 if (*needed > offered) {
5033 result = WERR_INSUFFICIENT_BUFFER;
5034 goto out;
5037 if (!rpcbuf_alloc_size(buffer, *needed)) {
5038 result = WERR_NOMEM;
5039 goto out;
5043 /* fill the buffer with the structures */
5044 smb_io_printer_info_7("", buffer, printer, 0);
5046 out:
5047 /* clear memory */
5048 free_printer_info_7(printer);
5050 return result;
5053 /****************************************************************************
5054 ****************************************************************************/
5056 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5058 POLICY_HND *handle = &q_u->handle;
5059 uint32 level = q_u->level;
5060 RPC_BUFFER *buffer = NULL;
5061 uint32 offered = q_u->offered;
5062 uint32 *needed = &r_u->needed;
5063 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5065 int snum;
5067 /* that's an [in out] buffer */
5069 if (!q_u->buffer && (offered!=0)) {
5070 return WERR_INVALID_PARAM;
5073 rpcbuf_move(q_u->buffer, &r_u->buffer);
5074 buffer = r_u->buffer;
5076 *needed=0;
5078 if (!get_printer_snum(p, handle, &snum, NULL))
5079 return WERR_BADFID;
5081 switch (level) {
5082 case 0:
5083 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5084 case 1:
5085 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5086 case 2:
5087 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5088 case 3:
5089 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5090 case 4:
5091 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5092 case 5:
5093 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5094 case 6:
5095 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5096 case 7:
5097 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5099 return WERR_UNKNOWN_LEVEL;
5102 /********************************************************************
5103 * fill a DRIVER_INFO_1 struct
5104 ********************************************************************/
5106 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5108 init_unistr( &info->name, driver.info_3->name);
5111 /********************************************************************
5112 * construct_printer_driver_info_1
5113 ********************************************************************/
5115 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5117 NT_PRINTER_INFO_LEVEL *printer = NULL;
5118 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5120 ZERO_STRUCT(driver);
5122 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5123 return WERR_INVALID_PRINTER_NAME;
5125 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5126 free_a_printer(&printer, 2);
5127 return WERR_UNKNOWN_PRINTER_DRIVER;
5130 fill_printer_driver_info_1(info, driver, servername, architecture);
5132 free_a_printer(&printer,2);
5134 return WERR_OK;
5137 /********************************************************************
5138 * construct_printer_driver_info_2
5139 * fill a printer_info_2 struct
5140 ********************************************************************/
5142 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5144 TALLOC_CTX *ctx = talloc_tos();
5145 char *temp = NULL;
5147 info->version=driver.info_3->cversion;
5149 init_unistr( &info->name, driver.info_3->name );
5150 init_unistr( &info->architecture, driver.info_3->environment );
5153 if (strlen(driver.info_3->driverpath)) {
5154 temp = talloc_asprintf(ctx,
5155 "\\\\%s%s",
5156 servername,
5157 driver.info_3->driverpath);
5158 init_unistr( &info->driverpath, temp );
5159 } else {
5160 init_unistr( &info->driverpath, "" );
5163 TALLOC_FREE(temp);
5164 if (strlen(driver.info_3->datafile)) {
5165 temp = talloc_asprintf(ctx,
5166 "\\\\%s%s",
5167 servername,
5168 driver.info_3->datafile);
5169 init_unistr( &info->datafile, temp );
5170 } else
5171 init_unistr( &info->datafile, "" );
5173 TALLOC_FREE(temp);
5174 if (strlen(driver.info_3->configfile)) {
5175 temp = talloc_asprintf(ctx,
5176 "\\\\%s%s",
5177 servername,
5178 driver.info_3->configfile);
5179 init_unistr( &info->configfile, temp );
5180 } else
5181 init_unistr( &info->configfile, "" );
5184 /********************************************************************
5185 * construct_printer_driver_info_2
5186 * fill a printer_info_2 struct
5187 ********************************************************************/
5189 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5191 NT_PRINTER_INFO_LEVEL *printer = NULL;
5192 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5194 ZERO_STRUCT(printer);
5195 ZERO_STRUCT(driver);
5197 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5198 return WERR_INVALID_PRINTER_NAME;
5200 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5201 free_a_printer(&printer, 2);
5202 return WERR_UNKNOWN_PRINTER_DRIVER;
5205 fill_printer_driver_info_2(info, driver, servername);
5207 free_a_printer(&printer,2);
5209 return WERR_OK;
5212 /********************************************************************
5213 * copy a strings array and convert to UNICODE
5215 * convert an array of ascii string to a UNICODE string
5216 ********************************************************************/
5218 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5220 int i=0;
5221 int j=0;
5222 const char *v;
5223 char *line = NULL;
5224 TALLOC_CTX *ctx = talloc_tos();
5226 DEBUG(6,("init_unistr_array\n"));
5227 *uni_array=NULL;
5229 while (true) {
5230 if ( !char_array ) {
5231 v = "";
5232 } else {
5233 v = char_array[i];
5234 if (!v)
5235 v = ""; /* hack to handle null lists */
5238 /* hack to allow this to be used in places other than when generating
5239 the list of dependent files */
5241 TALLOC_FREE(line);
5242 if ( servername ) {
5243 line = talloc_asprintf(ctx,
5244 "\\\\%s%s",
5245 servername,
5247 } else {
5248 line = talloc_strdup(ctx, v);
5251 if (!line) {
5252 SAFE_FREE(*uni_array);
5253 return 0;
5255 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5257 /* add one extra unit16 for the second terminating NULL */
5259 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5260 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5261 return 0;
5264 if ( !strlen(v) )
5265 break;
5267 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5268 i++;
5271 if (*uni_array) {
5272 /* special case for ""; we need to add both NULL's here */
5273 if (!j)
5274 (*uni_array)[j++]=0x0000;
5275 (*uni_array)[j]=0x0000;
5278 DEBUGADD(6,("last one:done\n"));
5280 /* return size of array in uint16's */
5282 return j+1;
5285 /********************************************************************
5286 * construct_printer_info_3
5287 * fill a printer_info_3 struct
5288 ********************************************************************/
5290 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5292 char *temp = NULL;
5293 TALLOC_CTX *ctx = talloc_tos();
5295 ZERO_STRUCTP(info);
5297 info->version=driver.info_3->cversion;
5299 init_unistr( &info->name, driver.info_3->name );
5300 init_unistr( &info->architecture, driver.info_3->environment );
5302 if (strlen(driver.info_3->driverpath)) {
5303 temp = talloc_asprintf(ctx,
5304 "\\\\%s%s",
5305 servername,
5306 driver.info_3->driverpath);
5307 init_unistr( &info->driverpath, temp );
5308 } else
5309 init_unistr( &info->driverpath, "" );
5311 TALLOC_FREE(temp);
5312 if (strlen(driver.info_3->datafile)) {
5313 temp = talloc_asprintf(ctx,
5314 "\\\\%s%s",
5315 servername,
5316 driver.info_3->datafile);
5317 init_unistr( &info->datafile, temp );
5318 } else
5319 init_unistr( &info->datafile, "" );
5321 TALLOC_FREE(temp);
5322 if (strlen(driver.info_3->configfile)) {
5323 temp = talloc_asprintf(ctx,
5324 "\\\\%s%s",
5325 servername,
5326 driver.info_3->configfile);
5327 init_unistr( &info->configfile, temp );
5328 } else
5329 init_unistr( &info->configfile, "" );
5331 TALLOC_FREE(temp);
5332 if (strlen(driver.info_3->helpfile)) {
5333 temp = talloc_asprintf(ctx,
5334 "\\\\%s%s",
5335 servername,
5336 driver.info_3->helpfile);
5337 init_unistr( &info->helpfile, temp );
5338 } else
5339 init_unistr( &info->helpfile, "" );
5341 TALLOC_FREE(temp);
5342 init_unistr( &info->monitorname, driver.info_3->monitorname );
5343 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5345 info->dependentfiles=NULL;
5346 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5349 /********************************************************************
5350 * construct_printer_info_3
5351 * fill a printer_info_3 struct
5352 ********************************************************************/
5354 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5356 NT_PRINTER_INFO_LEVEL *printer = NULL;
5357 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5358 WERROR status;
5359 ZERO_STRUCT(driver);
5361 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5362 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5363 if (!W_ERROR_IS_OK(status))
5364 return WERR_INVALID_PRINTER_NAME;
5366 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5367 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5369 #if 0 /* JERRY */
5372 * I put this code in during testing. Helpful when commenting out the
5373 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5374 * as win2k always queries the driver using an infor level of 6.
5375 * I've left it in (but ifdef'd out) because I'll probably
5376 * use it in experimentation again in the future. --jerry 22/01/2002
5379 if (!W_ERROR_IS_OK(status)) {
5381 * Is this a W2k client ?
5383 if (version == 3) {
5384 /* Yes - try again with a WinNT driver. */
5385 version = 2;
5386 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5387 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5389 #endif
5391 if (!W_ERROR_IS_OK(status)) {
5392 free_a_printer(&printer,2);
5393 return WERR_UNKNOWN_PRINTER_DRIVER;
5396 #if 0 /* JERRY */
5398 #endif
5401 fill_printer_driver_info_3(info, driver, servername);
5403 free_a_printer(&printer,2);
5405 return WERR_OK;
5408 /********************************************************************
5409 * construct_printer_info_6
5410 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5411 ********************************************************************/
5413 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5415 char *temp = NULL;
5416 fstring nullstr;
5417 TALLOC_CTX *ctx = talloc_tos();
5419 ZERO_STRUCTP(info);
5420 memset(&nullstr, '\0', sizeof(fstring));
5422 info->version=driver.info_3->cversion;
5424 init_unistr( &info->name, driver.info_3->name );
5425 init_unistr( &info->architecture, driver.info_3->environment );
5427 if (strlen(driver.info_3->driverpath)) {
5428 temp = talloc_asprintf(ctx,
5429 "\\\\%s%s",
5430 servername,
5431 driver.info_3->driverpath);
5432 init_unistr( &info->driverpath, temp );
5433 } else
5434 init_unistr( &info->driverpath, "" );
5436 TALLOC_FREE(temp);
5437 if (strlen(driver.info_3->datafile)) {
5438 temp = talloc_asprintf(ctx,
5439 "\\\\%s%s",
5440 servername,
5441 driver.info_3->datafile);
5442 init_unistr( &info->datafile, temp );
5443 } else
5444 init_unistr( &info->datafile, "" );
5446 TALLOC_FREE(temp);
5447 if (strlen(driver.info_3->configfile)) {
5448 temp = talloc_asprintf(ctx,
5449 "\\\\%s%s",
5450 servername,
5451 driver.info_3->configfile);
5452 init_unistr( &info->configfile, temp );
5453 } else
5454 init_unistr( &info->configfile, "" );
5456 TALLOC_FREE(temp);
5457 if (strlen(driver.info_3->helpfile)) {
5458 temp = talloc_asprintf(ctx,
5459 "\\\\%s%s",
5460 servername,
5461 driver.info_3->helpfile);
5462 init_unistr( &info->helpfile, temp );
5463 } else
5464 init_unistr( &info->helpfile, "" );
5466 TALLOC_FREE(temp);
5467 init_unistr( &info->monitorname, driver.info_3->monitorname );
5468 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5470 info->dependentfiles = NULL;
5471 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5473 info->previousdrivernames=NULL;
5474 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5476 info->driver_date=0;
5478 info->padding=0;
5479 info->driver_version_low=0;
5480 info->driver_version_high=0;
5482 init_unistr( &info->mfgname, "");
5483 init_unistr( &info->oem_url, "");
5484 init_unistr( &info->hardware_id, "");
5485 init_unistr( &info->provider, "");
5488 /********************************************************************
5489 * construct_printer_info_6
5490 * fill a printer_info_6 struct
5491 ********************************************************************/
5493 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5494 fstring servername, fstring architecture, uint32 version)
5496 NT_PRINTER_INFO_LEVEL *printer = NULL;
5497 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5498 WERROR status;
5500 ZERO_STRUCT(driver);
5502 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5504 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5506 if (!W_ERROR_IS_OK(status))
5507 return WERR_INVALID_PRINTER_NAME;
5509 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5511 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5513 if (!W_ERROR_IS_OK(status))
5516 * Is this a W2k client ?
5519 if (version < 3) {
5520 free_a_printer(&printer,2);
5521 return WERR_UNKNOWN_PRINTER_DRIVER;
5524 /* Yes - try again with a WinNT driver. */
5525 version = 2;
5526 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5527 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5528 if (!W_ERROR_IS_OK(status)) {
5529 free_a_printer(&printer,2);
5530 return WERR_UNKNOWN_PRINTER_DRIVER;
5534 fill_printer_driver_info_6(info, driver, servername);
5536 free_a_printer(&printer,2);
5537 free_a_printer_driver(driver, 3);
5539 return WERR_OK;
5542 /****************************************************************************
5543 ****************************************************************************/
5545 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5547 SAFE_FREE(info->dependentfiles);
5550 /****************************************************************************
5551 ****************************************************************************/
5553 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5555 SAFE_FREE(info->dependentfiles);
5558 /****************************************************************************
5559 ****************************************************************************/
5561 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5563 DRIVER_INFO_1 *info=NULL;
5564 WERROR result;
5566 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5567 return WERR_NOMEM;
5569 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5570 if (!W_ERROR_IS_OK(result))
5571 goto out;
5573 /* check the required size. */
5574 *needed += spoolss_size_printer_driver_info_1(info);
5576 if (*needed > offered) {
5577 result = WERR_INSUFFICIENT_BUFFER;
5578 goto out;
5581 if (!rpcbuf_alloc_size(buffer, *needed)) {
5582 result = WERR_NOMEM;
5583 goto out;
5586 /* fill the buffer with the structures */
5587 smb_io_printer_driver_info_1("", buffer, info, 0);
5589 out:
5590 /* clear memory */
5591 SAFE_FREE(info);
5593 return result;
5596 /****************************************************************************
5597 ****************************************************************************/
5599 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5601 DRIVER_INFO_2 *info=NULL;
5602 WERROR result;
5604 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5605 return WERR_NOMEM;
5607 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5608 if (!W_ERROR_IS_OK(result))
5609 goto out;
5611 /* check the required size. */
5612 *needed += spoolss_size_printer_driver_info_2(info);
5614 if (*needed > offered) {
5615 result = WERR_INSUFFICIENT_BUFFER;
5616 goto out;
5619 if (!rpcbuf_alloc_size(buffer, *needed)) {
5620 result = WERR_NOMEM;
5621 goto out;
5624 /* fill the buffer with the structures */
5625 smb_io_printer_driver_info_2("", buffer, info, 0);
5627 out:
5628 /* clear memory */
5629 SAFE_FREE(info);
5631 return result;
5634 /****************************************************************************
5635 ****************************************************************************/
5637 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5639 DRIVER_INFO_3 info;
5640 WERROR result;
5642 ZERO_STRUCT(info);
5644 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5645 if (!W_ERROR_IS_OK(result))
5646 goto out;
5648 /* check the required size. */
5649 *needed += spoolss_size_printer_driver_info_3(&info);
5651 if (*needed > offered) {
5652 result = WERR_INSUFFICIENT_BUFFER;
5653 goto out;
5656 if (!rpcbuf_alloc_size(buffer, *needed)) {
5657 result = WERR_NOMEM;
5658 goto out;
5661 /* fill the buffer with the structures */
5662 smb_io_printer_driver_info_3("", buffer, &info, 0);
5664 out:
5665 free_printer_driver_info_3(&info);
5667 return result;
5670 /****************************************************************************
5671 ****************************************************************************/
5673 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5675 DRIVER_INFO_6 info;
5676 WERROR result;
5678 ZERO_STRUCT(info);
5680 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5681 if (!W_ERROR_IS_OK(result))
5682 goto out;
5684 /* check the required size. */
5685 *needed += spoolss_size_printer_driver_info_6(&info);
5687 if (*needed > offered) {
5688 result = WERR_INSUFFICIENT_BUFFER;
5689 goto out;
5692 if (!rpcbuf_alloc_size(buffer, *needed)) {
5693 result = WERR_NOMEM;
5694 goto out;
5697 /* fill the buffer with the structures */
5698 smb_io_printer_driver_info_6("", buffer, &info, 0);
5700 out:
5701 free_printer_driver_info_6(&info);
5703 return result;
5706 /****************************************************************************
5707 ****************************************************************************/
5709 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5712 UNISTR2 *uni_arch = &q_u->architecture;
5713 uint32 level = q_u->level;
5714 uint32 clientmajorversion = q_u->clientmajorversion;
5715 RPC_BUFFER *buffer = NULL;
5716 uint32 offered = q_u->offered;
5717 uint32 *needed = &r_u->needed;
5718 uint32 *servermajorversion = &r_u->servermajorversion;
5719 uint32 *serverminorversion = &r_u->serverminorversion;
5720 Printer_entry *printer;
5722 fstring servername;
5723 fstring architecture;
5724 int snum;
5726 /* that's an [in out] buffer */
5728 if (!q_u->buffer && (offered!=0)) {
5729 return WERR_INVALID_PARAM;
5732 rpcbuf_move(q_u->buffer, &r_u->buffer);
5733 buffer = r_u->buffer;
5735 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5737 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5738 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5739 return WERR_INVALID_PRINTER_NAME;
5742 *needed = 0;
5743 *servermajorversion = 0;
5744 *serverminorversion = 0;
5746 fstrcpy(servername, get_server_name( printer ));
5747 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5749 if (!get_printer_snum(p, handle, &snum, NULL))
5750 return WERR_BADFID;
5752 switch (level) {
5753 case 1:
5754 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5755 case 2:
5756 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5757 case 3:
5758 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5759 case 6:
5760 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5761 #if 0 /* JERRY */
5762 case 101:
5763 /* apparently this call is the equivalent of
5764 EnumPrinterDataEx() for the DsDriver key */
5765 break;
5766 #endif
5769 return WERR_UNKNOWN_LEVEL;
5772 /****************************************************************************
5773 ****************************************************************************/
5775 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5777 POLICY_HND *handle = &q_u->handle;
5779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5781 if (!Printer) {
5782 DEBUG(3,("Error in startpageprinter printer handle\n"));
5783 return WERR_BADFID;
5786 Printer->page_started=True;
5787 return WERR_OK;
5790 /****************************************************************************
5791 ****************************************************************************/
5793 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5795 POLICY_HND *handle = &q_u->handle;
5796 int snum;
5798 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5800 if (!Printer) {
5801 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5802 return WERR_BADFID;
5805 if (!get_printer_snum(p, handle, &snum, NULL))
5806 return WERR_BADFID;
5808 Printer->page_started=False;
5809 print_job_endpage(snum, Printer->jobid);
5811 return WERR_OK;
5814 /********************************************************************
5815 * api_spoolss_getprinter
5816 * called from the spoolss dispatcher
5818 ********************************************************************/
5820 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5822 POLICY_HND *handle = &q_u->handle;
5823 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5824 uint32 *jobid = &r_u->jobid;
5825 TALLOC_CTX *ctx = p->mem_ctx;
5826 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5827 int snum;
5828 char *jobname = NULL;
5829 fstring datatype;
5830 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5832 if (!Printer) {
5833 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5834 return WERR_BADFID;
5838 * a nice thing with NT is it doesn't listen to what you tell it.
5839 * when asked to send _only_ RAW datas, it tries to send datas
5840 * in EMF format.
5842 * So I add checks like in NT Server ...
5845 if (info_1->p_datatype != 0) {
5846 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5847 if (strcmp(datatype, "RAW") != 0) {
5848 (*jobid)=0;
5849 return WERR_INVALID_DATATYPE;
5853 /* get the share number of the printer */
5854 if (!get_printer_snum(p, handle, &snum, NULL)) {
5855 return WERR_BADFID;
5858 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5860 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5862 /* An error occured in print_job_start() so return an appropriate
5863 NT error code. */
5865 if (Printer->jobid == -1) {
5866 return map_werror_from_unix(errno);
5869 Printer->document_started=True;
5870 (*jobid) = Printer->jobid;
5872 return WERR_OK;
5875 /********************************************************************
5876 * api_spoolss_getprinter
5877 * called from the spoolss dispatcher
5879 ********************************************************************/
5881 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5883 POLICY_HND *handle = &q_u->handle;
5885 return _spoolss_enddocprinter_internal(p, handle);
5888 /****************************************************************************
5889 ****************************************************************************/
5891 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5893 POLICY_HND *handle = &q_u->handle;
5894 uint32 buffer_size = q_u->buffer_size;
5895 uint8 *buffer = q_u->buffer;
5896 uint32 *buffer_written = &q_u->buffer_size2;
5897 int snum;
5898 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5900 if (!Printer) {
5901 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5902 r_u->buffer_written = q_u->buffer_size2;
5903 return WERR_BADFID;
5906 if (!get_printer_snum(p, handle, &snum, NULL))
5907 return WERR_BADFID;
5909 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5910 (SMB_OFF_T)-1, (size_t)buffer_size);
5911 if (*buffer_written == (uint32)-1) {
5912 r_u->buffer_written = 0;
5913 if (errno == ENOSPC)
5914 return WERR_NO_SPOOL_SPACE;
5915 else
5916 return WERR_ACCESS_DENIED;
5919 r_u->buffer_written = q_u->buffer_size2;
5921 return WERR_OK;
5924 /********************************************************************
5925 * api_spoolss_getprinter
5926 * called from the spoolss dispatcher
5928 ********************************************************************/
5930 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5931 pipes_struct *p)
5933 int snum;
5934 WERROR errcode = WERR_BADFUNC;
5935 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5937 if (!Printer) {
5938 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5939 return WERR_BADFID;
5942 if (!get_printer_snum(p, handle, &snum, NULL))
5943 return WERR_BADFID;
5945 switch (command) {
5946 case PRINTER_CONTROL_PAUSE:
5947 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5948 errcode = WERR_OK;
5950 break;
5951 case PRINTER_CONTROL_RESUME:
5952 case PRINTER_CONTROL_UNPAUSE:
5953 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5954 errcode = WERR_OK;
5956 break;
5957 case PRINTER_CONTROL_PURGE:
5958 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5959 errcode = WERR_OK;
5961 break;
5962 default:
5963 return WERR_UNKNOWN_LEVEL;
5966 return errcode;
5969 /********************************************************************
5970 * api_spoolss_abortprinter
5971 * From MSDN: "Deletes printer's spool file if printer is configured
5972 * for spooling"
5973 ********************************************************************/
5975 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5977 POLICY_HND *handle = &q_u->handle;
5978 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5979 int snum;
5980 WERROR errcode = WERR_OK;
5982 if (!Printer) {
5983 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5984 return WERR_BADFID;
5987 if (!get_printer_snum(p, handle, &snum, NULL))
5988 return WERR_BADFID;
5990 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5992 return errcode;
5995 /********************************************************************
5996 * called by spoolss_api_setprinter
5997 * when updating a printer description
5998 ********************************************************************/
6000 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6001 const SPOOL_PRINTER_INFO_LEVEL *info,
6002 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6004 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6005 WERROR result;
6006 int snum;
6008 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6010 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6011 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6012 OUR_HANDLE(handle)));
6014 result = WERR_BADFID;
6015 goto done;
6018 if (!secdesc_ctr) {
6019 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6020 result = WERR_INVALID_PARAM;
6021 goto done;
6024 /* Check the user has permissions to change the security
6025 descriptor. By experimentation with two NT machines, the user
6026 requires Full Access to the printer to change security
6027 information. */
6029 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6030 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6031 result = WERR_ACCESS_DENIED;
6032 goto done;
6035 /* NT seems to like setting the security descriptor even though
6036 nothing may have actually changed. */
6038 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6039 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6040 result = WERR_BADFID;
6041 goto done;
6044 if (DEBUGLEVEL >= 10) {
6045 SEC_ACL *the_acl;
6046 int i;
6048 the_acl = old_secdesc_ctr->sd->dacl;
6049 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6050 PRINTERNAME(snum), the_acl->num_aces));
6052 for (i = 0; i < the_acl->num_aces; i++) {
6053 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6054 &the_acl->aces[i].trustee),
6055 the_acl->aces[i].access_mask));
6058 the_acl = secdesc_ctr->sd->dacl;
6060 if (the_acl) {
6061 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6062 PRINTERNAME(snum), the_acl->num_aces));
6064 for (i = 0; i < the_acl->num_aces; i++) {
6065 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6066 &the_acl->aces[i].trustee),
6067 the_acl->aces[i].access_mask));
6069 } else {
6070 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6074 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6075 if (!new_secdesc_ctr) {
6076 result = WERR_NOMEM;
6077 goto done;
6080 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6081 result = WERR_OK;
6082 goto done;
6085 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6087 done:
6089 return result;
6092 /********************************************************************
6093 Canonicalize printer info from a client
6095 ATTN: It does not matter what we set the servername to hear
6096 since we do the necessary work in get_a_printer() to set it to
6097 the correct value based on what the client sent in the
6098 _spoolss_open_printer_ex().
6099 ********************************************************************/
6101 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6103 fstring printername;
6104 const char *p;
6106 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6107 "portname=%s drivername=%s comment=%s location=%s\n",
6108 info->servername, info->printername, info->sharename,
6109 info->portname, info->drivername, info->comment, info->location));
6111 /* we force some elements to "correct" values */
6112 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6113 fstrcpy(info->sharename, lp_servicename(snum));
6115 /* check to see if we allow printername != sharename */
6117 if ( lp_force_printername(snum) ) {
6118 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6119 global_myname(), info->sharename );
6120 } else {
6122 /* make sure printername is in \\server\printername format */
6124 fstrcpy( printername, info->printername );
6125 p = printername;
6126 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6127 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6128 p++;
6131 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6132 global_myname(), p );
6135 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6136 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6140 return True;
6143 /****************************************************************************
6144 ****************************************************************************/
6146 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6148 char *cmd = lp_addport_cmd();
6149 char *command = NULL;
6150 int ret;
6151 int fd;
6152 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6153 bool is_print_op = False;
6155 if ( !*cmd ) {
6156 return WERR_ACCESS_DENIED;
6159 command = talloc_asprintf(ctx,
6160 "%s \"%s\" \"%s\"", cmd, portname, uri );
6161 if (!command) {
6162 return WERR_NOMEM;
6165 if ( token )
6166 is_print_op = user_has_privileges( token, &se_printop );
6168 DEBUG(10,("Running [%s]\n", command));
6170 /********* BEGIN SePrintOperatorPrivilege **********/
6172 if ( is_print_op )
6173 become_root();
6175 ret = smbrun(command, &fd);
6177 if ( is_print_op )
6178 unbecome_root();
6180 /********* END SePrintOperatorPrivilege **********/
6182 DEBUGADD(10,("returned [%d]\n", ret));
6184 TALLOC_FREE(command);
6186 if ( ret != 0 ) {
6187 if (fd != -1)
6188 close(fd);
6189 return WERR_ACCESS_DENIED;
6192 return WERR_OK;
6195 /****************************************************************************
6196 ****************************************************************************/
6198 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6200 char *cmd = lp_addprinter_cmd();
6201 char **qlines;
6202 char *command = NULL;
6203 int numlines;
6204 int ret;
6205 int fd;
6206 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6207 bool is_print_op = False;
6208 char *remote_machine = talloc_strdup(ctx, "%m");
6210 if (!remote_machine) {
6211 return false;
6213 remote_machine = talloc_sub_basic(ctx,
6214 current_user_info.smb_name,
6215 current_user_info.domain,
6216 remote_machine);
6217 if (!remote_machine) {
6218 return false;
6221 command = talloc_asprintf(ctx,
6222 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6223 cmd, printer->info_2->printername, printer->info_2->sharename,
6224 printer->info_2->portname, printer->info_2->drivername,
6225 printer->info_2->location, printer->info_2->comment, remote_machine);
6226 if (!command) {
6227 return false;
6230 if ( token )
6231 is_print_op = user_has_privileges( token, &se_printop );
6233 DEBUG(10,("Running [%s]\n", command));
6235 /********* BEGIN SePrintOperatorPrivilege **********/
6237 if ( is_print_op )
6238 become_root();
6240 if ( (ret = smbrun(command, &fd)) == 0 ) {
6241 /* Tell everyone we updated smb.conf. */
6242 message_send_all(smbd_messaging_context(),
6243 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6246 if ( is_print_op )
6247 unbecome_root();
6249 /********* END SePrintOperatorPrivilege **********/
6251 DEBUGADD(10,("returned [%d]\n", ret));
6253 TALLOC_FREE(command);
6254 TALLOC_FREE(remote_machine);
6256 if ( ret != 0 ) {
6257 if (fd != -1)
6258 close(fd);
6259 return False;
6262 /* reload our services immediately */
6263 reload_services( False );
6265 numlines = 0;
6266 /* Get lines and convert them back to dos-codepage */
6267 qlines = fd_lines_load(fd, &numlines, 0);
6268 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6269 close(fd);
6271 /* Set the portname to what the script says the portname should be. */
6272 /* but don't require anything to be return from the script exit a good error code */
6274 if (numlines) {
6275 /* Set the portname to what the script says the portname should be. */
6276 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6277 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6280 file_lines_free(qlines);
6281 return True;
6285 /********************************************************************
6286 * Called by spoolss_api_setprinter
6287 * when updating a printer description.
6288 ********************************************************************/
6290 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6291 const SPOOL_PRINTER_INFO_LEVEL *info,
6292 DEVICEMODE *devmode)
6294 int snum;
6295 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6296 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6297 WERROR result;
6298 UNISTR2 buffer;
6299 fstring asc_buffer;
6301 DEBUG(8,("update_printer\n"));
6303 result = WERR_OK;
6305 if (!Printer) {
6306 result = WERR_BADFID;
6307 goto done;
6310 if (!get_printer_snum(p, handle, &snum, NULL)) {
6311 result = WERR_BADFID;
6312 goto done;
6315 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6316 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6317 result = WERR_BADFID;
6318 goto done;
6321 DEBUGADD(8,("Converting info_2 struct\n"));
6324 * convert_printer_info converts the incoming
6325 * info from the client and overwrites the info
6326 * just read from the tdb in the pointer 'printer'.
6329 if (!convert_printer_info(info, printer, level)) {
6330 result = WERR_NOMEM;
6331 goto done;
6334 if (devmode) {
6335 /* we have a valid devmode
6336 convert it and link it*/
6338 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6339 if (!convert_devicemode(printer->info_2->printername, devmode,
6340 &printer->info_2->devmode)) {
6341 result = WERR_NOMEM;
6342 goto done;
6346 /* Do sanity check on the requested changes for Samba */
6348 if (!check_printer_ok(printer->info_2, snum)) {
6349 result = WERR_INVALID_PARAM;
6350 goto done;
6353 /* FIXME!!! If the driver has changed we really should verify that
6354 it is installed before doing much else --jerry */
6356 /* Check calling user has permission to update printer description */
6358 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6359 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6360 result = WERR_ACCESS_DENIED;
6361 goto done;
6364 /* Call addprinter hook */
6365 /* Check changes to see if this is really needed */
6367 if ( *lp_addprinter_cmd()
6368 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6369 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6370 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6371 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6373 /* add_printer_hook() will call reload_services() */
6375 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6376 result = WERR_ACCESS_DENIED;
6377 goto done;
6382 * When a *new* driver is bound to a printer, the drivername is used to
6383 * lookup previously saved driver initialization info, which is then
6384 * bound to the printer, simulating what happens in the Windows arch.
6386 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6388 if (!set_driver_init(printer, 2))
6390 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6391 printer->info_2->drivername));
6394 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6395 printer->info_2->drivername));
6397 notify_printer_driver(snum, printer->info_2->drivername);
6401 * flag which changes actually occured. This is a small subset of
6402 * all the possible changes. We also have to update things in the
6403 * DsSpooler key.
6406 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6407 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6408 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6409 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6411 notify_printer_comment(snum, printer->info_2->comment);
6414 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6415 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6416 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6417 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6419 notify_printer_sharename(snum, printer->info_2->sharename);
6422 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6423 char *pname;
6425 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6426 pname++;
6427 else
6428 pname = printer->info_2->printername;
6431 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6432 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6433 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6435 notify_printer_printername( snum, pname );
6438 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6439 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6440 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6441 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6443 notify_printer_port(snum, printer->info_2->portname);
6446 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6447 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6448 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6449 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6451 notify_printer_location(snum, printer->info_2->location);
6454 /* here we need to update some more DsSpooler keys */
6455 /* uNCName, serverName, shortServerName */
6457 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6458 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6459 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6460 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6461 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6463 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6464 global_myname(), printer->info_2->sharename );
6465 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6466 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6467 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6469 /* Update printer info */
6470 result = mod_a_printer(printer, 2);
6472 done:
6473 free_a_printer(&printer, 2);
6474 free_a_printer(&old_printer, 2);
6477 return result;
6480 /****************************************************************************
6481 ****************************************************************************/
6482 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6483 const SPOOL_PRINTER_INFO_LEVEL *info)
6485 #ifdef HAVE_ADS
6486 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6487 int snum;
6488 Printer_entry *Printer;
6490 if ( lp_security() != SEC_ADS ) {
6491 return WERR_UNKNOWN_LEVEL;
6494 Printer = find_printer_index_by_hnd(p, handle);
6496 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6498 if (!Printer)
6499 return WERR_BADFID;
6501 if (!get_printer_snum(p, handle, &snum, NULL))
6502 return WERR_BADFID;
6504 nt_printer_publish(Printer, snum, info7->action);
6506 return WERR_OK;
6507 #else
6508 return WERR_UNKNOWN_LEVEL;
6509 #endif
6511 /****************************************************************************
6512 ****************************************************************************/
6514 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6516 POLICY_HND *handle = &q_u->handle;
6517 uint32 level = q_u->level;
6518 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6519 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6520 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6521 uint32 command = q_u->command;
6522 WERROR result;
6524 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6526 if (!Printer) {
6527 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6528 return WERR_BADFID;
6531 /* check the level */
6532 switch (level) {
6533 case 0:
6534 return control_printer(handle, command, p);
6535 case 2:
6536 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6537 if (!W_ERROR_IS_OK(result))
6538 return result;
6539 if (secdesc_ctr)
6540 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6541 return result;
6542 case 3:
6543 return update_printer_sec(handle, level, info, p,
6544 secdesc_ctr);
6545 case 7:
6546 return publish_or_unpublish_printer(p, handle, info);
6547 default:
6548 return WERR_UNKNOWN_LEVEL;
6552 /****************************************************************************
6553 ****************************************************************************/
6555 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6557 POLICY_HND *handle = &q_u->handle;
6558 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6560 if (!Printer) {
6561 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6562 return WERR_BADFID;
6565 if (Printer->notify.client_connected==True) {
6566 int snum = -1;
6568 if ( Printer->printer_type == SPLHND_SERVER)
6569 snum = -1;
6570 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6571 !get_printer_snum(p, handle, &snum, NULL) )
6572 return WERR_BADFID;
6574 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6577 Printer->notify.flags=0;
6578 Printer->notify.options=0;
6579 Printer->notify.localmachine[0]='\0';
6580 Printer->notify.printerlocal=0;
6581 if (Printer->notify.option)
6582 free_spool_notify_option(&Printer->notify.option);
6583 Printer->notify.client_connected=False;
6585 return WERR_OK;
6588 /****************************************************************************
6589 ****************************************************************************/
6591 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6593 /* that's an [in out] buffer */
6595 if (!q_u->buffer && (q_u->offered!=0)) {
6596 return WERR_INVALID_PARAM;
6599 rpcbuf_move(q_u->buffer, &r_u->buffer);
6601 r_u->needed = 0;
6602 return WERR_INVALID_PARAM; /* this is what a NT server
6603 returns for AddJob. AddJob
6604 must fail on non-local
6605 printers */
6608 /****************************************************************************
6609 ****************************************************************************/
6611 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6612 int position, int snum,
6613 const NT_PRINTER_INFO_LEVEL *ntprinter)
6615 struct tm *t;
6617 t=gmtime(&queue->time);
6619 job_info->jobid=queue->job;
6620 init_unistr(&job_info->printername, lp_servicename(snum));
6621 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6622 init_unistr(&job_info->username, queue->fs_user);
6623 init_unistr(&job_info->document, queue->fs_file);
6624 init_unistr(&job_info->datatype, "RAW");
6625 init_unistr(&job_info->text_status, "");
6626 job_info->status=nt_printj_status(queue->status);
6627 job_info->priority=queue->priority;
6628 job_info->position=position;
6629 job_info->totalpages=queue->page_count;
6630 job_info->pagesprinted=0;
6632 make_systemtime(&job_info->submitted, t);
6635 /****************************************************************************
6636 ****************************************************************************/
6638 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6639 int position, int snum,
6640 const NT_PRINTER_INFO_LEVEL *ntprinter,
6641 DEVICEMODE *devmode)
6643 struct tm *t;
6645 t=gmtime(&queue->time);
6647 job_info->jobid=queue->job;
6649 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6651 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6652 init_unistr(&job_info->username, queue->fs_user);
6653 init_unistr(&job_info->document, queue->fs_file);
6654 init_unistr(&job_info->notifyname, queue->fs_user);
6655 init_unistr(&job_info->datatype, "RAW");
6656 init_unistr(&job_info->printprocessor, "winprint");
6657 init_unistr(&job_info->parameters, "");
6658 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6659 init_unistr(&job_info->text_status, "");
6661 /* and here the security descriptor */
6663 job_info->status=nt_printj_status(queue->status);
6664 job_info->priority=queue->priority;
6665 job_info->position=position;
6666 job_info->starttime=0;
6667 job_info->untiltime=0;
6668 job_info->totalpages=queue->page_count;
6669 job_info->size=queue->size;
6670 make_systemtime(&(job_info->submitted), t);
6671 job_info->timeelapsed=0;
6672 job_info->pagesprinted=0;
6674 job_info->devmode = devmode;
6676 return (True);
6679 /****************************************************************************
6680 Enumjobs at level 1.
6681 ****************************************************************************/
6683 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6684 const NT_PRINTER_INFO_LEVEL *ntprinter,
6685 RPC_BUFFER *buffer, uint32 offered,
6686 uint32 *needed, uint32 *returned)
6688 JOB_INFO_1 *info;
6689 int i;
6690 WERROR result = WERR_OK;
6692 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6693 if (info==NULL) {
6694 *returned=0;
6695 return WERR_NOMEM;
6698 for (i=0; i<*returned; i++)
6699 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6701 /* check the required size. */
6702 for (i=0; i<*returned; i++)
6703 (*needed) += spoolss_size_job_info_1(&info[i]);
6705 if (*needed > offered) {
6706 result = WERR_INSUFFICIENT_BUFFER;
6707 goto out;
6710 if (!rpcbuf_alloc_size(buffer, *needed)) {
6711 result = WERR_NOMEM;
6712 goto out;
6715 /* fill the buffer with the structures */
6716 for (i=0; i<*returned; i++)
6717 smb_io_job_info_1("", buffer, &info[i], 0);
6719 out:
6720 /* clear memory */
6721 SAFE_FREE(info);
6723 if ( !W_ERROR_IS_OK(result) )
6724 *returned = 0;
6726 return result;
6729 /****************************************************************************
6730 Enumjobs at level 2.
6731 ****************************************************************************/
6733 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6734 const NT_PRINTER_INFO_LEVEL *ntprinter,
6735 RPC_BUFFER *buffer, uint32 offered,
6736 uint32 *needed, uint32 *returned)
6738 JOB_INFO_2 *info = NULL;
6739 int i;
6740 WERROR result = WERR_OK;
6741 DEVICEMODE *devmode = NULL;
6743 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6744 *returned=0;
6745 return WERR_NOMEM;
6748 /* this should not be a failure condition if the devmode is NULL */
6750 devmode = construct_dev_mode(lp_const_servicename(snum));
6752 for (i=0; i<*returned; i++)
6753 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6755 /* check the required size. */
6756 for (i=0; i<*returned; i++)
6757 (*needed) += spoolss_size_job_info_2(&info[i]);
6759 if (*needed > offered) {
6760 result = WERR_INSUFFICIENT_BUFFER;
6761 goto out;
6764 if (!rpcbuf_alloc_size(buffer, *needed)) {
6765 result = WERR_NOMEM;
6766 goto out;
6769 /* fill the buffer with the structures */
6770 for (i=0; i<*returned; i++)
6771 smb_io_job_info_2("", buffer, &info[i], 0);
6773 out:
6774 free_devmode(devmode);
6775 SAFE_FREE(info);
6777 if ( !W_ERROR_IS_OK(result) )
6778 *returned = 0;
6780 return result;
6784 /****************************************************************************
6785 Enumjobs.
6786 ****************************************************************************/
6788 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6790 POLICY_HND *handle = &q_u->handle;
6791 uint32 level = q_u->level;
6792 RPC_BUFFER *buffer = NULL;
6793 uint32 offered = q_u->offered;
6794 uint32 *needed = &r_u->needed;
6795 uint32 *returned = &r_u->returned;
6796 WERROR wret;
6797 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6798 int snum;
6799 print_status_struct prt_status;
6800 print_queue_struct *queue=NULL;
6802 /* that's an [in out] buffer */
6804 if (!q_u->buffer && (offered!=0)) {
6805 return WERR_INVALID_PARAM;
6808 rpcbuf_move(q_u->buffer, &r_u->buffer);
6809 buffer = r_u->buffer;
6811 DEBUG(4,("_spoolss_enumjobs\n"));
6813 *needed=0;
6814 *returned=0;
6816 /* lookup the printer snum and tdb entry */
6818 if (!get_printer_snum(p, handle, &snum, NULL))
6819 return WERR_BADFID;
6821 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6822 if ( !W_ERROR_IS_OK(wret) )
6823 return wret;
6825 *returned = print_queue_status(snum, &queue, &prt_status);
6826 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6828 if (*returned == 0) {
6829 SAFE_FREE(queue);
6830 free_a_printer(&ntprinter, 2);
6831 return WERR_OK;
6834 switch (level) {
6835 case 1:
6836 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6837 break;
6838 case 2:
6839 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6840 break;
6841 default:
6842 *returned=0;
6843 wret = WERR_UNKNOWN_LEVEL;
6844 break;
6847 SAFE_FREE(queue);
6848 free_a_printer( &ntprinter, 2 );
6849 return wret;
6852 /****************************************************************************
6853 ****************************************************************************/
6855 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6857 return WERR_OK;
6860 /****************************************************************************
6861 ****************************************************************************/
6863 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6865 POLICY_HND *handle = &q_u->handle;
6866 uint32 jobid = q_u->jobid;
6867 uint32 command = q_u->command;
6869 int snum;
6870 WERROR errcode = WERR_BADFUNC;
6872 if (!get_printer_snum(p, handle, &snum, NULL)) {
6873 return WERR_BADFID;
6876 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6877 return WERR_INVALID_PRINTER_NAME;
6880 switch (command) {
6881 case JOB_CONTROL_CANCEL:
6882 case JOB_CONTROL_DELETE:
6883 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6884 errcode = WERR_OK;
6886 break;
6887 case JOB_CONTROL_PAUSE:
6888 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6889 errcode = WERR_OK;
6891 break;
6892 case JOB_CONTROL_RESTART:
6893 case JOB_CONTROL_RESUME:
6894 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6895 errcode = WERR_OK;
6897 break;
6898 default:
6899 return WERR_UNKNOWN_LEVEL;
6902 return errcode;
6905 /****************************************************************************
6906 Enumerates all printer drivers at level 1.
6907 ****************************************************************************/
6909 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6911 int i;
6912 int ndrivers;
6913 uint32 version;
6914 fstring *list = NULL;
6915 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6916 DRIVER_INFO_1 *driver_info_1=NULL;
6917 WERROR result = WERR_OK;
6919 *returned=0;
6921 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6922 list=NULL;
6923 ndrivers=get_ntdrivers(&list, architecture, version);
6924 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6926 if(ndrivers == -1) {
6927 SAFE_FREE(driver_info_1);
6928 return WERR_NOMEM;
6931 if(ndrivers != 0) {
6932 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6933 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6934 SAFE_FREE(list);
6935 return WERR_NOMEM;
6939 for (i=0; i<ndrivers; i++) {
6940 WERROR status;
6941 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6942 ZERO_STRUCT(driver);
6943 status = get_a_printer_driver(&driver, 3, list[i],
6944 architecture, version);
6945 if (!W_ERROR_IS_OK(status)) {
6946 SAFE_FREE(list);
6947 SAFE_FREE(driver_info_1);
6948 return status;
6950 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6951 free_a_printer_driver(driver, 3);
6954 *returned+=ndrivers;
6955 SAFE_FREE(list);
6958 /* check the required size. */
6959 for (i=0; i<*returned; i++) {
6960 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6961 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6964 if (*needed > offered) {
6965 result = WERR_INSUFFICIENT_BUFFER;
6966 goto out;
6969 if (!rpcbuf_alloc_size(buffer, *needed)) {
6970 result = WERR_NOMEM;
6971 goto out;
6974 /* fill the buffer with the driver structures */
6975 for (i=0; i<*returned; i++) {
6976 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6977 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6980 out:
6981 SAFE_FREE(driver_info_1);
6983 if ( !W_ERROR_IS_OK(result) )
6984 *returned = 0;
6986 return result;
6989 /****************************************************************************
6990 Enumerates all printer drivers at level 2.
6991 ****************************************************************************/
6993 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6995 int i;
6996 int ndrivers;
6997 uint32 version;
6998 fstring *list = NULL;
6999 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7000 DRIVER_INFO_2 *driver_info_2=NULL;
7001 WERROR result = WERR_OK;
7003 *returned=0;
7005 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7006 list=NULL;
7007 ndrivers=get_ntdrivers(&list, architecture, version);
7008 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7010 if(ndrivers == -1) {
7011 SAFE_FREE(driver_info_2);
7012 return WERR_NOMEM;
7015 if(ndrivers != 0) {
7016 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7017 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7018 SAFE_FREE(list);
7019 return WERR_NOMEM;
7023 for (i=0; i<ndrivers; i++) {
7024 WERROR status;
7026 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7027 ZERO_STRUCT(driver);
7028 status = get_a_printer_driver(&driver, 3, list[i],
7029 architecture, version);
7030 if (!W_ERROR_IS_OK(status)) {
7031 SAFE_FREE(list);
7032 SAFE_FREE(driver_info_2);
7033 return status;
7035 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7036 free_a_printer_driver(driver, 3);
7039 *returned+=ndrivers;
7040 SAFE_FREE(list);
7043 /* check the required size. */
7044 for (i=0; i<*returned; i++) {
7045 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7046 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7049 if (*needed > offered) {
7050 result = WERR_INSUFFICIENT_BUFFER;
7051 goto out;
7054 if (!rpcbuf_alloc_size(buffer, *needed)) {
7055 result = WERR_NOMEM;
7056 goto out;
7059 /* fill the buffer with the form structures */
7060 for (i=0; i<*returned; i++) {
7061 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7062 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7065 out:
7066 SAFE_FREE(driver_info_2);
7068 if ( !W_ERROR_IS_OK(result) )
7069 *returned = 0;
7071 return result;
7074 /****************************************************************************
7075 Enumerates all printer drivers at level 3.
7076 ****************************************************************************/
7078 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7080 int i;
7081 int ndrivers;
7082 uint32 version;
7083 fstring *list = NULL;
7084 DRIVER_INFO_3 *driver_info_3=NULL;
7085 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7086 WERROR result = WERR_OK;
7088 *returned=0;
7090 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7091 list=NULL;
7092 ndrivers=get_ntdrivers(&list, architecture, version);
7093 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7095 if(ndrivers == -1) {
7096 SAFE_FREE(driver_info_3);
7097 return WERR_NOMEM;
7100 if(ndrivers != 0) {
7101 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7102 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7103 SAFE_FREE(list);
7104 return WERR_NOMEM;
7108 for (i=0; i<ndrivers; i++) {
7109 WERROR status;
7111 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7112 ZERO_STRUCT(driver);
7113 status = get_a_printer_driver(&driver, 3, list[i],
7114 architecture, version);
7115 if (!W_ERROR_IS_OK(status)) {
7116 SAFE_FREE(list);
7117 SAFE_FREE(driver_info_3);
7118 return status;
7120 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7121 free_a_printer_driver(driver, 3);
7124 *returned+=ndrivers;
7125 SAFE_FREE(list);
7128 /* check the required size. */
7129 for (i=0; i<*returned; i++) {
7130 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7131 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7134 if (*needed > offered) {
7135 result = WERR_INSUFFICIENT_BUFFER;
7136 goto out;
7139 if (!rpcbuf_alloc_size(buffer, *needed)) {
7140 result = WERR_NOMEM;
7141 goto out;
7144 /* fill the buffer with the driver structures */
7145 for (i=0; i<*returned; i++) {
7146 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7147 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7150 out:
7151 for (i=0; i<*returned; i++) {
7152 SAFE_FREE(driver_info_3[i].dependentfiles);
7155 SAFE_FREE(driver_info_3);
7157 if ( !W_ERROR_IS_OK(result) )
7158 *returned = 0;
7160 return result;
7163 /****************************************************************************
7164 Enumerates all printer drivers.
7165 ****************************************************************************/
7167 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7169 uint32 level = q_u->level;
7170 RPC_BUFFER *buffer = NULL;
7171 uint32 offered = q_u->offered;
7172 uint32 *needed = &r_u->needed;
7173 uint32 *returned = &r_u->returned;
7175 fstring servername;
7176 fstring architecture;
7178 /* that's an [in out] buffer */
7180 if (!q_u->buffer && (offered!=0)) {
7181 return WERR_INVALID_PARAM;
7184 rpcbuf_move(q_u->buffer, &r_u->buffer);
7185 buffer = r_u->buffer;
7187 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7189 *needed = 0;
7190 *returned = 0;
7192 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7193 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7195 if ( !is_myname_or_ipaddr( servername ) )
7196 return WERR_UNKNOWN_PRINTER_DRIVER;
7198 switch (level) {
7199 case 1:
7200 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7201 case 2:
7202 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7203 case 3:
7204 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7205 default:
7206 return WERR_UNKNOWN_LEVEL;
7210 /****************************************************************************
7211 ****************************************************************************/
7213 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7215 form->flag=list->flag;
7216 init_unistr(&form->name, list->name);
7217 form->width=list->width;
7218 form->length=list->length;
7219 form->left=list->left;
7220 form->top=list->top;
7221 form->right=list->right;
7222 form->bottom=list->bottom;
7225 /****************************************************************************
7226 ****************************************************************************/
7228 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7230 uint32 level = q_u->level;
7231 RPC_BUFFER *buffer = NULL;
7232 uint32 offered = q_u->offered;
7233 uint32 *needed = &r_u->needed;
7234 uint32 *numofforms = &r_u->numofforms;
7235 uint32 numbuiltinforms;
7237 nt_forms_struct *list=NULL;
7238 nt_forms_struct *builtinlist=NULL;
7239 FORM_1 *forms_1;
7240 int buffer_size=0;
7241 int i;
7243 /* that's an [in out] buffer */
7245 if (!q_u->buffer && (offered!=0) ) {
7246 return WERR_INVALID_PARAM;
7249 rpcbuf_move(q_u->buffer, &r_u->buffer);
7250 buffer = r_u->buffer;
7252 DEBUG(4,("_spoolss_enumforms\n"));
7253 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7254 DEBUGADD(5,("Info level [%d]\n", level));
7256 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7257 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7258 *numofforms = get_ntforms(&list);
7259 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7260 *numofforms += numbuiltinforms;
7262 if (*numofforms == 0) {
7263 SAFE_FREE(builtinlist);
7264 SAFE_FREE(list);
7265 return WERR_NO_MORE_ITEMS;
7268 switch (level) {
7269 case 1:
7270 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7271 SAFE_FREE(builtinlist);
7272 SAFE_FREE(list);
7273 *numofforms=0;
7274 return WERR_NOMEM;
7277 /* construct the list of form structures */
7278 for (i=0; i<numbuiltinforms; i++) {
7279 DEBUGADD(6,("Filling form number [%d]\n",i));
7280 fill_form_1(&forms_1[i], &builtinlist[i]);
7283 SAFE_FREE(builtinlist);
7285 for (; i<*numofforms; i++) {
7286 DEBUGADD(6,("Filling form number [%d]\n",i));
7287 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7290 SAFE_FREE(list);
7292 /* check the required size. */
7293 for (i=0; i<numbuiltinforms; i++) {
7294 DEBUGADD(6,("adding form [%d]'s size\n",i));
7295 buffer_size += spoolss_size_form_1(&forms_1[i]);
7297 for (; i<*numofforms; i++) {
7298 DEBUGADD(6,("adding form [%d]'s size\n",i));
7299 buffer_size += spoolss_size_form_1(&forms_1[i]);
7302 *needed=buffer_size;
7304 if (*needed > offered) {
7305 SAFE_FREE(forms_1);
7306 *numofforms=0;
7307 return WERR_INSUFFICIENT_BUFFER;
7310 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7311 SAFE_FREE(forms_1);
7312 *numofforms=0;
7313 return WERR_NOMEM;
7316 /* fill the buffer with the form structures */
7317 for (i=0; i<numbuiltinforms; i++) {
7318 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7319 smb_io_form_1("", buffer, &forms_1[i], 0);
7321 for (; i<*numofforms; i++) {
7322 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7323 smb_io_form_1("", buffer, &forms_1[i], 0);
7326 SAFE_FREE(forms_1);
7328 return WERR_OK;
7330 default:
7331 SAFE_FREE(list);
7332 SAFE_FREE(builtinlist);
7333 return WERR_UNKNOWN_LEVEL;
7337 /****************************************************************************
7338 ****************************************************************************/
7340 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7342 uint32 level = q_u->level;
7343 UNISTR2 *uni_formname = &q_u->formname;
7344 RPC_BUFFER *buffer = NULL;
7345 uint32 offered = q_u->offered;
7346 uint32 *needed = &r_u->needed;
7348 nt_forms_struct *list=NULL;
7349 nt_forms_struct builtin_form;
7350 bool foundBuiltin;
7351 FORM_1 form_1;
7352 fstring form_name;
7353 int buffer_size=0;
7354 int numofforms=0, i=0;
7356 /* that's an [in out] buffer */
7358 if (!q_u->buffer && (offered!=0)) {
7359 return WERR_INVALID_PARAM;
7362 rpcbuf_move(q_u->buffer, &r_u->buffer);
7363 buffer = r_u->buffer;
7365 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7367 DEBUG(4,("_spoolss_getform\n"));
7368 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7369 DEBUGADD(5,("Info level [%d]\n", level));
7371 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7372 if (!foundBuiltin) {
7373 numofforms = get_ntforms(&list);
7374 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7376 if (numofforms == 0)
7377 return WERR_BADFID;
7380 switch (level) {
7381 case 1:
7382 if (foundBuiltin) {
7383 fill_form_1(&form_1, &builtin_form);
7384 } else {
7386 /* Check if the requested name is in the list of form structures */
7387 for (i=0; i<numofforms; i++) {
7389 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7391 if (strequal(form_name, list[i].name)) {
7392 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7393 fill_form_1(&form_1, &list[i]);
7394 break;
7398 SAFE_FREE(list);
7399 if (i == numofforms) {
7400 return WERR_BADFID;
7403 /* check the required size. */
7405 *needed=spoolss_size_form_1(&form_1);
7407 if (*needed > offered)
7408 return WERR_INSUFFICIENT_BUFFER;
7410 if (!rpcbuf_alloc_size(buffer, buffer_size))
7411 return WERR_NOMEM;
7413 /* fill the buffer with the form structures */
7414 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7415 smb_io_form_1("", buffer, &form_1, 0);
7417 return WERR_OK;
7419 default:
7420 SAFE_FREE(list);
7421 return WERR_UNKNOWN_LEVEL;
7425 /****************************************************************************
7426 ****************************************************************************/
7428 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7430 init_unistr(&port->port_name, name);
7433 /****************************************************************************
7434 TODO: This probably needs distinguish between TCP/IP and Local ports
7435 somehow.
7436 ****************************************************************************/
7438 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7440 init_unistr(&port->port_name, name);
7441 init_unistr(&port->monitor_name, "Local Monitor");
7442 init_unistr(&port->description, SPL_LOCAL_PORT );
7443 port->port_type=PORT_TYPE_WRITE;
7444 port->reserved=0x0;
7448 /****************************************************************************
7449 wrapper around the enumer ports command
7450 ****************************************************************************/
7452 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7454 char *cmd = lp_enumports_cmd();
7455 char **qlines = NULL;
7456 char *command = NULL;
7457 int numlines;
7458 int ret;
7459 int fd;
7461 *count = 0;
7462 *lines = NULL;
7464 /* if no hook then just fill in the default port */
7466 if ( !*cmd ) {
7467 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7468 return WERR_NOMEM;
7470 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7471 SAFE_FREE(qlines);
7472 return WERR_NOMEM;
7474 qlines[1] = NULL;
7475 numlines = 1;
7477 else {
7478 /* we have a valid enumport command */
7480 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7481 if (!command) {
7482 return WERR_NOMEM;
7485 DEBUG(10,("Running [%s]\n", command));
7486 ret = smbrun(command, &fd);
7487 DEBUG(10,("Returned [%d]\n", ret));
7488 TALLOC_FREE(command);
7489 if (ret != 0) {
7490 if (fd != -1) {
7491 close(fd);
7493 return WERR_ACCESS_DENIED;
7496 numlines = 0;
7497 qlines = fd_lines_load(fd, &numlines, 0);
7498 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7499 close(fd);
7502 *count = numlines;
7503 *lines = qlines;
7505 return WERR_OK;
7508 /****************************************************************************
7509 enumports level 1.
7510 ****************************************************************************/
7512 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7514 PORT_INFO_1 *ports=NULL;
7515 int i=0;
7516 WERROR result = WERR_OK;
7517 char **qlines = NULL;
7518 int numlines = 0;
7520 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7521 if (!W_ERROR_IS_OK(result)) {
7522 file_lines_free(qlines);
7523 return result;
7526 if(numlines) {
7527 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7528 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7529 dos_errstr(WERR_NOMEM)));
7530 file_lines_free(qlines);
7531 return WERR_NOMEM;
7534 for (i=0; i<numlines; i++) {
7535 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7536 fill_port_1(&ports[i], qlines[i]);
7539 file_lines_free(qlines);
7541 *returned = numlines;
7543 /* check the required size. */
7544 for (i=0; i<*returned; i++) {
7545 DEBUGADD(6,("adding port [%d]'s size\n", i));
7546 *needed += spoolss_size_port_info_1(&ports[i]);
7549 if (*needed > offered) {
7550 result = WERR_INSUFFICIENT_BUFFER;
7551 goto out;
7554 if (!rpcbuf_alloc_size(buffer, *needed)) {
7555 result = WERR_NOMEM;
7556 goto out;
7559 /* fill the buffer with the ports structures */
7560 for (i=0; i<*returned; i++) {
7561 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7562 smb_io_port_1("", buffer, &ports[i], 0);
7565 out:
7566 SAFE_FREE(ports);
7568 if ( !W_ERROR_IS_OK(result) )
7569 *returned = 0;
7571 return result;
7574 /****************************************************************************
7575 enumports level 2.
7576 ****************************************************************************/
7578 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7580 PORT_INFO_2 *ports=NULL;
7581 int i=0;
7582 WERROR result = WERR_OK;
7583 char **qlines = NULL;
7584 int numlines = 0;
7586 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7587 if ( !W_ERROR_IS_OK(result)) {
7588 file_lines_free(qlines);
7589 return result;
7592 if(numlines) {
7593 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7594 file_lines_free(qlines);
7595 return WERR_NOMEM;
7598 for (i=0; i<numlines; i++) {
7599 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7600 fill_port_2(&(ports[i]), qlines[i]);
7604 file_lines_free(qlines);
7606 *returned = numlines;
7608 /* check the required size. */
7609 for (i=0; i<*returned; i++) {
7610 DEBUGADD(6,("adding port [%d]'s size\n", i));
7611 *needed += spoolss_size_port_info_2(&ports[i]);
7614 if (*needed > offered) {
7615 result = WERR_INSUFFICIENT_BUFFER;
7616 goto out;
7619 if (!rpcbuf_alloc_size(buffer, *needed)) {
7620 result = WERR_NOMEM;
7621 goto out;
7624 /* fill the buffer with the ports structures */
7625 for (i=0; i<*returned; i++) {
7626 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7627 smb_io_port_2("", buffer, &ports[i], 0);
7630 out:
7631 SAFE_FREE(ports);
7633 if ( !W_ERROR_IS_OK(result) )
7634 *returned = 0;
7636 return result;
7639 /****************************************************************************
7640 enumports.
7641 ****************************************************************************/
7643 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7645 uint32 level = q_u->level;
7646 RPC_BUFFER *buffer = NULL;
7647 uint32 offered = q_u->offered;
7648 uint32 *needed = &r_u->needed;
7649 uint32 *returned = &r_u->returned;
7651 /* that's an [in out] buffer */
7653 if (!q_u->buffer && (offered!=0)) {
7654 return WERR_INVALID_PARAM;
7657 rpcbuf_move(q_u->buffer, &r_u->buffer);
7658 buffer = r_u->buffer;
7660 DEBUG(4,("_spoolss_enumports\n"));
7662 *returned=0;
7663 *needed=0;
7665 switch (level) {
7666 case 1:
7667 return enumports_level_1(buffer, offered, needed, returned);
7668 case 2:
7669 return enumports_level_2(buffer, offered, needed, returned);
7670 default:
7671 return WERR_UNKNOWN_LEVEL;
7675 /****************************************************************************
7676 ****************************************************************************/
7678 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7679 const SPOOL_PRINTER_INFO_LEVEL *info,
7680 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7681 uint32 user_switch, const SPOOL_USER_CTR *user,
7682 POLICY_HND *handle)
7684 NT_PRINTER_INFO_LEVEL *printer = NULL;
7685 fstring name;
7686 int snum;
7687 WERROR err = WERR_OK;
7689 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7690 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7691 return WERR_NOMEM;
7694 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7695 if (!convert_printer_info(info, printer, 2)) {
7696 free_a_printer(&printer, 2);
7697 return WERR_NOMEM;
7700 /* check to see if the printer already exists */
7702 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7703 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7704 printer->info_2->sharename));
7705 free_a_printer(&printer, 2);
7706 return WERR_PRINTER_ALREADY_EXISTS;
7709 /* FIXME!!! smbd should check to see if the driver is installed before
7710 trying to add a printer like this --jerry */
7712 if (*lp_addprinter_cmd() ) {
7713 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7714 free_a_printer(&printer,2);
7715 return WERR_ACCESS_DENIED;
7717 } else {
7718 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7719 "smb.conf parameter \"addprinter command\" is defined. This"
7720 "parameter must exist for this call to succeed\n",
7721 printer->info_2->sharename ));
7724 /* use our primary netbios name since get_a_printer() will convert
7725 it to what the client expects on a case by case basis */
7727 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7728 printer->info_2->sharename);
7731 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7732 free_a_printer(&printer,2);
7733 return WERR_ACCESS_DENIED;
7736 /* you must be a printer admin to add a new printer */
7737 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7738 free_a_printer(&printer,2);
7739 return WERR_ACCESS_DENIED;
7743 * Do sanity check on the requested changes for Samba.
7746 if (!check_printer_ok(printer->info_2, snum)) {
7747 free_a_printer(&printer,2);
7748 return WERR_INVALID_PARAM;
7752 * When a printer is created, the drivername bound to the printer is used
7753 * to lookup previously saved driver initialization info, which is then
7754 * bound to the new printer, simulating what happens in the Windows arch.
7757 if (!devmode)
7759 set_driver_init(printer, 2);
7761 else
7763 /* A valid devmode was included, convert and link it
7765 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7767 if (!convert_devicemode(printer->info_2->printername, devmode,
7768 &printer->info_2->devmode))
7769 return WERR_NOMEM;
7772 /* write the ASCII on disk */
7773 err = mod_a_printer(printer, 2);
7774 if (!W_ERROR_IS_OK(err)) {
7775 free_a_printer(&printer,2);
7776 return err;
7779 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7780 /* Handle open failed - remove addition. */
7781 del_a_printer(printer->info_2->sharename);
7782 free_a_printer(&printer,2);
7783 return WERR_ACCESS_DENIED;
7786 update_c_setprinter(False);
7787 free_a_printer(&printer,2);
7789 return WERR_OK;
7792 /****************************************************************************
7793 ****************************************************************************/
7795 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7797 UNISTR2 *uni_srv_name = q_u->server_name;
7798 uint32 level = q_u->level;
7799 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7800 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7801 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7802 uint32 user_switch = q_u->user_switch;
7803 SPOOL_USER_CTR *user = &q_u->user_ctr;
7804 POLICY_HND *handle = &r_u->handle;
7806 switch (level) {
7807 case 1:
7808 /* we don't handle yet */
7809 /* but I know what to do ... */
7810 return WERR_UNKNOWN_LEVEL;
7811 case 2:
7812 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7813 devmode, sdb,
7814 user_switch, user, handle);
7815 default:
7816 return WERR_UNKNOWN_LEVEL;
7820 /****************************************************************************
7821 ****************************************************************************/
7823 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7825 uint32 level = q_u->level;
7826 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7827 WERROR err = WERR_OK;
7828 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7829 fstring driver_name;
7830 uint32 version;
7832 ZERO_STRUCT(driver);
7834 if (!convert_printer_driver_info(info, &driver, level)) {
7835 err = WERR_NOMEM;
7836 goto done;
7839 DEBUG(5,("Cleaning driver's information\n"));
7840 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7841 if (!W_ERROR_IS_OK(err))
7842 goto done;
7844 DEBUG(5,("Moving driver to final destination\n"));
7845 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7846 goto done;
7849 if (add_a_printer_driver(driver, level)!=0) {
7850 err = WERR_ACCESS_DENIED;
7851 goto done;
7855 * I think this is where he DrvUpgradePrinter() hook would be
7856 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7857 * server. Right now, we just need to send ourselves a message
7858 * to update each printer bound to this driver. --jerry
7861 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7862 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7863 driver_name));
7867 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7868 * decide if the driver init data should be deleted. The rules are:
7869 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7870 * 2) delete init data only if there is no 2k/Xp driver
7871 * 3) always delete init data
7872 * The generalized rule is always use init data from the highest order driver.
7873 * It is necessary to follow the driver install by an initialization step to
7874 * finish off this process.
7876 if (level == 3)
7877 version = driver.info_3->cversion;
7878 else if (level == 6)
7879 version = driver.info_6->version;
7880 else
7881 version = -1;
7882 switch (version) {
7884 * 9x printer driver - never delete init data
7886 case 0:
7887 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7888 driver_name));
7889 break;
7892 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7893 * there is no 2k/Xp driver init data for this driver name.
7895 case 2:
7897 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7899 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7901 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7903 if (!del_driver_init(driver_name))
7904 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7905 } else {
7907 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7909 free_a_printer_driver(driver1,3);
7910 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7911 driver_name));
7914 break;
7917 * 2k or Xp printer driver - always delete init data
7919 case 3:
7920 if (!del_driver_init(driver_name))
7921 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7922 break;
7924 default:
7925 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7926 break;
7930 done:
7931 free_a_printer_driver(driver, level);
7932 return err;
7935 /********************************************************************
7936 * spoolss_addprinterdriverex
7937 ********************************************************************/
7939 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7941 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7942 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7945 * we only support the semantics of AddPrinterDriver()
7946 * i.e. only copy files that are newer than existing ones
7949 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7950 return WERR_ACCESS_DENIED;
7952 ZERO_STRUCT(q_u_local);
7953 ZERO_STRUCT(r_u_local);
7955 /* just pass the information off to _spoolss_addprinterdriver() */
7956 q_u_local.server_name_ptr = q_u->server_name_ptr;
7957 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7958 q_u_local.level = q_u->level;
7959 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7961 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7964 /****************************************************************************
7965 ****************************************************************************/
7967 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7969 init_unistr(&info->name, name);
7972 /****************************************************************************
7973 ****************************************************************************/
7975 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7977 char *path = NULL;
7978 char *long_archi = NULL;
7979 char *servername = NULL;
7980 char *pservername = NULL;
7981 const char *short_archi;
7982 DRIVER_DIRECTORY_1 *info=NULL;
7983 WERROR result = WERR_OK;
7984 TALLOC_CTX *ctx = talloc_tos();
7986 servername = unistr2_to_ascii_talloc(ctx, name);
7987 if (!servername) {
7988 return WERR_NOMEM;
7990 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
7991 if (!long_archi) {
7992 return WERR_NOMEM;
7995 /* check for beginning double '\'s and that the server
7996 long enough */
7998 pservername = servername;
7999 if ( *pservername == '\\' && strlen(servername)>2 ) {
8000 pservername += 2;
8003 if ( !is_myname_or_ipaddr( pservername ) )
8004 return WERR_INVALID_PARAM;
8006 if (!(short_archi = get_short_archi(long_archi)))
8007 return WERR_INVALID_ENVIRONMENT;
8009 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8010 return WERR_NOMEM;
8012 path = talloc_asprintf(ctx,
8013 "\\\\%s\\print$\\%s", pservername, short_archi);
8014 if (!path) {
8015 result = WERR_NOMEM;
8016 goto out;
8019 DEBUG(4,("printer driver directory: [%s]\n", path));
8021 fill_driverdir_1(info, path);
8023 *needed += spoolss_size_driverdir_info_1(info);
8025 if (*needed > offered) {
8026 result = WERR_INSUFFICIENT_BUFFER;
8027 goto out;
8030 if (!rpcbuf_alloc_size(buffer, *needed)) {
8031 result = WERR_NOMEM;
8032 goto out;
8035 smb_io_driverdir_1("", buffer, info, 0);
8037 out:
8038 SAFE_FREE(info);
8040 return result;
8043 /****************************************************************************
8044 ****************************************************************************/
8046 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8048 UNISTR2 *name = &q_u->name;
8049 UNISTR2 *uni_environment = &q_u->environment;
8050 uint32 level = q_u->level;
8051 RPC_BUFFER *buffer = NULL;
8052 uint32 offered = q_u->offered;
8053 uint32 *needed = &r_u->needed;
8055 /* that's an [in out] buffer */
8057 if (!q_u->buffer && (offered!=0)) {
8058 return WERR_INVALID_PARAM;
8061 rpcbuf_move(q_u->buffer, &r_u->buffer);
8062 buffer = r_u->buffer;
8064 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8066 *needed=0;
8068 switch(level) {
8069 case 1:
8070 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8071 default:
8072 return WERR_UNKNOWN_LEVEL;
8076 /****************************************************************************
8077 ****************************************************************************/
8079 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8081 POLICY_HND *handle = &q_u->handle;
8082 uint32 idx = q_u->index;
8083 uint32 in_value_len = q_u->valuesize;
8084 uint32 in_data_len = q_u->datasize;
8085 uint32 *out_max_value_len = &r_u->valuesize;
8086 uint16 **out_value = &r_u->value;
8087 uint32 *out_value_len = &r_u->realvaluesize;
8088 uint32 *out_type = &r_u->type;
8089 uint32 *out_max_data_len = &r_u->datasize;
8090 uint8 **data_out = &r_u->data;
8091 uint32 *out_data_len = &r_u->realdatasize;
8093 NT_PRINTER_INFO_LEVEL *printer = NULL;
8095 uint32 biggest_valuesize;
8096 uint32 biggest_datasize;
8097 uint32 data_len;
8098 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8099 int snum;
8100 WERROR result;
8101 REGISTRY_VALUE *val = NULL;
8102 NT_PRINTER_DATA *p_data;
8103 int i, key_index, num_values;
8104 int name_length;
8106 *out_type = 0;
8108 *out_max_data_len = 0;
8109 *data_out = NULL;
8110 *out_data_len = 0;
8112 DEBUG(5,("spoolss_enumprinterdata\n"));
8114 if (!Printer) {
8115 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8116 return WERR_BADFID;
8119 if (!get_printer_snum(p,handle, &snum, NULL))
8120 return WERR_BADFID;
8122 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8123 if (!W_ERROR_IS_OK(result))
8124 return result;
8126 p_data = printer->info_2->data;
8127 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8129 result = WERR_OK;
8132 * The NT machine wants to know the biggest size of value and data
8134 * cf: MSDN EnumPrinterData remark section
8137 if ( !in_value_len && !in_data_len && (key_index != -1) )
8139 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8141 biggest_valuesize = 0;
8142 biggest_datasize = 0;
8144 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8146 for ( i=0; i<num_values; i++ )
8148 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8150 name_length = strlen(val->valuename);
8151 if ( strlen(val->valuename) > biggest_valuesize )
8152 biggest_valuesize = name_length;
8154 if ( val->size > biggest_datasize )
8155 biggest_datasize = val->size;
8157 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8158 biggest_datasize));
8161 /* the value is an UNICODE string but real_value_size is the length
8162 in bytes including the trailing 0 */
8164 *out_value_len = 2 * (1+biggest_valuesize);
8165 *out_data_len = biggest_datasize;
8167 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8169 goto done;
8173 * the value len is wrong in NT sp3
8174 * that's the number of bytes not the number of unicode chars
8177 if ( key_index != -1 )
8178 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8180 if ( !val )
8183 /* out_value should default to "" or else NT4 has
8184 problems unmarshalling the response */
8186 *out_max_value_len=(in_value_len/sizeof(uint16));
8188 if (in_value_len) {
8189 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8191 result = WERR_NOMEM;
8192 goto done;
8194 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8195 } else {
8196 *out_value=NULL;
8197 *out_value_len = 0;
8200 /* the data is counted in bytes */
8202 *out_max_data_len = in_data_len;
8203 *out_data_len = in_data_len;
8205 /* only allocate when given a non-zero data_len */
8207 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8209 result = WERR_NOMEM;
8210 goto done;
8213 result = WERR_NO_MORE_ITEMS;
8215 else
8218 * the value is:
8219 * - counted in bytes in the request
8220 * - counted in UNICODE chars in the max reply
8221 * - counted in bytes in the real size
8223 * take a pause *before* coding not *during* coding
8226 /* name */
8227 *out_max_value_len=(in_value_len/sizeof(uint16));
8228 if (in_value_len) {
8229 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8231 result = WERR_NOMEM;
8232 goto done;
8235 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8236 } else {
8237 *out_value = NULL;
8238 *out_value_len = 0;
8241 /* type */
8243 *out_type = regval_type( val );
8245 /* data - counted in bytes */
8247 *out_max_data_len = in_data_len;
8248 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8250 result = WERR_NOMEM;
8251 goto done;
8253 data_len = regval_size(val);
8254 if ( *data_out && data_len )
8255 memcpy( *data_out, regval_data_p(val), data_len );
8256 *out_data_len = data_len;
8259 done:
8260 free_a_printer(&printer, 2);
8261 return result;
8264 /****************************************************************************
8265 ****************************************************************************/
8267 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8269 POLICY_HND *handle = &q_u->handle;
8270 UNISTR2 *value = &q_u->value;
8271 uint32 type = q_u->type;
8272 uint8 *data = q_u->data;
8273 uint32 real_len = q_u->real_len;
8275 NT_PRINTER_INFO_LEVEL *printer = NULL;
8276 int snum=0;
8277 WERROR status = WERR_OK;
8278 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8279 fstring valuename;
8281 DEBUG(5,("spoolss_setprinterdata\n"));
8283 if (!Printer) {
8284 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8285 return WERR_BADFID;
8288 if ( Printer->printer_type == SPLHND_SERVER ) {
8289 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8290 return WERR_INVALID_PARAM;
8293 if (!get_printer_snum(p,handle, &snum, NULL))
8294 return WERR_BADFID;
8297 * Access check : NT returns "access denied" if you make a
8298 * SetPrinterData call without the necessary privildge.
8299 * we were originally returning OK if nothing changed
8300 * which made Win2k issue **a lot** of SetPrinterData
8301 * when connecting to a printer --jerry
8304 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8306 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8307 status = WERR_ACCESS_DENIED;
8308 goto done;
8311 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8312 if (!W_ERROR_IS_OK(status))
8313 return status;
8315 unistr2_to_ascii(valuename, value, sizeof(valuename));
8318 * When client side code sets a magic printer data key, detect it and save
8319 * the current printer data and the magic key's data (its the DEVMODE) for
8320 * future printer/driver initializations.
8322 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8324 /* Set devmode and printer initialization info */
8325 status = save_driver_init( printer, 2, data, real_len );
8327 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8329 else
8331 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8332 type, data, real_len );
8333 if ( W_ERROR_IS_OK(status) )
8334 status = mod_a_printer(printer, 2);
8337 done:
8338 free_a_printer(&printer, 2);
8340 return status;
8343 /****************************************************************************
8344 ****************************************************************************/
8346 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8348 POLICY_HND *handle = &q_u->handle;
8349 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8350 int snum;
8352 DEBUG(5,("_spoolss_resetprinter\n"));
8355 * All we do is to check to see if the handle and queue is valid.
8356 * This call really doesn't mean anything to us because we only
8357 * support RAW printing. --jerry
8360 if (!Printer) {
8361 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8362 return WERR_BADFID;
8365 if (!get_printer_snum(p,handle, &snum, NULL))
8366 return WERR_BADFID;
8369 /* blindly return success */
8370 return WERR_OK;
8374 /****************************************************************************
8375 ****************************************************************************/
8377 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8379 POLICY_HND *handle = &q_u->handle;
8380 UNISTR2 *value = &q_u->valuename;
8382 NT_PRINTER_INFO_LEVEL *printer = NULL;
8383 int snum=0;
8384 WERROR status = WERR_OK;
8385 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8386 char *valuename = NULL;
8387 TALLOC_CTX *ctx = p->mem_ctx;
8389 DEBUG(5,("spoolss_deleteprinterdata\n"));
8391 if (!Printer) {
8392 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8393 return WERR_BADFID;
8396 if (!get_printer_snum(p, handle, &snum, NULL))
8397 return WERR_BADFID;
8399 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8400 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8401 return WERR_ACCESS_DENIED;
8404 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8405 if (!W_ERROR_IS_OK(status))
8406 return status;
8408 valuename = unistr2_to_ascii_talloc(ctx, value);
8409 if (!valuename) {
8410 free_a_printer(&printer, 2);
8411 return WERR_NOMEM;
8414 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8416 if ( W_ERROR_IS_OK(status) )
8417 mod_a_printer( printer, 2 );
8419 free_a_printer(&printer, 2);
8420 TALLOC_FREE(valuename);
8422 return status;
8425 /****************************************************************************
8426 ****************************************************************************/
8428 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8430 POLICY_HND *handle = &q_u->handle;
8431 FORM *form = &q_u->form;
8432 nt_forms_struct tmpForm;
8433 int snum;
8434 WERROR status = WERR_OK;
8435 NT_PRINTER_INFO_LEVEL *printer = NULL;
8437 int count=0;
8438 nt_forms_struct *list=NULL;
8439 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8441 DEBUG(5,("spoolss_addform\n"));
8443 if (!Printer) {
8444 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8445 return WERR_BADFID;
8449 /* forms can be added on printer of on the print server handle */
8451 if ( Printer->printer_type == SPLHND_PRINTER )
8453 if (!get_printer_snum(p,handle, &snum, NULL))
8454 return WERR_BADFID;
8456 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8457 if (!W_ERROR_IS_OK(status))
8458 goto done;
8461 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8462 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8463 status = WERR_ACCESS_DENIED;
8464 goto done;
8467 /* can't add if builtin */
8469 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8470 status = WERR_ALREADY_EXISTS;
8471 goto done;
8474 count = get_ntforms(&list);
8476 if(!add_a_form(&list, form, &count)) {
8477 status = WERR_NOMEM;
8478 goto done;
8481 write_ntforms(&list, count);
8484 * ChangeID must always be set if this is a printer
8487 if ( Printer->printer_type == SPLHND_PRINTER )
8488 status = mod_a_printer(printer, 2);
8490 done:
8491 if ( printer )
8492 free_a_printer(&printer, 2);
8493 SAFE_FREE(list);
8495 return status;
8498 /****************************************************************************
8499 ****************************************************************************/
8501 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8503 POLICY_HND *handle = &q_u->handle;
8504 UNISTR2 *form_name = &q_u->name;
8505 nt_forms_struct tmpForm;
8506 int count=0;
8507 nt_forms_struct *list=NULL;
8508 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8509 int snum;
8510 WERROR status = WERR_OK;
8511 NT_PRINTER_INFO_LEVEL *printer = NULL;
8513 DEBUG(5,("spoolss_deleteform\n"));
8515 if (!Printer) {
8516 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8517 return WERR_BADFID;
8520 /* forms can be deleted on printer of on the print server handle */
8522 if ( Printer->printer_type == SPLHND_PRINTER )
8524 if (!get_printer_snum(p,handle, &snum, NULL))
8525 return WERR_BADFID;
8527 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8528 if (!W_ERROR_IS_OK(status))
8529 goto done;
8532 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8533 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8534 status = WERR_ACCESS_DENIED;
8535 goto done;
8538 /* can't delete if builtin */
8540 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8541 status = WERR_INVALID_PARAM;
8542 goto done;
8545 count = get_ntforms(&list);
8547 if ( !delete_a_form(&list, form_name, &count, &status ))
8548 goto done;
8551 * ChangeID must always be set if this is a printer
8554 if ( Printer->printer_type == SPLHND_PRINTER )
8555 status = mod_a_printer(printer, 2);
8557 done:
8558 if ( printer )
8559 free_a_printer(&printer, 2);
8560 SAFE_FREE(list);
8562 return status;
8565 /****************************************************************************
8566 ****************************************************************************/
8568 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8570 POLICY_HND *handle = &q_u->handle;
8571 FORM *form = &q_u->form;
8572 nt_forms_struct tmpForm;
8573 int snum;
8574 WERROR status = WERR_OK;
8575 NT_PRINTER_INFO_LEVEL *printer = NULL;
8577 int count=0;
8578 nt_forms_struct *list=NULL;
8579 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8581 DEBUG(5,("spoolss_setform\n"));
8583 if (!Printer) {
8584 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8585 return WERR_BADFID;
8588 /* forms can be modified on printer of on the print server handle */
8590 if ( Printer->printer_type == SPLHND_PRINTER )
8592 if (!get_printer_snum(p,handle, &snum, NULL))
8593 return WERR_BADFID;
8595 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8596 if (!W_ERROR_IS_OK(status))
8597 goto done;
8600 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8601 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8602 status = WERR_ACCESS_DENIED;
8603 goto done;
8606 /* can't set if builtin */
8607 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8608 status = WERR_INVALID_PARAM;
8609 goto done;
8612 count = get_ntforms(&list);
8613 update_a_form(&list, form, count);
8614 write_ntforms(&list, count);
8617 * ChangeID must always be set if this is a printer
8620 if ( Printer->printer_type == SPLHND_PRINTER )
8621 status = mod_a_printer(printer, 2);
8624 done:
8625 if ( printer )
8626 free_a_printer(&printer, 2);
8627 SAFE_FREE(list);
8629 return status;
8632 /****************************************************************************
8633 enumprintprocessors level 1.
8634 ****************************************************************************/
8636 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8638 PRINTPROCESSOR_1 *info_1=NULL;
8639 WERROR result = WERR_OK;
8641 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8642 return WERR_NOMEM;
8644 (*returned) = 0x1;
8646 init_unistr(&info_1->name, "winprint");
8648 *needed += spoolss_size_printprocessor_info_1(info_1);
8650 if (*needed > offered) {
8651 result = WERR_INSUFFICIENT_BUFFER;
8652 goto out;
8655 if (!rpcbuf_alloc_size(buffer, *needed)) {
8656 result = WERR_NOMEM;
8657 goto out;
8660 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8662 out:
8663 SAFE_FREE(info_1);
8665 if ( !W_ERROR_IS_OK(result) )
8666 *returned = 0;
8668 return result;
8671 /****************************************************************************
8672 ****************************************************************************/
8674 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8676 uint32 level = q_u->level;
8677 RPC_BUFFER *buffer = NULL;
8678 uint32 offered = q_u->offered;
8679 uint32 *needed = &r_u->needed;
8680 uint32 *returned = &r_u->returned;
8682 /* that's an [in out] buffer */
8684 if (!q_u->buffer && (offered!=0)) {
8685 return WERR_INVALID_PARAM;
8688 rpcbuf_move(q_u->buffer, &r_u->buffer);
8689 buffer = r_u->buffer;
8691 DEBUG(5,("spoolss_enumprintprocessors\n"));
8694 * Enumerate the print processors ...
8696 * Just reply with "winprint", to keep NT happy
8697 * and I can use my nice printer checker.
8700 *returned=0;
8701 *needed=0;
8703 switch (level) {
8704 case 1:
8705 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8706 default:
8707 return WERR_UNKNOWN_LEVEL;
8711 /****************************************************************************
8712 enumprintprocdatatypes level 1.
8713 ****************************************************************************/
8715 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8717 PRINTPROCDATATYPE_1 *info_1=NULL;
8718 WERROR result = WERR_OK;
8720 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8721 return WERR_NOMEM;
8723 (*returned) = 0x1;
8725 init_unistr(&info_1->name, "RAW");
8727 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8729 if (*needed > offered) {
8730 result = WERR_INSUFFICIENT_BUFFER;
8731 goto out;
8734 if (!rpcbuf_alloc_size(buffer, *needed)) {
8735 result = WERR_NOMEM;
8736 goto out;
8739 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8741 out:
8742 SAFE_FREE(info_1);
8744 if ( !W_ERROR_IS_OK(result) )
8745 *returned = 0;
8747 return result;
8750 /****************************************************************************
8751 ****************************************************************************/
8753 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8755 uint32 level = q_u->level;
8756 RPC_BUFFER *buffer = NULL;
8757 uint32 offered = q_u->offered;
8758 uint32 *needed = &r_u->needed;
8759 uint32 *returned = &r_u->returned;
8761 /* that's an [in out] buffer */
8763 if (!q_u->buffer && (offered!=0)) {
8764 return WERR_INVALID_PARAM;
8767 rpcbuf_move(q_u->buffer, &r_u->buffer);
8768 buffer = r_u->buffer;
8770 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8772 *returned=0;
8773 *needed=0;
8775 switch (level) {
8776 case 1:
8777 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8778 default:
8779 return WERR_UNKNOWN_LEVEL;
8783 /****************************************************************************
8784 enumprintmonitors level 1.
8785 ****************************************************************************/
8787 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8789 PRINTMONITOR_1 *info_1;
8790 WERROR result = WERR_OK;
8791 int i;
8793 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8794 return WERR_NOMEM;
8796 *returned = 2;
8798 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8799 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8801 for ( i=0; i<*returned; i++ ) {
8802 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8805 if (*needed > offered) {
8806 result = WERR_INSUFFICIENT_BUFFER;
8807 goto out;
8810 if (!rpcbuf_alloc_size(buffer, *needed)) {
8811 result = WERR_NOMEM;
8812 goto out;
8815 for ( i=0; i<*returned; i++ ) {
8816 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8819 out:
8820 SAFE_FREE(info_1);
8822 if ( !W_ERROR_IS_OK(result) )
8823 *returned = 0;
8825 return result;
8828 /****************************************************************************
8829 enumprintmonitors level 2.
8830 ****************************************************************************/
8832 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8834 PRINTMONITOR_2 *info_2;
8835 WERROR result = WERR_OK;
8836 int i;
8838 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8839 return WERR_NOMEM;
8841 *returned = 2;
8843 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8844 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8845 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8847 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8848 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8849 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8851 for ( i=0; i<*returned; i++ ) {
8852 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8855 if (*needed > offered) {
8856 result = WERR_INSUFFICIENT_BUFFER;
8857 goto out;
8860 if (!rpcbuf_alloc_size(buffer, *needed)) {
8861 result = WERR_NOMEM;
8862 goto out;
8865 for ( i=0; i<*returned; i++ ) {
8866 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8869 out:
8870 SAFE_FREE(info_2);
8872 if ( !W_ERROR_IS_OK(result) )
8873 *returned = 0;
8875 return result;
8878 /****************************************************************************
8879 ****************************************************************************/
8881 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8883 uint32 level = q_u->level;
8884 RPC_BUFFER *buffer = NULL;
8885 uint32 offered = q_u->offered;
8886 uint32 *needed = &r_u->needed;
8887 uint32 *returned = &r_u->returned;
8889 /* that's an [in out] buffer */
8891 if (!q_u->buffer && (offered!=0)) {
8892 return WERR_INVALID_PARAM;
8895 rpcbuf_move(q_u->buffer, &r_u->buffer);
8896 buffer = r_u->buffer;
8898 DEBUG(5,("spoolss_enumprintmonitors\n"));
8901 * Enumerate the print monitors ...
8903 * Just reply with "Local Port", to keep NT happy
8904 * and I can use my nice printer checker.
8907 *returned=0;
8908 *needed=0;
8910 switch (level) {
8911 case 1:
8912 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8913 case 2:
8914 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8915 default:
8916 return WERR_UNKNOWN_LEVEL;
8920 /****************************************************************************
8921 ****************************************************************************/
8923 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8924 NT_PRINTER_INFO_LEVEL *ntprinter,
8925 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8926 uint32 *needed)
8928 int i=0;
8929 bool found=False;
8930 JOB_INFO_1 *info_1=NULL;
8931 WERROR result = WERR_OK;
8933 info_1=SMB_MALLOC_P(JOB_INFO_1);
8935 if (info_1 == NULL) {
8936 return WERR_NOMEM;
8939 for (i=0; i<count && found==False; i++) {
8940 if ((*queue)[i].job==(int)jobid)
8941 found=True;
8944 if (found==False) {
8945 SAFE_FREE(info_1);
8946 /* NT treats not found as bad param... yet another bad choice */
8947 return WERR_INVALID_PARAM;
8950 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8952 *needed += spoolss_size_job_info_1(info_1);
8954 if (*needed > offered) {
8955 result = WERR_INSUFFICIENT_BUFFER;
8956 goto out;
8959 if (!rpcbuf_alloc_size(buffer, *needed)) {
8960 result = WERR_NOMEM;
8961 goto out;
8964 smb_io_job_info_1("", buffer, info_1, 0);
8966 out:
8967 SAFE_FREE(info_1);
8969 return result;
8972 /****************************************************************************
8973 ****************************************************************************/
8975 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8976 NT_PRINTER_INFO_LEVEL *ntprinter,
8977 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8978 uint32 *needed)
8980 int i = 0;
8981 bool found = False;
8982 JOB_INFO_2 *info_2;
8983 WERROR result;
8984 DEVICEMODE *devmode = NULL;
8985 NT_DEVICEMODE *nt_devmode = NULL;
8987 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8988 return WERR_NOMEM;
8990 ZERO_STRUCTP(info_2);
8992 for ( i=0; i<count && found==False; i++ )
8994 if ((*queue)[i].job == (int)jobid)
8995 found = True;
8998 if ( !found ) {
8999 /* NT treats not found as bad param... yet another bad
9000 choice */
9001 result = WERR_INVALID_PARAM;
9002 goto done;
9006 * if the print job does not have a DEVMODE associated with it,
9007 * just use the one for the printer. A NULL devicemode is not
9008 * a failure condition
9011 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9012 devmode = construct_dev_mode(lp_const_servicename(snum));
9013 else {
9014 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9015 ZERO_STRUCTP( devmode );
9016 convert_nt_devicemode( devmode, nt_devmode );
9020 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9022 *needed += spoolss_size_job_info_2(info_2);
9024 if (*needed > offered) {
9025 result = WERR_INSUFFICIENT_BUFFER;
9026 goto done;
9029 if (!rpcbuf_alloc_size(buffer, *needed)) {
9030 result = WERR_NOMEM;
9031 goto done;
9034 smb_io_job_info_2("", buffer, info_2, 0);
9036 result = WERR_OK;
9038 done:
9039 /* Cleanup allocated memory */
9041 free_job_info_2(info_2); /* Also frees devmode */
9042 SAFE_FREE(info_2);
9044 return result;
9047 /****************************************************************************
9048 ****************************************************************************/
9050 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9052 POLICY_HND *handle = &q_u->handle;
9053 uint32 jobid = q_u->jobid;
9054 uint32 level = q_u->level;
9055 RPC_BUFFER *buffer = NULL;
9056 uint32 offered = q_u->offered;
9057 uint32 *needed = &r_u->needed;
9058 WERROR wstatus = WERR_OK;
9059 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9060 int snum;
9061 int count;
9062 print_queue_struct *queue = NULL;
9063 print_status_struct prt_status;
9065 /* that's an [in out] buffer */
9067 if (!q_u->buffer && (offered!=0)) {
9068 return WERR_INVALID_PARAM;
9071 rpcbuf_move(q_u->buffer, &r_u->buffer);
9072 buffer = r_u->buffer;
9074 DEBUG(5,("spoolss_getjob\n"));
9076 *needed = 0;
9078 if (!get_printer_snum(p, handle, &snum, NULL))
9079 return WERR_BADFID;
9081 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9082 if ( !W_ERROR_IS_OK(wstatus) )
9083 return wstatus;
9085 count = print_queue_status(snum, &queue, &prt_status);
9087 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9088 count, prt_status.status, prt_status.message));
9090 switch ( level ) {
9091 case 1:
9092 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9093 buffer, offered, needed);
9094 break;
9095 case 2:
9096 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9097 buffer, offered, needed);
9098 break;
9099 default:
9100 wstatus = WERR_UNKNOWN_LEVEL;
9101 break;
9104 SAFE_FREE(queue);
9105 free_a_printer( &ntprinter, 2 );
9107 return wstatus;
9110 /********************************************************************
9111 spoolss_getprinterdataex
9113 From MSDN documentation of GetPrinterDataEx: pass request
9114 to GetPrinterData if key is "PrinterDriverData".
9115 ********************************************************************/
9117 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9119 POLICY_HND *handle = &q_u->handle;
9120 uint32 in_size = q_u->size;
9121 uint32 *type = &r_u->type;
9122 uint32 *out_size = &r_u->size;
9123 uint8 **data = &r_u->data;
9124 uint32 *needed = &r_u->needed;
9125 fstring keyname, valuename;
9127 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9129 NT_PRINTER_INFO_LEVEL *printer = NULL;
9130 int snum = 0;
9131 WERROR status = WERR_OK;
9133 DEBUG(4,("_spoolss_getprinterdataex\n"));
9135 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9136 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9138 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9139 keyname, valuename));
9141 /* in case of problem, return some default values */
9143 *needed = 0;
9144 *type = 0;
9145 *out_size = in_size;
9147 if (!Printer) {
9148 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9149 status = WERR_BADFID;
9150 goto done;
9153 /* Is the handle to a printer or to the server? */
9155 if (Printer->printer_type == SPLHND_SERVER) {
9156 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9157 status = WERR_INVALID_PARAM;
9158 goto done;
9161 if ( !get_printer_snum(p,handle, &snum, NULL) )
9162 return WERR_BADFID;
9164 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9165 if ( !W_ERROR_IS_OK(status) )
9166 goto done;
9168 /* check to see if the keyname is valid */
9169 if ( !strlen(keyname) ) {
9170 status = WERR_INVALID_PARAM;
9171 goto done;
9174 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9175 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9176 free_a_printer( &printer, 2 );
9177 status = WERR_BADFILE;
9178 goto done;
9181 /* When given a new keyname, we should just create it */
9183 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9185 if (*needed > *out_size)
9186 status = WERR_MORE_DATA;
9188 done:
9189 if ( !W_ERROR_IS_OK(status) )
9191 DEBUG(5, ("error: allocating %d\n", *out_size));
9193 /* reply this param doesn't exist */
9195 if ( *out_size )
9197 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9198 status = WERR_NOMEM;
9199 goto done;
9201 } else {
9202 *data = NULL;
9206 if ( printer )
9207 free_a_printer( &printer, 2 );
9209 return status;
9212 /********************************************************************
9213 * spoolss_setprinterdataex
9214 ********************************************************************/
9216 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9218 POLICY_HND *handle = &q_u->handle;
9219 uint32 type = q_u->type;
9220 uint8 *data = q_u->data;
9221 uint32 real_len = q_u->real_len;
9223 NT_PRINTER_INFO_LEVEL *printer = NULL;
9224 int snum = 0;
9225 WERROR status = WERR_OK;
9226 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9227 fstring valuename;
9228 fstring keyname;
9229 char *oid_string;
9231 DEBUG(4,("_spoolss_setprinterdataex\n"));
9233 /* From MSDN documentation of SetPrinterDataEx: pass request to
9234 SetPrinterData if key is "PrinterDriverData" */
9236 if (!Printer) {
9237 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9238 return WERR_BADFID;
9241 if ( Printer->printer_type == SPLHND_SERVER ) {
9242 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9243 return WERR_INVALID_PARAM;
9246 if ( !get_printer_snum(p,handle, &snum, NULL) )
9247 return WERR_BADFID;
9250 * Access check : NT returns "access denied" if you make a
9251 * SetPrinterData call without the necessary privildge.
9252 * we were originally returning OK if nothing changed
9253 * which made Win2k issue **a lot** of SetPrinterData
9254 * when connecting to a printer --jerry
9257 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9259 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9260 return WERR_ACCESS_DENIED;
9263 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9264 if (!W_ERROR_IS_OK(status))
9265 return status;
9267 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9268 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9270 /* check for OID in valuename */
9272 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9274 *oid_string = '\0';
9275 oid_string++;
9278 /* save the registry data */
9280 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9282 if ( W_ERROR_IS_OK(status) )
9284 /* save the OID if one was specified */
9285 if ( oid_string ) {
9286 fstrcat( keyname, "\\" );
9287 fstrcat( keyname, SPOOL_OID_KEY );
9290 * I'm not checking the status here on purpose. Don't know
9291 * if this is right, but I'm returning the status from the
9292 * previous set_printer_dataex() call. I have no idea if
9293 * this is right. --jerry
9296 set_printer_dataex( printer, keyname, valuename,
9297 REG_SZ, (uint8 *)oid_string,
9298 strlen(oid_string)+1 );
9301 status = mod_a_printer(printer, 2);
9304 free_a_printer(&printer, 2);
9306 return status;
9310 /********************************************************************
9311 * spoolss_deleteprinterdataex
9312 ********************************************************************/
9314 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9316 POLICY_HND *handle = &q_u->handle;
9317 UNISTR2 *value = &q_u->valuename;
9318 UNISTR2 *key = &q_u->keyname;
9320 NT_PRINTER_INFO_LEVEL *printer = NULL;
9321 int snum=0;
9322 WERROR status = WERR_OK;
9323 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9324 char *valuename = NULL;
9325 char *keyname = NULL;
9326 TALLOC_CTX *ctx = p->mem_ctx;
9328 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9330 if (!Printer) {
9331 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9332 return WERR_BADFID;
9335 if (!get_printer_snum(p, handle, &snum, NULL))
9336 return WERR_BADFID;
9338 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9339 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9340 return WERR_ACCESS_DENIED;
9343 valuename = unistr2_to_ascii_talloc(ctx, value);
9344 keyname = unistr2_to_ascii_talloc(ctx, key);
9345 if (!valuename || !keyname) {
9346 return WERR_NOMEM;
9349 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9350 if (!W_ERROR_IS_OK(status))
9351 return status;
9353 status = delete_printer_dataex( printer, keyname, valuename );
9355 if ( W_ERROR_IS_OK(status) )
9356 mod_a_printer( printer, 2 );
9358 free_a_printer(&printer, 2);
9360 return status;
9363 /********************************************************************
9364 * spoolss_enumprinterkey
9365 ********************************************************************/
9368 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9370 fstring key;
9371 fstring *keynames = NULL;
9372 uint16 *enumkeys = NULL;
9373 int num_keys;
9374 int printerkey_len;
9375 POLICY_HND *handle = &q_u->handle;
9376 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9377 NT_PRINTER_DATA *data;
9378 NT_PRINTER_INFO_LEVEL *printer = NULL;
9379 int snum = 0;
9380 WERROR status = WERR_BADFILE;
9383 DEBUG(4,("_spoolss_enumprinterkey\n"));
9385 if (!Printer) {
9386 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9387 return WERR_BADFID;
9390 if ( !get_printer_snum(p,handle, &snum, NULL) )
9391 return WERR_BADFID;
9393 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9394 if (!W_ERROR_IS_OK(status))
9395 return status;
9397 /* get the list of subkey names */
9399 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9400 data = printer->info_2->data;
9402 num_keys = get_printer_subkeys( data, key, &keynames );
9404 if ( num_keys == -1 ) {
9405 status = WERR_BADFILE;
9406 goto done;
9409 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9411 r_u->needed = printerkey_len*2;
9413 if ( q_u->size < r_u->needed ) {
9414 status = WERR_MORE_DATA;
9415 goto done;
9418 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9419 status = WERR_NOMEM;
9420 goto done;
9423 status = WERR_OK;
9425 if ( q_u->size < r_u->needed )
9426 status = WERR_MORE_DATA;
9428 done:
9429 free_a_printer( &printer, 2 );
9430 SAFE_FREE( keynames );
9432 return status;
9435 /********************************************************************
9436 * spoolss_deleteprinterkey
9437 ********************************************************************/
9439 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9441 POLICY_HND *handle = &q_u->handle;
9442 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9443 fstring key;
9444 NT_PRINTER_INFO_LEVEL *printer = NULL;
9445 int snum=0;
9446 WERROR status;
9448 DEBUG(5,("spoolss_deleteprinterkey\n"));
9450 if (!Printer) {
9451 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9452 return WERR_BADFID;
9455 /* if keyname == NULL, return error */
9457 if ( !q_u->keyname.buffer )
9458 return WERR_INVALID_PARAM;
9460 if (!get_printer_snum(p, handle, &snum, NULL))
9461 return WERR_BADFID;
9463 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9464 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9465 return WERR_ACCESS_DENIED;
9468 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9469 if (!W_ERROR_IS_OK(status))
9470 return status;
9472 /* delete the key and all subneys */
9474 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9476 status = delete_all_printer_data( printer->info_2, key );
9478 if ( W_ERROR_IS_OK(status) )
9479 status = mod_a_printer(printer, 2);
9481 free_a_printer( &printer, 2 );
9483 return status;
9487 /********************************************************************
9488 * spoolss_enumprinterdataex
9489 ********************************************************************/
9491 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9493 POLICY_HND *handle = &q_u->handle;
9494 uint32 in_size = q_u->size;
9495 uint32 num_entries,
9496 needed;
9497 NT_PRINTER_INFO_LEVEL *printer = NULL;
9498 PRINTER_ENUM_VALUES *enum_values = NULL;
9499 NT_PRINTER_DATA *p_data;
9500 fstring key;
9501 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9502 int snum;
9503 WERROR result;
9504 int key_index;
9505 int i;
9506 REGISTRY_VALUE *val;
9507 char *value_name;
9508 uint32 data_len;
9511 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9513 if (!Printer) {
9514 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9515 return WERR_BADFID;
9519 * first check for a keyname of NULL or "". Win2k seems to send
9520 * this a lot and we should send back WERR_INVALID_PARAM
9521 * no need to spend time looking up the printer in this case.
9522 * --jerry
9525 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9526 if ( !strlen(key) ) {
9527 result = WERR_INVALID_PARAM;
9528 goto done;
9531 /* get the printer off of disk */
9533 if (!get_printer_snum(p,handle, &snum, NULL))
9534 return WERR_BADFID;
9536 ZERO_STRUCT(printer);
9537 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9538 if (!W_ERROR_IS_OK(result))
9539 return result;
9541 /* now look for a match on the key name */
9543 p_data = printer->info_2->data;
9545 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9546 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9548 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9549 result = WERR_INVALID_PARAM;
9550 goto done;
9553 result = WERR_OK;
9554 needed = 0;
9556 /* allocate the memory for the array of pointers -- if necessary */
9558 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9559 if ( num_entries )
9561 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9563 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9564 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9565 result = WERR_NOMEM;
9566 goto done;
9569 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9573 * loop through all params and build the array to pass
9574 * back to the client
9577 for ( i=0; i<num_entries; i++ )
9579 /* lookup the registry value */
9581 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9582 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9584 /* copy the data */
9586 value_name = regval_name( val );
9587 init_unistr( &enum_values[i].valuename, value_name );
9588 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9589 enum_values[i].type = regval_type( val );
9591 data_len = regval_size( val );
9592 if ( data_len ) {
9593 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9595 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9596 data_len ));
9597 result = WERR_NOMEM;
9598 goto done;
9601 enum_values[i].data_len = data_len;
9603 /* keep track of the size of the array in bytes */
9605 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9608 /* housekeeping information in the reply */
9610 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9611 * the hand marshalled container size is a multiple
9612 * of 4 bytes for RPC alignment.
9615 if (needed % 4) {
9616 needed += 4-(needed % 4);
9619 r_u->needed = needed;
9620 r_u->returned = num_entries;
9622 if (needed > in_size) {
9623 result = WERR_MORE_DATA;
9624 goto done;
9627 /* copy data into the reply */
9629 r_u->ctr.size = r_u->needed;
9631 r_u->ctr.size_of_array = r_u->returned;
9632 r_u->ctr.values = enum_values;
9636 done:
9637 if ( printer )
9638 free_a_printer(&printer, 2);
9640 return result;
9643 /****************************************************************************
9644 ****************************************************************************/
9646 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9648 init_unistr(&info->name, name);
9651 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9652 UNISTR2 *environment,
9653 RPC_BUFFER *buffer,
9654 uint32 offered,
9655 uint32 *needed)
9657 char *long_archi = NULL;
9658 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9659 WERROR result = WERR_OK;
9660 TALLOC_CTX *ctx = talloc_tos();
9662 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9663 if (!long_archi) {
9664 return WERR_NOMEM;
9667 if (!get_short_archi(long_archi))
9668 return WERR_INVALID_ENVIRONMENT;
9670 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9671 return WERR_NOMEM;
9673 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9675 *needed += spoolss_size_printprocessordirectory_info_1(info);
9677 if (*needed > offered) {
9678 result = WERR_INSUFFICIENT_BUFFER;
9679 goto out;
9682 if (!rpcbuf_alloc_size(buffer, *needed)) {
9683 result = WERR_INSUFFICIENT_BUFFER;
9684 goto out;
9687 smb_io_printprocessordirectory_1("", buffer, info, 0);
9689 out:
9690 SAFE_FREE(info);
9692 return result;
9695 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9697 uint32 level = q_u->level;
9698 RPC_BUFFER *buffer = NULL;
9699 uint32 offered = q_u->offered;
9700 uint32 *needed = &r_u->needed;
9701 WERROR result;
9703 /* that's an [in out] buffer */
9705 if (!q_u->buffer && (offered!=0)) {
9706 return WERR_INVALID_PARAM;
9709 rpcbuf_move(q_u->buffer, &r_u->buffer);
9710 buffer = r_u->buffer;
9712 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9714 *needed=0;
9716 switch(level) {
9717 case 1:
9718 result = getprintprocessordirectory_level_1
9719 (&q_u->name, &q_u->environment, buffer, offered, needed);
9720 break;
9721 default:
9722 result = WERR_UNKNOWN_LEVEL;
9725 return result;
9728 /*******************************************************************
9729 Streams the monitor UI DLL name in UNICODE
9730 *******************************************************************/
9732 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9733 RPC_BUFFER *out, uint32 *needed )
9735 const char *dllname = "tcpmonui.dll";
9737 *needed = (strlen(dllname)+1) * 2;
9739 if ( rpcbuf_get_size(out) < *needed ) {
9740 return WERR_INSUFFICIENT_BUFFER;
9743 if ( !make_monitorui_buf( out, dllname ) ) {
9744 return WERR_NOMEM;
9747 return WERR_OK;
9750 /*******************************************************************
9751 Create a new TCP/IP port
9752 *******************************************************************/
9754 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9755 RPC_BUFFER *out, uint32 *needed )
9757 NT_PORT_DATA_1 port1;
9758 TALLOC_CTX *ctx = talloc_tos();
9759 char *device_uri = NULL;
9761 ZERO_STRUCT( port1 );
9763 /* convert to our internal port data structure */
9765 if ( !convert_port_data_1( &port1, in ) ) {
9766 return WERR_NOMEM;
9769 /* create the device URI and call the add_port_hook() */
9771 switch ( port1.protocol ) {
9772 case PORT_PROTOCOL_DIRECT:
9773 device_uri = talloc_asprintf(ctx,
9774 "socket://%s:%d/", port1.hostaddr, port1.port );
9775 break;
9777 case PORT_PROTOCOL_LPR:
9778 device_uri = talloc_asprintf(ctx,
9779 "lpr://%s/%s", port1.hostaddr, port1.queue );
9780 break;
9782 default:
9783 return WERR_UNKNOWN_PORT;
9786 if (!device_uri) {
9787 return WERR_NOMEM;
9790 return add_port_hook(ctx, token, port1.name, device_uri );
9793 /*******************************************************************
9794 *******************************************************************/
9796 struct xcv_api_table xcvtcp_cmds[] = {
9797 { "MonitorUI", xcvtcp_monitorui },
9798 { "AddPort", xcvtcp_addport},
9799 { NULL, NULL }
9802 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9803 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9804 uint32 *needed )
9806 int i;
9808 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9810 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9811 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9812 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9815 return WERR_BADFUNC;
9818 /*******************************************************************
9819 *******************************************************************/
9820 #if 0 /* don't support management using the "Local Port" monitor */
9822 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9823 RPC_BUFFER *out, uint32 *needed )
9825 const char *dllname = "localui.dll";
9827 *needed = (strlen(dllname)+1) * 2;
9829 if ( rpcbuf_get_size(out) < *needed ) {
9830 return WERR_INSUFFICIENT_BUFFER;
9833 if ( !make_monitorui_buf( out, dllname )) {
9834 return WERR_NOMEM;
9837 return WERR_OK;
9840 /*******************************************************************
9841 *******************************************************************/
9843 struct xcv_api_table xcvlocal_cmds[] = {
9844 { "MonitorUI", xcvlocal_monitorui },
9845 { NULL, NULL }
9847 #else
9848 struct xcv_api_table xcvlocal_cmds[] = {
9849 { NULL, NULL }
9851 #endif
9855 /*******************************************************************
9856 *******************************************************************/
9858 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9859 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9860 uint32 *needed )
9862 int i;
9864 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9866 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9867 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9868 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9870 return WERR_BADFUNC;
9873 /*******************************************************************
9874 *******************************************************************/
9876 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9878 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9879 fstring command;
9881 if (!Printer) {
9882 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9883 return WERR_BADFID;
9886 /* Has to be a handle to the TCP/IP port monitor */
9888 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9889 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9890 return WERR_BADFID;
9893 /* requires administrative access to the server */
9895 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9896 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9897 return WERR_ACCESS_DENIED;
9900 /* Get the command name. There's numerous commands supported by the
9901 TCPMON interface. */
9903 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9904 q_u->dataname.uni_str_len*2, 0);
9906 /* Allocate the outgoing buffer */
9908 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9910 switch ( Printer->printer_type ) {
9911 case SPLHND_PORTMON_TCP:
9912 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9913 &q_u->indata, &r_u->outdata, &r_u->needed );
9914 case SPLHND_PORTMON_LOCAL:
9915 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9916 &q_u->indata, &r_u->outdata, &r_u->needed );
9919 return WERR_INVALID_PRINT_MONITOR;