r19028: Implement getprinterinfo level 6 (only the status) and get rid of snum in the
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob8d9ba7cb907496a3cf3047e4ff8e1159120c7b99
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 extern userdom_struct current_user_info;
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
38 #endif
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
43 struct table_node {
44 const char *long_archi;
45 const char *short_archi;
46 int version;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
55 int snum;
56 uint32 counter;
57 } counter_printer_0;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table {
72 const char *name;
73 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v)
80 switch (v) {
81 case LPQ_QUEUED:
82 return 0;
83 case LPQ_PAUSED:
84 return JOB_STATUS_PAUSED;
85 case LPQ_SPOOLING:
86 return JOB_STATUS_SPOOLING;
87 case LPQ_PRINTING:
88 return JOB_STATUS_PRINTING;
89 case LPQ_ERROR:
90 return JOB_STATUS_ERROR;
91 case LPQ_DELETING:
92 return JOB_STATUS_DELETING;
93 case LPQ_OFFLINE:
94 return JOB_STATUS_OFFLINE;
95 case LPQ_PAPEROUT:
96 return JOB_STATUS_PAPEROUT;
97 case LPQ_PRINTED:
98 return JOB_STATUS_PRINTED;
99 case LPQ_DELETED:
100 return JOB_STATUS_DELETED;
101 case LPQ_BLOCKED:
102 return JOB_STATUS_BLOCKED;
103 case LPQ_USER_INTERVENTION:
104 return JOB_STATUS_USER_INTERVENTION;
106 return 0;
109 static int nt_printq_status(int v)
111 switch (v) {
112 case LPQ_PAUSED:
113 return PRINTER_STATUS_PAUSED;
114 case LPQ_QUEUED:
115 case LPQ_SPOOLING:
116 case LPQ_PRINTING:
117 return 0;
119 return 0;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
128 if (*pp == NULL)
129 return;
131 SAFE_FREE((*pp)->ctr.type);
132 SAFE_FREE(*pp);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
141 WERROR result;
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
154 return;
157 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
159 if (!W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( notify_cli_pipe->cli );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
177 smb_connections--;
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True) {
189 int snum = -1;
191 if ( Printer->printer_type == SPLHND_SERVER) {
192 snum = -1;
193 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
194 } else if (Printer->printer_type == SPLHND_PRINTER) {
195 snum = print_queue_snum(Printer->sharename);
196 if (snum != -1)
197 srv_spoolss_replycloseprinter(snum,
198 &Printer->notify.client_hnd);
202 Printer->notify.flags=0;
203 Printer->notify.options=0;
204 Printer->notify.localmachine[0]='\0';
205 Printer->notify.printerlocal=0;
206 free_spool_notify_option(&Printer->notify.option);
207 Printer->notify.option=NULL;
208 Printer->notify.client_connected=False;
210 free_nt_devicemode( &Printer->nt_devmode );
211 free_a_printer( &Printer->printer_info, 2 );
213 talloc_destroy( Printer->ctx );
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list, Printer);
218 SAFE_FREE(Printer);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
227 SPOOL_NOTIFY_OPTION *new_sp = NULL;
229 if (!sp)
230 return NULL;
232 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
233 if (!new_sp)
234 return NULL;
236 *new_sp = *sp;
238 if (sp->ctr.count) {
239 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
241 if (!new_sp->ctr.type) {
242 SAFE_FREE(new_sp);
243 return NULL;
247 return new_sp;
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
256 Printer_entry *find_printer = NULL;
258 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
260 return NULL;
263 return find_printer;
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
272 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
274 if (!Printer) {
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
276 return False;
279 close_policy_hnd(p, hnd);
281 return True;
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
289 char *cmd = lp_deleteprinter_cmd();
290 pstring command;
291 int ret;
292 SE_PRIV se_printop = SE_PRINT_OPERATOR;
293 BOOL is_print_op = False;
295 /* can't fail if we don't try */
297 if ( !*cmd )
298 return WERR_OK;
300 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
302 if ( token )
303 is_print_op = user_has_privileges( token, &se_printop );
305 DEBUG(10,("Running [%s]\n", command));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
309 if ( is_print_op )
310 become_root();
312 if ( (ret = smbrun(command, NULL)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
317 if ( is_print_op )
318 unbecome_root();
320 /********** END SePrintOperatorPrivlege BLOCK **********/
322 DEBUGADD(10,("returned [%d]\n", ret));
324 if (ret != 0)
325 return WERR_BADFID; /* What to return here? */
327 /* go ahead and re-read the services immediately */
328 reload_services( False );
330 if ( share_defined( sharename ) )
331 return WERR_ACCESS_DENIED;
333 return WERR_OK;
336 /****************************************************************************
337 Delete a printer given a handle.
338 ****************************************************************************/
340 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
342 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
344 if (!Printer) {
345 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
346 return WERR_BADFID;
350 * It turns out that Windows allows delete printer on a handle
351 * opened by an admin user, then used on a pipe handle created
352 * by an anonymous user..... but they're working on security.... riiight !
353 * JRA.
356 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
357 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
358 return WERR_ACCESS_DENIED;
361 /* this does not need a become root since the access check has been
362 done on the handle already */
364 if (del_a_printer( Printer->sharename ) != 0) {
365 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
366 return WERR_BADFID;
369 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
372 /****************************************************************************
373 Return the snum of a printer corresponding to an handle.
374 ****************************************************************************/
376 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
377 struct share_params **params)
379 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
381 if (!Printer) {
382 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
383 return False;
386 switch (Printer->printer_type) {
387 case SPLHND_PRINTER:
388 DEBUG(4,("short name:%s\n", Printer->sharename));
389 *number = print_queue_snum(Printer->sharename);
390 if ((*number != -1) && (params != NULL)) {
391 *params = get_share_params(tmp_talloc_ctx(),
392 Printer->sharename);
393 if (*params == NULL) {
394 return False;
397 return (*number != -1);
398 case SPLHND_SERVER:
399 return False;
400 default:
401 return False;
405 /****************************************************************************
406 Set printer handle type.
407 Check if it's \\server or \\server\printer
408 ****************************************************************************/
410 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
412 DEBUG(3,("Setting printer type=%s\n", handlename));
414 if ( strlen(handlename) < 3 ) {
415 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
416 return False;
419 /* it's a print server */
420 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
421 DEBUGADD(4,("Printer is a print server\n"));
422 Printer->printer_type = SPLHND_SERVER;
424 /* it's a printer (set_printer_hnd_name() will handle port monitors */
425 else {
426 DEBUGADD(4,("Printer is a printer\n"));
427 Printer->printer_type = SPLHND_PRINTER;
430 return True;
433 /****************************************************************************
434 Set printer handle name.. Accept names like \\server, \\server\printer,
435 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
436 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
437 XcvDataPort() interface.
438 ****************************************************************************/
440 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
442 int snum;
443 int n_services=lp_numservices();
444 char *aprinter, *printername;
445 const char *servername;
446 fstring sname;
447 BOOL found=False;
448 NT_PRINTER_INFO_LEVEL *printer = NULL;
449 WERROR result;
451 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
453 aprinter = handlename;
454 if ( *handlename == '\\' ) {
455 servername = handlename + 2;
456 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
457 *aprinter = '\0';
458 aprinter++;
461 else {
462 servername = "";
465 /* save the servername to fill in replies on this handle */
467 if ( !is_myname_or_ipaddr( servername ) )
468 return False;
470 fstrcpy( Printer->servername, servername );
472 if ( Printer->printer_type == SPLHND_SERVER )
473 return True;
475 if ( Printer->printer_type != SPLHND_PRINTER )
476 return False;
478 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
480 /* check for the Port Monitor Interface */
482 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
483 Printer->printer_type = SPLHND_PORTMON_TCP;
484 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
485 found = True;
487 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
488 Printer->printer_type = SPLHND_PORTMON_LOCAL;
489 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
490 found = True;
493 /* Search all sharenames first as this is easier than pulling
494 the printer_info_2 off of disk. Don't use find_service() since
495 that calls out to map_username() */
497 /* do another loop to look for printernames */
499 for (snum=0; !found && snum<n_services; snum++) {
501 /* no point going on if this is not a printer */
503 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
504 continue;
506 fstrcpy(sname, lp_servicename(snum));
507 if ( strequal( aprinter, sname ) ) {
508 found = True;
509 break;
512 /* no point looking up the printer object if
513 we aren't allowing printername != sharename */
515 if ( lp_force_printername(snum) )
516 continue;
518 fstrcpy(sname, lp_servicename(snum));
520 printer = NULL;
521 result = get_a_printer( NULL, &printer, 2, sname );
522 if ( !W_ERROR_IS_OK(result) ) {
523 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
524 sname, dos_errstr(result)));
525 continue;
528 /* printername is always returned as \\server\printername */
529 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
530 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
531 printer->info_2->printername));
532 free_a_printer( &printer, 2);
533 continue;
536 printername++;
538 if ( strequal(printername, aprinter) ) {
539 free_a_printer( &printer, 2);
540 found = True;
541 break;
544 DEBUGADD(10, ("printername: %s\n", printername));
546 free_a_printer( &printer, 2);
549 free_a_printer( &printer, 2);
551 if ( !found ) {
552 DEBUGADD(4,("Printer not found\n"));
553 return False;
556 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
558 fstrcpy(Printer->sharename, sname);
560 return True;
563 /****************************************************************************
564 Find first available printer slot. creates a printer handle for you.
565 ****************************************************************************/
567 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
569 Printer_entry *new_printer;
571 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
573 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
574 return False;
576 ZERO_STRUCTP(new_printer);
578 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
579 SAFE_FREE(new_printer);
580 return False;
583 /* Add to the internal list. */
584 DLIST_ADD(printers_list, new_printer);
586 new_printer->notify.option=NULL;
588 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
589 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
590 close_printer_handle(p, hnd);
591 return False;
594 if (!set_printer_hnd_printertype(new_printer, name)) {
595 close_printer_handle(p, hnd);
596 return False;
599 if (!set_printer_hnd_name(new_printer, name)) {
600 close_printer_handle(p, hnd);
601 return False;
604 new_printer->access_granted = access_granted;
606 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
608 return True;
611 /***************************************************************************
612 check to see if the client motify handle is monitoring the notification
613 given by (notify_type, notify_field).
614 **************************************************************************/
616 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
617 uint16 notify_field)
619 return True;
622 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
623 uint16 notify_field)
625 SPOOL_NOTIFY_OPTION *option = p->notify.option;
626 uint32 i, j;
629 * Flags should always be zero when the change notify
630 * is registered by the client's spooler. A user Win32 app
631 * might use the flags though instead of the NOTIFY_OPTION_INFO
632 * --jerry
635 if (!option) {
636 return False;
639 if (p->notify.flags)
640 return is_monitoring_event_flags(
641 p->notify.flags, notify_type, notify_field);
643 for (i = 0; i < option->count; i++) {
645 /* Check match for notify_type */
647 if (option->ctr.type[i].type != notify_type)
648 continue;
650 /* Check match for field */
652 for (j = 0; j < option->ctr.type[i].count; j++) {
653 if (option->ctr.type[i].fields[j] == notify_field) {
654 return True;
659 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
660 p->servername, p->sharename, notify_type, notify_field));
662 return False;
665 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
667 static void notify_one_value(struct spoolss_notify_msg *msg,
668 SPOOL_NOTIFY_INFO_DATA *data,
669 TALLOC_CTX *mem_ctx)
671 data->notify_data.value[0] = msg->notify.value[0];
672 data->notify_data.value[1] = 0;
675 static void notify_string(struct spoolss_notify_msg *msg,
676 SPOOL_NOTIFY_INFO_DATA *data,
677 TALLOC_CTX *mem_ctx)
679 UNISTR2 unistr;
681 /* The length of the message includes the trailing \0 */
683 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
685 data->notify_data.data.length = msg->len * 2;
686 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
688 if (!data->notify_data.data.string) {
689 data->notify_data.data.length = 0;
690 return;
693 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
696 static void notify_system_time(struct spoolss_notify_msg *msg,
697 SPOOL_NOTIFY_INFO_DATA *data,
698 TALLOC_CTX *mem_ctx)
700 SYSTEMTIME systime;
701 prs_struct ps;
703 if (msg->len != sizeof(time_t)) {
704 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
705 msg->len));
706 return;
709 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
710 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
711 return;
714 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
715 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
716 prs_mem_free(&ps);
717 return;
720 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
721 prs_mem_free(&ps);
722 return;
725 data->notify_data.data.length = prs_offset(&ps);
726 data->notify_data.data.string = (uint16 *)
727 TALLOC(mem_ctx, prs_offset(&ps));
728 if (!data->notify_data.data.string) {
729 prs_mem_free(&ps);
730 return;
733 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
735 prs_mem_free(&ps);
738 struct notify2_message_table {
739 const char *name;
740 void (*fn)(struct spoolss_notify_msg *msg,
741 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
744 static struct notify2_message_table printer_notify_table[] = {
745 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
746 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
747 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
748 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
749 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
750 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
751 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
752 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
753 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
754 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
755 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
756 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
757 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
758 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
759 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
760 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
761 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
762 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
763 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
766 static struct notify2_message_table job_notify_table[] = {
767 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
768 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
769 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
770 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
771 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
772 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
773 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
774 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
775 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
776 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
777 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
778 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
779 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
780 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
781 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
782 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
783 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
784 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
785 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
786 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
787 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
788 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
789 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
790 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
794 /***********************************************************************
795 Allocate talloc context for container object
796 **********************************************************************/
798 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
800 if ( !ctr )
801 return;
803 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
805 return;
808 /***********************************************************************
809 release all allocated memory and zero out structure
810 **********************************************************************/
812 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 if ( !ctr )
815 return;
817 if ( ctr->ctx )
818 talloc_destroy(ctr->ctx);
820 ZERO_STRUCTP(ctr);
822 return;
825 /***********************************************************************
826 **********************************************************************/
828 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
830 if ( !ctr )
831 return NULL;
833 return ctr->ctx;
836 /***********************************************************************
837 **********************************************************************/
839 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
841 if ( !ctr || !ctr->msg_groups )
842 return NULL;
844 if ( idx >= ctr->num_groups )
845 return NULL;
847 return &ctr->msg_groups[idx];
851 /***********************************************************************
852 How many groups of change messages do we have ?
853 **********************************************************************/
855 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
857 if ( !ctr )
858 return 0;
860 return ctr->num_groups;
863 /***********************************************************************
864 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
865 **********************************************************************/
867 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
869 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
870 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
871 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
872 int i, new_slot;
874 if ( !ctr || !msg )
875 return 0;
877 /* loop over all groups looking for a matching printer name */
879 for ( i=0; i<ctr->num_groups; i++ ) {
880 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
881 break;
884 /* add a new group? */
886 if ( i == ctr->num_groups ) {
887 ctr->num_groups++;
889 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
890 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
891 return 0;
893 ctr->msg_groups = groups;
895 /* clear the new entry and set the printer name */
897 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
898 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
901 /* add the change messages; 'i' is the correct index now regardless */
903 msg_grp = &ctr->msg_groups[i];
905 msg_grp->num_msgs++;
907 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
908 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
909 return 0;
911 msg_grp->msgs = msg_list;
913 new_slot = msg_grp->num_msgs-1;
914 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
916 /* need to allocate own copy of data */
918 if ( msg->len != 0 )
919 msg_grp->msgs[new_slot].notify.data = (char *)
920 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
922 return ctr->num_groups;
925 /***********************************************************************
926 Send a change notication message on all handles which have a call
927 back registered
928 **********************************************************************/
930 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
932 Printer_entry *p;
933 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
934 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
935 SPOOLSS_NOTIFY_MSG *messages;
936 int sending_msg_count;
938 if ( !msg_group ) {
939 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
940 return;
943 messages = msg_group->msgs;
945 if ( !messages ) {
946 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
947 return;
950 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
952 /* loop over all printers */
954 for (p = printers_list; p; p = p->next) {
955 SPOOL_NOTIFY_INFO_DATA *data;
956 uint32 data_len = 0;
957 uint32 id;
958 int i;
960 /* Is there notification on this handle? */
962 if ( !p->notify.client_connected )
963 continue;
965 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
967 /* For this printer? Print servers always receive
968 notifications. */
970 if ( ( p->printer_type == SPLHND_PRINTER ) &&
971 ( !strequal(msg_group->printername, p->sharename) ) )
972 continue;
974 DEBUG(10,("Our printer\n"));
976 /* allocate the max entries possible */
978 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
979 if (!data) {
980 return;
983 ZERO_STRUCTP(data);
985 /* build the array of change notifications */
987 sending_msg_count = 0;
989 for ( i=0; i<msg_group->num_msgs; i++ ) {
990 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
992 /* Are we monitoring this event? */
994 if (!is_monitoring_event(p, msg->type, msg->field))
995 continue;
997 sending_msg_count++;
1000 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1001 msg->type, msg->field, p->sharename));
1004 * if the is a printer notification handle and not a job notification
1005 * type, then set the id to 0. Other wise just use what was specified
1006 * in the message.
1008 * When registering change notification on a print server handle
1009 * we always need to send back the id (snum) matching the printer
1010 * for which the change took place. For change notify registered
1011 * on a printer handle, this does not matter and the id should be 0.
1013 * --jerry
1016 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1017 id = 0;
1018 else
1019 id = msg->id;
1022 /* Convert unix jobid to smb jobid */
1024 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1025 id = sysjob_to_jobid(msg->id);
1027 if (id == -1) {
1028 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1029 goto done;
1033 construct_info_data( &data[data_len], msg->type, msg->field, id );
1035 switch(msg->type) {
1036 case PRINTER_NOTIFY_TYPE:
1037 if ( printer_notify_table[msg->field].fn )
1038 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1039 break;
1041 case JOB_NOTIFY_TYPE:
1042 if ( job_notify_table[msg->field].fn )
1043 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1044 break;
1046 default:
1047 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1048 goto done;
1051 data_len++;
1054 if ( sending_msg_count ) {
1055 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1056 data_len, data, p->notify.change, 0 );
1060 done:
1061 DEBUG(8,("send_notify2_changes: Exit...\n"));
1062 return;
1065 /***********************************************************************
1066 **********************************************************************/
1068 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1071 uint32 tv_sec, tv_usec;
1072 size_t offset = 0;
1074 /* Unpack message */
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1077 msg->printer);
1079 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1080 &tv_sec, &tv_usec,
1081 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1083 if (msg->len == 0)
1084 tdb_unpack((char *)buf + offset, len - offset, "dd",
1085 &msg->notify.value[0], &msg->notify.value[1]);
1086 else
1087 tdb_unpack((char *)buf + offset, len - offset, "B",
1088 &msg->len, &msg->notify.data);
1090 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1091 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1093 tv->tv_sec = tv_sec;
1094 tv->tv_usec = tv_usec;
1096 if (msg->len == 0)
1097 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1098 msg->notify.value[1]));
1099 else
1100 dump_data(3, msg->notify.data, msg->len);
1102 return True;
1105 /********************************************************************
1106 Receive a notify2 message list
1107 ********************************************************************/
1109 static void receive_notify2_message_list(int msg_type, struct process_id src,
1110 void *msg, size_t len)
1112 size_t msg_count, i;
1113 char *buf = (char *)msg;
1114 char *msg_ptr;
1115 size_t msg_len;
1116 SPOOLSS_NOTIFY_MSG notify;
1117 SPOOLSS_NOTIFY_MSG_CTR messages;
1118 int num_groups;
1120 if (len < 4) {
1121 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1122 return;
1125 msg_count = IVAL(buf, 0);
1126 msg_ptr = buf + 4;
1128 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1130 if (msg_count == 0) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1132 return;
1135 /* initialize the container */
1137 ZERO_STRUCT( messages );
1138 notify_msg_ctr_init( &messages );
1141 * build message groups for each printer identified
1142 * in a change_notify msg. Remember that a PCN message
1143 * includes the handle returned for the srv_spoolss_replyopenprinter()
1144 * call. Therefore messages are grouped according to printer handle.
1147 for ( i=0; i<msg_count; i++ ) {
1148 struct timeval msg_tv;
1150 if (msg_ptr + 4 - buf > len) {
1151 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1152 return;
1155 msg_len = IVAL(msg_ptr,0);
1156 msg_ptr += 4;
1158 if (msg_ptr + msg_len - buf > len) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1160 return;
1163 /* unpack messages */
1165 ZERO_STRUCT( notify );
1166 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1167 msg_ptr += msg_len;
1169 /* add to correct list in container */
1171 notify_msg_ctr_addmsg( &messages, &notify );
1173 /* free memory that might have been allocated by notify2_unpack_msg() */
1175 if ( notify.len != 0 )
1176 SAFE_FREE( notify.notify.data );
1179 /* process each group of messages */
1181 num_groups = notify_msg_ctr_numgroups( &messages );
1182 for ( i=0; i<num_groups; i++ )
1183 send_notify2_changes( &messages, i );
1186 /* cleanup */
1188 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1190 notify_msg_ctr_destroy( &messages );
1192 return;
1195 /********************************************************************
1196 Send a message to ourself about new driver being installed
1197 so we can upgrade the information for each printer bound to this
1198 driver
1199 ********************************************************************/
1201 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1203 int len = strlen(drivername);
1205 if (!len)
1206 return False;
1208 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1209 drivername));
1211 message_send_pid(pid_to_procid(sys_getpid()),
1212 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1214 return True;
1217 /**********************************************************************
1218 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1219 over all printers, upgrading ones as necessary
1220 **********************************************************************/
1222 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1224 fstring drivername;
1225 int snum;
1226 int n_services = lp_numservices();
1228 len = MIN(len,sizeof(drivername)-1);
1229 strncpy(drivername, (const char *)buf, len);
1231 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1233 /* Iterate the printer list */
1235 for (snum=0; snum<n_services; snum++)
1237 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1239 WERROR result;
1240 NT_PRINTER_INFO_LEVEL *printer = NULL;
1242 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1243 if (!W_ERROR_IS_OK(result))
1244 continue;
1246 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1248 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1250 /* all we care about currently is the change_id */
1252 result = mod_a_printer(printer, 2);
1253 if (!W_ERROR_IS_OK(result)) {
1254 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1255 dos_errstr(result)));
1259 free_a_printer(&printer, 2);
1263 /* all done */
1266 /********************************************************************
1267 Update the cache for all printq's with a registered client
1268 connection
1269 ********************************************************************/
1271 void update_monitored_printq_cache( void )
1273 Printer_entry *printer = printers_list;
1274 int snum;
1276 /* loop through all printers and update the cache where
1277 client_connected == True */
1278 while ( printer )
1280 if ( (printer->printer_type == SPLHND_PRINTER)
1281 && printer->notify.client_connected )
1283 snum = print_queue_snum(printer->sharename);
1284 print_queue_status( snum, NULL, NULL );
1287 printer = printer->next;
1290 return;
1292 /********************************************************************
1293 Send a message to ourself about new driver being installed
1294 so we can upgrade the information for each printer bound to this
1295 driver
1296 ********************************************************************/
1298 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1300 int len = strlen(drivername);
1302 if (!len)
1303 return False;
1305 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1306 drivername));
1308 message_send_pid(pid_to_procid(sys_getpid()),
1309 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1311 return True;
1314 /**********************************************************************
1315 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1316 over all printers, resetting printer data as neessary
1317 **********************************************************************/
1319 void reset_all_printerdata(int msg_type, struct process_id src,
1320 void *buf, size_t len)
1322 fstring drivername;
1323 int snum;
1324 int n_services = lp_numservices();
1326 len = MIN( len, sizeof(drivername)-1 );
1327 strncpy( drivername, (const char *)buf, len );
1329 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1331 /* Iterate the printer list */
1333 for ( snum=0; snum<n_services; snum++ )
1335 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1337 WERROR result;
1338 NT_PRINTER_INFO_LEVEL *printer = NULL;
1340 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1341 if ( !W_ERROR_IS_OK(result) )
1342 continue;
1345 * if the printer is bound to the driver,
1346 * then reset to the new driver initdata
1349 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1351 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1353 if ( !set_driver_init(printer, 2) ) {
1354 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1355 printer->info_2->printername, printer->info_2->drivername));
1358 result = mod_a_printer( printer, 2 );
1359 if ( !W_ERROR_IS_OK(result) ) {
1360 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1361 get_dos_error_msg(result)));
1365 free_a_printer( &printer, 2 );
1369 /* all done */
1371 return;
1374 /********************************************************************
1375 Copy routines used by convert_to_openprinterex()
1376 *******************************************************************/
1378 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1380 DEVICEMODE *d;
1381 int len;
1383 if (!devmode)
1384 return NULL;
1386 DEBUG (8,("dup_devmode\n"));
1388 /* bulk copy first */
1390 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1391 if (!d)
1392 return NULL;
1394 /* dup the pointer members separately */
1396 len = unistrlen(devmode->devicename.buffer);
1397 if (len != -1) {
1398 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1399 if (!d->devicename.buffer) {
1400 return NULL;
1402 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1403 return NULL;
1407 len = unistrlen(devmode->formname.buffer);
1408 if (len != -1) {
1409 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1410 if (!d->devicename.buffer) {
1411 return NULL;
1413 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1414 return NULL;
1417 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1418 devmode->driverextra);
1419 if (!d->dev_private) {
1420 return NULL;
1422 return d;
1425 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1427 if (!new_ctr || !ctr)
1428 return;
1430 DEBUG(8,("copy_devmode_ctr\n"));
1432 new_ctr->size = ctr->size;
1433 new_ctr->devmode_ptr = ctr->devmode_ptr;
1435 if(ctr->devmode_ptr)
1436 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1439 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1441 if (!new_def || !def)
1442 return;
1444 DEBUG(8,("copy_printer_defaults\n"));
1446 new_def->datatype_ptr = def->datatype_ptr;
1448 if (def->datatype_ptr)
1449 copy_unistr2(&new_def->datatype, &def->datatype);
1451 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1453 new_def->access_required = def->access_required;
1456 /********************************************************************
1457 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1458 * SPOOL_Q_OPEN_PRINTER_EX structure
1459 ********************************************************************/
1461 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1463 if (!q_u_ex || !q_u)
1464 return WERR_OK;
1466 DEBUG(8,("convert_to_openprinterex\n"));
1468 if ( q_u->printername ) {
1469 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1470 if (q_u_ex->printername == NULL)
1471 return WERR_NOMEM;
1472 copy_unistr2(q_u_ex->printername, q_u->printername);
1475 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1477 return WERR_OK;
1480 /********************************************************************
1481 * spoolss_open_printer
1483 * called from the spoolss dispatcher
1484 ********************************************************************/
1486 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1488 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1489 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1491 if (!q_u || !r_u)
1492 return WERR_NOMEM;
1494 ZERO_STRUCT(q_u_ex);
1495 ZERO_STRUCT(r_u_ex);
1497 /* convert the OpenPrinter() call to OpenPrinterEx() */
1499 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1500 if (!W_ERROR_IS_OK(r_u_ex.status))
1501 return r_u_ex.status;
1503 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1505 /* convert back to OpenPrinter() */
1507 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1509 return r_u->status;
1512 /********************************************************************
1513 ********************************************************************/
1515 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1517 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1518 POLICY_HND *handle = &r_u->handle;
1520 fstring name;
1521 int snum;
1522 Printer_entry *Printer=NULL;
1524 if ( !q_u->printername )
1525 return WERR_INVALID_PRINTER_NAME;
1527 /* some sanity check because you can open a printer or a print server */
1528 /* aka: \\server\printer or \\server */
1530 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1532 DEBUGADD(3,("checking name: %s\n",name));
1534 if (!open_printer_hnd(p, handle, name, 0))
1535 return WERR_INVALID_PRINTER_NAME;
1537 Printer=find_printer_index_by_hnd(p, handle);
1538 if ( !Printer ) {
1539 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1540 "handle we created for printer %s\n", name ));
1541 close_printer_handle(p,handle);
1542 return WERR_INVALID_PRINTER_NAME;
1546 * First case: the user is opening the print server:
1548 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1549 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1551 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1552 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1553 * or if the user is listed in the smb.conf printer admin parameter.
1555 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1556 * client view printer folder, but does not show the MSAPW.
1558 * Note: this test needs code to check access rights here too. Jeremy
1559 * could you look at this?
1561 * Second case: the user is opening a printer:
1562 * NT doesn't let us connect to a printer if the connecting user
1563 * doesn't have print permission.
1565 * Third case: user is opening a Port Monitor
1566 * access checks same as opening a handle to the print server.
1569 switch (Printer->printer_type )
1571 case SPLHND_SERVER:
1572 case SPLHND_PORTMON_TCP:
1573 case SPLHND_PORTMON_LOCAL:
1574 /* Printserver handles use global struct... */
1576 snum = -1;
1578 /* Map standard access rights to object specific access rights */
1580 se_map_standard(&printer_default->access_required,
1581 &printserver_std_mapping);
1583 /* Deny any object specific bits that don't apply to print
1584 servers (i.e printer and job specific bits) */
1586 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1588 if (printer_default->access_required &
1589 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1590 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1591 close_printer_handle(p, handle);
1592 return WERR_ACCESS_DENIED;
1595 /* Allow admin access */
1597 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1599 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1601 if (!lp_ms_add_printer_wizard()) {
1602 close_printer_handle(p, handle);
1603 return WERR_ACCESS_DENIED;
1606 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1607 and not a printer admin, then fail */
1609 if ((p->pipe_user.ut.uid != 0) &&
1610 !user_has_privileges(p->pipe_user.nt_user_token,
1611 &se_printop ) &&
1612 !token_contains_name_in_list(
1613 uidtoname(p->pipe_user.ut.uid), NULL,
1614 p->pipe_user.nt_user_token,
1615 lp_printer_admin(snum))) {
1616 close_printer_handle(p, handle);
1617 return WERR_ACCESS_DENIED;
1620 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1622 else
1624 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1627 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1628 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1630 /* We fall through to return WERR_OK */
1631 break;
1633 case SPLHND_PRINTER:
1634 /* NT doesn't let us connect to a printer if the connecting user
1635 doesn't have print permission. */
1637 if (!get_printer_snum(p, handle, &snum, NULL)) {
1638 close_printer_handle(p, handle);
1639 return WERR_BADFID;
1642 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1644 /* map an empty access mask to the minimum access mask */
1645 if (printer_default->access_required == 0x0)
1646 printer_default->access_required = PRINTER_ACCESS_USE;
1649 * If we are not serving the printer driver for this printer,
1650 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1651 * will keep NT clients happy --jerry
1654 if (lp_use_client_driver(snum)
1655 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1657 printer_default->access_required = PRINTER_ACCESS_USE;
1660 /* check smb.conf parameters and the the sec_desc */
1662 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1663 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1664 return WERR_ACCESS_DENIED;
1667 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1668 p->pipe_user.nt_user_token, snum) ||
1669 !print_access_check(&p->pipe_user, snum,
1670 printer_default->access_required)) {
1671 DEBUG(3, ("access DENIED for printer open\n"));
1672 close_printer_handle(p, handle);
1673 return WERR_ACCESS_DENIED;
1676 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1677 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1678 close_printer_handle(p, handle);
1679 return WERR_ACCESS_DENIED;
1682 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1683 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1684 else
1685 printer_default->access_required = PRINTER_ACCESS_USE;
1687 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1688 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1690 break;
1692 default:
1693 /* sanity check to prevent programmer error */
1694 return WERR_BADFID;
1697 Printer->access_granted = printer_default->access_required;
1700 * If the client sent a devmode in the OpenPrinter() call, then
1701 * save it here in case we get a job submission on this handle
1704 if ( (Printer->printer_type != SPLHND_SERVER)
1705 && q_u->printer_default.devmode_cont.devmode_ptr )
1707 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1708 &Printer->nt_devmode );
1711 #if 0 /* JERRY -- I'm doubtful this is really effective */
1712 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713 optimization in Windows 2000 clients --jerry */
1715 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1716 && (RA_WIN2K == get_remote_arch()) )
1718 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1719 sys_usleep( 500000 );
1721 #endif
1723 return WERR_OK;
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1732 BOOL ret;
1734 switch (level) {
1735 case 2:
1736 /* allocate memory if needed. Messy because
1737 convert_printer_info is used to update an existing
1738 printer or build a new one */
1740 if ( !printer->info_2 ) {
1741 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1742 if ( !printer->info_2 ) {
1743 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1744 return False;
1748 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1749 printer->info_2->setuptime = time(NULL);
1751 return ret;
1754 return False;
1757 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1758 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1760 BOOL result = True;
1762 switch (level) {
1763 case 3:
1764 printer->info_3=NULL;
1765 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1766 result = False;
1767 break;
1768 case 6:
1769 printer->info_6=NULL;
1770 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1771 result = False;
1772 break;
1773 default:
1774 break;
1777 return result;
1780 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1781 NT_DEVICEMODE **pp_nt_devmode)
1783 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1786 * Ensure nt_devmode is a valid pointer
1787 * as we will be overwriting it.
1790 if (nt_devmode == NULL) {
1791 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1792 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1793 return False;
1796 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1797 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1799 nt_devmode->specversion=devmode->specversion;
1800 nt_devmode->driverversion=devmode->driverversion;
1801 nt_devmode->size=devmode->size;
1802 nt_devmode->fields=devmode->fields;
1803 nt_devmode->orientation=devmode->orientation;
1804 nt_devmode->papersize=devmode->papersize;
1805 nt_devmode->paperlength=devmode->paperlength;
1806 nt_devmode->paperwidth=devmode->paperwidth;
1807 nt_devmode->scale=devmode->scale;
1808 nt_devmode->copies=devmode->copies;
1809 nt_devmode->defaultsource=devmode->defaultsource;
1810 nt_devmode->printquality=devmode->printquality;
1811 nt_devmode->color=devmode->color;
1812 nt_devmode->duplex=devmode->duplex;
1813 nt_devmode->yresolution=devmode->yresolution;
1814 nt_devmode->ttoption=devmode->ttoption;
1815 nt_devmode->collate=devmode->collate;
1817 nt_devmode->logpixels=devmode->logpixels;
1818 nt_devmode->bitsperpel=devmode->bitsperpel;
1819 nt_devmode->pelswidth=devmode->pelswidth;
1820 nt_devmode->pelsheight=devmode->pelsheight;
1821 nt_devmode->displayflags=devmode->displayflags;
1822 nt_devmode->displayfrequency=devmode->displayfrequency;
1823 nt_devmode->icmmethod=devmode->icmmethod;
1824 nt_devmode->icmintent=devmode->icmintent;
1825 nt_devmode->mediatype=devmode->mediatype;
1826 nt_devmode->dithertype=devmode->dithertype;
1827 nt_devmode->reserved1=devmode->reserved1;
1828 nt_devmode->reserved2=devmode->reserved2;
1829 nt_devmode->panningwidth=devmode->panningwidth;
1830 nt_devmode->panningheight=devmode->panningheight;
1833 * Only change private and driverextra if the incoming devmode
1834 * has a new one. JRA.
1837 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1838 SAFE_FREE(nt_devmode->nt_dev_private);
1839 nt_devmode->driverextra=devmode->driverextra;
1840 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1841 return False;
1842 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1845 *pp_nt_devmode = nt_devmode;
1847 return True;
1850 /********************************************************************
1851 * _spoolss_enddocprinter_internal.
1852 ********************************************************************/
1854 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1856 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1857 int snum;
1859 if (!Printer) {
1860 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1861 return WERR_BADFID;
1864 if (!get_printer_snum(p, handle, &snum, NULL))
1865 return WERR_BADFID;
1867 Printer->document_started=False;
1868 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1869 /* error codes unhandled so far ... */
1871 return WERR_OK;
1874 /********************************************************************
1875 * api_spoolss_closeprinter
1876 ********************************************************************/
1878 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1880 POLICY_HND *handle = &q_u->handle;
1882 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1884 if (Printer && Printer->document_started)
1885 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1887 if (!close_printer_handle(p, handle))
1888 return WERR_BADFID;
1890 /* clear the returned printer handle. Observed behavior
1891 from Win2k server. Don't think this really matters.
1892 Previous code just copied the value of the closed
1893 handle. --jerry */
1895 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1897 return WERR_OK;
1900 /********************************************************************
1901 * api_spoolss_deleteprinter
1903 ********************************************************************/
1905 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1907 POLICY_HND *handle = &q_u->handle;
1908 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1909 WERROR result;
1911 if (Printer && Printer->document_started)
1912 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1914 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1916 result = delete_printer_handle(p, handle);
1918 update_c_setprinter(False);
1920 return result;
1923 /*******************************************************************
1924 * static function to lookup the version id corresponding to an
1925 * long architecture string
1926 ******************************************************************/
1928 static int get_version_id (char * arch)
1930 int i;
1931 struct table_node archi_table[]= {
1933 {"Windows 4.0", "WIN40", 0 },
1934 {"Windows NT x86", "W32X86", 2 },
1935 {"Windows NT R4000", "W32MIPS", 2 },
1936 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1937 {"Windows NT PowerPC", "W32PPC", 2 },
1938 {"Windows IA64", "IA64", 3 },
1939 {"Windows x64", "x64", 3 },
1940 {NULL, "", -1 }
1943 for (i=0; archi_table[i].long_archi != NULL; i++)
1945 if (strcmp(arch, archi_table[i].long_archi) == 0)
1946 return (archi_table[i].version);
1949 return -1;
1952 /********************************************************************
1953 * _spoolss_deleteprinterdriver
1954 ********************************************************************/
1956 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1958 fstring driver;
1959 fstring arch;
1960 NT_PRINTER_DRIVER_INFO_LEVEL info;
1961 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1962 int version;
1963 WERROR status;
1964 WERROR status_win2k = WERR_ACCESS_DENIED;
1965 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1967 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1968 and not a printer admin, then fail */
1970 if ( (p->pipe_user.ut.uid != 0)
1971 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1972 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1973 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1975 return WERR_ACCESS_DENIED;
1978 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1979 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1981 /* check that we have a valid driver name first */
1983 if ((version=get_version_id(arch)) == -1)
1984 return WERR_INVALID_ENVIRONMENT;
1986 ZERO_STRUCT(info);
1987 ZERO_STRUCT(info_win2k);
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1991 /* try for Win2k driver if "Windows NT x86" */
1993 if ( version == 2 ) {
1994 version = 3;
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1996 status = WERR_UNKNOWN_PRINTER_DRIVER;
1997 goto done;
2000 /* otherwise it was a failure */
2001 else {
2002 status = WERR_UNKNOWN_PRINTER_DRIVER;
2003 goto done;
2008 if (printer_driver_in_use(info.info_3)) {
2009 status = WERR_PRINTER_DRIVER_IN_USE;
2010 goto done;
2013 if ( version == 2 )
2015 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2017 /* if we get to here, we now have 2 driver info structures to remove */
2018 /* remove the Win2k driver first*/
2020 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2021 free_a_printer_driver( info_win2k, 3 );
2023 /* this should not have failed---if it did, report to client */
2024 if ( !W_ERROR_IS_OK(status_win2k) )
2026 status = status_win2k;
2027 goto done;
2032 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2034 /* if at least one of the deletes succeeded return OK */
2036 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2037 status = WERR_OK;
2039 done:
2040 free_a_printer_driver( info, 3 );
2042 return status;
2045 /********************************************************************
2046 * spoolss_deleteprinterdriverex
2047 ********************************************************************/
2049 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2051 fstring driver;
2052 fstring arch;
2053 NT_PRINTER_DRIVER_INFO_LEVEL info;
2054 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2055 int version;
2056 uint32 flags = q_u->delete_flags;
2057 BOOL delete_files;
2058 WERROR status;
2059 WERROR status_win2k = WERR_ACCESS_DENIED;
2060 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2062 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2063 and not a printer admin, then fail */
2065 if ( (p->pipe_user.ut.uid != 0)
2066 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2067 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2068 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2070 return WERR_ACCESS_DENIED;
2073 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2074 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2076 /* check that we have a valid driver name first */
2077 if ((version=get_version_id(arch)) == -1) {
2078 /* this is what NT returns */
2079 return WERR_INVALID_ENVIRONMENT;
2082 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2083 version = q_u->version;
2085 ZERO_STRUCT(info);
2086 ZERO_STRUCT(info_win2k);
2088 status = get_a_printer_driver(&info, 3, driver, arch, version);
2090 if ( !W_ERROR_IS_OK(status) )
2093 * if the client asked for a specific version,
2094 * or this is something other than Windows NT x86,
2095 * then we've failed
2098 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2099 goto done;
2101 /* try for Win2k driver if "Windows NT x86" */
2103 version = 3;
2104 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2105 status = WERR_UNKNOWN_PRINTER_DRIVER;
2106 goto done;
2110 if ( printer_driver_in_use(info.info_3) ) {
2111 status = WERR_PRINTER_DRIVER_IN_USE;
2112 goto done;
2116 * we have a couple of cases to consider.
2117 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2118 * then the delete should fail if **any** files overlap with
2119 * other drivers
2120 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2121 * non-overlapping files
2122 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2123 * is set, the do not delete any files
2124 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2127 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2129 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2131 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2132 /* no idea of the correct error here */
2133 status = WERR_ACCESS_DENIED;
2134 goto done;
2138 /* also check for W32X86/3 if necessary; maybe we already have? */
2140 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2141 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2144 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2145 /* no idea of the correct error here */
2146 free_a_printer_driver( info_win2k, 3 );
2147 status = WERR_ACCESS_DENIED;
2148 goto done;
2151 /* if we get to here, we now have 2 driver info structures to remove */
2152 /* remove the Win2k driver first*/
2154 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2155 free_a_printer_driver( info_win2k, 3 );
2157 /* this should not have failed---if it did, report to client */
2159 if ( !W_ERROR_IS_OK(status_win2k) )
2160 goto done;
2164 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2166 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2167 status = WERR_OK;
2168 done:
2169 free_a_printer_driver( info, 3 );
2171 return status;
2175 /****************************************************************************
2176 Internal routine for retreiving printerdata
2177 ***************************************************************************/
2179 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2180 const char *key, const char *value, uint32 *type, uint8 **data,
2181 uint32 *needed, uint32 in_size )
2183 REGISTRY_VALUE *val;
2184 uint32 size;
2185 int data_len;
2187 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2188 return WERR_BADFILE;
2190 *type = regval_type( val );
2192 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2194 size = regval_size( val );
2196 /* copy the min(in_size, len) */
2198 if ( in_size ) {
2199 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2201 /* special case for 0 length values */
2202 if ( data_len ) {
2203 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2204 return WERR_NOMEM;
2206 else {
2207 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2208 return WERR_NOMEM;
2211 else
2212 *data = NULL;
2214 *needed = size;
2216 DEBUG(5,("get_printer_dataex: copy done\n"));
2218 return WERR_OK;
2221 /****************************************************************************
2222 Internal routine for removing printerdata
2223 ***************************************************************************/
2225 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2227 return delete_printer_data( printer->info_2, key, value );
2230 /****************************************************************************
2231 Internal routine for storing printerdata
2232 ***************************************************************************/
2234 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2235 uint32 type, uint8 *data, int real_len )
2237 /* the registry objects enforce uniqueness based on value name */
2239 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2242 /********************************************************************
2243 GetPrinterData on a printer server Handle.
2244 ********************************************************************/
2246 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2248 int i;
2250 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2252 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2253 *type = REG_DWORD;
2254 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2255 return WERR_NOMEM;
2256 *needed = 0x4;
2257 return WERR_OK;
2260 if (!StrCaseCmp(value, "BeepEnabled")) {
2261 *type = REG_DWORD;
2262 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2263 return WERR_NOMEM;
2264 SIVAL(*data, 0, 0x00);
2265 *needed = 0x4;
2266 return WERR_OK;
2269 if (!StrCaseCmp(value, "EventLog")) {
2270 *type = REG_DWORD;
2271 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2272 return WERR_NOMEM;
2273 /* formally was 0x1b */
2274 SIVAL(*data, 0, 0x0);
2275 *needed = 0x4;
2276 return WERR_OK;
2279 if (!StrCaseCmp(value, "NetPopup")) {
2280 *type = REG_DWORD;
2281 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2282 return WERR_NOMEM;
2283 SIVAL(*data, 0, 0x00);
2284 *needed = 0x4;
2285 return WERR_OK;
2288 if (!StrCaseCmp(value, "MajorVersion")) {
2289 *type = REG_DWORD;
2290 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2291 return WERR_NOMEM;
2293 /* Windows NT 4.0 seems to not allow uploading of drivers
2294 to a server that reports 0x3 as the MajorVersion.
2295 need to investigate more how Win2k gets around this .
2296 -- jerry */
2298 if ( RA_WINNT == get_remote_arch() )
2299 SIVAL(*data, 0, 2);
2300 else
2301 SIVAL(*data, 0, 3);
2303 *needed = 0x4;
2304 return WERR_OK;
2307 if (!StrCaseCmp(value, "MinorVersion")) {
2308 *type = REG_DWORD;
2309 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2310 return WERR_NOMEM;
2311 SIVAL(*data, 0, 0);
2312 *needed = 0x4;
2313 return WERR_OK;
2316 /* REG_BINARY
2317 * uint32 size = 0x114
2318 * uint32 major = 5
2319 * uint32 minor = [0|1]
2320 * uint32 build = [2195|2600]
2321 * extra unicode string = e.g. "Service Pack 3"
2323 if (!StrCaseCmp(value, "OSVersion")) {
2324 *type = REG_BINARY;
2325 *needed = 0x114;
2327 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2328 return WERR_NOMEM;
2330 SIVAL(*data, 0, *needed); /* size */
2331 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2332 SIVAL(*data, 8, 0);
2333 SIVAL(*data, 12, 2195); /* build */
2335 /* leave extra string empty */
2337 return WERR_OK;
2341 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2342 const char *string="C:\\PRINTERS";
2343 *type = REG_SZ;
2344 *needed = 2*(strlen(string)+1);
2345 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2346 return WERR_NOMEM;
2347 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2349 /* it's done by hand ready to go on the wire */
2350 for (i=0; i<strlen(string); i++) {
2351 (*data)[2*i]=string[i];
2352 (*data)[2*i+1]='\0';
2354 return WERR_OK;
2357 if (!StrCaseCmp(value, "Architecture")) {
2358 const char *string="Windows NT x86";
2359 *type = REG_SZ;
2360 *needed = 2*(strlen(string)+1);
2361 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2362 return WERR_NOMEM;
2363 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2364 for (i=0; i<strlen(string); i++) {
2365 (*data)[2*i]=string[i];
2366 (*data)[2*i+1]='\0';
2368 return WERR_OK;
2371 if (!StrCaseCmp(value, "DsPresent")) {
2372 *type = REG_DWORD;
2373 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2374 return WERR_NOMEM;
2376 /* only show the publish check box if we are a
2377 memeber of a AD domain */
2379 if ( lp_security() == SEC_ADS )
2380 SIVAL(*data, 0, 0x01);
2381 else
2382 SIVAL(*data, 0, 0x00);
2384 *needed = 0x4;
2385 return WERR_OK;
2388 if (!StrCaseCmp(value, "DNSMachineName")) {
2389 pstring hostname;
2391 if (!get_mydnsfullname(hostname))
2392 return WERR_BADFILE;
2393 *type = REG_SZ;
2394 *needed = 2*(strlen(hostname)+1);
2395 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2396 return WERR_NOMEM;
2397 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2398 for (i=0; i<strlen(hostname); i++) {
2399 (*data)[2*i]=hostname[i];
2400 (*data)[2*i+1]='\0';
2402 return WERR_OK;
2406 return WERR_BADFILE;
2409 /********************************************************************
2410 * spoolss_getprinterdata
2411 ********************************************************************/
2413 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2415 POLICY_HND *handle = &q_u->handle;
2416 UNISTR2 *valuename = &q_u->valuename;
2417 uint32 in_size = q_u->size;
2418 uint32 *type = &r_u->type;
2419 uint32 *out_size = &r_u->size;
2420 uint8 **data = &r_u->data;
2421 uint32 *needed = &r_u->needed;
2422 WERROR status;
2423 fstring value;
2424 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2425 NT_PRINTER_INFO_LEVEL *printer = NULL;
2426 int snum = 0;
2429 * Reminder: when it's a string, the length is in BYTES
2430 * even if UNICODE is negociated.
2432 * JFM, 4/19/1999
2435 *out_size = in_size;
2437 /* in case of problem, return some default values */
2439 *needed = 0;
2440 *type = 0;
2442 DEBUG(4,("_spoolss_getprinterdata\n"));
2444 if ( !Printer ) {
2445 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2446 status = WERR_BADFID;
2447 goto done;
2450 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2452 if ( Printer->printer_type == SPLHND_SERVER )
2453 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2454 else
2456 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2457 status = WERR_BADFID;
2458 goto done;
2461 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2462 if ( !W_ERROR_IS_OK(status) )
2463 goto done;
2465 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2467 if ( strequal(value, "ChangeId") ) {
2468 *type = REG_DWORD;
2469 *needed = sizeof(uint32);
2470 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2471 status = WERR_NOMEM;
2472 goto done;
2474 SIVAL( *data, 0, printer->info_2->changeid );
2475 status = WERR_OK;
2477 else
2478 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2481 if (*needed > *out_size)
2482 status = WERR_MORE_DATA;
2484 done:
2485 if ( !W_ERROR_IS_OK(status) )
2487 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2489 /* reply this param doesn't exist */
2491 if ( *out_size ) {
2492 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2493 if ( printer )
2494 free_a_printer( &printer, 2 );
2495 return WERR_NOMEM;
2498 else {
2499 *data = NULL;
2503 /* cleanup & exit */
2505 if ( printer )
2506 free_a_printer( &printer, 2 );
2508 return status;
2511 /*********************************************************
2512 Connect to the client machine.
2513 **********************************************************/
2515 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2516 struct in_addr *client_ip, const char *remote_machine)
2518 NTSTATUS ret;
2519 struct cli_state *the_cli;
2520 struct in_addr rm_addr;
2522 if ( is_zero_ip(*client_ip) ) {
2523 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2524 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2525 return False;
2528 if ( ismyip( rm_addr )) {
2529 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2530 return False;
2532 } else {
2533 rm_addr.s_addr = client_ip->s_addr;
2534 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2535 inet_ntoa(*client_ip) ));
2538 /* setup the connection */
2540 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2541 &rm_addr, 0, "IPC$", "IPC",
2542 "", /* username */
2543 "", /* domain */
2544 "", /* password */
2545 0, lp_client_signing(), NULL );
2547 if ( !NT_STATUS_IS_OK( ret ) ) {
2548 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2549 remote_machine ));
2550 return False;
2553 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2554 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2555 cli_shutdown(the_cli);
2556 return False;
2560 * Ok - we have an anonymous connection to the IPC$ share.
2561 * Now start the NT Domain stuff :-).
2564 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2565 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2566 remote_machine, nt_errstr(ret)));
2567 cli_shutdown(the_cli);
2568 return False;
2571 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2573 (*pp_pipe)->cli = the_cli;
2575 return True;
2578 /***************************************************************************
2579 Connect to the client.
2580 ****************************************************************************/
2582 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2583 uint32 localprinter, uint32 type,
2584 POLICY_HND *handle, struct in_addr *client_ip)
2586 WERROR result;
2589 * If it's the first connection, contact the client
2590 * and connect to the IPC$ share anonymously
2592 if (smb_connections==0) {
2593 fstring unix_printer;
2595 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2597 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2598 return False;
2600 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2601 /* Tell the connections db we're now interested in printer
2602 * notify messages. */
2603 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2607 * Tell the specific printing tdb we want messages for this printer
2608 * by registering our PID.
2611 if (!print_notify_register_pid(snum))
2612 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2614 smb_connections++;
2616 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2617 type, handle);
2619 if (!W_ERROR_IS_OK(result))
2620 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2621 dos_errstr(result)));
2623 return (W_ERROR_IS_OK(result));
2626 /********************************************************************
2627 * _spoolss_rffpcnex
2628 * ReplyFindFirstPrinterChangeNotifyEx
2630 * before replying OK: status=0 a rpc call is made to the workstation
2631 * asking ReplyOpenPrinter
2633 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2634 * called from api_spoolss_rffpcnex
2635 ********************************************************************/
2637 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2639 POLICY_HND *handle = &q_u->handle;
2640 uint32 flags = q_u->flags;
2641 uint32 options = q_u->options;
2642 UNISTR2 *localmachine = &q_u->localmachine;
2643 uint32 printerlocal = q_u->printerlocal;
2644 int snum = -1;
2645 SPOOL_NOTIFY_OPTION *option = q_u->option;
2646 struct in_addr client_ip;
2648 /* store the notify value in the printer struct */
2650 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2652 if (!Printer) {
2653 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2654 return WERR_BADFID;
2657 Printer->notify.flags=flags;
2658 Printer->notify.options=options;
2659 Printer->notify.printerlocal=printerlocal;
2661 if (Printer->notify.option)
2662 free_spool_notify_option(&Printer->notify.option);
2664 Printer->notify.option=dup_spool_notify_option(option);
2666 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2667 sizeof(Printer->notify.localmachine)-1);
2669 /* Connect to the client machine and send a ReplyOpenPrinter */
2671 if ( Printer->printer_type == SPLHND_SERVER)
2672 snum = -1;
2673 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2674 !get_printer_snum(p, handle, &snum, NULL) )
2675 return WERR_BADFID;
2677 client_ip.s_addr = inet_addr(p->conn->client_address);
2679 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2680 Printer->notify.printerlocal, 1,
2681 &Printer->notify.client_hnd, &client_ip))
2682 return WERR_SERVER_UNAVAILABLE;
2684 Printer->notify.client_connected=True;
2686 return WERR_OK;
2689 /*******************************************************************
2690 * fill a notify_info_data with the servername
2691 ********************************************************************/
2693 void spoolss_notify_server_name(int snum,
2694 SPOOL_NOTIFY_INFO_DATA *data,
2695 print_queue_struct *queue,
2696 NT_PRINTER_INFO_LEVEL *printer,
2697 TALLOC_CTX *mem_ctx)
2699 pstring temp;
2700 uint32 len;
2702 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2704 data->notify_data.data.length = len;
2705 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2707 if (!data->notify_data.data.string) {
2708 data->notify_data.data.length = 0;
2709 return;
2712 memcpy(data->notify_data.data.string, temp, len);
2715 /*******************************************************************
2716 * fill a notify_info_data with the printername (not including the servername).
2717 ********************************************************************/
2719 void spoolss_notify_printer_name(int snum,
2720 SPOOL_NOTIFY_INFO_DATA *data,
2721 print_queue_struct *queue,
2722 NT_PRINTER_INFO_LEVEL *printer,
2723 TALLOC_CTX *mem_ctx)
2725 pstring temp;
2726 uint32 len;
2728 /* the notify name should not contain the \\server\ part */
2729 char *p = strrchr(printer->info_2->printername, '\\');
2731 if (!p) {
2732 p = printer->info_2->printername;
2733 } else {
2734 p++;
2737 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2739 data->notify_data.data.length = len;
2740 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2742 if (!data->notify_data.data.string) {
2743 data->notify_data.data.length = 0;
2744 return;
2747 memcpy(data->notify_data.data.string, temp, len);
2750 /*******************************************************************
2751 * fill a notify_info_data with the servicename
2752 ********************************************************************/
2754 void spoolss_notify_share_name(int snum,
2755 SPOOL_NOTIFY_INFO_DATA *data,
2756 print_queue_struct *queue,
2757 NT_PRINTER_INFO_LEVEL *printer,
2758 TALLOC_CTX *mem_ctx)
2760 pstring temp;
2761 uint32 len;
2763 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2765 data->notify_data.data.length = len;
2766 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2768 if (!data->notify_data.data.string) {
2769 data->notify_data.data.length = 0;
2770 return;
2773 memcpy(data->notify_data.data.string, temp, len);
2776 /*******************************************************************
2777 * fill a notify_info_data with the port name
2778 ********************************************************************/
2780 void spoolss_notify_port_name(int snum,
2781 SPOOL_NOTIFY_INFO_DATA *data,
2782 print_queue_struct *queue,
2783 NT_PRINTER_INFO_LEVEL *printer,
2784 TALLOC_CTX *mem_ctx)
2786 pstring temp;
2787 uint32 len;
2789 /* even if it's strange, that's consistant in all the code */
2791 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2793 data->notify_data.data.length = len;
2794 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2796 if (!data->notify_data.data.string) {
2797 data->notify_data.data.length = 0;
2798 return;
2801 memcpy(data->notify_data.data.string, temp, len);
2804 /*******************************************************************
2805 * fill a notify_info_data with the printername
2806 * but it doesn't exist, have to see what to do
2807 ********************************************************************/
2809 void spoolss_notify_driver_name(int snum,
2810 SPOOL_NOTIFY_INFO_DATA *data,
2811 print_queue_struct *queue,
2812 NT_PRINTER_INFO_LEVEL *printer,
2813 TALLOC_CTX *mem_ctx)
2815 pstring temp;
2816 uint32 len;
2818 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2820 data->notify_data.data.length = len;
2821 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2823 if (!data->notify_data.data.string) {
2824 data->notify_data.data.length = 0;
2825 return;
2828 memcpy(data->notify_data.data.string, temp, len);
2831 /*******************************************************************
2832 * fill a notify_info_data with the comment
2833 ********************************************************************/
2835 void spoolss_notify_comment(int snum,
2836 SPOOL_NOTIFY_INFO_DATA *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2841 pstring temp;
2842 uint32 len;
2844 if (*printer->info_2->comment == '\0')
2845 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2846 else
2847 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2849 data->notify_data.data.length = len;
2850 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2852 if (!data->notify_data.data.string) {
2853 data->notify_data.data.length = 0;
2854 return;
2857 memcpy(data->notify_data.data.string, temp, len);
2860 /*******************************************************************
2861 * fill a notify_info_data with the comment
2862 * location = "Room 1, floor 2, building 3"
2863 ********************************************************************/
2865 void spoolss_notify_location(int snum,
2866 SPOOL_NOTIFY_INFO_DATA *data,
2867 print_queue_struct *queue,
2868 NT_PRINTER_INFO_LEVEL *printer,
2869 TALLOC_CTX *mem_ctx)
2871 pstring temp;
2872 uint32 len;
2874 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2876 data->notify_data.data.length = len;
2877 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2879 if (!data->notify_data.data.string) {
2880 data->notify_data.data.length = 0;
2881 return;
2884 memcpy(data->notify_data.data.string, temp, len);
2887 /*******************************************************************
2888 * fill a notify_info_data with the device mode
2889 * jfm:xxxx don't to it for know but that's a real problem !!!
2890 ********************************************************************/
2892 static void spoolss_notify_devmode(int snum,
2893 SPOOL_NOTIFY_INFO_DATA *data,
2894 print_queue_struct *queue,
2895 NT_PRINTER_INFO_LEVEL *printer,
2896 TALLOC_CTX *mem_ctx)
2898 /* for a dummy implementation we have to zero the fields */
2899 data->notify_data.data.length = 0;
2900 data->notify_data.data.string = NULL;
2903 /*******************************************************************
2904 * fill a notify_info_data with the separator file name
2905 ********************************************************************/
2907 void spoolss_notify_sepfile(int snum,
2908 SPOOL_NOTIFY_INFO_DATA *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2913 pstring temp;
2914 uint32 len;
2916 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2918 data->notify_data.data.length = len;
2919 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2921 if (!data->notify_data.data.string) {
2922 data->notify_data.data.length = 0;
2923 return;
2926 memcpy(data->notify_data.data.string, temp, len);
2929 /*******************************************************************
2930 * fill a notify_info_data with the print processor
2931 * jfm:xxxx return always winprint to indicate we don't do anything to it
2932 ********************************************************************/
2934 void spoolss_notify_print_processor(int snum,
2935 SPOOL_NOTIFY_INFO_DATA *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer,
2938 TALLOC_CTX *mem_ctx)
2940 pstring temp;
2941 uint32 len;
2943 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2945 data->notify_data.data.length = len;
2946 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2948 if (!data->notify_data.data.string) {
2949 data->notify_data.data.length = 0;
2950 return;
2953 memcpy(data->notify_data.data.string, temp, len);
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor options
2958 * jfm:xxxx send an empty string
2959 ********************************************************************/
2961 void spoolss_notify_parameters(int snum,
2962 SPOOL_NOTIFY_INFO_DATA *data,
2963 print_queue_struct *queue,
2964 NT_PRINTER_INFO_LEVEL *printer,
2965 TALLOC_CTX *mem_ctx)
2967 pstring temp;
2968 uint32 len;
2970 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2972 data->notify_data.data.length = len;
2973 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2975 if (!data->notify_data.data.string) {
2976 data->notify_data.data.length = 0;
2977 return;
2980 memcpy(data->notify_data.data.string, temp, len);
2983 /*******************************************************************
2984 * fill a notify_info_data with the data type
2985 * jfm:xxxx always send RAW as data type
2986 ********************************************************************/
2988 void spoolss_notify_datatype(int snum,
2989 SPOOL_NOTIFY_INFO_DATA *data,
2990 print_queue_struct *queue,
2991 NT_PRINTER_INFO_LEVEL *printer,
2992 TALLOC_CTX *mem_ctx)
2994 pstring temp;
2995 uint32 len;
2997 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2999 data->notify_data.data.length = len;
3000 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3002 if (!data->notify_data.data.string) {
3003 data->notify_data.data.length = 0;
3004 return;
3007 memcpy(data->notify_data.data.string, temp, len);
3010 /*******************************************************************
3011 * fill a notify_info_data with the security descriptor
3012 * jfm:xxxx send an null pointer to say no security desc
3013 * have to implement security before !
3014 ********************************************************************/
3016 static void spoolss_notify_security_desc(int snum,
3017 SPOOL_NOTIFY_INFO_DATA *data,
3018 print_queue_struct *queue,
3019 NT_PRINTER_INFO_LEVEL *printer,
3020 TALLOC_CTX *mem_ctx)
3022 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3023 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3026 /*******************************************************************
3027 * fill a notify_info_data with the attributes
3028 * jfm:xxxx a samba printer is always shared
3029 ********************************************************************/
3031 void spoolss_notify_attributes(int snum,
3032 SPOOL_NOTIFY_INFO_DATA *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3037 data->notify_data.value[0] = printer->info_2->attributes;
3038 data->notify_data.value[1] = 0;
3041 /*******************************************************************
3042 * fill a notify_info_data with the priority
3043 ********************************************************************/
3045 static void spoolss_notify_priority(int snum,
3046 SPOOL_NOTIFY_INFO_DATA *data,
3047 print_queue_struct *queue,
3048 NT_PRINTER_INFO_LEVEL *printer,
3049 TALLOC_CTX *mem_ctx)
3051 data->notify_data.value[0] = printer->info_2->priority;
3052 data->notify_data.value[1] = 0;
3055 /*******************************************************************
3056 * fill a notify_info_data with the default priority
3057 ********************************************************************/
3059 static void spoolss_notify_default_priority(int snum,
3060 SPOOL_NOTIFY_INFO_DATA *data,
3061 print_queue_struct *queue,
3062 NT_PRINTER_INFO_LEVEL *printer,
3063 TALLOC_CTX *mem_ctx)
3065 data->notify_data.value[0] = printer->info_2->default_priority;
3066 data->notify_data.value[1] = 0;
3069 /*******************************************************************
3070 * fill a notify_info_data with the start time
3071 ********************************************************************/
3073 static void spoolss_notify_start_time(int snum,
3074 SPOOL_NOTIFY_INFO_DATA *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3079 data->notify_data.value[0] = printer->info_2->starttime;
3080 data->notify_data.value[1] = 0;
3083 /*******************************************************************
3084 * fill a notify_info_data with the until time
3085 ********************************************************************/
3087 static void spoolss_notify_until_time(int snum,
3088 SPOOL_NOTIFY_INFO_DATA *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3093 data->notify_data.value[0] = printer->info_2->untiltime;
3094 data->notify_data.value[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the status
3099 ********************************************************************/
3101 static void spoolss_notify_status(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 print_status_struct status;
3109 print_queue_length(snum, &status);
3110 data->notify_data.value[0]=(uint32) status.status;
3111 data->notify_data.value[1] = 0;
3114 /*******************************************************************
3115 * fill a notify_info_data with the number of jobs queued
3116 ********************************************************************/
3118 void spoolss_notify_cjobs(int snum,
3119 SPOOL_NOTIFY_INFO_DATA *data,
3120 print_queue_struct *queue,
3121 NT_PRINTER_INFO_LEVEL *printer,
3122 TALLOC_CTX *mem_ctx)
3124 data->notify_data.value[0] = print_queue_length(snum, NULL);
3125 data->notify_data.value[1] = 0;
3128 /*******************************************************************
3129 * fill a notify_info_data with the average ppm
3130 ********************************************************************/
3132 static void spoolss_notify_average_ppm(int snum,
3133 SPOOL_NOTIFY_INFO_DATA *data,
3134 print_queue_struct *queue,
3135 NT_PRINTER_INFO_LEVEL *printer,
3136 TALLOC_CTX *mem_ctx)
3138 /* always respond 8 pages per minutes */
3139 /* a little hard ! */
3140 data->notify_data.value[0] = printer->info_2->averageppm;
3141 data->notify_data.value[1] = 0;
3144 /*******************************************************************
3145 * fill a notify_info_data with username
3146 ********************************************************************/
3148 static void spoolss_notify_username(int snum,
3149 SPOOL_NOTIFY_INFO_DATA *data,
3150 print_queue_struct *queue,
3151 NT_PRINTER_INFO_LEVEL *printer,
3152 TALLOC_CTX *mem_ctx)
3154 pstring temp;
3155 uint32 len;
3157 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3159 data->notify_data.data.length = len;
3160 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3162 if (!data->notify_data.data.string) {
3163 data->notify_data.data.length = 0;
3164 return;
3167 memcpy(data->notify_data.data.string, temp, len);
3170 /*******************************************************************
3171 * fill a notify_info_data with job status
3172 ********************************************************************/
3174 static void spoolss_notify_job_status(int snum,
3175 SPOOL_NOTIFY_INFO_DATA *data,
3176 print_queue_struct *queue,
3177 NT_PRINTER_INFO_LEVEL *printer,
3178 TALLOC_CTX *mem_ctx)
3180 data->notify_data.value[0]=nt_printj_status(queue->status);
3181 data->notify_data.value[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with job name
3186 ********************************************************************/
3188 static void spoolss_notify_job_name(int snum,
3189 SPOOL_NOTIFY_INFO_DATA *data,
3190 print_queue_struct *queue,
3191 NT_PRINTER_INFO_LEVEL *printer,
3192 TALLOC_CTX *mem_ctx)
3194 pstring temp;
3195 uint32 len;
3197 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3199 data->notify_data.data.length = len;
3200 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3202 if (!data->notify_data.data.string) {
3203 data->notify_data.data.length = 0;
3204 return;
3207 memcpy(data->notify_data.data.string, temp, len);
3210 /*******************************************************************
3211 * fill a notify_info_data with job status
3212 ********************************************************************/
3214 static void spoolss_notify_job_status_string(int snum,
3215 SPOOL_NOTIFY_INFO_DATA *data,
3216 print_queue_struct *queue,
3217 NT_PRINTER_INFO_LEVEL *printer,
3218 TALLOC_CTX *mem_ctx)
3221 * Now we're returning job status codes we just return a "" here. JRA.
3224 const char *p = "";
3225 pstring temp;
3226 uint32 len;
3228 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3229 p = "unknown";
3231 switch (queue->status) {
3232 case LPQ_QUEUED:
3233 p = "Queued";
3234 break;
3235 case LPQ_PAUSED:
3236 p = ""; /* NT provides the paused string */
3237 break;
3238 case LPQ_SPOOLING:
3239 p = "Spooling";
3240 break;
3241 case LPQ_PRINTING:
3242 p = "Printing";
3243 break;
3245 #endif /* NO LONGER NEEDED. */
3247 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3249 data->notify_data.data.length = len;
3250 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3252 if (!data->notify_data.data.string) {
3253 data->notify_data.data.length = 0;
3254 return;
3257 memcpy(data->notify_data.data.string, temp, len);
3260 /*******************************************************************
3261 * fill a notify_info_data with job time
3262 ********************************************************************/
3264 static void spoolss_notify_job_time(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3270 data->notify_data.value[0]=0x0;
3271 data->notify_data.value[1]=0;
3274 /*******************************************************************
3275 * fill a notify_info_data with job size
3276 ********************************************************************/
3278 static void spoolss_notify_job_size(int snum,
3279 SPOOL_NOTIFY_INFO_DATA *data,
3280 print_queue_struct *queue,
3281 NT_PRINTER_INFO_LEVEL *printer,
3282 TALLOC_CTX *mem_ctx)
3284 data->notify_data.value[0]=queue->size;
3285 data->notify_data.value[1]=0;
3288 /*******************************************************************
3289 * fill a notify_info_data with page info
3290 ********************************************************************/
3291 static void spoolss_notify_total_pages(int snum,
3292 SPOOL_NOTIFY_INFO_DATA *data,
3293 print_queue_struct *queue,
3294 NT_PRINTER_INFO_LEVEL *printer,
3295 TALLOC_CTX *mem_ctx)
3297 data->notify_data.value[0]=queue->page_count;
3298 data->notify_data.value[1]=0;
3301 /*******************************************************************
3302 * fill a notify_info_data with pages printed info.
3303 ********************************************************************/
3304 static void spoolss_notify_pages_printed(int snum,
3305 SPOOL_NOTIFY_INFO_DATA *data,
3306 print_queue_struct *queue,
3307 NT_PRINTER_INFO_LEVEL *printer,
3308 TALLOC_CTX *mem_ctx)
3310 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3311 data->notify_data.value[1]=0;
3314 /*******************************************************************
3315 Fill a notify_info_data with job position.
3316 ********************************************************************/
3318 static void spoolss_notify_job_position(int snum,
3319 SPOOL_NOTIFY_INFO_DATA *data,
3320 print_queue_struct *queue,
3321 NT_PRINTER_INFO_LEVEL *printer,
3322 TALLOC_CTX *mem_ctx)
3324 data->notify_data.value[0]=queue->job;
3325 data->notify_data.value[1]=0;
3328 /*******************************************************************
3329 Fill a notify_info_data with submitted time.
3330 ********************************************************************/
3332 static void spoolss_notify_submitted_time(int snum,
3333 SPOOL_NOTIFY_INFO_DATA *data,
3334 print_queue_struct *queue,
3335 NT_PRINTER_INFO_LEVEL *printer,
3336 TALLOC_CTX *mem_ctx)
3338 struct tm *t;
3339 uint32 len;
3340 SYSTEMTIME st;
3341 char *p;
3343 t=gmtime(&queue->time);
3345 len = sizeof(SYSTEMTIME);
3347 data->notify_data.data.length = len;
3348 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3350 if (!data->notify_data.data.string) {
3351 data->notify_data.data.length = 0;
3352 return;
3355 make_systemtime(&st, t);
3358 * Systemtime must be linearized as a set of UINT16's.
3359 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3362 p = (char *)data->notify_data.data.string;
3363 SSVAL(p, 0, st.year);
3364 SSVAL(p, 2, st.month);
3365 SSVAL(p, 4, st.dayofweek);
3366 SSVAL(p, 6, st.day);
3367 SSVAL(p, 8, st.hour);
3368 SSVAL(p, 10, st.minute);
3369 SSVAL(p, 12, st.second);
3370 SSVAL(p, 14, st.milliseconds);
3373 struct s_notify_info_data_table
3375 uint16 type;
3376 uint16 field;
3377 const char *name;
3378 uint32 size;
3379 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3380 print_queue_struct *queue,
3381 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3384 /* A table describing the various print notification constants and
3385 whether the notification data is a pointer to a variable sized
3386 buffer, a one value uint32 or a two value uint32. */
3388 static const struct s_notify_info_data_table notify_info_data_table[] =
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3439 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3442 /*******************************************************************
3443 Return the size of info_data structure.
3444 ********************************************************************/
3446 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3448 int i=0;
3450 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3451 if ( (notify_info_data_table[i].type == type)
3452 && (notify_info_data_table[i].field == field) ) {
3453 switch(notify_info_data_table[i].size) {
3454 case NOTIFY_ONE_VALUE:
3455 case NOTIFY_TWO_VALUE:
3456 return 1;
3457 case NOTIFY_STRING:
3458 return 2;
3460 /* The only pointer notify data I have seen on
3461 the wire is the submitted time and this has
3462 the notify size set to 4. -tpot */
3464 case NOTIFY_POINTER:
3465 return 4;
3467 case NOTIFY_SECDESC:
3468 return 5;
3473 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3475 return 0;
3478 /*******************************************************************
3479 Return the type of notify_info_data.
3480 ********************************************************************/
3482 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3484 uint32 i=0;
3486 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3487 if (notify_info_data_table[i].type == type &&
3488 notify_info_data_table[i].field == field)
3489 return notify_info_data_table[i].size;
3492 return 0;
3495 /****************************************************************************
3496 ****************************************************************************/
3498 static BOOL search_notify(uint16 type, uint16 field, int *value)
3500 int i;
3502 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3503 if (notify_info_data_table[i].type == type &&
3504 notify_info_data_table[i].field == field &&
3505 notify_info_data_table[i].fn != NULL) {
3506 *value = i;
3507 return True;
3511 return False;
3514 /****************************************************************************
3515 ****************************************************************************/
3517 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3519 info_data->type = type;
3520 info_data->field = field;
3521 info_data->reserved = 0;
3523 info_data->size = size_of_notify_info_data(type, field);
3524 info_data->enc_type = type_of_notify_info_data(type, field);
3526 info_data->id = id;
3529 /*******************************************************************
3531 * fill a notify_info struct with info asked
3533 ********************************************************************/
3535 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3536 snum, SPOOL_NOTIFY_OPTION_TYPE
3537 *option_type, uint32 id,
3538 TALLOC_CTX *mem_ctx)
3540 int field_num,j;
3541 uint16 type;
3542 uint16 field;
3544 SPOOL_NOTIFY_INFO_DATA *current_data;
3545 NT_PRINTER_INFO_LEVEL *printer = NULL;
3546 print_queue_struct *queue=NULL;
3548 type=option_type->type;
3550 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3551 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3552 option_type->count, lp_servicename(snum)));
3554 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3555 return False;
3557 for(field_num=0; field_num<option_type->count; field_num++) {
3558 field = option_type->fields[field_num];
3560 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3562 if (!search_notify(type, field, &j) )
3563 continue;
3565 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3566 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3567 free_a_printer(&printer, 2);
3568 return False;
3571 current_data = &info->data[info->count];
3573 construct_info_data(current_data, type, field, id);
3575 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3576 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3578 notify_info_data_table[j].fn(snum, current_data, queue,
3579 printer, mem_ctx);
3581 info->count++;
3584 free_a_printer(&printer, 2);
3585 return True;
3588 /*******************************************************************
3590 * fill a notify_info struct with info asked
3592 ********************************************************************/
3594 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3595 SPOOL_NOTIFY_INFO *info,
3596 NT_PRINTER_INFO_LEVEL *printer,
3597 int snum, SPOOL_NOTIFY_OPTION_TYPE
3598 *option_type, uint32 id,
3599 TALLOC_CTX *mem_ctx)
3601 int field_num,j;
3602 uint16 type;
3603 uint16 field;
3605 SPOOL_NOTIFY_INFO_DATA *current_data;
3607 DEBUG(4,("construct_notify_jobs_info\n"));
3609 type = option_type->type;
3611 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3612 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3613 option_type->count));
3615 for(field_num=0; field_num<option_type->count; field_num++) {
3616 field = option_type->fields[field_num];
3618 if (!search_notify(type, field, &j) )
3619 continue;
3621 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3622 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3623 return False;
3626 current_data=&(info->data[info->count]);
3628 construct_info_data(current_data, type, field, id);
3629 notify_info_data_table[j].fn(snum, current_data, queue,
3630 printer, mem_ctx);
3631 info->count++;
3634 return True;
3638 * JFM: The enumeration is not that simple, it's even non obvious.
3640 * let's take an example: I want to monitor the PRINTER SERVER for
3641 * the printer's name and the number of jobs currently queued.
3642 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3643 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3645 * I have 3 printers on the back of my server.
3647 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3648 * structures.
3649 * Number Data Id
3650 * 1 printer 1 name 1
3651 * 2 printer 1 cjob 1
3652 * 3 printer 2 name 2
3653 * 4 printer 2 cjob 2
3654 * 5 printer 3 name 3
3655 * 6 printer 3 name 3
3657 * that's the print server case, the printer case is even worse.
3660 /*******************************************************************
3662 * enumerate all printers on the printserver
3663 * fill a notify_info struct with info asked
3665 ********************************************************************/
3667 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3668 SPOOL_NOTIFY_INFO *info,
3669 TALLOC_CTX *mem_ctx)
3671 int snum;
3672 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3673 int n_services=lp_numservices();
3674 int i;
3675 SPOOL_NOTIFY_OPTION *option;
3676 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3678 DEBUG(4,("printserver_notify_info\n"));
3680 if (!Printer)
3681 return WERR_BADFID;
3683 option=Printer->notify.option;
3684 info->version=2;
3685 info->data=NULL;
3686 info->count=0;
3688 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3689 sending a ffpcn() request first */
3691 if ( !option )
3692 return WERR_BADFID;
3694 for (i=0; i<option->count; i++) {
3695 option_type=&(option->ctr.type[i]);
3697 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3698 continue;
3700 for (snum=0; snum<n_services; snum++)
3702 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3703 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3707 #if 0
3709 * Debugging information, don't delete.
3712 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3714 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3716 for (i=0; i<info->count; i++) {
3717 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3719 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3721 #endif
3723 return WERR_OK;
3726 /*******************************************************************
3728 * fill a notify_info struct with info asked
3730 ********************************************************************/
3732 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3733 TALLOC_CTX *mem_ctx)
3735 int snum;
3736 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3737 int i;
3738 uint32 id;
3739 SPOOL_NOTIFY_OPTION *option;
3740 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3741 int count,j;
3742 print_queue_struct *queue=NULL;
3743 print_status_struct status;
3745 DEBUG(4,("printer_notify_info\n"));
3747 if (!Printer)
3748 return WERR_BADFID;
3750 option=Printer->notify.option;
3751 id = 0x0;
3752 info->version=2;
3753 info->data=NULL;
3754 info->count=0;
3756 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3757 sending a ffpcn() request first */
3759 if ( !option )
3760 return WERR_BADFID;
3762 get_printer_snum(p, hnd, &snum, NULL);
3764 for (i=0; i<option->count; i++) {
3765 option_type=&option->ctr.type[i];
3767 switch ( option_type->type ) {
3768 case PRINTER_NOTIFY_TYPE:
3769 if(construct_notify_printer_info(Printer, info, snum,
3770 option_type, id,
3771 mem_ctx))
3772 id--;
3773 break;
3775 case JOB_NOTIFY_TYPE: {
3776 NT_PRINTER_INFO_LEVEL *printer = NULL;
3778 count = print_queue_status(snum, &queue, &status);
3780 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3781 goto done;
3783 for (j=0; j<count; j++) {
3784 construct_notify_jobs_info(&queue[j], info,
3785 printer, snum,
3786 option_type,
3787 queue[j].job,
3788 mem_ctx);
3791 free_a_printer(&printer, 2);
3793 done:
3794 SAFE_FREE(queue);
3795 break;
3801 * Debugging information, don't delete.
3804 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3805 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3806 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3808 for (i=0; i<info->count; i++) {
3809 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3810 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3811 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3814 return WERR_OK;
3817 /********************************************************************
3818 * spoolss_rfnpcnex
3819 ********************************************************************/
3821 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3823 POLICY_HND *handle = &q_u->handle;
3824 SPOOL_NOTIFY_INFO *info = &r_u->info;
3826 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3827 WERROR result = WERR_BADFID;
3829 /* we always have a NOTIFY_INFO struct */
3830 r_u->info_ptr=0x1;
3832 if (!Printer) {
3833 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3834 OUR_HANDLE(handle)));
3835 goto done;
3838 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3841 * We are now using the change value, and
3842 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3843 * I don't have a global notification system, I'm sending back all the
3844 * informations even when _NOTHING_ has changed.
3847 /* We need to keep track of the change value to send back in
3848 RRPCN replies otherwise our updates are ignored. */
3850 Printer->notify.fnpcn = True;
3852 if (Printer->notify.client_connected) {
3853 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3854 Printer->notify.change = q_u->change;
3857 /* just ignore the SPOOL_NOTIFY_OPTION */
3859 switch (Printer->printer_type) {
3860 case SPLHND_SERVER:
3861 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3862 break;
3864 case SPLHND_PRINTER:
3865 result = printer_notify_info(p, handle, info, p->mem_ctx);
3866 break;
3869 Printer->notify.fnpcn = False;
3871 done:
3872 return result;
3875 /********************************************************************
3876 * construct_printer_info_0
3877 * fill a printer_info_0 struct
3878 ********************************************************************/
3880 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3881 PRINTER_INFO_0 *printer,
3882 const struct share_params *params)
3884 pstring chaine;
3885 int count;
3886 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3887 counter_printer_0 *session_counter;
3888 uint32 global_counter;
3889 struct tm *t;
3890 time_t setuptime;
3891 print_status_struct status;
3893 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3894 lp_const_servicename(params->service))))
3895 return False;
3897 count = print_queue_length(params->service, &status);
3899 /* check if we already have a counter for this printer */
3900 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3901 if (session_counter->snum == params->service)
3902 break;
3905 /* it's the first time, add it to the list */
3906 if (session_counter==NULL) {
3907 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3908 free_a_printer(&ntprinter, 2);
3909 return False;
3911 ZERO_STRUCTP(session_counter);
3912 session_counter->snum=params->service;
3913 session_counter->counter=0;
3914 DLIST_ADD(counter_list, session_counter);
3917 /* increment it */
3918 session_counter->counter++;
3920 /* JFM:
3921 * the global_counter should be stored in a TDB as it's common to all the clients
3922 * and should be zeroed on samba startup
3924 global_counter=session_counter->counter;
3926 pstrcpy(chaine,ntprinter->info_2->printername);
3928 init_unistr(&printer->printername, chaine);
3930 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3931 init_unistr(&printer->servername, chaine);
3933 printer->cjobs = count;
3934 printer->total_jobs = 0;
3935 printer->total_bytes = 0;
3937 setuptime = (time_t)ntprinter->info_2->setuptime;
3938 t=gmtime(&setuptime);
3940 printer->year = t->tm_year+1900;
3941 printer->month = t->tm_mon+1;
3942 printer->dayofweek = t->tm_wday;
3943 printer->day = t->tm_mday;
3944 printer->hour = t->tm_hour;
3945 printer->minute = t->tm_min;
3946 printer->second = t->tm_sec;
3947 printer->milliseconds = 0;
3949 printer->global_counter = global_counter;
3950 printer->total_pages = 0;
3952 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3953 printer->major_version = 0x0005; /* NT 5 */
3954 printer->build_version = 0x0893; /* build 2195 */
3956 printer->unknown7 = 0x1;
3957 printer->unknown8 = 0x0;
3958 printer->unknown9 = 0x0;
3959 printer->session_counter = session_counter->counter;
3960 printer->unknown11 = 0x0;
3961 printer->printer_errors = 0x0; /* number of print failure */
3962 printer->unknown13 = 0x0;
3963 printer->unknown14 = 0x1;
3964 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3965 printer->unknown16 = 0x0;
3966 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3967 printer->unknown18 = 0x0;
3968 printer->status = nt_printq_status(status.status);
3969 printer->unknown20 = 0x0;
3970 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3971 printer->unknown22 = 0x0;
3972 printer->unknown23 = 0x6; /* 6 ???*/
3973 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3974 printer->unknown25 = 0;
3975 printer->unknown26 = 0;
3976 printer->unknown27 = 0;
3977 printer->unknown28 = 0;
3978 printer->unknown29 = 0;
3980 free_a_printer(&ntprinter,2);
3981 return (True);
3984 /********************************************************************
3985 * construct_printer_info_1
3986 * fill a printer_info_1 struct
3987 ********************************************************************/
3988 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
3989 PRINTER_INFO_1 *printer,
3990 const struct share_params *params)
3992 pstring chaine;
3993 pstring chaine2;
3994 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3996 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3997 lp_const_servicename(params->service))))
3998 return False;
4000 printer->flags=flags;
4002 if (*ntprinter->info_2->comment == '\0') {
4003 init_unistr(&printer->comment, lp_comment(params->service));
4004 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4005 ntprinter->info_2->drivername,
4006 lp_comment(params->service));
4008 else {
4009 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4010 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4011 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4014 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4016 init_unistr(&printer->description, chaine);
4017 init_unistr(&printer->name, chaine2);
4019 free_a_printer(&ntprinter,2);
4021 return True;
4024 /****************************************************************************
4025 Free a DEVMODE struct.
4026 ****************************************************************************/
4028 static void free_dev_mode(DEVICEMODE *dev)
4030 if (dev == NULL)
4031 return;
4033 SAFE_FREE(dev->dev_private);
4034 SAFE_FREE(dev);
4038 /****************************************************************************
4039 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4040 should be valid upon entry
4041 ****************************************************************************/
4043 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4045 if ( !devmode || !ntdevmode )
4046 return False;
4048 init_unistr(&devmode->devicename, ntdevmode->devicename);
4050 init_unistr(&devmode->formname, ntdevmode->formname);
4052 devmode->specversion = ntdevmode->specversion;
4053 devmode->driverversion = ntdevmode->driverversion;
4054 devmode->size = ntdevmode->size;
4055 devmode->driverextra = ntdevmode->driverextra;
4056 devmode->fields = ntdevmode->fields;
4058 devmode->orientation = ntdevmode->orientation;
4059 devmode->papersize = ntdevmode->papersize;
4060 devmode->paperlength = ntdevmode->paperlength;
4061 devmode->paperwidth = ntdevmode->paperwidth;
4062 devmode->scale = ntdevmode->scale;
4063 devmode->copies = ntdevmode->copies;
4064 devmode->defaultsource = ntdevmode->defaultsource;
4065 devmode->printquality = ntdevmode->printquality;
4066 devmode->color = ntdevmode->color;
4067 devmode->duplex = ntdevmode->duplex;
4068 devmode->yresolution = ntdevmode->yresolution;
4069 devmode->ttoption = ntdevmode->ttoption;
4070 devmode->collate = ntdevmode->collate;
4071 devmode->icmmethod = ntdevmode->icmmethod;
4072 devmode->icmintent = ntdevmode->icmintent;
4073 devmode->mediatype = ntdevmode->mediatype;
4074 devmode->dithertype = ntdevmode->dithertype;
4076 if (ntdevmode->nt_dev_private != NULL) {
4077 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4078 return False;
4081 return True;
4084 /****************************************************************************
4085 Create a DEVMODE struct. Returns malloced memory.
4086 ****************************************************************************/
4088 DEVICEMODE *construct_dev_mode(const char *servicename)
4090 NT_PRINTER_INFO_LEVEL *printer = NULL;
4091 DEVICEMODE *devmode = NULL;
4093 DEBUG(7,("construct_dev_mode\n"));
4095 DEBUGADD(8,("getting printer characteristics\n"));
4097 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4098 return NULL;
4100 if ( !printer->info_2->devmode ) {
4101 DEBUG(5, ("BONG! There was no device mode!\n"));
4102 goto done;
4105 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4106 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4107 goto done;
4110 ZERO_STRUCTP(devmode);
4112 DEBUGADD(8,("loading DEVICEMODE\n"));
4114 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4115 free_dev_mode( devmode );
4116 devmode = NULL;
4119 done:
4120 free_a_printer(&printer,2);
4122 return devmode;
4125 /********************************************************************
4126 * construct_printer_info_2
4127 * fill a printer_info_2 struct
4128 ********************************************************************/
4130 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4131 PRINTER_INFO_2 *printer,
4132 const struct share_params *params)
4134 int count;
4135 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4137 print_status_struct status;
4139 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4140 lp_const_servicename(params->service))))
4141 return False;
4143 count = print_queue_length(params->service, &status);
4145 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4146 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4147 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4148 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4149 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4151 if (*ntprinter->info_2->comment == '\0')
4152 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4153 else
4154 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4156 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4157 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4158 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4159 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4160 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4162 printer->attributes = ntprinter->info_2->attributes;
4164 printer->priority = ntprinter->info_2->priority; /* priority */
4165 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4166 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4167 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4168 printer->status = nt_printq_status(status.status); /* status */
4169 printer->cjobs = count; /* jobs */
4170 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4172 if ( !(printer->devmode = construct_dev_mode(
4173 lp_const_servicename(params->service))) )
4174 DEBUG(8, ("Returning NULL Devicemode!\n"));
4176 printer->secdesc = NULL;
4178 if ( ntprinter->info_2->secdesc_buf
4179 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4181 /* don't use talloc_steal() here unless you do a deep steal of all
4182 the SEC_DESC members */
4184 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4185 ntprinter->info_2->secdesc_buf->sd );
4188 free_a_printer(&ntprinter, 2);
4190 return True;
4193 /********************************************************************
4194 * construct_printer_info_3
4195 * fill a printer_info_3 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4199 PRINTER_INFO_3 **pp_printer,
4200 const struct share_params *params)
4202 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 PRINTER_INFO_3 *printer = NULL;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4206 lp_const_servicename(params->service))))
4207 return False;
4209 *pp_printer = NULL;
4210 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4211 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4212 free_a_printer(&ntprinter, 2);
4213 return False;
4216 ZERO_STRUCTP(printer);
4218 /* These are the components of the SD we are returning. */
4220 printer->flags = 0x4;
4222 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4223 /* don't use talloc_steal() here unless you do a deep steal of all
4224 the SEC_DESC members */
4226 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4227 ntprinter->info_2->secdesc_buf->sd );
4230 free_a_printer(&ntprinter, 2);
4232 *pp_printer = printer;
4233 return True;
4236 /********************************************************************
4237 * construct_printer_info_4
4238 * fill a printer_info_4 struct
4239 ********************************************************************/
4241 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4242 PRINTER_INFO_4 *printer,
4243 const struct share_params *params)
4245 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4247 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4248 lp_const_servicename(params->service))))
4249 return False;
4251 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4252 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4253 printer->attributes = ntprinter->info_2->attributes;
4255 free_a_printer(&ntprinter, 2);
4256 return True;
4259 /********************************************************************
4260 * construct_printer_info_5
4261 * fill a printer_info_5 struct
4262 ********************************************************************/
4264 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4265 PRINTER_INFO_5 *printer,
4266 const struct share_params *params)
4268 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4270 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4271 lp_const_servicename(params->service))))
4272 return False;
4274 init_unistr(&printer->printername, ntprinter->info_2->printername);
4275 init_unistr(&printer->portname, ntprinter->info_2->portname);
4276 printer->attributes = ntprinter->info_2->attributes;
4278 /* these two are not used by NT+ according to MSDN */
4280 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4281 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4283 free_a_printer(&ntprinter, 2);
4285 return True;
4288 /********************************************************************
4289 * construct_printer_info_6
4290 * fill a printer_info_6 struct
4291 ********************************************************************/
4293 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4294 PRINTER_INFO_6 *printer,
4295 const struct share_params *params)
4297 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4298 int count;
4299 print_status_struct status;
4301 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4302 lp_const_servicename(params->service))))
4303 return False;
4305 count = print_queue_length(params->service, &status);
4307 printer->status = nt_printq_status(status.status);
4309 free_a_printer(&ntprinter, 2);
4311 return True;
4314 /********************************************************************
4315 * construct_printer_info_7
4316 * fill a printer_info_7 struct
4317 ********************************************************************/
4319 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4320 PRINTER_INFO_7 *printer,
4321 const struct share_params *params)
4323 char *guid_str = NULL;
4324 struct GUID guid;
4326 if (is_printer_published(print_hnd, params->service, &guid)) {
4327 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4328 strupper_m(guid_str);
4329 init_unistr(&printer->guid, guid_str);
4330 printer->action = SPOOL_DS_PUBLISH;
4331 } else {
4332 init_unistr(&printer->guid, "");
4333 printer->action = SPOOL_DS_UNPUBLISH;
4336 return True;
4339 /********************************************************************
4340 Spoolss_enumprinters.
4341 ********************************************************************/
4343 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4345 int snum;
4346 int i;
4347 int n_services=lp_numservices();
4348 PRINTER_INFO_1 *printers=NULL;
4349 PRINTER_INFO_1 current_prt;
4350 WERROR result = WERR_OK;
4352 DEBUG(4,("enum_all_printers_info_1\n"));
4354 for (snum=0; snum<n_services; snum++) {
4355 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4356 struct share_params params;
4357 params.service = snum;
4359 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4361 if (construct_printer_info_1(NULL, flags, &current_prt, &params)) {
4362 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4363 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4364 *returned=0;
4365 return WERR_NOMEM;
4367 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4369 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4370 (*returned)++;
4375 /* check the required size. */
4376 for (i=0; i<*returned; i++)
4377 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4379 if (*needed > offered) {
4380 result = WERR_INSUFFICIENT_BUFFER;
4381 goto out;
4384 if (!rpcbuf_alloc_size(buffer, *needed)) {
4385 result = WERR_NOMEM;
4386 goto out;
4389 /* fill the buffer with the structures */
4390 for (i=0; i<*returned; i++)
4391 smb_io_printer_info_1("", buffer, &printers[i], 0);
4393 out:
4394 /* clear memory */
4396 SAFE_FREE(printers);
4398 if ( !W_ERROR_IS_OK(result) )
4399 *returned = 0;
4401 return result;
4404 /********************************************************************
4405 enum_all_printers_info_1_local.
4406 *********************************************************************/
4408 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4410 DEBUG(4,("enum_all_printers_info_1_local\n"));
4412 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4415 /********************************************************************
4416 enum_all_printers_info_1_name.
4417 *********************************************************************/
4419 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4421 char *s = name;
4423 DEBUG(4,("enum_all_printers_info_1_name\n"));
4425 if ((name[0] == '\\') && (name[1] == '\\'))
4426 s = name + 2;
4428 if (is_myname_or_ipaddr(s)) {
4429 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4431 else
4432 return WERR_INVALID_NAME;
4435 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4436 /********************************************************************
4437 enum_all_printers_info_1_remote.
4438 *********************************************************************/
4440 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4442 PRINTER_INFO_1 *printer;
4443 fstring printername;
4444 fstring desc;
4445 fstring comment;
4446 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4447 WERROR result = WERR_OK;
4449 /* JFM: currently it's more a place holder than anything else.
4450 * In the spooler world there is a notion of server registration.
4451 * the print servers are registered on the PDC (in the same domain)
4453 * We should have a TDB here. The registration is done thru an
4454 * undocumented RPC call.
4457 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4458 return WERR_NOMEM;
4460 *returned=1;
4462 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4463 slprintf(desc, sizeof(desc)-1,"%s", name);
4464 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4466 init_unistr(&printer->description, desc);
4467 init_unistr(&printer->name, printername);
4468 init_unistr(&printer->comment, comment);
4469 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4471 /* check the required size. */
4472 *needed += spoolss_size_printer_info_1(printer);
4474 if (*needed > offered) {
4475 result = WERR_INSUFFICIENT_BUFFER;
4476 goto out;
4479 if (!rpcbuf_alloc_size(buffer, *needed)) {
4480 result = WERR_NOMEM;
4481 goto out;
4484 /* fill the buffer with the structures */
4485 smb_io_printer_info_1("", buffer, printer, 0);
4487 out:
4488 /* clear memory */
4489 SAFE_FREE(printer);
4491 if ( !W_ERROR_IS_OK(result) )
4492 *returned = 0;
4494 return result;
4497 #endif
4499 /********************************************************************
4500 enum_all_printers_info_1_network.
4501 *********************************************************************/
4503 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4505 char *s = name;
4507 DEBUG(4,("enum_all_printers_info_1_network\n"));
4509 /* If we respond to a enum_printers level 1 on our name with flags
4510 set to PRINTER_ENUM_REMOTE with a list of printers then these
4511 printers incorrectly appear in the APW browse list.
4512 Specifically the printers for the server appear at the workgroup
4513 level where all the other servers in the domain are
4514 listed. Windows responds to this call with a
4515 WERR_CAN_NOT_COMPLETE so we should do the same. */
4517 if (name[0] == '\\' && name[1] == '\\')
4518 s = name + 2;
4520 if (is_myname_or_ipaddr(s))
4521 return WERR_CAN_NOT_COMPLETE;
4523 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4526 /********************************************************************
4527 * api_spoolss_enumprinters
4529 * called from api_spoolss_enumprinters (see this to understand)
4530 ********************************************************************/
4532 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4534 int snum;
4535 int i;
4536 int n_services=lp_numservices();
4537 PRINTER_INFO_2 *printers=NULL;
4538 PRINTER_INFO_2 current_prt;
4539 WERROR result = WERR_OK;
4541 *returned = 0;
4543 for (snum=0; snum<n_services; snum++) {
4544 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4545 struct share_params params;
4546 params.service = snum;
4547 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4549 if (construct_printer_info_2(NULL, &current_prt, &params)) {
4550 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4551 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4552 *returned = 0;
4553 return WERR_NOMEM;
4556 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4558 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4560 (*returned)++;
4565 /* check the required size. */
4566 for (i=0; i<*returned; i++)
4567 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4569 if (*needed > offered) {
4570 result = WERR_INSUFFICIENT_BUFFER;
4571 goto out;
4574 if (!rpcbuf_alloc_size(buffer, *needed)) {
4575 result = WERR_NOMEM;
4576 goto out;
4579 /* fill the buffer with the structures */
4580 for (i=0; i<*returned; i++)
4581 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4583 out:
4584 /* clear memory */
4586 for (i=0; i<*returned; i++)
4587 free_devmode(printers[i].devmode);
4589 SAFE_FREE(printers);
4591 if ( !W_ERROR_IS_OK(result) )
4592 *returned = 0;
4594 return result;
4597 /********************************************************************
4598 * handle enumeration of printers at level 1
4599 ********************************************************************/
4601 static WERROR enumprinters_level1( uint32 flags, fstring name,
4602 RPC_BUFFER *buffer, uint32 offered,
4603 uint32 *needed, uint32 *returned)
4605 /* Not all the flags are equals */
4607 if (flags & PRINTER_ENUM_LOCAL)
4608 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4610 if (flags & PRINTER_ENUM_NAME)
4611 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4613 #if 0 /* JERRY - disabled for now */
4614 if (flags & PRINTER_ENUM_REMOTE)
4615 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4616 #endif
4618 if (flags & PRINTER_ENUM_NETWORK)
4619 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4621 return WERR_OK; /* NT4sp5 does that */
4624 /********************************************************************
4625 * handle enumeration of printers at level 2
4626 ********************************************************************/
4628 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4629 RPC_BUFFER *buffer, uint32 offered,
4630 uint32 *needed, uint32 *returned)
4632 char *s = servername;
4634 if (flags & PRINTER_ENUM_LOCAL) {
4635 return enum_all_printers_info_2(buffer, offered, needed, returned);
4638 if (flags & PRINTER_ENUM_NAME) {
4639 if ((servername[0] == '\\') && (servername[1] == '\\'))
4640 s = servername + 2;
4641 if (is_myname_or_ipaddr(s))
4642 return enum_all_printers_info_2(buffer, offered, needed, returned);
4643 else
4644 return WERR_INVALID_NAME;
4647 if (flags & PRINTER_ENUM_REMOTE)
4648 return WERR_UNKNOWN_LEVEL;
4650 return WERR_OK;
4653 /********************************************************************
4654 * handle enumeration of printers at level 5
4655 ********************************************************************/
4657 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4658 RPC_BUFFER *buffer, uint32 offered,
4659 uint32 *needed, uint32 *returned)
4661 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4662 return WERR_OK;
4665 /********************************************************************
4666 * api_spoolss_enumprinters
4668 * called from api_spoolss_enumprinters (see this to understand)
4669 ********************************************************************/
4671 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4673 uint32 flags = q_u->flags;
4674 UNISTR2 *servername = &q_u->servername;
4675 uint32 level = q_u->level;
4676 RPC_BUFFER *buffer = NULL;
4677 uint32 offered = q_u->offered;
4678 uint32 *needed = &r_u->needed;
4679 uint32 *returned = &r_u->returned;
4681 fstring name;
4683 /* that's an [in out] buffer */
4685 if (!q_u->buffer && (offered!=0)) {
4686 return WERR_INVALID_PARAM;
4689 rpcbuf_move(q_u->buffer, &r_u->buffer);
4690 buffer = r_u->buffer;
4692 DEBUG(4,("_spoolss_enumprinters\n"));
4694 *needed=0;
4695 *returned=0;
4698 * Level 1:
4699 * flags==PRINTER_ENUM_NAME
4700 * if name=="" then enumerates all printers
4701 * if name!="" then enumerate the printer
4702 * flags==PRINTER_ENUM_REMOTE
4703 * name is NULL, enumerate printers
4704 * Level 2: name!="" enumerates printers, name can't be NULL
4705 * Level 3: doesn't exist
4706 * Level 4: does a local registry lookup
4707 * Level 5: same as Level 2
4710 unistr2_to_ascii(name, servername, sizeof(name)-1);
4711 strupper_m(name);
4713 switch (level) {
4714 case 1:
4715 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4716 case 2:
4717 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4718 case 5:
4719 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4720 case 3:
4721 case 4:
4722 break;
4724 return WERR_UNKNOWN_LEVEL;
4727 /****************************************************************************
4728 ****************************************************************************/
4730 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4731 const struct share_params *params,
4732 RPC_BUFFER *buffer, uint32 offered,
4733 uint32 *needed)
4735 PRINTER_INFO_0 *printer=NULL;
4736 WERROR result = WERR_OK;
4738 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4739 return WERR_NOMEM;
4741 construct_printer_info_0(print_hnd, printer, params);
4743 /* check the required size. */
4744 *needed += spoolss_size_printer_info_0(printer);
4746 if (*needed > offered) {
4747 result = WERR_INSUFFICIENT_BUFFER;
4748 goto out;
4751 if (!rpcbuf_alloc_size(buffer, *needed)) {
4752 result = WERR_NOMEM;
4753 goto out;
4756 /* fill the buffer with the structures */
4757 smb_io_printer_info_0("", buffer, printer, 0);
4759 out:
4760 /* clear memory */
4762 SAFE_FREE(printer);
4764 return result;
4767 /****************************************************************************
4768 ****************************************************************************/
4770 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4771 const struct share_params *params,
4772 RPC_BUFFER *buffer, uint32 offered,
4773 uint32 *needed)
4775 PRINTER_INFO_1 *printer=NULL;
4776 WERROR result = WERR_OK;
4778 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4779 return WERR_NOMEM;
4781 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4782 params);
4784 /* check the required size. */
4785 *needed += spoolss_size_printer_info_1(printer);
4787 if (*needed > offered) {
4788 result = WERR_INSUFFICIENT_BUFFER;
4789 goto out;
4792 if (!rpcbuf_alloc_size(buffer, *needed)) {
4793 result = WERR_NOMEM;
4794 goto out;
4797 /* fill the buffer with the structures */
4798 smb_io_printer_info_1("", buffer, printer, 0);
4800 out:
4801 /* clear memory */
4802 SAFE_FREE(printer);
4804 return result;
4807 /****************************************************************************
4808 ****************************************************************************/
4810 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4811 const struct share_params *params,
4812 RPC_BUFFER *buffer, uint32 offered,
4813 uint32 *needed)
4815 PRINTER_INFO_2 *printer=NULL;
4816 WERROR result = WERR_OK;
4818 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4819 return WERR_NOMEM;
4821 construct_printer_info_2(print_hnd, printer, params);
4823 /* check the required size. */
4824 *needed += spoolss_size_printer_info_2(printer);
4826 if (*needed > offered) {
4827 result = WERR_INSUFFICIENT_BUFFER;
4828 goto out;
4831 if (!rpcbuf_alloc_size(buffer, *needed)) {
4832 result = WERR_NOMEM;
4833 goto out;
4836 /* fill the buffer with the structures */
4837 if (!smb_io_printer_info_2("", buffer, printer, 0))
4838 result = WERR_NOMEM;
4840 out:
4841 /* clear memory */
4842 free_printer_info_2(printer);
4844 return result;
4847 /****************************************************************************
4848 ****************************************************************************/
4850 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4851 const struct share_params *params,
4852 RPC_BUFFER *buffer, uint32 offered,
4853 uint32 *needed)
4855 PRINTER_INFO_3 *printer=NULL;
4856 WERROR result = WERR_OK;
4858 if (!construct_printer_info_3(print_hnd, &printer, params))
4859 return WERR_NOMEM;
4861 /* check the required size. */
4862 *needed += spoolss_size_printer_info_3(printer);
4864 if (*needed > offered) {
4865 result = WERR_INSUFFICIENT_BUFFER;
4866 goto out;
4869 if (!rpcbuf_alloc_size(buffer, *needed)) {
4870 result = WERR_NOMEM;
4871 goto out;
4874 /* fill the buffer with the structures */
4875 smb_io_printer_info_3("", buffer, printer, 0);
4877 out:
4878 /* clear memory */
4879 free_printer_info_3(printer);
4881 return result;
4884 /****************************************************************************
4885 ****************************************************************************/
4887 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4888 const struct share_params *params,
4889 RPC_BUFFER *buffer, uint32 offered,
4890 uint32 *needed)
4892 PRINTER_INFO_4 *printer=NULL;
4893 WERROR result = WERR_OK;
4895 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4896 return WERR_NOMEM;
4898 if (!construct_printer_info_4(print_hnd, printer, params)) {
4899 SAFE_FREE(printer);
4900 return WERR_NOMEM;
4903 /* check the required size. */
4904 *needed += spoolss_size_printer_info_4(printer);
4906 if (*needed > offered) {
4907 result = WERR_INSUFFICIENT_BUFFER;
4908 goto out;
4911 if (!rpcbuf_alloc_size(buffer, *needed)) {
4912 result = WERR_NOMEM;
4913 goto out;
4916 /* fill the buffer with the structures */
4917 smb_io_printer_info_4("", buffer, printer, 0);
4919 out:
4920 /* clear memory */
4921 free_printer_info_4(printer);
4923 return result;
4926 /****************************************************************************
4927 ****************************************************************************/
4929 static WERROR getprinter_level_5(Printer_entry *print_hnd,
4930 const struct share_params *params,
4931 RPC_BUFFER *buffer, uint32 offered,
4932 uint32 *needed)
4934 PRINTER_INFO_5 *printer=NULL;
4935 WERROR result = WERR_OK;
4937 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4938 return WERR_NOMEM;
4940 if (!construct_printer_info_5(print_hnd, printer, params)) {
4941 free_printer_info_5(printer);
4942 return WERR_NOMEM;
4945 /* check the required size. */
4946 *needed += spoolss_size_printer_info_5(printer);
4948 if (*needed > offered) {
4949 result = WERR_INSUFFICIENT_BUFFER;
4950 goto out;
4953 if (!rpcbuf_alloc_size(buffer, *needed)) {
4954 result = WERR_NOMEM;
4955 goto out;
4958 /* fill the buffer with the structures */
4959 smb_io_printer_info_5("", buffer, printer, 0);
4961 out:
4962 /* clear memory */
4963 free_printer_info_5(printer);
4965 return result;
4968 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4969 const struct share_params *params,
4970 RPC_BUFFER *buffer, uint32 offered,
4971 uint32 *needed)
4973 PRINTER_INFO_6 *printer;
4974 WERROR result = WERR_OK;
4976 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4977 return WERR_NOMEM;
4980 if (!construct_printer_info_6(print_hnd, printer, params)) {
4981 free_printer_info_6(printer);
4982 return WERR_NOMEM;
4985 /* check the required size. */
4986 *needed += spoolss_size_printer_info_6(printer);
4988 if (*needed > offered) {
4989 result = WERR_INSUFFICIENT_BUFFER;
4990 goto out;
4993 if (!rpcbuf_alloc_size(buffer, *needed)) {
4994 result = WERR_NOMEM;
4995 goto out;
4998 /* fill the buffer with the structures */
4999 smb_io_printer_info_6("", buffer, printer, 0);
5001 out:
5002 /* clear memory */
5003 free_printer_info_6(printer);
5005 return result;
5008 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5009 const struct share_params *params,
5010 RPC_BUFFER *buffer, uint32 offered,
5011 uint32 *needed)
5013 PRINTER_INFO_7 *printer=NULL;
5014 WERROR result = WERR_OK;
5016 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5017 return WERR_NOMEM;
5019 if (!construct_printer_info_7(print_hnd, printer, params))
5020 return WERR_NOMEM;
5022 /* check the required size. */
5023 *needed += spoolss_size_printer_info_7(printer);
5025 if (*needed > offered) {
5026 result = WERR_INSUFFICIENT_BUFFER;
5027 goto out;
5030 if (!rpcbuf_alloc_size(buffer, *needed)) {
5031 result = WERR_NOMEM;
5032 goto out;
5036 /* fill the buffer with the structures */
5037 smb_io_printer_info_7("", buffer, printer, 0);
5039 out:
5040 /* clear memory */
5041 free_printer_info_7(printer);
5043 return result;
5046 /****************************************************************************
5047 ****************************************************************************/
5049 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5051 POLICY_HND *handle = &q_u->handle;
5052 uint32 level = q_u->level;
5053 RPC_BUFFER *buffer = NULL;
5054 uint32 offered = q_u->offered;
5055 uint32 *needed = &r_u->needed;
5056 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5057 struct share_params *params;
5059 int snum;
5061 /* that's an [in out] buffer */
5063 if (!q_u->buffer && (offered!=0)) {
5064 return WERR_INVALID_PARAM;
5067 rpcbuf_move(q_u->buffer, &r_u->buffer);
5068 buffer = r_u->buffer;
5070 *needed=0;
5072 if (!get_printer_snum(p, handle, &snum, &params))
5073 return WERR_BADFID;
5075 switch (level) {
5076 case 0:
5077 return getprinter_level_0(Printer, params, buffer, offered,
5078 needed);
5079 case 1:
5080 return getprinter_level_1(Printer, params, buffer, offered,
5081 needed);
5082 case 2:
5083 return getprinter_level_2(Printer, params, buffer, offered,
5084 needed);
5085 case 3:
5086 return getprinter_level_3(Printer, params, buffer, offered,
5087 needed);
5088 case 4:
5089 return getprinter_level_4(Printer, params, buffer, offered,
5090 needed);
5091 case 5:
5092 return getprinter_level_5(Printer, params, buffer, offered,
5093 needed);
5094 case 6:
5095 return getprinter_level_6(Printer, params, buffer, offered,
5096 needed);
5097 case 7:
5098 return getprinter_level_7(Printer, params, buffer, offered,
5099 needed);
5101 return WERR_UNKNOWN_LEVEL;
5104 /********************************************************************
5105 * fill a DRIVER_INFO_1 struct
5106 ********************************************************************/
5108 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5110 init_unistr( &info->name, driver.info_3->name);
5113 /********************************************************************
5114 * construct_printer_driver_info_1
5115 ********************************************************************/
5117 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5119 NT_PRINTER_INFO_LEVEL *printer = NULL;
5120 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5122 ZERO_STRUCT(driver);
5124 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5125 return WERR_INVALID_PRINTER_NAME;
5127 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5128 free_a_printer(&printer, 2);
5129 return WERR_UNKNOWN_PRINTER_DRIVER;
5132 fill_printer_driver_info_1(info, driver, servername, architecture);
5134 free_a_printer(&printer,2);
5136 return WERR_OK;
5139 /********************************************************************
5140 * construct_printer_driver_info_2
5141 * fill a printer_info_2 struct
5142 ********************************************************************/
5144 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5146 pstring temp;
5148 info->version=driver.info_3->cversion;
5150 init_unistr( &info->name, driver.info_3->name );
5151 init_unistr( &info->architecture, driver.info_3->environment );
5154 if (strlen(driver.info_3->driverpath)) {
5155 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5156 init_unistr( &info->driverpath, temp );
5157 } else
5158 init_unistr( &info->driverpath, "" );
5160 if (strlen(driver.info_3->datafile)) {
5161 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5162 init_unistr( &info->datafile, temp );
5163 } else
5164 init_unistr( &info->datafile, "" );
5166 if (strlen(driver.info_3->configfile)) {
5167 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5168 init_unistr( &info->configfile, temp );
5169 } else
5170 init_unistr( &info->configfile, "" );
5173 /********************************************************************
5174 * construct_printer_driver_info_2
5175 * fill a printer_info_2 struct
5176 ********************************************************************/
5178 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5180 NT_PRINTER_INFO_LEVEL *printer = NULL;
5181 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5183 ZERO_STRUCT(printer);
5184 ZERO_STRUCT(driver);
5186 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5187 return WERR_INVALID_PRINTER_NAME;
5189 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5190 free_a_printer(&printer, 2);
5191 return WERR_UNKNOWN_PRINTER_DRIVER;
5194 fill_printer_driver_info_2(info, driver, servername);
5196 free_a_printer(&printer,2);
5198 return WERR_OK;
5201 /********************************************************************
5202 * copy a strings array and convert to UNICODE
5204 * convert an array of ascii string to a UNICODE string
5205 ********************************************************************/
5207 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5209 int i=0;
5210 int j=0;
5211 const char *v;
5212 pstring line;
5214 DEBUG(6,("init_unistr_array\n"));
5215 *uni_array=NULL;
5217 while (True)
5219 if ( !char_array )
5220 v = "";
5221 else
5223 v = char_array[i];
5224 if (!v)
5225 v = ""; /* hack to handle null lists */
5228 /* hack to allow this to be used in places other than when generating
5229 the list of dependent files */
5231 if ( servername )
5232 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5233 else
5234 pstrcpy( line, v );
5236 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5238 /* add one extra unit16 for the second terminating NULL */
5240 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5241 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5242 return 0;
5245 if ( !strlen(v) )
5246 break;
5248 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5249 i++;
5252 if (*uni_array) {
5253 /* special case for ""; we need to add both NULL's here */
5254 if (!j)
5255 (*uni_array)[j++]=0x0000;
5256 (*uni_array)[j]=0x0000;
5259 DEBUGADD(6,("last one:done\n"));
5261 /* return size of array in uint16's */
5263 return j+1;
5266 /********************************************************************
5267 * construct_printer_info_3
5268 * fill a printer_info_3 struct
5269 ********************************************************************/
5271 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5273 pstring temp;
5275 ZERO_STRUCTP(info);
5277 info->version=driver.info_3->cversion;
5279 init_unistr( &info->name, driver.info_3->name );
5280 init_unistr( &info->architecture, driver.info_3->environment );
5282 if (strlen(driver.info_3->driverpath)) {
5283 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5284 init_unistr( &info->driverpath, temp );
5285 } else
5286 init_unistr( &info->driverpath, "" );
5288 if (strlen(driver.info_3->datafile)) {
5289 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5290 init_unistr( &info->datafile, temp );
5291 } else
5292 init_unistr( &info->datafile, "" );
5294 if (strlen(driver.info_3->configfile)) {
5295 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5296 init_unistr( &info->configfile, temp );
5297 } else
5298 init_unistr( &info->configfile, "" );
5300 if (strlen(driver.info_3->helpfile)) {
5301 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5302 init_unistr( &info->helpfile, temp );
5303 } else
5304 init_unistr( &info->helpfile, "" );
5306 init_unistr( &info->monitorname, driver.info_3->monitorname );
5307 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5309 info->dependentfiles=NULL;
5310 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5313 /********************************************************************
5314 * construct_printer_info_3
5315 * fill a printer_info_3 struct
5316 ********************************************************************/
5318 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5320 NT_PRINTER_INFO_LEVEL *printer = NULL;
5321 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5322 WERROR status;
5323 ZERO_STRUCT(driver);
5325 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5326 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5327 if (!W_ERROR_IS_OK(status))
5328 return WERR_INVALID_PRINTER_NAME;
5330 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5331 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5333 #if 0 /* JERRY */
5336 * I put this code in during testing. Helpful when commenting out the
5337 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5338 * as win2k always queries the driver using an infor level of 6.
5339 * I've left it in (but ifdef'd out) because I'll probably
5340 * use it in experimentation again in the future. --jerry 22/01/2002
5343 if (!W_ERROR_IS_OK(status)) {
5345 * Is this a W2k client ?
5347 if (version == 3) {
5348 /* Yes - try again with a WinNT driver. */
5349 version = 2;
5350 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5351 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5353 #endif
5355 if (!W_ERROR_IS_OK(status)) {
5356 free_a_printer(&printer,2);
5357 return WERR_UNKNOWN_PRINTER_DRIVER;
5360 #if 0 /* JERRY */
5362 #endif
5365 fill_printer_driver_info_3(info, driver, servername);
5367 free_a_printer(&printer,2);
5369 return WERR_OK;
5372 /********************************************************************
5373 * construct_printer_info_6
5374 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5375 ********************************************************************/
5377 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5379 pstring temp;
5380 fstring nullstr;
5382 ZERO_STRUCTP(info);
5383 memset(&nullstr, '\0', sizeof(fstring));
5385 info->version=driver.info_3->cversion;
5387 init_unistr( &info->name, driver.info_3->name );
5388 init_unistr( &info->architecture, driver.info_3->environment );
5390 if (strlen(driver.info_3->driverpath)) {
5391 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5392 init_unistr( &info->driverpath, temp );
5393 } else
5394 init_unistr( &info->driverpath, "" );
5396 if (strlen(driver.info_3->datafile)) {
5397 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5398 init_unistr( &info->datafile, temp );
5399 } else
5400 init_unistr( &info->datafile, "" );
5402 if (strlen(driver.info_3->configfile)) {
5403 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5404 init_unistr( &info->configfile, temp );
5405 } else
5406 init_unistr( &info->configfile, "" );
5408 if (strlen(driver.info_3->helpfile)) {
5409 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5410 init_unistr( &info->helpfile, temp );
5411 } else
5412 init_unistr( &info->helpfile, "" );
5414 init_unistr( &info->monitorname, driver.info_3->monitorname );
5415 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5417 info->dependentfiles = NULL;
5418 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5420 info->previousdrivernames=NULL;
5421 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5423 info->driver_date=0;
5425 info->padding=0;
5426 info->driver_version_low=0;
5427 info->driver_version_high=0;
5429 init_unistr( &info->mfgname, "");
5430 init_unistr( &info->oem_url, "");
5431 init_unistr( &info->hardware_id, "");
5432 init_unistr( &info->provider, "");
5435 /********************************************************************
5436 * construct_printer_info_6
5437 * fill a printer_info_6 struct
5438 ********************************************************************/
5440 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5441 fstring servername, fstring architecture, uint32 version)
5443 NT_PRINTER_INFO_LEVEL *printer = NULL;
5444 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5445 WERROR status;
5447 ZERO_STRUCT(driver);
5449 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5451 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5453 if (!W_ERROR_IS_OK(status))
5454 return WERR_INVALID_PRINTER_NAME;
5456 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5458 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5460 if (!W_ERROR_IS_OK(status))
5463 * Is this a W2k client ?
5466 if (version < 3) {
5467 free_a_printer(&printer,2);
5468 return WERR_UNKNOWN_PRINTER_DRIVER;
5471 /* Yes - try again with a WinNT driver. */
5472 version = 2;
5473 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5474 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5475 if (!W_ERROR_IS_OK(status)) {
5476 free_a_printer(&printer,2);
5477 return WERR_UNKNOWN_PRINTER_DRIVER;
5481 fill_printer_driver_info_6(info, driver, servername);
5483 free_a_printer(&printer,2);
5484 free_a_printer_driver(driver, 3);
5486 return WERR_OK;
5489 /****************************************************************************
5490 ****************************************************************************/
5492 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5494 SAFE_FREE(info->dependentfiles);
5497 /****************************************************************************
5498 ****************************************************************************/
5500 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5502 SAFE_FREE(info->dependentfiles);
5505 /****************************************************************************
5506 ****************************************************************************/
5508 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5510 DRIVER_INFO_1 *info=NULL;
5511 WERROR result;
5513 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5514 return WERR_NOMEM;
5516 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5517 if (!W_ERROR_IS_OK(result))
5518 goto out;
5520 /* check the required size. */
5521 *needed += spoolss_size_printer_driver_info_1(info);
5523 if (*needed > offered) {
5524 result = WERR_INSUFFICIENT_BUFFER;
5525 goto out;
5528 if (!rpcbuf_alloc_size(buffer, *needed)) {
5529 result = WERR_NOMEM;
5530 goto out;
5533 /* fill the buffer with the structures */
5534 smb_io_printer_driver_info_1("", buffer, info, 0);
5536 out:
5537 /* clear memory */
5538 SAFE_FREE(info);
5540 return result;
5543 /****************************************************************************
5544 ****************************************************************************/
5546 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5548 DRIVER_INFO_2 *info=NULL;
5549 WERROR result;
5551 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5552 return WERR_NOMEM;
5554 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5555 if (!W_ERROR_IS_OK(result))
5556 goto out;
5558 /* check the required size. */
5559 *needed += spoolss_size_printer_driver_info_2(info);
5561 if (*needed > offered) {
5562 result = WERR_INSUFFICIENT_BUFFER;
5563 goto out;
5566 if (!rpcbuf_alloc_size(buffer, *needed)) {
5567 result = WERR_NOMEM;
5568 goto out;
5571 /* fill the buffer with the structures */
5572 smb_io_printer_driver_info_2("", buffer, info, 0);
5574 out:
5575 /* clear memory */
5576 SAFE_FREE(info);
5578 return result;
5581 /****************************************************************************
5582 ****************************************************************************/
5584 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5586 DRIVER_INFO_3 info;
5587 WERROR result;
5589 ZERO_STRUCT(info);
5591 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5592 if (!W_ERROR_IS_OK(result))
5593 goto out;
5595 /* check the required size. */
5596 *needed += spoolss_size_printer_driver_info_3(&info);
5598 if (*needed > offered) {
5599 result = WERR_INSUFFICIENT_BUFFER;
5600 goto out;
5603 if (!rpcbuf_alloc_size(buffer, *needed)) {
5604 result = WERR_NOMEM;
5605 goto out;
5608 /* fill the buffer with the structures */
5609 smb_io_printer_driver_info_3("", buffer, &info, 0);
5611 out:
5612 free_printer_driver_info_3(&info);
5614 return result;
5617 /****************************************************************************
5618 ****************************************************************************/
5620 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5622 DRIVER_INFO_6 info;
5623 WERROR result;
5625 ZERO_STRUCT(info);
5627 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5628 if (!W_ERROR_IS_OK(result))
5629 goto out;
5631 /* check the required size. */
5632 *needed += spoolss_size_printer_driver_info_6(&info);
5634 if (*needed > offered) {
5635 result = WERR_INSUFFICIENT_BUFFER;
5636 goto out;
5639 if (!rpcbuf_alloc_size(buffer, *needed)) {
5640 result = WERR_NOMEM;
5641 goto out;
5644 /* fill the buffer with the structures */
5645 smb_io_printer_driver_info_6("", buffer, &info, 0);
5647 out:
5648 free_printer_driver_info_6(&info);
5650 return result;
5653 /****************************************************************************
5654 ****************************************************************************/
5656 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5658 POLICY_HND *handle = &q_u->handle;
5659 UNISTR2 *uni_arch = &q_u->architecture;
5660 uint32 level = q_u->level;
5661 uint32 clientmajorversion = q_u->clientmajorversion;
5662 RPC_BUFFER *buffer = NULL;
5663 uint32 offered = q_u->offered;
5664 uint32 *needed = &r_u->needed;
5665 uint32 *servermajorversion = &r_u->servermajorversion;
5666 uint32 *serverminorversion = &r_u->serverminorversion;
5667 Printer_entry *printer;
5669 fstring servername;
5670 fstring architecture;
5671 int snum;
5673 /* that's an [in out] buffer */
5675 if (!q_u->buffer && (offered!=0)) {
5676 return WERR_INVALID_PARAM;
5679 rpcbuf_move(q_u->buffer, &r_u->buffer);
5680 buffer = r_u->buffer;
5682 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5684 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5685 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5686 return WERR_INVALID_PRINTER_NAME;
5689 *needed = 0;
5690 *servermajorversion = 0;
5691 *serverminorversion = 0;
5693 fstrcpy(servername, get_server_name( printer ));
5694 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5696 if (!get_printer_snum(p, handle, &snum, NULL))
5697 return WERR_BADFID;
5699 switch (level) {
5700 case 1:
5701 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5702 case 2:
5703 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5704 case 3:
5705 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5706 case 6:
5707 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5708 #if 0 /* JERRY */
5709 case 101:
5710 /* apparently this call is the equivalent of
5711 EnumPrinterDataEx() for the DsDriver key */
5712 break;
5713 #endif
5716 return WERR_UNKNOWN_LEVEL;
5719 /****************************************************************************
5720 ****************************************************************************/
5722 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5724 POLICY_HND *handle = &q_u->handle;
5726 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5728 if (!Printer) {
5729 DEBUG(3,("Error in startpageprinter printer handle\n"));
5730 return WERR_BADFID;
5733 Printer->page_started=True;
5734 return WERR_OK;
5737 /****************************************************************************
5738 ****************************************************************************/
5740 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5742 POLICY_HND *handle = &q_u->handle;
5743 int snum;
5745 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5747 if (!Printer) {
5748 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5749 return WERR_BADFID;
5752 if (!get_printer_snum(p, handle, &snum, NULL))
5753 return WERR_BADFID;
5755 Printer->page_started=False;
5756 print_job_endpage(snum, Printer->jobid);
5758 return WERR_OK;
5761 /********************************************************************
5762 * api_spoolss_getprinter
5763 * called from the spoolss dispatcher
5765 ********************************************************************/
5767 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5769 POLICY_HND *handle = &q_u->handle;
5770 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5771 uint32 *jobid = &r_u->jobid;
5773 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5774 int snum;
5775 pstring jobname;
5776 fstring datatype;
5777 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5779 if (!Printer) {
5780 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5781 return WERR_BADFID;
5785 * a nice thing with NT is it doesn't listen to what you tell it.
5786 * when asked to send _only_ RAW datas, it tries to send datas
5787 * in EMF format.
5789 * So I add checks like in NT Server ...
5792 if (info_1->p_datatype != 0) {
5793 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5794 if (strcmp(datatype, "RAW") != 0) {
5795 (*jobid)=0;
5796 return WERR_INVALID_DATATYPE;
5800 /* get the share number of the printer */
5801 if (!get_printer_snum(p, handle, &snum, NULL)) {
5802 return WERR_BADFID;
5805 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5807 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5809 /* An error occured in print_job_start() so return an appropriate
5810 NT error code. */
5812 if (Printer->jobid == -1) {
5813 return map_werror_from_unix(errno);
5816 Printer->document_started=True;
5817 (*jobid) = Printer->jobid;
5819 return WERR_OK;
5822 /********************************************************************
5823 * api_spoolss_getprinter
5824 * called from the spoolss dispatcher
5826 ********************************************************************/
5828 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5830 POLICY_HND *handle = &q_u->handle;
5832 return _spoolss_enddocprinter_internal(p, handle);
5835 /****************************************************************************
5836 ****************************************************************************/
5838 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5840 POLICY_HND *handle = &q_u->handle;
5841 uint32 buffer_size = q_u->buffer_size;
5842 uint8 *buffer = q_u->buffer;
5843 uint32 *buffer_written = &q_u->buffer_size2;
5844 int snum;
5845 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5847 if (!Printer) {
5848 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5849 r_u->buffer_written = q_u->buffer_size2;
5850 return WERR_BADFID;
5853 if (!get_printer_snum(p, handle, &snum, NULL))
5854 return WERR_BADFID;
5856 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5857 (SMB_OFF_T)-1, (size_t)buffer_size);
5858 if (*buffer_written == (uint32)-1) {
5859 r_u->buffer_written = 0;
5860 if (errno == ENOSPC)
5861 return WERR_NO_SPOOL_SPACE;
5862 else
5863 return WERR_ACCESS_DENIED;
5866 r_u->buffer_written = q_u->buffer_size2;
5868 return WERR_OK;
5871 /********************************************************************
5872 * api_spoolss_getprinter
5873 * called from the spoolss dispatcher
5875 ********************************************************************/
5877 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5878 pipes_struct *p)
5880 int snum;
5881 WERROR errcode = WERR_BADFUNC;
5882 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5884 if (!Printer) {
5885 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5886 return WERR_BADFID;
5889 if (!get_printer_snum(p, handle, &snum, NULL))
5890 return WERR_BADFID;
5892 switch (command) {
5893 case PRINTER_CONTROL_PAUSE:
5894 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5895 errcode = WERR_OK;
5897 break;
5898 case PRINTER_CONTROL_RESUME:
5899 case PRINTER_CONTROL_UNPAUSE:
5900 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5901 errcode = WERR_OK;
5903 break;
5904 case PRINTER_CONTROL_PURGE:
5905 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5906 errcode = WERR_OK;
5908 break;
5909 default:
5910 return WERR_UNKNOWN_LEVEL;
5913 return errcode;
5916 /********************************************************************
5917 * api_spoolss_abortprinter
5918 * From MSDN: "Deletes printer's spool file if printer is configured
5919 * for spooling"
5920 ********************************************************************/
5922 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5924 POLICY_HND *handle = &q_u->handle;
5925 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5926 int snum;
5927 WERROR errcode = WERR_OK;
5929 if (!Printer) {
5930 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5931 return WERR_BADFID;
5934 if (!get_printer_snum(p, handle, &snum, NULL))
5935 return WERR_BADFID;
5937 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5939 return errcode;
5942 /********************************************************************
5943 * called by spoolss_api_setprinter
5944 * when updating a printer description
5945 ********************************************************************/
5947 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5948 const SPOOL_PRINTER_INFO_LEVEL *info,
5949 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5951 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5952 WERROR result;
5953 int snum;
5955 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5957 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5958 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5959 OUR_HANDLE(handle)));
5961 result = WERR_BADFID;
5962 goto done;
5965 /* Check the user has permissions to change the security
5966 descriptor. By experimentation with two NT machines, the user
5967 requires Full Access to the printer to change security
5968 information. */
5970 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5971 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5972 result = WERR_ACCESS_DENIED;
5973 goto done;
5976 /* NT seems to like setting the security descriptor even though
5977 nothing may have actually changed. */
5979 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5981 if (DEBUGLEVEL >= 10) {
5982 SEC_ACL *the_acl;
5983 int i;
5985 the_acl = old_secdesc_ctr->sd->dacl;
5986 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5987 PRINTERNAME(snum), the_acl->num_aces));
5989 for (i = 0; i < the_acl->num_aces; i++) {
5990 fstring sid_str;
5992 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5994 DEBUG(10, ("%s 0x%08x\n", sid_str,
5995 the_acl->aces[i].access_mask));
5998 the_acl = secdesc_ctr->sd->dacl;
6000 if (the_acl) {
6001 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6002 PRINTERNAME(snum), the_acl->num_aces));
6004 for (i = 0; i < the_acl->num_aces; i++) {
6005 fstring sid_str;
6007 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6009 DEBUG(10, ("%s 0x%08x\n", sid_str,
6010 the_acl->aces[i].access_mask));
6012 } else {
6013 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6017 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6018 if (!new_secdesc_ctr) {
6019 result = WERR_NOMEM;
6020 goto done;
6023 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6024 result = WERR_OK;
6025 goto done;
6028 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6030 done:
6032 return result;
6035 /********************************************************************
6036 Canonicalize printer info from a client
6038 ATTN: It does not matter what we set the servername to hear
6039 since we do the necessary work in get_a_printer() to set it to
6040 the correct value based on what the client sent in the
6041 _spoolss_open_printer_ex().
6042 ********************************************************************/
6044 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6046 fstring printername;
6047 const char *p;
6049 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6050 "portname=%s drivername=%s comment=%s location=%s\n",
6051 info->servername, info->printername, info->sharename,
6052 info->portname, info->drivername, info->comment, info->location));
6054 /* we force some elements to "correct" values */
6055 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6056 fstrcpy(info->sharename, lp_servicename(snum));
6058 /* check to see if we allow printername != sharename */
6060 if ( lp_force_printername(snum) ) {
6061 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6062 global_myname(), info->sharename );
6063 } else {
6065 /* make sure printername is in \\server\printername format */
6067 fstrcpy( printername, info->printername );
6068 p = printername;
6069 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6070 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6071 p++;
6074 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6075 global_myname(), p );
6078 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6079 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6083 return True;
6086 /****************************************************************************
6087 ****************************************************************************/
6089 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6091 char *cmd = lp_addport_cmd();
6092 pstring command;
6093 int ret;
6094 int fd;
6095 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6096 BOOL is_print_op = False;
6098 if ( !*cmd ) {
6099 return WERR_ACCESS_DENIED;
6102 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6104 if ( token )
6105 is_print_op = user_has_privileges( token, &se_printop );
6107 DEBUG(10,("Running [%s]\n", command));
6109 /********* BEGIN SePrintOperatorPrivilege **********/
6111 if ( is_print_op )
6112 become_root();
6114 ret = smbrun(command, &fd);
6116 if ( is_print_op )
6117 unbecome_root();
6119 /********* END SePrintOperatorPrivilege **********/
6121 DEBUGADD(10,("returned [%d]\n", ret));
6123 if ( ret != 0 ) {
6124 if (fd != -1)
6125 close(fd);
6126 return WERR_ACCESS_DENIED;
6129 return WERR_OK;
6132 /****************************************************************************
6133 ****************************************************************************/
6135 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6137 char *cmd = lp_addprinter_cmd();
6138 char **qlines;
6139 pstring command;
6140 int numlines;
6141 int ret;
6142 int fd;
6143 fstring remote_machine = "%m";
6144 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6145 BOOL is_print_op = False;
6147 standard_sub_basic(current_user_info.smb_name,
6148 current_user_info.domain,
6149 remote_machine,sizeof(remote_machine));
6151 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6152 cmd, printer->info_2->printername, printer->info_2->sharename,
6153 printer->info_2->portname, printer->info_2->drivername,
6154 printer->info_2->location, printer->info_2->comment, remote_machine);
6156 if ( token )
6157 is_print_op = user_has_privileges( token, &se_printop );
6159 DEBUG(10,("Running [%s]\n", command));
6161 /********* BEGIN SePrintOperatorPrivilege **********/
6163 if ( is_print_op )
6164 become_root();
6166 if ( (ret = smbrun(command, &fd)) == 0 ) {
6167 /* Tell everyone we updated smb.conf. */
6168 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6171 if ( is_print_op )
6172 unbecome_root();
6174 /********* END SePrintOperatorPrivilege **********/
6176 DEBUGADD(10,("returned [%d]\n", ret));
6178 if ( ret != 0 ) {
6179 if (fd != -1)
6180 close(fd);
6181 return False;
6184 /* reload our services immediately */
6185 reload_services( False );
6187 numlines = 0;
6188 /* Get lines and convert them back to dos-codepage */
6189 qlines = fd_lines_load(fd, &numlines, 0);
6190 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6191 close(fd);
6193 /* Set the portname to what the script says the portname should be. */
6194 /* but don't require anything to be return from the script exit a good error code */
6196 if (numlines) {
6197 /* Set the portname to what the script says the portname should be. */
6198 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6199 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6202 file_lines_free(qlines);
6203 return True;
6207 /********************************************************************
6208 * Called by spoolss_api_setprinter
6209 * when updating a printer description.
6210 ********************************************************************/
6212 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6213 const SPOOL_PRINTER_INFO_LEVEL *info,
6214 DEVICEMODE *devmode)
6216 int snum;
6217 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6218 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6219 WERROR result;
6220 UNISTR2 buffer;
6221 fstring asc_buffer;
6223 DEBUG(8,("update_printer\n"));
6225 result = WERR_OK;
6227 if (!Printer) {
6228 result = WERR_BADFID;
6229 goto done;
6232 if (!get_printer_snum(p, handle, &snum, NULL)) {
6233 result = WERR_BADFID;
6234 goto done;
6237 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6238 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6239 result = WERR_BADFID;
6240 goto done;
6243 DEBUGADD(8,("Converting info_2 struct\n"));
6246 * convert_printer_info converts the incoming
6247 * info from the client and overwrites the info
6248 * just read from the tdb in the pointer 'printer'.
6251 if (!convert_printer_info(info, printer, level)) {
6252 result = WERR_NOMEM;
6253 goto done;
6256 if (devmode) {
6257 /* we have a valid devmode
6258 convert it and link it*/
6260 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6261 if (!convert_devicemode(printer->info_2->printername, devmode,
6262 &printer->info_2->devmode)) {
6263 result = WERR_NOMEM;
6264 goto done;
6268 /* Do sanity check on the requested changes for Samba */
6270 if (!check_printer_ok(printer->info_2, snum)) {
6271 result = WERR_INVALID_PARAM;
6272 goto done;
6275 /* FIXME!!! If the driver has changed we really should verify that
6276 it is installed before doing much else --jerry */
6278 /* Check calling user has permission to update printer description */
6280 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6281 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6282 result = WERR_ACCESS_DENIED;
6283 goto done;
6286 /* Call addprinter hook */
6287 /* Check changes to see if this is really needed */
6289 if ( *lp_addprinter_cmd()
6290 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6291 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6292 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6293 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6295 /* add_printer_hook() will call reload_services() */
6297 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6298 result = WERR_ACCESS_DENIED;
6299 goto done;
6304 * When a *new* driver is bound to a printer, the drivername is used to
6305 * lookup previously saved driver initialization info, which is then
6306 * bound to the printer, simulating what happens in the Windows arch.
6308 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6310 if (!set_driver_init(printer, 2))
6312 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6313 printer->info_2->drivername));
6316 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6317 printer->info_2->drivername));
6319 notify_printer_driver(snum, printer->info_2->drivername);
6323 * flag which changes actually occured. This is a small subset of
6324 * all the possible changes. We also have to update things in the
6325 * DsSpooler key.
6328 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6329 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6330 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6331 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6333 notify_printer_comment(snum, printer->info_2->comment);
6336 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6337 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6338 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6339 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6341 notify_printer_sharename(snum, printer->info_2->sharename);
6344 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6345 char *pname;
6347 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6348 pname++;
6349 else
6350 pname = printer->info_2->printername;
6353 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6354 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6355 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6357 notify_printer_printername( snum, pname );
6360 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6361 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6362 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6363 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6365 notify_printer_port(snum, printer->info_2->portname);
6368 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6369 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6370 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6371 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6373 notify_printer_location(snum, printer->info_2->location);
6376 /* here we need to update some more DsSpooler keys */
6377 /* uNCName, serverName, shortServerName */
6379 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6380 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6381 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6382 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6383 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6385 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6386 global_myname(), printer->info_2->sharename );
6387 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6388 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6389 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6391 /* Update printer info */
6392 result = mod_a_printer(printer, 2);
6394 done:
6395 free_a_printer(&printer, 2);
6396 free_a_printer(&old_printer, 2);
6399 return result;
6402 /****************************************************************************
6403 ****************************************************************************/
6404 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6405 const SPOOL_PRINTER_INFO_LEVEL *info)
6407 #ifdef HAVE_ADS
6408 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6409 int snum;
6410 Printer_entry *Printer;
6412 if ( lp_security() != SEC_ADS ) {
6413 return WERR_UNKNOWN_LEVEL;
6416 Printer = find_printer_index_by_hnd(p, handle);
6418 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6420 if (!Printer)
6421 return WERR_BADFID;
6423 if (!get_printer_snum(p, handle, &snum, NULL))
6424 return WERR_BADFID;
6426 nt_printer_publish(Printer, snum, info7->action);
6428 return WERR_OK;
6429 #else
6430 return WERR_UNKNOWN_LEVEL;
6431 #endif
6433 /****************************************************************************
6434 ****************************************************************************/
6436 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6438 POLICY_HND *handle = &q_u->handle;
6439 uint32 level = q_u->level;
6440 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6441 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6442 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6443 uint32 command = q_u->command;
6444 WERROR result;
6446 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6448 if (!Printer) {
6449 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6450 return WERR_BADFID;
6453 /* check the level */
6454 switch (level) {
6455 case 0:
6456 return control_printer(handle, command, p);
6457 case 2:
6458 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6459 if (!W_ERROR_IS_OK(result))
6460 return result;
6461 if (secdesc_ctr)
6462 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6463 return result;
6464 case 3:
6465 return update_printer_sec(handle, level, info, p,
6466 secdesc_ctr);
6467 case 7:
6468 return publish_or_unpublish_printer(p, handle, info);
6469 default:
6470 return WERR_UNKNOWN_LEVEL;
6474 /****************************************************************************
6475 ****************************************************************************/
6477 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6479 POLICY_HND *handle = &q_u->handle;
6480 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6482 if (!Printer) {
6483 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6484 return WERR_BADFID;
6487 if (Printer->notify.client_connected==True) {
6488 int snum = -1;
6490 if ( Printer->printer_type == SPLHND_SERVER)
6491 snum = -1;
6492 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6493 !get_printer_snum(p, handle, &snum, NULL) )
6494 return WERR_BADFID;
6496 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6499 Printer->notify.flags=0;
6500 Printer->notify.options=0;
6501 Printer->notify.localmachine[0]='\0';
6502 Printer->notify.printerlocal=0;
6503 if (Printer->notify.option)
6504 free_spool_notify_option(&Printer->notify.option);
6505 Printer->notify.client_connected=False;
6507 return WERR_OK;
6510 /****************************************************************************
6511 ****************************************************************************/
6513 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6515 /* that's an [in out] buffer */
6517 if (!q_u->buffer && (q_u->offered!=0)) {
6518 return WERR_INVALID_PARAM;
6521 rpcbuf_move(q_u->buffer, &r_u->buffer);
6523 r_u->needed = 0;
6524 return WERR_INVALID_PARAM; /* this is what a NT server
6525 returns for AddJob. AddJob
6526 must fail on non-local
6527 printers */
6530 /****************************************************************************
6531 ****************************************************************************/
6533 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6534 int position, int snum,
6535 const NT_PRINTER_INFO_LEVEL *ntprinter)
6537 struct tm *t;
6539 t=gmtime(&queue->time);
6541 job_info->jobid=queue->job;
6542 init_unistr(&job_info->printername, lp_servicename(snum));
6543 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6544 init_unistr(&job_info->username, queue->fs_user);
6545 init_unistr(&job_info->document, queue->fs_file);
6546 init_unistr(&job_info->datatype, "RAW");
6547 init_unistr(&job_info->text_status, "");
6548 job_info->status=nt_printj_status(queue->status);
6549 job_info->priority=queue->priority;
6550 job_info->position=position;
6551 job_info->totalpages=queue->page_count;
6552 job_info->pagesprinted=0;
6554 make_systemtime(&job_info->submitted, t);
6557 /****************************************************************************
6558 ****************************************************************************/
6560 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6561 int position, int snum,
6562 const NT_PRINTER_INFO_LEVEL *ntprinter,
6563 DEVICEMODE *devmode)
6565 struct tm *t;
6567 t=gmtime(&queue->time);
6569 job_info->jobid=queue->job;
6571 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6573 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6574 init_unistr(&job_info->username, queue->fs_user);
6575 init_unistr(&job_info->document, queue->fs_file);
6576 init_unistr(&job_info->notifyname, queue->fs_user);
6577 init_unistr(&job_info->datatype, "RAW");
6578 init_unistr(&job_info->printprocessor, "winprint");
6579 init_unistr(&job_info->parameters, "");
6580 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6581 init_unistr(&job_info->text_status, "");
6583 /* and here the security descriptor */
6585 job_info->status=nt_printj_status(queue->status);
6586 job_info->priority=queue->priority;
6587 job_info->position=position;
6588 job_info->starttime=0;
6589 job_info->untiltime=0;
6590 job_info->totalpages=queue->page_count;
6591 job_info->size=queue->size;
6592 make_systemtime(&(job_info->submitted), t);
6593 job_info->timeelapsed=0;
6594 job_info->pagesprinted=0;
6596 job_info->devmode = devmode;
6598 return (True);
6601 /****************************************************************************
6602 Enumjobs at level 1.
6603 ****************************************************************************/
6605 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6606 const NT_PRINTER_INFO_LEVEL *ntprinter,
6607 RPC_BUFFER *buffer, uint32 offered,
6608 uint32 *needed, uint32 *returned)
6610 JOB_INFO_1 *info;
6611 int i;
6612 WERROR result = WERR_OK;
6614 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6615 if (info==NULL) {
6616 *returned=0;
6617 return WERR_NOMEM;
6620 for (i=0; i<*returned; i++)
6621 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6623 /* check the required size. */
6624 for (i=0; i<*returned; i++)
6625 (*needed) += spoolss_size_job_info_1(&info[i]);
6627 if (*needed > offered) {
6628 result = WERR_INSUFFICIENT_BUFFER;
6629 goto out;
6632 if (!rpcbuf_alloc_size(buffer, *needed)) {
6633 result = WERR_NOMEM;
6634 goto out;
6637 /* fill the buffer with the structures */
6638 for (i=0; i<*returned; i++)
6639 smb_io_job_info_1("", buffer, &info[i], 0);
6641 out:
6642 /* clear memory */
6643 SAFE_FREE(info);
6645 if ( !W_ERROR_IS_OK(result) )
6646 *returned = 0;
6648 return result;
6651 /****************************************************************************
6652 Enumjobs at level 2.
6653 ****************************************************************************/
6655 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6656 const NT_PRINTER_INFO_LEVEL *ntprinter,
6657 RPC_BUFFER *buffer, uint32 offered,
6658 uint32 *needed, uint32 *returned)
6660 JOB_INFO_2 *info = NULL;
6661 int i;
6662 WERROR result = WERR_OK;
6663 DEVICEMODE *devmode = NULL;
6665 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6666 *returned=0;
6667 return WERR_NOMEM;
6670 /* this should not be a failure condition if the devmode is NULL */
6672 devmode = construct_dev_mode(lp_const_servicename(snum));
6674 for (i=0; i<*returned; i++)
6675 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6677 /* check the required size. */
6678 for (i=0; i<*returned; i++)
6679 (*needed) += spoolss_size_job_info_2(&info[i]);
6681 if (*needed > offered) {
6682 result = WERR_INSUFFICIENT_BUFFER;
6683 goto out;
6686 if (!rpcbuf_alloc_size(buffer, *needed)) {
6687 result = WERR_NOMEM;
6688 goto out;
6691 /* fill the buffer with the structures */
6692 for (i=0; i<*returned; i++)
6693 smb_io_job_info_2("", buffer, &info[i], 0);
6695 out:
6696 free_devmode(devmode);
6697 SAFE_FREE(info);
6699 if ( !W_ERROR_IS_OK(result) )
6700 *returned = 0;
6702 return result;
6706 /****************************************************************************
6707 Enumjobs.
6708 ****************************************************************************/
6710 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6712 POLICY_HND *handle = &q_u->handle;
6713 uint32 level = q_u->level;
6714 RPC_BUFFER *buffer = NULL;
6715 uint32 offered = q_u->offered;
6716 uint32 *needed = &r_u->needed;
6717 uint32 *returned = &r_u->returned;
6718 WERROR wret;
6719 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6720 int snum;
6721 print_status_struct prt_status;
6722 print_queue_struct *queue=NULL;
6724 /* that's an [in out] buffer */
6726 if (!q_u->buffer && (offered!=0)) {
6727 return WERR_INVALID_PARAM;
6730 rpcbuf_move(q_u->buffer, &r_u->buffer);
6731 buffer = r_u->buffer;
6733 DEBUG(4,("_spoolss_enumjobs\n"));
6735 *needed=0;
6736 *returned=0;
6738 /* lookup the printer snum and tdb entry */
6740 if (!get_printer_snum(p, handle, &snum, NULL))
6741 return WERR_BADFID;
6743 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6744 if ( !W_ERROR_IS_OK(wret) )
6745 return wret;
6747 *returned = print_queue_status(snum, &queue, &prt_status);
6748 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6750 if (*returned == 0) {
6751 SAFE_FREE(queue);
6752 free_a_printer(&ntprinter, 2);
6753 return WERR_OK;
6756 switch (level) {
6757 case 1:
6758 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6759 break;
6760 case 2:
6761 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6762 break;
6763 default:
6764 *returned=0;
6765 wret = WERR_UNKNOWN_LEVEL;
6766 break;
6769 SAFE_FREE(queue);
6770 free_a_printer( &ntprinter, 2 );
6771 return wret;
6774 /****************************************************************************
6775 ****************************************************************************/
6777 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6779 return WERR_OK;
6782 /****************************************************************************
6783 ****************************************************************************/
6785 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6787 POLICY_HND *handle = &q_u->handle;
6788 uint32 jobid = q_u->jobid;
6789 uint32 command = q_u->command;
6791 int snum;
6792 WERROR errcode = WERR_BADFUNC;
6794 if (!get_printer_snum(p, handle, &snum, NULL)) {
6795 return WERR_BADFID;
6798 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6799 return WERR_INVALID_PRINTER_NAME;
6802 switch (command) {
6803 case JOB_CONTROL_CANCEL:
6804 case JOB_CONTROL_DELETE:
6805 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6806 errcode = WERR_OK;
6808 break;
6809 case JOB_CONTROL_PAUSE:
6810 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6811 errcode = WERR_OK;
6813 break;
6814 case JOB_CONTROL_RESTART:
6815 case JOB_CONTROL_RESUME:
6816 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6817 errcode = WERR_OK;
6819 break;
6820 default:
6821 return WERR_UNKNOWN_LEVEL;
6824 return errcode;
6827 /****************************************************************************
6828 Enumerates all printer drivers at level 1.
6829 ****************************************************************************/
6831 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6833 int i;
6834 int ndrivers;
6835 uint32 version;
6836 fstring *list = NULL;
6837 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6838 DRIVER_INFO_1 *driver_info_1=NULL;
6839 WERROR result = WERR_OK;
6841 *returned=0;
6843 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6844 list=NULL;
6845 ndrivers=get_ntdrivers(&list, architecture, version);
6846 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6848 if(ndrivers == -1) {
6849 SAFE_FREE(driver_info_1);
6850 return WERR_NOMEM;
6853 if(ndrivers != 0) {
6854 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6855 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6856 SAFE_FREE(list);
6857 return WERR_NOMEM;
6861 for (i=0; i<ndrivers; i++) {
6862 WERROR status;
6863 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6864 ZERO_STRUCT(driver);
6865 status = get_a_printer_driver(&driver, 3, list[i],
6866 architecture, version);
6867 if (!W_ERROR_IS_OK(status)) {
6868 SAFE_FREE(list);
6869 SAFE_FREE(driver_info_1);
6870 return status;
6872 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6873 free_a_printer_driver(driver, 3);
6876 *returned+=ndrivers;
6877 SAFE_FREE(list);
6880 /* check the required size. */
6881 for (i=0; i<*returned; i++) {
6882 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6883 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6886 if (*needed > offered) {
6887 result = WERR_INSUFFICIENT_BUFFER;
6888 goto out;
6891 if (!rpcbuf_alloc_size(buffer, *needed)) {
6892 result = WERR_NOMEM;
6893 goto out;
6896 /* fill the buffer with the driver structures */
6897 for (i=0; i<*returned; i++) {
6898 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6899 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6902 out:
6903 SAFE_FREE(driver_info_1);
6905 if ( !W_ERROR_IS_OK(result) )
6906 *returned = 0;
6908 return result;
6911 /****************************************************************************
6912 Enumerates all printer drivers at level 2.
6913 ****************************************************************************/
6915 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6917 int i;
6918 int ndrivers;
6919 uint32 version;
6920 fstring *list = NULL;
6921 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6922 DRIVER_INFO_2 *driver_info_2=NULL;
6923 WERROR result = WERR_OK;
6925 *returned=0;
6927 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6928 list=NULL;
6929 ndrivers=get_ntdrivers(&list, architecture, version);
6930 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6932 if(ndrivers == -1) {
6933 SAFE_FREE(driver_info_2);
6934 return WERR_NOMEM;
6937 if(ndrivers != 0) {
6938 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6939 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6940 SAFE_FREE(list);
6941 return WERR_NOMEM;
6945 for (i=0; i<ndrivers; i++) {
6946 WERROR status;
6948 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6949 ZERO_STRUCT(driver);
6950 status = get_a_printer_driver(&driver, 3, list[i],
6951 architecture, version);
6952 if (!W_ERROR_IS_OK(status)) {
6953 SAFE_FREE(list);
6954 SAFE_FREE(driver_info_2);
6955 return status;
6957 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6958 free_a_printer_driver(driver, 3);
6961 *returned+=ndrivers;
6962 SAFE_FREE(list);
6965 /* check the required size. */
6966 for (i=0; i<*returned; i++) {
6967 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6968 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6971 if (*needed > offered) {
6972 result = WERR_INSUFFICIENT_BUFFER;
6973 goto out;
6976 if (!rpcbuf_alloc_size(buffer, *needed)) {
6977 result = WERR_NOMEM;
6978 goto out;
6981 /* fill the buffer with the form structures */
6982 for (i=0; i<*returned; i++) {
6983 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6984 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6987 out:
6988 SAFE_FREE(driver_info_2);
6990 if ( !W_ERROR_IS_OK(result) )
6991 *returned = 0;
6993 return result;
6996 /****************************************************************************
6997 Enumerates all printer drivers at level 3.
6998 ****************************************************************************/
7000 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7002 int i;
7003 int ndrivers;
7004 uint32 version;
7005 fstring *list = NULL;
7006 DRIVER_INFO_3 *driver_info_3=NULL;
7007 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7008 WERROR result = WERR_OK;
7010 *returned=0;
7012 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7013 list=NULL;
7014 ndrivers=get_ntdrivers(&list, architecture, version);
7015 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7017 if(ndrivers == -1) {
7018 SAFE_FREE(driver_info_3);
7019 return WERR_NOMEM;
7022 if(ndrivers != 0) {
7023 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7024 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7025 SAFE_FREE(list);
7026 return WERR_NOMEM;
7030 for (i=0; i<ndrivers; i++) {
7031 WERROR status;
7033 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7034 ZERO_STRUCT(driver);
7035 status = get_a_printer_driver(&driver, 3, list[i],
7036 architecture, version);
7037 if (!W_ERROR_IS_OK(status)) {
7038 SAFE_FREE(list);
7039 SAFE_FREE(driver_info_3);
7040 return status;
7042 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7043 free_a_printer_driver(driver, 3);
7046 *returned+=ndrivers;
7047 SAFE_FREE(list);
7050 /* check the required size. */
7051 for (i=0; i<*returned; i++) {
7052 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7053 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7056 if (*needed > offered) {
7057 result = WERR_INSUFFICIENT_BUFFER;
7058 goto out;
7061 if (!rpcbuf_alloc_size(buffer, *needed)) {
7062 result = WERR_NOMEM;
7063 goto out;
7066 /* fill the buffer with the driver structures */
7067 for (i=0; i<*returned; i++) {
7068 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7069 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7072 out:
7073 for (i=0; i<*returned; i++) {
7074 SAFE_FREE(driver_info_3[i].dependentfiles);
7077 SAFE_FREE(driver_info_3);
7079 if ( !W_ERROR_IS_OK(result) )
7080 *returned = 0;
7082 return result;
7085 /****************************************************************************
7086 Enumerates all printer drivers.
7087 ****************************************************************************/
7089 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7091 uint32 level = q_u->level;
7092 RPC_BUFFER *buffer = NULL;
7093 uint32 offered = q_u->offered;
7094 uint32 *needed = &r_u->needed;
7095 uint32 *returned = &r_u->returned;
7097 fstring servername;
7098 fstring architecture;
7100 /* that's an [in out] buffer */
7102 if (!q_u->buffer && (offered!=0)) {
7103 return WERR_INVALID_PARAM;
7106 rpcbuf_move(q_u->buffer, &r_u->buffer);
7107 buffer = r_u->buffer;
7109 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7111 *needed = 0;
7112 *returned = 0;
7114 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7115 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7117 if ( !is_myname_or_ipaddr( servername ) )
7118 return WERR_UNKNOWN_PRINTER_DRIVER;
7120 switch (level) {
7121 case 1:
7122 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7123 case 2:
7124 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7125 case 3:
7126 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7127 default:
7128 return WERR_UNKNOWN_LEVEL;
7132 /****************************************************************************
7133 ****************************************************************************/
7135 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7137 form->flag=list->flag;
7138 init_unistr(&form->name, list->name);
7139 form->width=list->width;
7140 form->length=list->length;
7141 form->left=list->left;
7142 form->top=list->top;
7143 form->right=list->right;
7144 form->bottom=list->bottom;
7147 /****************************************************************************
7148 ****************************************************************************/
7150 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7152 uint32 level = q_u->level;
7153 RPC_BUFFER *buffer = NULL;
7154 uint32 offered = q_u->offered;
7155 uint32 *needed = &r_u->needed;
7156 uint32 *numofforms = &r_u->numofforms;
7157 uint32 numbuiltinforms;
7159 nt_forms_struct *list=NULL;
7160 nt_forms_struct *builtinlist=NULL;
7161 FORM_1 *forms_1;
7162 int buffer_size=0;
7163 int i;
7165 /* that's an [in out] buffer */
7167 if (!q_u->buffer && (offered!=0) ) {
7168 return WERR_INVALID_PARAM;
7171 rpcbuf_move(q_u->buffer, &r_u->buffer);
7172 buffer = r_u->buffer;
7174 DEBUG(4,("_spoolss_enumforms\n"));
7175 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7176 DEBUGADD(5,("Info level [%d]\n", level));
7178 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7179 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7180 *numofforms = get_ntforms(&list);
7181 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7182 *numofforms += numbuiltinforms;
7184 if (*numofforms == 0) {
7185 SAFE_FREE(builtinlist);
7186 SAFE_FREE(list);
7187 return WERR_NO_MORE_ITEMS;
7190 switch (level) {
7191 case 1:
7192 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7193 SAFE_FREE(builtinlist);
7194 SAFE_FREE(list);
7195 *numofforms=0;
7196 return WERR_NOMEM;
7199 /* construct the list of form structures */
7200 for (i=0; i<numbuiltinforms; i++) {
7201 DEBUGADD(6,("Filling form number [%d]\n",i));
7202 fill_form_1(&forms_1[i], &builtinlist[i]);
7205 SAFE_FREE(builtinlist);
7207 for (; i<*numofforms; i++) {
7208 DEBUGADD(6,("Filling form number [%d]\n",i));
7209 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7212 SAFE_FREE(list);
7214 /* check the required size. */
7215 for (i=0; i<numbuiltinforms; i++) {
7216 DEBUGADD(6,("adding form [%d]'s size\n",i));
7217 buffer_size += spoolss_size_form_1(&forms_1[i]);
7219 for (; i<*numofforms; i++) {
7220 DEBUGADD(6,("adding form [%d]'s size\n",i));
7221 buffer_size += spoolss_size_form_1(&forms_1[i]);
7224 *needed=buffer_size;
7226 if (*needed > offered) {
7227 SAFE_FREE(forms_1);
7228 *numofforms=0;
7229 return WERR_INSUFFICIENT_BUFFER;
7232 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7233 SAFE_FREE(forms_1);
7234 *numofforms=0;
7235 return WERR_NOMEM;
7238 /* fill the buffer with the form structures */
7239 for (i=0; i<numbuiltinforms; i++) {
7240 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7241 smb_io_form_1("", buffer, &forms_1[i], 0);
7243 for (; i<*numofforms; i++) {
7244 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7245 smb_io_form_1("", buffer, &forms_1[i], 0);
7248 SAFE_FREE(forms_1);
7250 return WERR_OK;
7252 default:
7253 SAFE_FREE(list);
7254 SAFE_FREE(builtinlist);
7255 return WERR_UNKNOWN_LEVEL;
7259 /****************************************************************************
7260 ****************************************************************************/
7262 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7264 uint32 level = q_u->level;
7265 UNISTR2 *uni_formname = &q_u->formname;
7266 RPC_BUFFER *buffer = NULL;
7267 uint32 offered = q_u->offered;
7268 uint32 *needed = &r_u->needed;
7270 nt_forms_struct *list=NULL;
7271 nt_forms_struct builtin_form;
7272 BOOL foundBuiltin;
7273 FORM_1 form_1;
7274 fstring form_name;
7275 int buffer_size=0;
7276 int numofforms=0, i=0;
7278 /* that's an [in out] buffer */
7280 if (!q_u->buffer && (offered!=0)) {
7281 return WERR_INVALID_PARAM;
7284 rpcbuf_move(q_u->buffer, &r_u->buffer);
7285 buffer = r_u->buffer;
7287 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7289 DEBUG(4,("_spoolss_getform\n"));
7290 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7291 DEBUGADD(5,("Info level [%d]\n", level));
7293 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7294 if (!foundBuiltin) {
7295 numofforms = get_ntforms(&list);
7296 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7298 if (numofforms == 0)
7299 return WERR_BADFID;
7302 switch (level) {
7303 case 1:
7304 if (foundBuiltin) {
7305 fill_form_1(&form_1, &builtin_form);
7306 } else {
7308 /* Check if the requested name is in the list of form structures */
7309 for (i=0; i<numofforms; i++) {
7311 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7313 if (strequal(form_name, list[i].name)) {
7314 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7315 fill_form_1(&form_1, &list[i]);
7316 break;
7320 SAFE_FREE(list);
7321 if (i == numofforms) {
7322 return WERR_BADFID;
7325 /* check the required size. */
7327 *needed=spoolss_size_form_1(&form_1);
7329 if (*needed > offered)
7330 return WERR_INSUFFICIENT_BUFFER;
7332 if (!rpcbuf_alloc_size(buffer, buffer_size))
7333 return WERR_NOMEM;
7335 /* fill the buffer with the form structures */
7336 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7337 smb_io_form_1("", buffer, &form_1, 0);
7339 return WERR_OK;
7341 default:
7342 SAFE_FREE(list);
7343 return WERR_UNKNOWN_LEVEL;
7347 /****************************************************************************
7348 ****************************************************************************/
7350 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7352 init_unistr(&port->port_name, name);
7355 /****************************************************************************
7356 TODO: This probably needs distinguish between TCP/IP and Local ports
7357 somehow.
7358 ****************************************************************************/
7360 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7362 init_unistr(&port->port_name, name);
7363 init_unistr(&port->monitor_name, "Local Monitor");
7364 init_unistr(&port->description, SPL_LOCAL_PORT );
7365 port->port_type=PORT_TYPE_WRITE;
7366 port->reserved=0x0;
7370 /****************************************************************************
7371 wrapper around the enumer ports command
7372 ****************************************************************************/
7374 WERROR enumports_hook( int *count, char ***lines )
7376 char *cmd = lp_enumports_cmd();
7377 char **qlines;
7378 pstring command;
7379 int numlines;
7380 int ret;
7381 int fd;
7383 *count = 0;
7384 *lines = NULL;
7386 /* if no hook then just fill in the default port */
7388 if ( !*cmd ) {
7389 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7390 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7391 qlines[1] = NULL;
7392 numlines = 1;
7394 else {
7395 /* we have a valid enumport command */
7397 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7399 DEBUG(10,("Running [%s]\n", command));
7400 ret = smbrun(command, &fd);
7401 DEBUG(10,("Returned [%d]\n", ret));
7402 if (ret != 0) {
7403 if (fd != -1) {
7404 close(fd);
7406 return WERR_ACCESS_DENIED;
7409 numlines = 0;
7410 qlines = fd_lines_load(fd, &numlines, 0);
7411 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7412 close(fd);
7415 *count = numlines;
7416 *lines = qlines;
7418 return WERR_OK;
7421 /****************************************************************************
7422 enumports level 1.
7423 ****************************************************************************/
7425 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7427 PORT_INFO_1 *ports=NULL;
7428 int i=0;
7429 WERROR result = WERR_OK;
7430 char **qlines = NULL;
7431 int numlines = 0;
7433 result = enumports_hook( &numlines, &qlines );
7434 if (!W_ERROR_IS_OK(result)) {
7435 file_lines_free(qlines);
7436 return result;
7439 if(numlines) {
7440 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7441 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7442 dos_errstr(WERR_NOMEM)));
7443 file_lines_free(qlines);
7444 return WERR_NOMEM;
7447 for (i=0; i<numlines; i++) {
7448 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7449 fill_port_1(&ports[i], qlines[i]);
7452 file_lines_free(qlines);
7454 *returned = numlines;
7456 /* check the required size. */
7457 for (i=0; i<*returned; i++) {
7458 DEBUGADD(6,("adding port [%d]'s size\n", i));
7459 *needed += spoolss_size_port_info_1(&ports[i]);
7462 if (*needed > offered) {
7463 result = WERR_INSUFFICIENT_BUFFER;
7464 goto out;
7467 if (!rpcbuf_alloc_size(buffer, *needed)) {
7468 result = WERR_NOMEM;
7469 goto out;
7472 /* fill the buffer with the ports structures */
7473 for (i=0; i<*returned; i++) {
7474 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7475 smb_io_port_1("", buffer, &ports[i], 0);
7478 out:
7479 SAFE_FREE(ports);
7481 if ( !W_ERROR_IS_OK(result) )
7482 *returned = 0;
7484 return result;
7487 /****************************************************************************
7488 enumports level 2.
7489 ****************************************************************************/
7491 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7493 PORT_INFO_2 *ports=NULL;
7494 int i=0;
7495 WERROR result = WERR_OK;
7496 char **qlines = NULL;
7497 int numlines = 0;
7499 result = enumports_hook( &numlines, &qlines );
7500 if ( !W_ERROR_IS_OK(result)) {
7501 file_lines_free(qlines);
7502 return result;
7505 if(numlines) {
7506 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7507 file_lines_free(qlines);
7508 return WERR_NOMEM;
7511 for (i=0; i<numlines; i++) {
7512 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7513 fill_port_2(&(ports[i]), qlines[i]);
7517 file_lines_free(qlines);
7519 *returned = numlines;
7521 /* check the required size. */
7522 for (i=0; i<*returned; i++) {
7523 DEBUGADD(6,("adding port [%d]'s size\n", i));
7524 *needed += spoolss_size_port_info_2(&ports[i]);
7527 if (*needed > offered) {
7528 result = WERR_INSUFFICIENT_BUFFER;
7529 goto out;
7532 if (!rpcbuf_alloc_size(buffer, *needed)) {
7533 result = WERR_NOMEM;
7534 goto out;
7537 /* fill the buffer with the ports structures */
7538 for (i=0; i<*returned; i++) {
7539 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7540 smb_io_port_2("", buffer, &ports[i], 0);
7543 out:
7544 SAFE_FREE(ports);
7546 if ( !W_ERROR_IS_OK(result) )
7547 *returned = 0;
7549 return result;
7552 /****************************************************************************
7553 enumports.
7554 ****************************************************************************/
7556 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7558 uint32 level = q_u->level;
7559 RPC_BUFFER *buffer = NULL;
7560 uint32 offered = q_u->offered;
7561 uint32 *needed = &r_u->needed;
7562 uint32 *returned = &r_u->returned;
7564 /* that's an [in out] buffer */
7566 if (!q_u->buffer && (offered!=0)) {
7567 return WERR_INVALID_PARAM;
7570 rpcbuf_move(q_u->buffer, &r_u->buffer);
7571 buffer = r_u->buffer;
7573 DEBUG(4,("_spoolss_enumports\n"));
7575 *returned=0;
7576 *needed=0;
7578 switch (level) {
7579 case 1:
7580 return enumports_level_1(buffer, offered, needed, returned);
7581 case 2:
7582 return enumports_level_2(buffer, offered, needed, returned);
7583 default:
7584 return WERR_UNKNOWN_LEVEL;
7588 /****************************************************************************
7589 ****************************************************************************/
7591 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7592 const SPOOL_PRINTER_INFO_LEVEL *info,
7593 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7594 uint32 user_switch, const SPOOL_USER_CTR *user,
7595 POLICY_HND *handle)
7597 NT_PRINTER_INFO_LEVEL *printer = NULL;
7598 fstring name;
7599 int snum;
7600 WERROR err = WERR_OK;
7602 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7603 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7604 return WERR_NOMEM;
7607 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7608 if (!convert_printer_info(info, printer, 2)) {
7609 free_a_printer(&printer, 2);
7610 return WERR_NOMEM;
7613 /* check to see if the printer already exists */
7615 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7616 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7617 printer->info_2->sharename));
7618 free_a_printer(&printer, 2);
7619 return WERR_PRINTER_ALREADY_EXISTS;
7622 /* FIXME!!! smbd should check to see if the driver is installed before
7623 trying to add a printer like this --jerry */
7625 if (*lp_addprinter_cmd() ) {
7626 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7627 free_a_printer(&printer,2);
7628 return WERR_ACCESS_DENIED;
7630 } else {
7631 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7632 "smb.conf parameter \"addprinter command\" is defined. This"
7633 "parameter must exist for this call to succeed\n",
7634 printer->info_2->sharename ));
7637 /* use our primary netbios name since get_a_printer() will convert
7638 it to what the client expects on a case by case basis */
7640 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7641 printer->info_2->sharename);
7644 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7645 free_a_printer(&printer,2);
7646 return WERR_ACCESS_DENIED;
7649 /* you must be a printer admin to add a new printer */
7650 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7651 free_a_printer(&printer,2);
7652 return WERR_ACCESS_DENIED;
7656 * Do sanity check on the requested changes for Samba.
7659 if (!check_printer_ok(printer->info_2, snum)) {
7660 free_a_printer(&printer,2);
7661 return WERR_INVALID_PARAM;
7665 * When a printer is created, the drivername bound to the printer is used
7666 * to lookup previously saved driver initialization info, which is then
7667 * bound to the new printer, simulating what happens in the Windows arch.
7670 if (!devmode)
7672 set_driver_init(printer, 2);
7674 else
7676 /* A valid devmode was included, convert and link it
7678 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7680 if (!convert_devicemode(printer->info_2->printername, devmode,
7681 &printer->info_2->devmode))
7682 return WERR_NOMEM;
7685 /* write the ASCII on disk */
7686 err = mod_a_printer(printer, 2);
7687 if (!W_ERROR_IS_OK(err)) {
7688 free_a_printer(&printer,2);
7689 return err;
7692 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7693 /* Handle open failed - remove addition. */
7694 del_a_printer(printer->info_2->sharename);
7695 free_a_printer(&printer,2);
7696 return WERR_ACCESS_DENIED;
7699 update_c_setprinter(False);
7700 free_a_printer(&printer,2);
7702 return WERR_OK;
7705 /****************************************************************************
7706 ****************************************************************************/
7708 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7710 UNISTR2 *uni_srv_name = q_u->server_name;
7711 uint32 level = q_u->level;
7712 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7713 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7714 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7715 uint32 user_switch = q_u->user_switch;
7716 SPOOL_USER_CTR *user = &q_u->user_ctr;
7717 POLICY_HND *handle = &r_u->handle;
7719 switch (level) {
7720 case 1:
7721 /* we don't handle yet */
7722 /* but I know what to do ... */
7723 return WERR_UNKNOWN_LEVEL;
7724 case 2:
7725 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7726 devmode, sdb,
7727 user_switch, user, handle);
7728 default:
7729 return WERR_UNKNOWN_LEVEL;
7733 /****************************************************************************
7734 ****************************************************************************/
7736 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7738 uint32 level = q_u->level;
7739 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7740 WERROR err = WERR_OK;
7741 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7742 fstring driver_name;
7743 uint32 version;
7745 ZERO_STRUCT(driver);
7747 if (!convert_printer_driver_info(info, &driver, level)) {
7748 err = WERR_NOMEM;
7749 goto done;
7752 DEBUG(5,("Cleaning driver's information\n"));
7753 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7754 if (!W_ERROR_IS_OK(err))
7755 goto done;
7757 DEBUG(5,("Moving driver to final destination\n"));
7758 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7759 goto done;
7762 if (add_a_printer_driver(driver, level)!=0) {
7763 err = WERR_ACCESS_DENIED;
7764 goto done;
7768 * I think this is where he DrvUpgradePrinter() hook would be
7769 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7770 * server. Right now, we just need to send ourselves a message
7771 * to update each printer bound to this driver. --jerry
7774 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7775 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7776 driver_name));
7780 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7781 * decide if the driver init data should be deleted. The rules are:
7782 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7783 * 2) delete init data only if there is no 2k/Xp driver
7784 * 3) always delete init data
7785 * The generalized rule is always use init data from the highest order driver.
7786 * It is necessary to follow the driver install by an initialization step to
7787 * finish off this process.
7789 if (level == 3)
7790 version = driver.info_3->cversion;
7791 else if (level == 6)
7792 version = driver.info_6->version;
7793 else
7794 version = -1;
7795 switch (version) {
7797 * 9x printer driver - never delete init data
7799 case 0:
7800 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7801 driver_name));
7802 break;
7805 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7806 * there is no 2k/Xp driver init data for this driver name.
7808 case 2:
7810 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7812 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7814 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7816 if (!del_driver_init(driver_name))
7817 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7818 } else {
7820 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7822 free_a_printer_driver(driver1,3);
7823 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7824 driver_name));
7827 break;
7830 * 2k or Xp printer driver - always delete init data
7832 case 3:
7833 if (!del_driver_init(driver_name))
7834 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7835 break;
7837 default:
7838 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7839 break;
7843 done:
7844 free_a_printer_driver(driver, level);
7845 return err;
7848 /********************************************************************
7849 * spoolss_addprinterdriverex
7850 ********************************************************************/
7852 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7854 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7855 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7858 * we only support the semantics of AddPrinterDriver()
7859 * i.e. only copy files that are newer than existing ones
7862 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7863 return WERR_ACCESS_DENIED;
7865 ZERO_STRUCT(q_u_local);
7866 ZERO_STRUCT(r_u_local);
7868 /* just pass the information off to _spoolss_addprinterdriver() */
7869 q_u_local.server_name_ptr = q_u->server_name_ptr;
7870 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7871 q_u_local.level = q_u->level;
7872 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7874 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7877 /****************************************************************************
7878 ****************************************************************************/
7880 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7882 init_unistr(&info->name, name);
7885 /****************************************************************************
7886 ****************************************************************************/
7888 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7890 pstring path;
7891 pstring long_archi;
7892 fstring servername;
7893 char *pservername;
7894 const char *short_archi;
7895 DRIVER_DIRECTORY_1 *info=NULL;
7896 WERROR result = WERR_OK;
7898 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7899 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7901 /* check for beginning double '\'s and that the server
7902 long enough */
7904 pservername = servername;
7905 if ( *pservername == '\\' && strlen(servername)>2 ) {
7906 pservername += 2;
7909 if ( !is_myname_or_ipaddr( pservername ) )
7910 return WERR_INVALID_PARAM;
7912 if (!(short_archi = get_short_archi(long_archi)))
7913 return WERR_INVALID_ENVIRONMENT;
7915 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7916 return WERR_NOMEM;
7918 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7920 DEBUG(4,("printer driver directory: [%s]\n", path));
7922 fill_driverdir_1(info, path);
7924 *needed += spoolss_size_driverdir_info_1(info);
7926 if (*needed > offered) {
7927 result = WERR_INSUFFICIENT_BUFFER;
7928 goto out;
7931 if (!rpcbuf_alloc_size(buffer, *needed)) {
7932 result = WERR_NOMEM;
7933 goto out;
7936 smb_io_driverdir_1("", buffer, info, 0);
7938 out:
7939 SAFE_FREE(info);
7941 return result;
7944 /****************************************************************************
7945 ****************************************************************************/
7947 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7949 UNISTR2 *name = &q_u->name;
7950 UNISTR2 *uni_environment = &q_u->environment;
7951 uint32 level = q_u->level;
7952 RPC_BUFFER *buffer = NULL;
7953 uint32 offered = q_u->offered;
7954 uint32 *needed = &r_u->needed;
7956 /* that's an [in out] buffer */
7958 if (!q_u->buffer && (offered!=0)) {
7959 return WERR_INVALID_PARAM;
7962 rpcbuf_move(q_u->buffer, &r_u->buffer);
7963 buffer = r_u->buffer;
7965 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7967 *needed=0;
7969 switch(level) {
7970 case 1:
7971 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7972 default:
7973 return WERR_UNKNOWN_LEVEL;
7977 /****************************************************************************
7978 ****************************************************************************/
7980 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7982 POLICY_HND *handle = &q_u->handle;
7983 uint32 idx = q_u->index;
7984 uint32 in_value_len = q_u->valuesize;
7985 uint32 in_data_len = q_u->datasize;
7986 uint32 *out_max_value_len = &r_u->valuesize;
7987 uint16 **out_value = &r_u->value;
7988 uint32 *out_value_len = &r_u->realvaluesize;
7989 uint32 *out_type = &r_u->type;
7990 uint32 *out_max_data_len = &r_u->datasize;
7991 uint8 **data_out = &r_u->data;
7992 uint32 *out_data_len = &r_u->realdatasize;
7994 NT_PRINTER_INFO_LEVEL *printer = NULL;
7996 uint32 biggest_valuesize;
7997 uint32 biggest_datasize;
7998 uint32 data_len;
7999 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8000 int snum;
8001 WERROR result;
8002 REGISTRY_VALUE *val = NULL;
8003 NT_PRINTER_DATA *p_data;
8004 int i, key_index, num_values;
8005 int name_length;
8007 *out_type = 0;
8009 *out_max_data_len = 0;
8010 *data_out = NULL;
8011 *out_data_len = 0;
8013 DEBUG(5,("spoolss_enumprinterdata\n"));
8015 if (!Printer) {
8016 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8017 return WERR_BADFID;
8020 if (!get_printer_snum(p,handle, &snum, NULL))
8021 return WERR_BADFID;
8023 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8024 if (!W_ERROR_IS_OK(result))
8025 return result;
8027 p_data = printer->info_2->data;
8028 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8030 result = WERR_OK;
8033 * The NT machine wants to know the biggest size of value and data
8035 * cf: MSDN EnumPrinterData remark section
8038 if ( !in_value_len && !in_data_len && (key_index != -1) )
8040 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8042 biggest_valuesize = 0;
8043 biggest_datasize = 0;
8045 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8047 for ( i=0; i<num_values; i++ )
8049 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8051 name_length = strlen(val->valuename);
8052 if ( strlen(val->valuename) > biggest_valuesize )
8053 biggest_valuesize = name_length;
8055 if ( val->size > biggest_datasize )
8056 biggest_datasize = val->size;
8058 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8059 biggest_datasize));
8062 /* the value is an UNICODE string but real_value_size is the length
8063 in bytes including the trailing 0 */
8065 *out_value_len = 2 * (1+biggest_valuesize);
8066 *out_data_len = biggest_datasize;
8068 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8070 goto done;
8074 * the value len is wrong in NT sp3
8075 * that's the number of bytes not the number of unicode chars
8078 if ( key_index != -1 )
8079 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8081 if ( !val )
8084 /* out_value should default to "" or else NT4 has
8085 problems unmarshalling the response */
8087 *out_max_value_len=(in_value_len/sizeof(uint16));
8089 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8091 result = WERR_NOMEM;
8092 goto done;
8095 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8097 /* the data is counted in bytes */
8099 *out_max_data_len = in_data_len;
8100 *out_data_len = in_data_len;
8102 /* only allocate when given a non-zero data_len */
8104 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8106 result = WERR_NOMEM;
8107 goto done;
8110 result = WERR_NO_MORE_ITEMS;
8112 else
8115 * the value is:
8116 * - counted in bytes in the request
8117 * - counted in UNICODE chars in the max reply
8118 * - counted in bytes in the real size
8120 * take a pause *before* coding not *during* coding
8123 /* name */
8124 *out_max_value_len=(in_value_len/sizeof(uint16));
8125 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8127 result = WERR_NOMEM;
8128 goto done;
8131 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8133 /* type */
8135 *out_type = regval_type( val );
8137 /* data - counted in bytes */
8139 *out_max_data_len = in_data_len;
8140 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8142 result = WERR_NOMEM;
8143 goto done;
8145 data_len = regval_size(val);
8146 if ( *data_out )
8147 memcpy( *data_out, regval_data_p(val), data_len );
8148 *out_data_len = data_len;
8151 done:
8152 free_a_printer(&printer, 2);
8153 return result;
8156 /****************************************************************************
8157 ****************************************************************************/
8159 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8161 POLICY_HND *handle = &q_u->handle;
8162 UNISTR2 *value = &q_u->value;
8163 uint32 type = q_u->type;
8164 uint8 *data = q_u->data;
8165 uint32 real_len = q_u->real_len;
8167 NT_PRINTER_INFO_LEVEL *printer = NULL;
8168 int snum=0;
8169 WERROR status = WERR_OK;
8170 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8171 fstring valuename;
8173 DEBUG(5,("spoolss_setprinterdata\n"));
8175 if (!Printer) {
8176 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8177 return WERR_BADFID;
8180 if ( Printer->printer_type == SPLHND_SERVER ) {
8181 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8182 return WERR_INVALID_PARAM;
8185 if (!get_printer_snum(p,handle, &snum, NULL))
8186 return WERR_BADFID;
8189 * Access check : NT returns "access denied" if you make a
8190 * SetPrinterData call without the necessary privildge.
8191 * we were originally returning OK if nothing changed
8192 * which made Win2k issue **a lot** of SetPrinterData
8193 * when connecting to a printer --jerry
8196 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8198 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8199 status = WERR_ACCESS_DENIED;
8200 goto done;
8203 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8204 if (!W_ERROR_IS_OK(status))
8205 return status;
8207 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8210 * When client side code sets a magic printer data key, detect it and save
8211 * the current printer data and the magic key's data (its the DEVMODE) for
8212 * future printer/driver initializations.
8214 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8216 /* Set devmode and printer initialization info */
8217 status = save_driver_init( printer, 2, data, real_len );
8219 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8221 else
8223 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8224 type, data, real_len );
8225 if ( W_ERROR_IS_OK(status) )
8226 status = mod_a_printer(printer, 2);
8229 done:
8230 free_a_printer(&printer, 2);
8232 return status;
8235 /****************************************************************************
8236 ****************************************************************************/
8238 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8240 POLICY_HND *handle = &q_u->handle;
8241 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8242 int snum;
8244 DEBUG(5,("_spoolss_resetprinter\n"));
8247 * All we do is to check to see if the handle and queue is valid.
8248 * This call really doesn't mean anything to us because we only
8249 * support RAW printing. --jerry
8252 if (!Printer) {
8253 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8254 return WERR_BADFID;
8257 if (!get_printer_snum(p,handle, &snum, NULL))
8258 return WERR_BADFID;
8261 /* blindly return success */
8262 return WERR_OK;
8266 /****************************************************************************
8267 ****************************************************************************/
8269 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8271 POLICY_HND *handle = &q_u->handle;
8272 UNISTR2 *value = &q_u->valuename;
8274 NT_PRINTER_INFO_LEVEL *printer = NULL;
8275 int snum=0;
8276 WERROR status = WERR_OK;
8277 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8278 pstring valuename;
8280 DEBUG(5,("spoolss_deleteprinterdata\n"));
8282 if (!Printer) {
8283 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8284 return WERR_BADFID;
8287 if (!get_printer_snum(p, handle, &snum, NULL))
8288 return WERR_BADFID;
8290 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8291 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8292 return WERR_ACCESS_DENIED;
8295 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8296 if (!W_ERROR_IS_OK(status))
8297 return status;
8299 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8301 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8303 if ( W_ERROR_IS_OK(status) )
8304 mod_a_printer( printer, 2 );
8306 free_a_printer(&printer, 2);
8308 return status;
8311 /****************************************************************************
8312 ****************************************************************************/
8314 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8316 POLICY_HND *handle = &q_u->handle;
8317 FORM *form = &q_u->form;
8318 nt_forms_struct tmpForm;
8319 int snum;
8320 WERROR status = WERR_OK;
8321 NT_PRINTER_INFO_LEVEL *printer = NULL;
8323 int count=0;
8324 nt_forms_struct *list=NULL;
8325 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8327 DEBUG(5,("spoolss_addform\n"));
8329 if (!Printer) {
8330 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8331 return WERR_BADFID;
8335 /* forms can be added on printer of on the print server handle */
8337 if ( Printer->printer_type == SPLHND_PRINTER )
8339 if (!get_printer_snum(p,handle, &snum, NULL))
8340 return WERR_BADFID;
8342 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8343 if (!W_ERROR_IS_OK(status))
8344 goto done;
8347 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8348 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8349 status = WERR_ACCESS_DENIED;
8350 goto done;
8353 /* can't add if builtin */
8355 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8356 status = WERR_ALREADY_EXISTS;
8357 goto done;
8360 count = get_ntforms(&list);
8362 if(!add_a_form(&list, form, &count)) {
8363 status = WERR_NOMEM;
8364 goto done;
8367 write_ntforms(&list, count);
8370 * ChangeID must always be set if this is a printer
8373 if ( Printer->printer_type == SPLHND_PRINTER )
8374 status = mod_a_printer(printer, 2);
8376 done:
8377 if ( printer )
8378 free_a_printer(&printer, 2);
8379 SAFE_FREE(list);
8381 return status;
8384 /****************************************************************************
8385 ****************************************************************************/
8387 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8389 POLICY_HND *handle = &q_u->handle;
8390 UNISTR2 *form_name = &q_u->name;
8391 nt_forms_struct tmpForm;
8392 int count=0;
8393 nt_forms_struct *list=NULL;
8394 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8395 int snum;
8396 WERROR status = WERR_OK;
8397 NT_PRINTER_INFO_LEVEL *printer = NULL;
8399 DEBUG(5,("spoolss_deleteform\n"));
8401 if (!Printer) {
8402 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8403 return WERR_BADFID;
8406 /* forms can be deleted on printer of on the print server handle */
8408 if ( Printer->printer_type == SPLHND_PRINTER )
8410 if (!get_printer_snum(p,handle, &snum, NULL))
8411 return WERR_BADFID;
8413 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8414 if (!W_ERROR_IS_OK(status))
8415 goto done;
8418 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8419 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8420 status = WERR_ACCESS_DENIED;
8421 goto done;
8424 /* can't delete if builtin */
8426 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8427 status = WERR_INVALID_PARAM;
8428 goto done;
8431 count = get_ntforms(&list);
8433 if ( !delete_a_form(&list, form_name, &count, &status ))
8434 goto done;
8437 * ChangeID must always be set if this is a printer
8440 if ( Printer->printer_type == SPLHND_PRINTER )
8441 status = mod_a_printer(printer, 2);
8443 done:
8444 if ( printer )
8445 free_a_printer(&printer, 2);
8446 SAFE_FREE(list);
8448 return status;
8451 /****************************************************************************
8452 ****************************************************************************/
8454 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8456 POLICY_HND *handle = &q_u->handle;
8457 FORM *form = &q_u->form;
8458 nt_forms_struct tmpForm;
8459 int snum;
8460 WERROR status = WERR_OK;
8461 NT_PRINTER_INFO_LEVEL *printer = NULL;
8463 int count=0;
8464 nt_forms_struct *list=NULL;
8465 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8467 DEBUG(5,("spoolss_setform\n"));
8469 if (!Printer) {
8470 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8471 return WERR_BADFID;
8474 /* forms can be modified on printer of on the print server handle */
8476 if ( Printer->printer_type == SPLHND_PRINTER )
8478 if (!get_printer_snum(p,handle, &snum, NULL))
8479 return WERR_BADFID;
8481 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8482 if (!W_ERROR_IS_OK(status))
8483 goto done;
8486 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8487 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8488 status = WERR_ACCESS_DENIED;
8489 goto done;
8492 /* can't set if builtin */
8493 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8494 status = WERR_INVALID_PARAM;
8495 goto done;
8498 count = get_ntforms(&list);
8499 update_a_form(&list, form, count);
8500 write_ntforms(&list, count);
8503 * ChangeID must always be set if this is a printer
8506 if ( Printer->printer_type == SPLHND_PRINTER )
8507 status = mod_a_printer(printer, 2);
8510 done:
8511 if ( printer )
8512 free_a_printer(&printer, 2);
8513 SAFE_FREE(list);
8515 return status;
8518 /****************************************************************************
8519 enumprintprocessors level 1.
8520 ****************************************************************************/
8522 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8524 PRINTPROCESSOR_1 *info_1=NULL;
8525 WERROR result = WERR_OK;
8527 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8528 return WERR_NOMEM;
8530 (*returned) = 0x1;
8532 init_unistr(&info_1->name, "winprint");
8534 *needed += spoolss_size_printprocessor_info_1(info_1);
8536 if (*needed > offered) {
8537 result = WERR_INSUFFICIENT_BUFFER;
8538 goto out;
8541 if (!rpcbuf_alloc_size(buffer, *needed)) {
8542 result = WERR_NOMEM;
8543 goto out;
8546 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8548 out:
8549 SAFE_FREE(info_1);
8551 if ( !W_ERROR_IS_OK(result) )
8552 *returned = 0;
8554 return result;
8557 /****************************************************************************
8558 ****************************************************************************/
8560 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8562 uint32 level = q_u->level;
8563 RPC_BUFFER *buffer = NULL;
8564 uint32 offered = q_u->offered;
8565 uint32 *needed = &r_u->needed;
8566 uint32 *returned = &r_u->returned;
8568 /* that's an [in out] buffer */
8570 if (!q_u->buffer && (offered!=0)) {
8571 return WERR_INVALID_PARAM;
8574 rpcbuf_move(q_u->buffer, &r_u->buffer);
8575 buffer = r_u->buffer;
8577 DEBUG(5,("spoolss_enumprintprocessors\n"));
8580 * Enumerate the print processors ...
8582 * Just reply with "winprint", to keep NT happy
8583 * and I can use my nice printer checker.
8586 *returned=0;
8587 *needed=0;
8589 switch (level) {
8590 case 1:
8591 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8592 default:
8593 return WERR_UNKNOWN_LEVEL;
8597 /****************************************************************************
8598 enumprintprocdatatypes level 1.
8599 ****************************************************************************/
8601 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8603 PRINTPROCDATATYPE_1 *info_1=NULL;
8604 WERROR result = WERR_NOMEM;
8606 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8607 return WERR_NOMEM;
8609 (*returned) = 0x1;
8611 init_unistr(&info_1->name, "RAW");
8613 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8615 if (*needed > offered) {
8616 result = WERR_INSUFFICIENT_BUFFER;
8617 goto out;
8620 if (!rpcbuf_alloc_size(buffer, *needed)) {
8621 result = WERR_NOMEM;
8622 goto out;
8625 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8627 out:
8628 SAFE_FREE(info_1);
8630 if ( !W_ERROR_IS_OK(result) )
8631 *returned = 0;
8633 return result;
8636 /****************************************************************************
8637 ****************************************************************************/
8639 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8641 uint32 level = q_u->level;
8642 RPC_BUFFER *buffer = NULL;
8643 uint32 offered = q_u->offered;
8644 uint32 *needed = &r_u->needed;
8645 uint32 *returned = &r_u->returned;
8647 /* that's an [in out] buffer */
8649 if (!q_u->buffer && (offered!=0)) {
8650 return WERR_INVALID_PARAM;
8653 rpcbuf_move(q_u->buffer, &r_u->buffer);
8654 buffer = r_u->buffer;
8656 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8658 *returned=0;
8659 *needed=0;
8661 switch (level) {
8662 case 1:
8663 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8664 default:
8665 return WERR_UNKNOWN_LEVEL;
8669 /****************************************************************************
8670 enumprintmonitors level 1.
8671 ****************************************************************************/
8673 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8675 PRINTMONITOR_1 *info_1;
8676 WERROR result = WERR_OK;
8677 int i;
8679 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8680 return WERR_NOMEM;
8682 *returned = 2;
8684 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8685 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8687 for ( i=0; i<*returned; i++ ) {
8688 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8691 if (*needed > offered) {
8692 result = WERR_INSUFFICIENT_BUFFER;
8693 goto out;
8696 if (!rpcbuf_alloc_size(buffer, *needed)) {
8697 result = WERR_NOMEM;
8698 goto out;
8701 for ( i=0; i<*returned; i++ ) {
8702 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8705 out:
8706 SAFE_FREE(info_1);
8708 if ( !W_ERROR_IS_OK(result) )
8709 *returned = 0;
8711 return result;
8714 /****************************************************************************
8715 enumprintmonitors level 2.
8716 ****************************************************************************/
8718 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8720 PRINTMONITOR_2 *info_2;
8721 WERROR result = WERR_OK;
8722 int i;
8724 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8725 return WERR_NOMEM;
8727 *returned = 2;
8729 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8730 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8731 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8733 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8734 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8735 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8737 for ( i=0; i<*returned; i++ ) {
8738 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8741 if (*needed > offered) {
8742 result = WERR_INSUFFICIENT_BUFFER;
8743 goto out;
8746 if (!rpcbuf_alloc_size(buffer, *needed)) {
8747 result = WERR_NOMEM;
8748 goto out;
8751 for ( i=0; i<*returned; i++ ) {
8752 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8755 out:
8756 SAFE_FREE(info_2);
8758 if ( !W_ERROR_IS_OK(result) )
8759 *returned = 0;
8761 return result;
8764 /****************************************************************************
8765 ****************************************************************************/
8767 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8769 uint32 level = q_u->level;
8770 RPC_BUFFER *buffer = NULL;
8771 uint32 offered = q_u->offered;
8772 uint32 *needed = &r_u->needed;
8773 uint32 *returned = &r_u->returned;
8775 /* that's an [in out] buffer */
8777 if (!q_u->buffer && (offered!=0)) {
8778 return WERR_INVALID_PARAM;
8781 rpcbuf_move(q_u->buffer, &r_u->buffer);
8782 buffer = r_u->buffer;
8784 DEBUG(5,("spoolss_enumprintmonitors\n"));
8787 * Enumerate the print monitors ...
8789 * Just reply with "Local Port", to keep NT happy
8790 * and I can use my nice printer checker.
8793 *returned=0;
8794 *needed=0;
8796 switch (level) {
8797 case 1:
8798 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8799 case 2:
8800 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8801 default:
8802 return WERR_UNKNOWN_LEVEL;
8806 /****************************************************************************
8807 ****************************************************************************/
8809 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8810 NT_PRINTER_INFO_LEVEL *ntprinter,
8811 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8812 uint32 *needed)
8814 int i=0;
8815 BOOL found=False;
8816 JOB_INFO_1 *info_1=NULL;
8817 WERROR result = WERR_OK;
8819 info_1=SMB_MALLOC_P(JOB_INFO_1);
8821 if (info_1 == NULL) {
8822 return WERR_NOMEM;
8825 for (i=0; i<count && found==False; i++) {
8826 if ((*queue)[i].job==(int)jobid)
8827 found=True;
8830 if (found==False) {
8831 SAFE_FREE(info_1);
8832 /* NT treats not found as bad param... yet another bad choice */
8833 return WERR_INVALID_PARAM;
8836 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8838 *needed += spoolss_size_job_info_1(info_1);
8840 if (*needed > offered) {
8841 result = WERR_INSUFFICIENT_BUFFER;
8842 goto out;
8845 if (!rpcbuf_alloc_size(buffer, *needed)) {
8846 result = WERR_NOMEM;
8847 goto out;
8850 smb_io_job_info_1("", buffer, info_1, 0);
8852 out:
8853 SAFE_FREE(info_1);
8855 return result;
8858 /****************************************************************************
8859 ****************************************************************************/
8861 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8862 NT_PRINTER_INFO_LEVEL *ntprinter,
8863 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8864 uint32 *needed)
8866 int i = 0;
8867 BOOL found = False;
8868 JOB_INFO_2 *info_2;
8869 WERROR result;
8870 DEVICEMODE *devmode = NULL;
8871 NT_DEVICEMODE *nt_devmode = NULL;
8873 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8874 return WERR_NOMEM;
8876 ZERO_STRUCTP(info_2);
8878 for ( i=0; i<count && found==False; i++ )
8880 if ((*queue)[i].job == (int)jobid)
8881 found = True;
8884 if ( !found ) {
8885 /* NT treats not found as bad param... yet another bad
8886 choice */
8887 result = WERR_INVALID_PARAM;
8888 goto done;
8892 * if the print job does not have a DEVMODE associated with it,
8893 * just use the one for the printer. A NULL devicemode is not
8894 * a failure condition
8897 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8898 devmode = construct_dev_mode(lp_const_servicename(snum));
8899 else {
8900 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8901 ZERO_STRUCTP( devmode );
8902 convert_nt_devicemode( devmode, nt_devmode );
8906 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8908 *needed += spoolss_size_job_info_2(info_2);
8910 if (*needed > offered) {
8911 result = WERR_INSUFFICIENT_BUFFER;
8912 goto done;
8915 if (!rpcbuf_alloc_size(buffer, *needed)) {
8916 result = WERR_NOMEM;
8917 goto done;
8920 smb_io_job_info_2("", buffer, info_2, 0);
8922 result = WERR_OK;
8924 done:
8925 /* Cleanup allocated memory */
8927 free_job_info_2(info_2); /* Also frees devmode */
8928 SAFE_FREE(info_2);
8930 return result;
8933 /****************************************************************************
8934 ****************************************************************************/
8936 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8938 POLICY_HND *handle = &q_u->handle;
8939 uint32 jobid = q_u->jobid;
8940 uint32 level = q_u->level;
8941 RPC_BUFFER *buffer = NULL;
8942 uint32 offered = q_u->offered;
8943 uint32 *needed = &r_u->needed;
8944 WERROR wstatus = WERR_OK;
8945 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8946 int snum;
8947 int count;
8948 print_queue_struct *queue = NULL;
8949 print_status_struct prt_status;
8951 /* that's an [in out] buffer */
8953 if (!q_u->buffer && (offered!=0)) {
8954 return WERR_INVALID_PARAM;
8957 rpcbuf_move(q_u->buffer, &r_u->buffer);
8958 buffer = r_u->buffer;
8960 DEBUG(5,("spoolss_getjob\n"));
8962 *needed = 0;
8964 if (!get_printer_snum(p, handle, &snum, NULL))
8965 return WERR_BADFID;
8967 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8968 if ( !W_ERROR_IS_OK(wstatus) )
8969 return wstatus;
8971 count = print_queue_status(snum, &queue, &prt_status);
8973 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8974 count, prt_status.status, prt_status.message));
8976 switch ( level ) {
8977 case 1:
8978 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8979 buffer, offered, needed);
8980 break;
8981 case 2:
8982 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8983 buffer, offered, needed);
8984 break;
8985 default:
8986 wstatus = WERR_UNKNOWN_LEVEL;
8987 break;
8990 SAFE_FREE(queue);
8991 free_a_printer( &ntprinter, 2 );
8993 return wstatus;
8996 /********************************************************************
8997 spoolss_getprinterdataex
8999 From MSDN documentation of GetPrinterDataEx: pass request
9000 to GetPrinterData if key is "PrinterDriverData".
9001 ********************************************************************/
9003 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9005 POLICY_HND *handle = &q_u->handle;
9006 uint32 in_size = q_u->size;
9007 uint32 *type = &r_u->type;
9008 uint32 *out_size = &r_u->size;
9009 uint8 **data = &r_u->data;
9010 uint32 *needed = &r_u->needed;
9011 fstring keyname, valuename;
9013 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9015 NT_PRINTER_INFO_LEVEL *printer = NULL;
9016 int snum = 0;
9017 WERROR status = WERR_OK;
9019 DEBUG(4,("_spoolss_getprinterdataex\n"));
9021 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9022 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9024 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9025 keyname, valuename));
9027 /* in case of problem, return some default values */
9029 *needed = 0;
9030 *type = 0;
9031 *out_size = in_size;
9033 if (!Printer) {
9034 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9035 status = WERR_BADFID;
9036 goto done;
9039 /* Is the handle to a printer or to the server? */
9041 if (Printer->printer_type == SPLHND_SERVER) {
9042 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9043 status = WERR_INVALID_PARAM;
9044 goto done;
9047 if ( !get_printer_snum(p,handle, &snum, NULL) )
9048 return WERR_BADFID;
9050 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9051 if ( !W_ERROR_IS_OK(status) )
9052 goto done;
9054 /* check to see if the keyname is valid */
9055 if ( !strlen(keyname) ) {
9056 status = WERR_INVALID_PARAM;
9057 goto done;
9060 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9061 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9062 free_a_printer( &printer, 2 );
9063 status = WERR_BADFILE;
9064 goto done;
9067 /* When given a new keyname, we should just create it */
9069 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9071 if (*needed > *out_size)
9072 status = WERR_MORE_DATA;
9074 done:
9075 if ( !W_ERROR_IS_OK(status) )
9077 DEBUG(5, ("error: allocating %d\n", *out_size));
9079 /* reply this param doesn't exist */
9081 if ( *out_size )
9083 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9084 status = WERR_NOMEM;
9085 goto done;
9088 else {
9089 *data = NULL;
9093 if ( printer )
9094 free_a_printer( &printer, 2 );
9096 return status;
9099 /********************************************************************
9100 * spoolss_setprinterdataex
9101 ********************************************************************/
9103 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9105 POLICY_HND *handle = &q_u->handle;
9106 uint32 type = q_u->type;
9107 uint8 *data = q_u->data;
9108 uint32 real_len = q_u->real_len;
9110 NT_PRINTER_INFO_LEVEL *printer = NULL;
9111 int snum = 0;
9112 WERROR status = WERR_OK;
9113 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9114 fstring valuename;
9115 fstring keyname;
9116 char *oid_string;
9118 DEBUG(4,("_spoolss_setprinterdataex\n"));
9120 /* From MSDN documentation of SetPrinterDataEx: pass request to
9121 SetPrinterData if key is "PrinterDriverData" */
9123 if (!Printer) {
9124 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9125 return WERR_BADFID;
9128 if ( Printer->printer_type == SPLHND_SERVER ) {
9129 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9130 return WERR_INVALID_PARAM;
9133 if ( !get_printer_snum(p,handle, &snum, NULL) )
9134 return WERR_BADFID;
9137 * Access check : NT returns "access denied" if you make a
9138 * SetPrinterData call without the necessary privildge.
9139 * we were originally returning OK if nothing changed
9140 * which made Win2k issue **a lot** of SetPrinterData
9141 * when connecting to a printer --jerry
9144 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9146 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9147 return WERR_ACCESS_DENIED;
9150 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9151 if (!W_ERROR_IS_OK(status))
9152 return status;
9154 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9155 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9157 /* check for OID in valuename */
9159 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9161 *oid_string = '\0';
9162 oid_string++;
9165 /* save the registry data */
9167 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9169 if ( W_ERROR_IS_OK(status) )
9171 /* save the OID if one was specified */
9172 if ( oid_string ) {
9173 fstrcat( keyname, "\\" );
9174 fstrcat( keyname, SPOOL_OID_KEY );
9177 * I'm not checking the status here on purpose. Don't know
9178 * if this is right, but I'm returning the status from the
9179 * previous set_printer_dataex() call. I have no idea if
9180 * this is right. --jerry
9183 set_printer_dataex( printer, keyname, valuename,
9184 REG_SZ, (uint8 *)oid_string,
9185 strlen(oid_string)+1 );
9188 status = mod_a_printer(printer, 2);
9191 free_a_printer(&printer, 2);
9193 return status;
9197 /********************************************************************
9198 * spoolss_deleteprinterdataex
9199 ********************************************************************/
9201 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9203 POLICY_HND *handle = &q_u->handle;
9204 UNISTR2 *value = &q_u->valuename;
9205 UNISTR2 *key = &q_u->keyname;
9207 NT_PRINTER_INFO_LEVEL *printer = NULL;
9208 int snum=0;
9209 WERROR status = WERR_OK;
9210 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9211 pstring valuename, keyname;
9213 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9215 if (!Printer) {
9216 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9217 return WERR_BADFID;
9220 if (!get_printer_snum(p, handle, &snum, NULL))
9221 return WERR_BADFID;
9223 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9224 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9225 return WERR_ACCESS_DENIED;
9228 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9229 if (!W_ERROR_IS_OK(status))
9230 return status;
9232 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9233 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9235 status = delete_printer_dataex( printer, keyname, valuename );
9237 if ( W_ERROR_IS_OK(status) )
9238 mod_a_printer( printer, 2 );
9240 free_a_printer(&printer, 2);
9242 return status;
9245 /********************************************************************
9246 * spoolss_enumprinterkey
9247 ********************************************************************/
9250 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9252 fstring key;
9253 fstring *keynames = NULL;
9254 uint16 *enumkeys = NULL;
9255 int num_keys;
9256 int printerkey_len;
9257 POLICY_HND *handle = &q_u->handle;
9258 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9259 NT_PRINTER_DATA *data;
9260 NT_PRINTER_INFO_LEVEL *printer = NULL;
9261 int snum = 0;
9262 WERROR status = WERR_BADFILE;
9265 DEBUG(4,("_spoolss_enumprinterkey\n"));
9267 if (!Printer) {
9268 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9269 return WERR_BADFID;
9272 if ( !get_printer_snum(p,handle, &snum, NULL) )
9273 return WERR_BADFID;
9275 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9276 if (!W_ERROR_IS_OK(status))
9277 return status;
9279 /* get the list of subkey names */
9281 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9282 data = printer->info_2->data;
9284 num_keys = get_printer_subkeys( data, key, &keynames );
9286 if ( num_keys == -1 ) {
9287 status = WERR_BADFILE;
9288 goto done;
9291 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9293 r_u->needed = printerkey_len*2;
9295 if ( q_u->size < r_u->needed ) {
9296 status = WERR_MORE_DATA;
9297 goto done;
9300 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9301 status = WERR_NOMEM;
9302 goto done;
9305 status = WERR_OK;
9307 if ( q_u->size < r_u->needed )
9308 status = WERR_MORE_DATA;
9310 done:
9311 free_a_printer( &printer, 2 );
9312 SAFE_FREE( keynames );
9314 return status;
9317 /********************************************************************
9318 * spoolss_deleteprinterkey
9319 ********************************************************************/
9321 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9323 POLICY_HND *handle = &q_u->handle;
9324 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9325 fstring key;
9326 NT_PRINTER_INFO_LEVEL *printer = NULL;
9327 int snum=0;
9328 WERROR status;
9330 DEBUG(5,("spoolss_deleteprinterkey\n"));
9332 if (!Printer) {
9333 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9334 return WERR_BADFID;
9337 /* if keyname == NULL, return error */
9339 if ( !q_u->keyname.buffer )
9340 return WERR_INVALID_PARAM;
9342 if (!get_printer_snum(p, handle, &snum, NULL))
9343 return WERR_BADFID;
9345 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9346 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9347 return WERR_ACCESS_DENIED;
9350 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9351 if (!W_ERROR_IS_OK(status))
9352 return status;
9354 /* delete the key and all subneys */
9356 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9358 status = delete_all_printer_data( printer->info_2, key );
9360 if ( W_ERROR_IS_OK(status) )
9361 status = mod_a_printer(printer, 2);
9363 free_a_printer( &printer, 2 );
9365 return status;
9369 /********************************************************************
9370 * spoolss_enumprinterdataex
9371 ********************************************************************/
9373 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9375 POLICY_HND *handle = &q_u->handle;
9376 uint32 in_size = q_u->size;
9377 uint32 num_entries,
9378 needed;
9379 NT_PRINTER_INFO_LEVEL *printer = NULL;
9380 PRINTER_ENUM_VALUES *enum_values = NULL;
9381 NT_PRINTER_DATA *p_data;
9382 fstring key;
9383 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9384 int snum;
9385 WERROR result;
9386 int key_index;
9387 int i;
9388 REGISTRY_VALUE *val;
9389 char *value_name;
9390 uint32 data_len;
9393 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9395 if (!Printer) {
9396 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9397 return WERR_BADFID;
9401 * first check for a keyname of NULL or "". Win2k seems to send
9402 * this a lot and we should send back WERR_INVALID_PARAM
9403 * no need to spend time looking up the printer in this case.
9404 * --jerry
9407 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9408 if ( !strlen(key) ) {
9409 result = WERR_INVALID_PARAM;
9410 goto done;
9413 /* get the printer off of disk */
9415 if (!get_printer_snum(p,handle, &snum, NULL))
9416 return WERR_BADFID;
9418 ZERO_STRUCT(printer);
9419 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9420 if (!W_ERROR_IS_OK(result))
9421 return result;
9423 /* now look for a match on the key name */
9425 p_data = printer->info_2->data;
9427 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9428 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9430 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9431 result = WERR_INVALID_PARAM;
9432 goto done;
9435 result = WERR_OK;
9436 needed = 0;
9438 /* allocate the memory for the array of pointers -- if necessary */
9440 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9441 if ( num_entries )
9443 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9445 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9446 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9447 result = WERR_NOMEM;
9448 goto done;
9451 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9455 * loop through all params and build the array to pass
9456 * back to the client
9459 for ( i=0; i<num_entries; i++ )
9461 /* lookup the registry value */
9463 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9464 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9466 /* copy the data */
9468 value_name = regval_name( val );
9469 init_unistr( &enum_values[i].valuename, value_name );
9470 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9471 enum_values[i].type = regval_type( val );
9473 data_len = regval_size( val );
9474 if ( data_len ) {
9475 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9477 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9478 data_len ));
9479 result = WERR_NOMEM;
9480 goto done;
9483 enum_values[i].data_len = data_len;
9485 /* keep track of the size of the array in bytes */
9487 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9490 /* housekeeping information in the reply */
9492 r_u->needed = needed;
9493 r_u->returned = num_entries;
9495 if (needed > in_size) {
9496 result = WERR_MORE_DATA;
9497 goto done;
9500 /* copy data into the reply */
9502 r_u->ctr.size = r_u->needed;
9503 r_u->ctr.size_of_array = r_u->returned;
9504 r_u->ctr.values = enum_values;
9508 done:
9509 if ( printer )
9510 free_a_printer(&printer, 2);
9512 return result;
9515 /****************************************************************************
9516 ****************************************************************************/
9518 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9520 init_unistr(&info->name, name);
9523 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9524 UNISTR2 *environment,
9525 RPC_BUFFER *buffer,
9526 uint32 offered,
9527 uint32 *needed)
9529 pstring path;
9530 pstring long_archi;
9531 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9532 WERROR result = WERR_OK;
9534 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9536 if (!get_short_archi(long_archi))
9537 return WERR_INVALID_ENVIRONMENT;
9539 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9540 return WERR_NOMEM;
9542 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9544 fill_printprocessordirectory_1(info, path);
9546 *needed += spoolss_size_printprocessordirectory_info_1(info);
9548 if (*needed > offered) {
9549 result = WERR_INSUFFICIENT_BUFFER;
9550 goto out;
9553 if (!rpcbuf_alloc_size(buffer, *needed)) {
9554 result = WERR_INSUFFICIENT_BUFFER;
9555 goto out;
9558 smb_io_printprocessordirectory_1("", buffer, info, 0);
9560 out:
9561 SAFE_FREE(info);
9563 return result;
9566 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9568 uint32 level = q_u->level;
9569 RPC_BUFFER *buffer = NULL;
9570 uint32 offered = q_u->offered;
9571 uint32 *needed = &r_u->needed;
9572 WERROR result;
9574 /* that's an [in out] buffer */
9576 if (!q_u->buffer && (offered!=0)) {
9577 return WERR_INVALID_PARAM;
9580 rpcbuf_move(q_u->buffer, &r_u->buffer);
9581 buffer = r_u->buffer;
9583 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9585 *needed=0;
9587 switch(level) {
9588 case 1:
9589 result = getprintprocessordirectory_level_1
9590 (&q_u->name, &q_u->environment, buffer, offered, needed);
9591 break;
9592 default:
9593 result = WERR_UNKNOWN_LEVEL;
9596 return result;
9599 /*******************************************************************
9600 Streams the monitor UI DLL name in UNICODE
9601 *******************************************************************/
9603 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9604 RPC_BUFFER *out, uint32 *needed )
9606 const char *dllname = "tcpmonui.dll";
9608 *needed = (strlen(dllname)+1) * 2;
9610 if ( rpcbuf_get_size(out) < *needed ) {
9611 return WERR_INSUFFICIENT_BUFFER;
9614 if ( !make_monitorui_buf( out, dllname ) ) {
9615 return WERR_NOMEM;
9618 return WERR_OK;
9621 /*******************************************************************
9622 Create a new TCP/IP port
9623 *******************************************************************/
9625 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9626 RPC_BUFFER *out, uint32 *needed )
9628 NT_PORT_DATA_1 port1;
9629 pstring device_uri;
9631 ZERO_STRUCT( port1 );
9633 /* convert to our internal port data structure */
9635 if ( !convert_port_data_1( &port1, in ) ) {
9636 return WERR_NOMEM;
9639 /* create the device URI and call the add_port_hook() */
9641 switch ( port1.protocol ) {
9642 case PORT_PROTOCOL_DIRECT:
9643 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9644 break;
9646 case PORT_PROTOCOL_LPR:
9647 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9648 break;
9650 default:
9651 return WERR_UNKNOWN_PORT;
9654 return add_port_hook( token, port1.name, device_uri );
9657 /*******************************************************************
9658 *******************************************************************/
9660 struct xcv_api_table xcvtcp_cmds[] = {
9661 { "MonitorUI", xcvtcp_monitorui },
9662 { "AddPort", xcvtcp_addport},
9663 { NULL, NULL }
9666 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9667 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9668 uint32 *needed )
9670 int i;
9672 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9674 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9675 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9676 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9679 return WERR_BADFUNC;
9682 /*******************************************************************
9683 *******************************************************************/
9684 #if 0 /* don't support management using the "Local Port" monitor */
9686 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9687 RPC_BUFFER *out, uint32 *needed )
9689 const char *dllname = "localui.dll";
9691 *needed = (strlen(dllname)+1) * 2;
9693 if ( rpcbuf_get_size(out) < *needed ) {
9694 return WERR_INSUFFICIENT_BUFFER;
9697 if ( !make_monitorui_buf( out, dllname )) {
9698 return WERR_NOMEM;
9701 return WERR_OK;
9704 /*******************************************************************
9705 *******************************************************************/
9707 struct xcv_api_table xcvlocal_cmds[] = {
9708 { "MonitorUI", xcvlocal_monitorui },
9709 { NULL, NULL }
9711 #else
9712 struct xcv_api_table xcvlocal_cmds[] = {
9713 { NULL, NULL }
9715 #endif
9719 /*******************************************************************
9720 *******************************************************************/
9722 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9723 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9724 uint32 *needed )
9726 int i;
9728 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9730 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9731 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9732 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9734 return WERR_BADFUNC;
9737 /*******************************************************************
9738 *******************************************************************/
9740 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9742 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9743 fstring command;
9745 if (!Printer) {
9746 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9747 return WERR_BADFID;
9750 /* Has to be a handle to the TCP/IP port monitor */
9752 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9753 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9754 return WERR_BADFID;
9757 /* requires administrative access to the server */
9759 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9760 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9761 return WERR_ACCESS_DENIED;
9764 /* Get the command name. There's numerous commands supported by the
9765 TCPMON interface. */
9767 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9768 q_u->dataname.uni_str_len*2, 0);
9770 /* Allocate the outgoing buffer */
9772 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9774 switch ( Printer->printer_type ) {
9775 case SPLHND_PORTMON_TCP:
9776 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9777 &q_u->indata, &r_u->outdata, &r_u->needed );
9778 case SPLHND_PORTMON_LOCAL:
9779 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9780 &q_u->indata, &r_u->outdata, &r_u->needed );
9783 return WERR_INVALID_PRINT_MONITOR;