libwbclient: add wbcGetGroups()
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob7788e763fa57644bb756a2e26db1e6cb944b1640
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 extern userdom_struct current_user_info;
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 struct table_node {
43 const char *long_archi;
44 const char *short_archi;
45 int version;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
54 int snum;
55 uint32 counter;
56 } counter_printer_0;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
71 const char *name;
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
76 /* translate between internal status numbers and NT status numbers */
77 static int nt_printj_status(int v)
79 switch (v) {
80 case LPQ_QUEUED:
81 return 0;
82 case LPQ_PAUSED:
83 return JOB_STATUS_PAUSED;
84 case LPQ_SPOOLING:
85 return JOB_STATUS_SPOOLING;
86 case LPQ_PRINTING:
87 return JOB_STATUS_PRINTING;
88 case LPQ_ERROR:
89 return JOB_STATUS_ERROR;
90 case LPQ_DELETING:
91 return JOB_STATUS_DELETING;
92 case LPQ_OFFLINE:
93 return JOB_STATUS_OFFLINE;
94 case LPQ_PAPEROUT:
95 return JOB_STATUS_PAPEROUT;
96 case LPQ_PRINTED:
97 return JOB_STATUS_PRINTED;
98 case LPQ_DELETED:
99 return JOB_STATUS_DELETED;
100 case LPQ_BLOCKED:
101 return JOB_STATUS_BLOCKED;
102 case LPQ_USER_INTERVENTION:
103 return JOB_STATUS_USER_INTERVENTION;
105 return 0;
108 static int nt_printq_status(int v)
110 switch (v) {
111 case LPQ_PAUSED:
112 return PRINTER_STATUS_PAUSED;
113 case LPQ_QUEUED:
114 case LPQ_SPOOLING:
115 case LPQ_PRINTING:
116 return 0;
118 return 0;
121 /****************************************************************************
122 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
123 ****************************************************************************/
125 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
127 if (*pp == NULL)
128 return;
130 SAFE_FREE((*pp)->ctr.type);
131 SAFE_FREE(*pp);
134 /***************************************************************************
135 Disconnect from the client
136 ****************************************************************************/
138 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
140 WERROR result;
143 * Tell the specific printing tdb we no longer want messages for this printer
144 * by deregistering our PID.
147 if (!print_notify_deregister_pid(snum))
148 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
150 /* weird if the test succeds !!! */
151 if (smb_connections==0) {
152 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
153 return;
156 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe,
157 talloc_tos(),
158 handle);
160 if (!W_ERROR_IS_OK(result))
161 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
162 dos_errstr(result)));
164 /* if it's the last connection, deconnect the IPC$ share */
165 if (smb_connections==1) {
167 cli_shutdown( notify_cli_pipe->cli );
168 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
170 messaging_deregister(smbd_messaging_context(),
171 MSG_PRINTER_NOTIFY2, NULL);
173 /* Tell the connections db we're no longer interested in
174 * printer notify messages. */
176 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
179 smb_connections--;
182 /****************************************************************************
183 Functions to free a printer entry datastruct.
184 ****************************************************************************/
186 static void free_printer_entry(void *ptr)
188 Printer_entry *Printer = (Printer_entry *)ptr;
190 if (Printer->notify.client_connected==True) {
191 int snum = -1;
193 if ( Printer->printer_type == SPLHND_SERVER) {
194 snum = -1;
195 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
196 } else if (Printer->printer_type == SPLHND_PRINTER) {
197 snum = print_queue_snum(Printer->sharename);
198 if (snum != -1)
199 srv_spoolss_replycloseprinter(snum,
200 &Printer->notify.client_hnd);
204 Printer->notify.flags=0;
205 Printer->notify.options=0;
206 Printer->notify.localmachine[0]='\0';
207 Printer->notify.printerlocal=0;
208 free_spool_notify_option(&Printer->notify.option);
209 Printer->notify.option=NULL;
210 Printer->notify.client_connected=False;
212 free_nt_devicemode( &Printer->nt_devmode );
213 free_a_printer( &Printer->printer_info, 2 );
215 talloc_destroy( Printer->ctx );
217 /* Remove from the internal list. */
218 DLIST_REMOVE(printers_list, Printer);
220 SAFE_FREE(Printer);
223 /****************************************************************************
224 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
225 ****************************************************************************/
227 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
229 SPOOL_NOTIFY_OPTION *new_sp = NULL;
231 if (!sp)
232 return NULL;
234 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
235 if (!new_sp)
236 return NULL;
238 *new_sp = *sp;
240 if (sp->ctr.count) {
241 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
243 if (!new_sp->ctr.type) {
244 SAFE_FREE(new_sp);
245 return NULL;
249 return new_sp;
252 /****************************************************************************
253 find printer index by handle
254 ****************************************************************************/
256 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *find_printer = NULL;
260 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
261 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
262 return NULL;
265 return find_printer;
268 /****************************************************************************
269 Close printer index by handle.
270 ****************************************************************************/
272 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
274 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
276 if (!Printer) {
277 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
278 return False;
281 close_policy_hnd(p, hnd);
283 return True;
286 /****************************************************************************
287 Delete a printer given a handle.
288 ****************************************************************************/
290 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
292 char *cmd = lp_deleteprinter_cmd();
293 char *command = NULL;
294 int ret;
295 SE_PRIV se_printop = SE_PRINT_OPERATOR;
296 bool is_print_op = False;
298 /* can't fail if we don't try */
300 if ( !*cmd )
301 return WERR_OK;
303 command = talloc_asprintf(ctx,
304 "%s \"%s\"",
305 cmd, sharename);
306 if (!command) {
307 return WERR_NOMEM;
309 if ( token )
310 is_print_op = user_has_privileges( token, &se_printop );
312 DEBUG(10,("Running [%s]\n", command));
314 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
316 if ( is_print_op )
317 become_root();
319 if ( (ret = smbrun(command, NULL)) == 0 ) {
320 /* Tell everyone we updated smb.conf. */
321 message_send_all(smbd_messaging_context(),
322 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
325 if ( is_print_op )
326 unbecome_root();
328 /********** END SePrintOperatorPrivlege BLOCK **********/
330 DEBUGADD(10,("returned [%d]\n", ret));
332 TALLOC_FREE(command);
334 if (ret != 0)
335 return WERR_BADFID; /* What to return here? */
337 /* go ahead and re-read the services immediately */
338 reload_services( False );
340 if ( lp_servicenumber( sharename ) < 0 )
341 return WERR_ACCESS_DENIED;
343 return WERR_OK;
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
354 if (!Printer) {
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
356 return WERR_BADFID;
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
363 * JRA.
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
371 /* this does not need a become root since the access check has been
372 done on the handle already */
374 if (del_a_printer( Printer->sharename ) != 0) {
375 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
376 return WERR_BADFID;
379 return delete_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, Printer->sharename );
382 /****************************************************************************
383 Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
386 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
387 struct share_params **params)
389 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
391 if (!Printer) {
392 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
393 return False;
396 switch (Printer->printer_type) {
397 case SPLHND_PRINTER:
398 DEBUG(4,("short name:%s\n", Printer->sharename));
399 *number = print_queue_snum(Printer->sharename);
400 return (*number != -1);
401 case SPLHND_SERVER:
402 return False;
403 default:
404 return False;
408 /****************************************************************************
409 Set printer handle type.
410 Check if it's \\server or \\server\printer
411 ****************************************************************************/
413 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
415 DEBUG(3,("Setting printer type=%s\n", handlename));
417 if ( strlen(handlename) < 3 ) {
418 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
419 return False;
422 /* it's a print server */
423 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
424 DEBUGADD(4,("Printer is a print server\n"));
425 Printer->printer_type = SPLHND_SERVER;
427 /* it's a printer (set_printer_hnd_name() will handle port monitors */
428 else {
429 DEBUGADD(4,("Printer is a printer\n"));
430 Printer->printer_type = SPLHND_PRINTER;
433 return True;
436 /****************************************************************************
437 Set printer handle name.. Accept names like \\server, \\server\printer,
438 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
439 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
440 XcvDataPort() interface.
441 ****************************************************************************/
443 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
445 int snum;
446 int n_services=lp_numservices();
447 char *aprinter, *printername;
448 const char *servername;
449 fstring sname;
450 bool found=False;
451 NT_PRINTER_INFO_LEVEL *printer = NULL;
452 WERROR result;
454 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
456 aprinter = handlename;
457 if ( *handlename == '\\' ) {
458 servername = handlename + 2;
459 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
460 *aprinter = '\0';
461 aprinter++;
464 else {
465 servername = "";
468 /* save the servername to fill in replies on this handle */
470 if ( !is_myname_or_ipaddr( servername ) )
471 return False;
473 fstrcpy( Printer->servername, servername );
475 if ( Printer->printer_type == SPLHND_SERVER )
476 return True;
478 if ( Printer->printer_type != SPLHND_PRINTER )
479 return False;
481 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
483 /* check for the Port Monitor Interface */
485 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
486 Printer->printer_type = SPLHND_PORTMON_TCP;
487 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
488 found = True;
490 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
491 Printer->printer_type = SPLHND_PORTMON_LOCAL;
492 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
493 found = True;
496 /* Search all sharenames first as this is easier than pulling
497 the printer_info_2 off of disk. Don't use find_service() since
498 that calls out to map_username() */
500 /* do another loop to look for printernames */
502 for (snum=0; !found && snum<n_services; snum++) {
504 /* no point going on if this is not a printer */
506 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
507 continue;
509 fstrcpy(sname, lp_servicename(snum));
510 if ( strequal( aprinter, sname ) ) {
511 found = True;
512 break;
515 /* no point looking up the printer object if
516 we aren't allowing printername != sharename */
518 if ( lp_force_printername(snum) )
519 continue;
521 fstrcpy(sname, lp_servicename(snum));
523 printer = NULL;
525 /* This call doesn't fill in the location or comment from
526 * a CUPS server for efficiency with large numbers of printers.
527 * JRA.
530 result = get_a_printer_search( NULL, &printer, 2, sname );
531 if ( !W_ERROR_IS_OK(result) ) {
532 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
533 sname, dos_errstr(result)));
534 continue;
537 /* printername is always returned as \\server\printername */
538 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
539 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
540 printer->info_2->printername));
541 free_a_printer( &printer, 2);
542 continue;
545 printername++;
547 if ( strequal(printername, aprinter) ) {
548 free_a_printer( &printer, 2);
549 found = True;
550 break;
553 DEBUGADD(10, ("printername: %s\n", printername));
555 free_a_printer( &printer, 2);
558 free_a_printer( &printer, 2);
560 if ( !found ) {
561 DEBUGADD(4,("Printer not found\n"));
562 return False;
565 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
567 fstrcpy(Printer->sharename, sname);
569 return True;
572 /****************************************************************************
573 Find first available printer slot. creates a printer handle for you.
574 ****************************************************************************/
576 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
578 Printer_entry *new_printer;
580 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
582 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
583 return False;
585 ZERO_STRUCTP(new_printer);
587 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
588 SAFE_FREE(new_printer);
589 return False;
592 /* Add to the internal list. */
593 DLIST_ADD(printers_list, new_printer);
595 new_printer->notify.option=NULL;
597 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
598 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
599 close_printer_handle(p, hnd);
600 return False;
603 if (!set_printer_hnd_printertype(new_printer, name)) {
604 close_printer_handle(p, hnd);
605 return False;
608 if (!set_printer_hnd_name(new_printer, name)) {
609 close_printer_handle(p, hnd);
610 return False;
613 new_printer->access_granted = access_granted;
615 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
617 return True;
620 /***************************************************************************
621 check to see if the client motify handle is monitoring the notification
622 given by (notify_type, notify_field).
623 **************************************************************************/
625 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
626 uint16 notify_field)
628 return True;
631 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
632 uint16 notify_field)
634 SPOOL_NOTIFY_OPTION *option = p->notify.option;
635 uint32 i, j;
638 * Flags should always be zero when the change notify
639 * is registered by the client's spooler. A user Win32 app
640 * might use the flags though instead of the NOTIFY_OPTION_INFO
641 * --jerry
644 if (!option) {
645 return False;
648 if (p->notify.flags)
649 return is_monitoring_event_flags(
650 p->notify.flags, notify_type, notify_field);
652 for (i = 0; i < option->count; i++) {
654 /* Check match for notify_type */
656 if (option->ctr.type[i].type != notify_type)
657 continue;
659 /* Check match for field */
661 for (j = 0; j < option->ctr.type[i].count; j++) {
662 if (option->ctr.type[i].fields[j] == notify_field) {
663 return True;
668 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
669 p->servername, p->sharename, notify_type, notify_field));
671 return False;
674 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
676 static void notify_one_value(struct spoolss_notify_msg *msg,
677 SPOOL_NOTIFY_INFO_DATA *data,
678 TALLOC_CTX *mem_ctx)
680 data->notify_data.value[0] = msg->notify.value[0];
681 data->notify_data.value[1] = 0;
684 static void notify_string(struct spoolss_notify_msg *msg,
685 SPOOL_NOTIFY_INFO_DATA *data,
686 TALLOC_CTX *mem_ctx)
688 UNISTR2 unistr;
690 /* The length of the message includes the trailing \0 */
692 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
694 data->notify_data.data.length = msg->len * 2;
695 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
697 if (!data->notify_data.data.string) {
698 data->notify_data.data.length = 0;
699 return;
702 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
705 static void notify_system_time(struct spoolss_notify_msg *msg,
706 SPOOL_NOTIFY_INFO_DATA *data,
707 TALLOC_CTX *mem_ctx)
709 SYSTEMTIME systime;
710 prs_struct ps;
712 if (msg->len != sizeof(time_t)) {
713 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
714 msg->len));
715 return;
718 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
719 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
720 return;
723 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
724 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
725 prs_mem_free(&ps);
726 return;
729 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
730 prs_mem_free(&ps);
731 return;
734 data->notify_data.data.length = prs_offset(&ps);
735 if (prs_offset(&ps)) {
736 data->notify_data.data.string = (uint16 *)
737 TALLOC(mem_ctx, prs_offset(&ps));
738 if (!data->notify_data.data.string) {
739 prs_mem_free(&ps);
740 return;
742 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
743 } else {
744 data->notify_data.data.string = NULL;
747 prs_mem_free(&ps);
750 struct notify2_message_table {
751 const char *name;
752 void (*fn)(struct spoolss_notify_msg *msg,
753 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
756 static struct notify2_message_table printer_notify_table[] = {
757 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
758 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
759 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
760 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
761 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
762 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
763 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
764 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
765 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
766 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
767 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
768 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
769 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
770 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
771 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
772 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
773 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
774 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
775 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
778 static struct notify2_message_table job_notify_table[] = {
779 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
780 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
781 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
782 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
783 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
784 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
785 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
786 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
787 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
788 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
789 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
790 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
791 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
792 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
793 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
794 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
795 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
796 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
797 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
798 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
799 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
800 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
801 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
802 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
806 /***********************************************************************
807 Allocate talloc context for container object
808 **********************************************************************/
810 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 if ( !ctr )
813 return;
815 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817 return;
820 /***********************************************************************
821 release all allocated memory and zero out structure
822 **********************************************************************/
824 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 if ( !ctr )
827 return;
829 if ( ctr->ctx )
830 talloc_destroy(ctr->ctx);
832 ZERO_STRUCTP(ctr);
834 return;
837 /***********************************************************************
838 **********************************************************************/
840 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 if ( !ctr )
843 return NULL;
845 return ctr->ctx;
848 /***********************************************************************
849 **********************************************************************/
851 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
853 if ( !ctr || !ctr->msg_groups )
854 return NULL;
856 if ( idx >= ctr->num_groups )
857 return NULL;
859 return &ctr->msg_groups[idx];
863 /***********************************************************************
864 How many groups of change messages do we have ?
865 **********************************************************************/
867 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 if ( !ctr )
870 return 0;
872 return ctr->num_groups;
875 /***********************************************************************
876 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
877 **********************************************************************/
879 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
882 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
883 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
884 int i, new_slot;
886 if ( !ctr || !msg )
887 return 0;
889 /* loop over all groups looking for a matching printer name */
891 for ( i=0; i<ctr->num_groups; i++ ) {
892 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
893 break;
896 /* add a new group? */
898 if ( i == ctr->num_groups ) {
899 ctr->num_groups++;
901 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
902 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
903 return 0;
905 ctr->msg_groups = groups;
907 /* clear the new entry and set the printer name */
909 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
910 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
913 /* add the change messages; 'i' is the correct index now regardless */
915 msg_grp = &ctr->msg_groups[i];
917 msg_grp->num_msgs++;
919 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
921 return 0;
923 msg_grp->msgs = msg_list;
925 new_slot = msg_grp->num_msgs-1;
926 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928 /* need to allocate own copy of data */
930 if ( msg->len != 0 )
931 msg_grp->msgs[new_slot].notify.data = (char *)
932 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934 return ctr->num_groups;
937 /***********************************************************************
938 Send a change notication message on all handles which have a call
939 back registered
940 **********************************************************************/
942 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
944 Printer_entry *p;
945 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
946 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
947 SPOOLSS_NOTIFY_MSG *messages;
948 int sending_msg_count;
950 if ( !msg_group ) {
951 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
952 return;
955 messages = msg_group->msgs;
957 if ( !messages ) {
958 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
959 return;
962 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964 /* loop over all printers */
966 for (p = printers_list; p; p = p->next) {
967 SPOOL_NOTIFY_INFO_DATA *data;
968 uint32 data_len = 0;
969 uint32 id;
970 int i;
972 /* Is there notification on this handle? */
974 if ( !p->notify.client_connected )
975 continue;
977 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979 /* For this printer? Print servers always receive
980 notifications. */
982 if ( ( p->printer_type == SPLHND_PRINTER ) &&
983 ( !strequal(msg_group->printername, p->sharename) ) )
984 continue;
986 DEBUG(10,("Our printer\n"));
988 /* allocate the max entries possible */
990 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
991 if (!data) {
992 return;
995 ZERO_STRUCTP(data);
997 /* build the array of change notifications */
999 sending_msg_count = 0;
1001 for ( i=0; i<msg_group->num_msgs; i++ ) {
1002 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1004 /* Are we monitoring this event? */
1006 if (!is_monitoring_event(p, msg->type, msg->field))
1007 continue;
1009 sending_msg_count++;
1012 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1013 msg->type, msg->field, p->sharename));
1016 * if the is a printer notification handle and not a job notification
1017 * type, then set the id to 0. Other wise just use what was specified
1018 * in the message.
1020 * When registering change notification on a print server handle
1021 * we always need to send back the id (snum) matching the printer
1022 * for which the change took place. For change notify registered
1023 * on a printer handle, this does not matter and the id should be 0.
1025 * --jerry
1028 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1029 id = 0;
1030 else
1031 id = msg->id;
1034 /* Convert unix jobid to smb jobid */
1036 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1037 id = sysjob_to_jobid(msg->id);
1039 if (id == -1) {
1040 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1041 goto done;
1045 construct_info_data( &data[data_len], msg->type, msg->field, id );
1047 switch(msg->type) {
1048 case PRINTER_NOTIFY_TYPE:
1049 if ( printer_notify_table[msg->field].fn )
1050 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1051 break;
1053 case JOB_NOTIFY_TYPE:
1054 if ( job_notify_table[msg->field].fn )
1055 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1056 break;
1058 default:
1059 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1060 goto done;
1063 data_len++;
1066 if ( sending_msg_count ) {
1067 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1068 data_len, data, p->notify.change, 0 );
1072 done:
1073 DEBUG(8,("send_notify2_changes: Exit...\n"));
1074 return;
1077 /***********************************************************************
1078 **********************************************************************/
1080 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1083 uint32 tv_sec, tv_usec;
1084 size_t offset = 0;
1086 /* Unpack message */
1088 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1089 msg->printer);
1091 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1092 &tv_sec, &tv_usec,
1093 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1095 if (msg->len == 0)
1096 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1097 &msg->notify.value[0], &msg->notify.value[1]);
1098 else
1099 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1100 &msg->len, &msg->notify.data);
1102 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1103 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1105 tv->tv_sec = tv_sec;
1106 tv->tv_usec = tv_usec;
1108 if (msg->len == 0)
1109 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1110 msg->notify.value[1]));
1111 else
1112 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1114 return True;
1117 /********************************************************************
1118 Receive a notify2 message list
1119 ********************************************************************/
1121 static void receive_notify2_message_list(struct messaging_context *msg,
1122 void *private_data,
1123 uint32_t msg_type,
1124 struct server_id server_id,
1125 DATA_BLOB *data)
1127 size_t msg_count, i;
1128 char *buf = (char *)data->data;
1129 char *msg_ptr;
1130 size_t msg_len;
1131 SPOOLSS_NOTIFY_MSG notify;
1132 SPOOLSS_NOTIFY_MSG_CTR messages;
1133 int num_groups;
1135 if (data->length < 4) {
1136 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1137 return;
1140 msg_count = IVAL(buf, 0);
1141 msg_ptr = buf + 4;
1143 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1145 if (msg_count == 0) {
1146 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1147 return;
1150 /* initialize the container */
1152 ZERO_STRUCT( messages );
1153 notify_msg_ctr_init( &messages );
1156 * build message groups for each printer identified
1157 * in a change_notify msg. Remember that a PCN message
1158 * includes the handle returned for the srv_spoolss_replyopenprinter()
1159 * call. Therefore messages are grouped according to printer handle.
1162 for ( i=0; i<msg_count; i++ ) {
1163 struct timeval msg_tv;
1165 if (msg_ptr + 4 - buf > data->length) {
1166 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1167 return;
1170 msg_len = IVAL(msg_ptr,0);
1171 msg_ptr += 4;
1173 if (msg_ptr + msg_len - buf > data->length) {
1174 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1175 return;
1178 /* unpack messages */
1180 ZERO_STRUCT( notify );
1181 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1182 msg_ptr += msg_len;
1184 /* add to correct list in container */
1186 notify_msg_ctr_addmsg( &messages, &notify );
1188 /* free memory that might have been allocated by notify2_unpack_msg() */
1190 if ( notify.len != 0 )
1191 SAFE_FREE( notify.notify.data );
1194 /* process each group of messages */
1196 num_groups = notify_msg_ctr_numgroups( &messages );
1197 for ( i=0; i<num_groups; i++ )
1198 send_notify2_changes( &messages, i );
1201 /* cleanup */
1203 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1205 notify_msg_ctr_destroy( &messages );
1207 return;
1210 /********************************************************************
1211 Send a message to ourself about new driver being installed
1212 so we can upgrade the information for each printer bound to this
1213 driver
1214 ********************************************************************/
1216 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1218 int len = strlen(drivername);
1220 if (!len)
1221 return False;
1223 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1224 drivername));
1226 messaging_send_buf(smbd_messaging_context(), procid_self(),
1227 MSG_PRINTER_DRVUPGRADE,
1228 (uint8 *)drivername, len+1);
1230 return True;
1233 /**********************************************************************
1234 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1235 over all printers, upgrading ones as necessary
1236 **********************************************************************/
1238 void do_drv_upgrade_printer(struct messaging_context *msg,
1239 void *private_data,
1240 uint32_t msg_type,
1241 struct server_id server_id,
1242 DATA_BLOB *data)
1244 fstring drivername;
1245 int snum;
1246 int n_services = lp_numservices();
1247 size_t len;
1249 len = MIN(data->length,sizeof(drivername)-1);
1250 strncpy(drivername, (const char *)data->data, len);
1252 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1254 /* Iterate the printer list */
1256 for (snum=0; snum<n_services; snum++)
1258 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1260 WERROR result;
1261 NT_PRINTER_INFO_LEVEL *printer = NULL;
1263 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1264 if (!W_ERROR_IS_OK(result))
1265 continue;
1267 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1269 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1271 /* all we care about currently is the change_id */
1273 result = mod_a_printer(printer, 2);
1274 if (!W_ERROR_IS_OK(result)) {
1275 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1276 dos_errstr(result)));
1280 free_a_printer(&printer, 2);
1284 /* all done */
1287 /********************************************************************
1288 Update the cache for all printq's with a registered client
1289 connection
1290 ********************************************************************/
1292 void update_monitored_printq_cache( void )
1294 Printer_entry *printer = printers_list;
1295 int snum;
1297 /* loop through all printers and update the cache where
1298 client_connected == True */
1299 while ( printer )
1301 if ( (printer->printer_type == SPLHND_PRINTER)
1302 && printer->notify.client_connected )
1304 snum = print_queue_snum(printer->sharename);
1305 print_queue_status( snum, NULL, NULL );
1308 printer = printer->next;
1311 return;
1313 /********************************************************************
1314 Send a message to ourself about new driver being installed
1315 so we can upgrade the information for each printer bound to this
1316 driver
1317 ********************************************************************/
1319 static bool srv_spoolss_reset_printerdata(char* drivername)
1321 int len = strlen(drivername);
1323 if (!len)
1324 return False;
1326 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1327 drivername));
1329 messaging_send_buf(smbd_messaging_context(), procid_self(),
1330 MSG_PRINTERDATA_INIT_RESET,
1331 (uint8 *)drivername, len+1);
1333 return True;
1336 /**********************************************************************
1337 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1338 over all printers, resetting printer data as neessary
1339 **********************************************************************/
1341 void reset_all_printerdata(struct messaging_context *msg,
1342 void *private_data,
1343 uint32_t msg_type,
1344 struct server_id server_id,
1345 DATA_BLOB *data)
1347 fstring drivername;
1348 int snum;
1349 int n_services = lp_numservices();
1350 size_t len;
1352 len = MIN( data->length, sizeof(drivername)-1 );
1353 strncpy( drivername, (const char *)data->data, len );
1355 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1357 /* Iterate the printer list */
1359 for ( snum=0; snum<n_services; snum++ )
1361 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1363 WERROR result;
1364 NT_PRINTER_INFO_LEVEL *printer = NULL;
1366 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1367 if ( !W_ERROR_IS_OK(result) )
1368 continue;
1371 * if the printer is bound to the driver,
1372 * then reset to the new driver initdata
1375 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1377 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1379 if ( !set_driver_init(printer, 2) ) {
1380 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1381 printer->info_2->printername, printer->info_2->drivername));
1384 result = mod_a_printer( printer, 2 );
1385 if ( !W_ERROR_IS_OK(result) ) {
1386 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1387 get_dos_error_msg(result)));
1391 free_a_printer( &printer, 2 );
1395 /* all done */
1397 return;
1400 /********************************************************************
1401 Copy routines used by convert_to_openprinterex()
1402 *******************************************************************/
1404 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1406 DEVICEMODE *d;
1407 int len;
1409 if (!devmode)
1410 return NULL;
1412 DEBUG (8,("dup_devmode\n"));
1414 /* bulk copy first */
1416 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1417 if (!d)
1418 return NULL;
1420 /* dup the pointer members separately */
1422 len = unistrlen(devmode->devicename.buffer);
1423 if (len != -1) {
1424 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1425 if (!d->devicename.buffer) {
1426 return NULL;
1428 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1429 return NULL;
1433 len = unistrlen(devmode->formname.buffer);
1434 if (len != -1) {
1435 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1436 if (!d->formname.buffer) {
1437 return NULL;
1439 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1440 return NULL;
1443 if (devmode->driverextra) {
1444 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1445 devmode->driverextra);
1446 if (!d->dev_private) {
1447 return NULL;
1449 } else {
1450 d->dev_private = NULL;
1452 return d;
1455 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1457 if (!new_ctr || !ctr)
1458 return;
1460 DEBUG(8,("copy_devmode_ctr\n"));
1462 new_ctr->size = ctr->size;
1463 new_ctr->devmode_ptr = ctr->devmode_ptr;
1465 if(ctr->devmode_ptr)
1466 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1469 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1471 if (!new_def || !def)
1472 return;
1474 DEBUG(8,("copy_printer_defaults\n"));
1476 new_def->datatype_ptr = def->datatype_ptr;
1478 if (def->datatype_ptr)
1479 copy_unistr2(&new_def->datatype, &def->datatype);
1481 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1483 new_def->access_required = def->access_required;
1486 /********************************************************************
1487 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1488 * SPOOL_Q_OPEN_PRINTER_EX structure
1489 ********************************************************************/
1491 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1493 if (!q_u_ex || !q_u)
1494 return WERR_OK;
1496 DEBUG(8,("convert_to_openprinterex\n"));
1498 if ( q_u->printername ) {
1499 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1500 if (q_u_ex->printername == NULL)
1501 return WERR_NOMEM;
1502 copy_unistr2(q_u_ex->printername, q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1507 return WERR_OK;
1510 /********************************************************************
1511 * spoolss_open_printer
1513 * called from the spoolss dispatcher
1514 ********************************************************************/
1516 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1518 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1519 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1521 if (!q_u || !r_u)
1522 return WERR_NOMEM;
1524 ZERO_STRUCT(q_u_ex);
1525 ZERO_STRUCT(r_u_ex);
1527 /* convert the OpenPrinter() call to OpenPrinterEx() */
1529 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1530 if (!W_ERROR_IS_OK(r_u_ex.status))
1531 return r_u_ex.status;
1533 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1535 /* convert back to OpenPrinter() */
1537 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1539 if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1540 /* OpenPrinterEx returns this for a bad
1541 * printer name. We must return WERR_INVALID_PRINTER_NAME
1542 * instead.
1544 r_u->status = WERR_INVALID_PRINTER_NAME;
1546 return r_u->status;
1549 /********************************************************************
1550 ********************************************************************/
1552 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1554 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1555 POLICY_HND *handle = &r_u->handle;
1557 fstring name;
1558 int snum;
1559 Printer_entry *Printer=NULL;
1561 if (!q_u->printername) {
1562 return WERR_INVALID_PARAM;
1565 /* some sanity check because you can open a printer or a print server */
1566 /* aka: \\server\printer or \\server */
1568 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1570 DEBUGADD(3,("checking name: %s\n",name));
1572 if (!open_printer_hnd(p, handle, name, 0)) {
1573 return WERR_INVALID_PARAM;
1576 Printer=find_printer_index_by_hnd(p, handle);
1577 if ( !Printer ) {
1578 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1579 "handle we created for printer %s\n", name ));
1580 close_printer_handle(p,handle);
1581 return WERR_INVALID_PARAM;
1585 * First case: the user is opening the print server:
1587 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1588 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1590 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1591 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1592 * or if the user is listed in the smb.conf printer admin parameter.
1594 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1595 * client view printer folder, but does not show the MSAPW.
1597 * Note: this test needs code to check access rights here too. Jeremy
1598 * could you look at this?
1600 * Second case: the user is opening a printer:
1601 * NT doesn't let us connect to a printer if the connecting user
1602 * doesn't have print permission.
1604 * Third case: user is opening a Port Monitor
1605 * access checks same as opening a handle to the print server.
1608 switch (Printer->printer_type )
1610 case SPLHND_SERVER:
1611 case SPLHND_PORTMON_TCP:
1612 case SPLHND_PORTMON_LOCAL:
1613 /* Printserver handles use global struct... */
1615 snum = -1;
1617 /* Map standard access rights to object specific access rights */
1619 se_map_standard(&printer_default->access_required,
1620 &printserver_std_mapping);
1622 /* Deny any object specific bits that don't apply to print
1623 servers (i.e printer and job specific bits) */
1625 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1627 if (printer_default->access_required &
1628 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1629 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1630 close_printer_handle(p, handle);
1631 return WERR_ACCESS_DENIED;
1634 /* Allow admin access */
1636 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1638 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1640 if (!lp_ms_add_printer_wizard()) {
1641 close_printer_handle(p, handle);
1642 return WERR_ACCESS_DENIED;
1645 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1646 and not a printer admin, then fail */
1648 if ((p->pipe_user.ut.uid != 0) &&
1649 !user_has_privileges(p->pipe_user.nt_user_token,
1650 &se_printop ) &&
1651 !token_contains_name_in_list(
1652 uidtoname(p->pipe_user.ut.uid), NULL,
1653 p->pipe_user.nt_user_token,
1654 lp_printer_admin(snum))) {
1655 close_printer_handle(p, handle);
1656 return WERR_ACCESS_DENIED;
1659 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1661 else
1663 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1666 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1667 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1669 /* We fall through to return WERR_OK */
1670 break;
1672 case SPLHND_PRINTER:
1673 /* NT doesn't let us connect to a printer if the connecting user
1674 doesn't have print permission. */
1676 if (!get_printer_snum(p, handle, &snum, NULL)) {
1677 close_printer_handle(p, handle);
1678 return WERR_BADFID;
1681 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1683 /* map an empty access mask to the minimum access mask */
1684 if (printer_default->access_required == 0x0)
1685 printer_default->access_required = PRINTER_ACCESS_USE;
1688 * If we are not serving the printer driver for this printer,
1689 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1690 * will keep NT clients happy --jerry
1693 if (lp_use_client_driver(snum)
1694 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1696 printer_default->access_required = PRINTER_ACCESS_USE;
1699 /* check smb.conf parameters and the the sec_desc */
1701 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1702 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1703 return WERR_ACCESS_DENIED;
1706 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1707 p->pipe_user.nt_user_token, snum) ||
1708 !print_access_check(&p->pipe_user, snum,
1709 printer_default->access_required)) {
1710 DEBUG(3, ("access DENIED for printer open\n"));
1711 close_printer_handle(p, handle);
1712 return WERR_ACCESS_DENIED;
1715 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1716 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1717 close_printer_handle(p, handle);
1718 return WERR_ACCESS_DENIED;
1721 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1722 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1723 else
1724 printer_default->access_required = PRINTER_ACCESS_USE;
1726 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1727 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1729 break;
1731 default:
1732 /* sanity check to prevent programmer error */
1733 return WERR_BADFID;
1736 Printer->access_granted = printer_default->access_required;
1739 * If the client sent a devmode in the OpenPrinter() call, then
1740 * save it here in case we get a job submission on this handle
1743 if ( (Printer->printer_type != SPLHND_SERVER)
1744 && q_u->printer_default.devmode_cont.devmode_ptr )
1746 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1747 &Printer->nt_devmode );
1750 #if 0 /* JERRY -- I'm doubtful this is really effective */
1751 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1752 optimization in Windows 2000 clients --jerry */
1754 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1755 && (RA_WIN2K == get_remote_arch()) )
1757 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1758 sys_usleep( 500000 );
1760 #endif
1762 return WERR_OK;
1765 /****************************************************************************
1766 ****************************************************************************/
1768 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1769 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1771 bool ret;
1773 switch (level) {
1774 case 2:
1775 /* allocate memory if needed. Messy because
1776 convert_printer_info is used to update an existing
1777 printer or build a new one */
1779 if ( !printer->info_2 ) {
1780 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1781 if ( !printer->info_2 ) {
1782 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1783 return False;
1787 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1788 printer->info_2->setuptime = time(NULL);
1790 return ret;
1793 return False;
1796 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1797 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1799 bool result = True;
1801 switch (level) {
1802 case 3:
1803 printer->info_3=NULL;
1804 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1805 result = False;
1806 break;
1807 case 6:
1808 printer->info_6=NULL;
1809 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1810 result = False;
1811 break;
1812 default:
1813 break;
1816 return result;
1819 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1820 NT_DEVICEMODE **pp_nt_devmode)
1822 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1825 * Ensure nt_devmode is a valid pointer
1826 * as we will be overwriting it.
1829 if (nt_devmode == NULL) {
1830 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1831 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1832 return False;
1835 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1836 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1838 nt_devmode->specversion=devmode->specversion;
1839 nt_devmode->driverversion=devmode->driverversion;
1840 nt_devmode->size=devmode->size;
1841 nt_devmode->fields=devmode->fields;
1842 nt_devmode->orientation=devmode->orientation;
1843 nt_devmode->papersize=devmode->papersize;
1844 nt_devmode->paperlength=devmode->paperlength;
1845 nt_devmode->paperwidth=devmode->paperwidth;
1846 nt_devmode->scale=devmode->scale;
1847 nt_devmode->copies=devmode->copies;
1848 nt_devmode->defaultsource=devmode->defaultsource;
1849 nt_devmode->printquality=devmode->printquality;
1850 nt_devmode->color=devmode->color;
1851 nt_devmode->duplex=devmode->duplex;
1852 nt_devmode->yresolution=devmode->yresolution;
1853 nt_devmode->ttoption=devmode->ttoption;
1854 nt_devmode->collate=devmode->collate;
1856 nt_devmode->logpixels=devmode->logpixels;
1857 nt_devmode->bitsperpel=devmode->bitsperpel;
1858 nt_devmode->pelswidth=devmode->pelswidth;
1859 nt_devmode->pelsheight=devmode->pelsheight;
1860 nt_devmode->displayflags=devmode->displayflags;
1861 nt_devmode->displayfrequency=devmode->displayfrequency;
1862 nt_devmode->icmmethod=devmode->icmmethod;
1863 nt_devmode->icmintent=devmode->icmintent;
1864 nt_devmode->mediatype=devmode->mediatype;
1865 nt_devmode->dithertype=devmode->dithertype;
1866 nt_devmode->reserved1=devmode->reserved1;
1867 nt_devmode->reserved2=devmode->reserved2;
1868 nt_devmode->panningwidth=devmode->panningwidth;
1869 nt_devmode->panningheight=devmode->panningheight;
1872 * Only change private and driverextra if the incoming devmode
1873 * has a new one. JRA.
1876 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1877 SAFE_FREE(nt_devmode->nt_dev_private);
1878 nt_devmode->driverextra=devmode->driverextra;
1879 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1880 return False;
1881 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1884 *pp_nt_devmode = nt_devmode;
1886 return True;
1889 /********************************************************************
1890 * _spoolss_enddocprinter_internal.
1891 ********************************************************************/
1893 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1896 int snum;
1898 if (!Printer) {
1899 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1900 return WERR_BADFID;
1903 if (!get_printer_snum(p, handle, &snum, NULL))
1904 return WERR_BADFID;
1906 Printer->document_started=False;
1907 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1908 /* error codes unhandled so far ... */
1910 return WERR_OK;
1913 /********************************************************************
1914 * api_spoolss_closeprinter
1915 ********************************************************************/
1917 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1919 POLICY_HND *handle = &q_u->handle;
1921 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1923 if (Printer && Printer->document_started)
1924 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1926 if (!close_printer_handle(p, handle))
1927 return WERR_BADFID;
1929 /* clear the returned printer handle. Observed behavior
1930 from Win2k server. Don't think this really matters.
1931 Previous code just copied the value of the closed
1932 handle. --jerry */
1934 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1936 return WERR_OK;
1939 /********************************************************************
1940 * api_spoolss_deleteprinter
1942 ********************************************************************/
1944 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1946 POLICY_HND *handle = &q_u->handle;
1947 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1948 WERROR result;
1950 if (Printer && Printer->document_started)
1951 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1953 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1955 result = delete_printer_handle(p, handle);
1957 update_c_setprinter(False);
1959 return result;
1962 /*******************************************************************
1963 * static function to lookup the version id corresponding to an
1964 * long architecture string
1965 ******************************************************************/
1967 static int get_version_id (char * arch)
1969 int i;
1970 struct table_node archi_table[]= {
1972 {"Windows 4.0", "WIN40", 0 },
1973 {"Windows NT x86", "W32X86", 2 },
1974 {"Windows NT R4000", "W32MIPS", 2 },
1975 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1976 {"Windows NT PowerPC", "W32PPC", 2 },
1977 {"Windows IA64", "IA64", 3 },
1978 {"Windows x64", "x64", 3 },
1979 {NULL, "", -1 }
1982 for (i=0; archi_table[i].long_archi != NULL; i++)
1984 if (strcmp(arch, archi_table[i].long_archi) == 0)
1985 return (archi_table[i].version);
1988 return -1;
1991 /********************************************************************
1992 * _spoolss_deleteprinterdriver
1993 ********************************************************************/
1995 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1997 fstring driver;
1998 fstring arch;
1999 NT_PRINTER_DRIVER_INFO_LEVEL info;
2000 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2001 int version;
2002 WERROR status;
2003 WERROR status_win2k = WERR_ACCESS_DENIED;
2004 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2006 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2007 and not a printer admin, then fail */
2009 if ( (p->pipe_user.ut.uid != 0)
2010 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2011 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2012 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2014 return WERR_ACCESS_DENIED;
2017 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2018 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2020 /* check that we have a valid driver name first */
2022 if ((version=get_version_id(arch)) == -1)
2023 return WERR_INVALID_ENVIRONMENT;
2025 ZERO_STRUCT(info);
2026 ZERO_STRUCT(info_win2k);
2028 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2030 /* try for Win2k driver if "Windows NT x86" */
2032 if ( version == 2 ) {
2033 version = 3;
2034 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2035 status = WERR_UNKNOWN_PRINTER_DRIVER;
2036 goto done;
2039 /* otherwise it was a failure */
2040 else {
2041 status = WERR_UNKNOWN_PRINTER_DRIVER;
2042 goto done;
2047 if (printer_driver_in_use(info.info_3)) {
2048 status = WERR_PRINTER_DRIVER_IN_USE;
2049 goto done;
2052 if ( version == 2 )
2054 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2056 /* if we get to here, we now have 2 driver info structures to remove */
2057 /* remove the Win2k driver first*/
2059 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2060 free_a_printer_driver( info_win2k, 3 );
2062 /* this should not have failed---if it did, report to client */
2063 if ( !W_ERROR_IS_OK(status_win2k) )
2065 status = status_win2k;
2066 goto done;
2071 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2073 /* if at least one of the deletes succeeded return OK */
2075 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2076 status = WERR_OK;
2078 done:
2079 free_a_printer_driver( info, 3 );
2081 return status;
2084 /********************************************************************
2085 * spoolss_deleteprinterdriverex
2086 ********************************************************************/
2088 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2090 fstring driver;
2091 fstring arch;
2092 NT_PRINTER_DRIVER_INFO_LEVEL info;
2093 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2094 int version;
2095 uint32 flags = q_u->delete_flags;
2096 bool delete_files;
2097 WERROR status;
2098 WERROR status_win2k = WERR_ACCESS_DENIED;
2099 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2101 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2102 and not a printer admin, then fail */
2104 if ( (p->pipe_user.ut.uid != 0)
2105 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2106 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2107 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2109 return WERR_ACCESS_DENIED;
2112 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2113 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2115 /* check that we have a valid driver name first */
2116 if ((version=get_version_id(arch)) == -1) {
2117 /* this is what NT returns */
2118 return WERR_INVALID_ENVIRONMENT;
2121 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2122 version = q_u->version;
2124 ZERO_STRUCT(info);
2125 ZERO_STRUCT(info_win2k);
2127 status = get_a_printer_driver(&info, 3, driver, arch, version);
2129 if ( !W_ERROR_IS_OK(status) )
2132 * if the client asked for a specific version,
2133 * or this is something other than Windows NT x86,
2134 * then we've failed
2137 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2138 goto done;
2140 /* try for Win2k driver if "Windows NT x86" */
2142 version = 3;
2143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2144 status = WERR_UNKNOWN_PRINTER_DRIVER;
2145 goto done;
2149 if ( printer_driver_in_use(info.info_3) ) {
2150 status = WERR_PRINTER_DRIVER_IN_USE;
2151 goto done;
2155 * we have a couple of cases to consider.
2156 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2157 * then the delete should fail if **any** files overlap with
2158 * other drivers
2159 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2160 * non-overlapping files
2161 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2162 * is set, the do not delete any files
2163 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2166 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2168 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2170 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2171 /* no idea of the correct error here */
2172 status = WERR_ACCESS_DENIED;
2173 goto done;
2177 /* also check for W32X86/3 if necessary; maybe we already have? */
2179 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2180 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2183 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2184 /* no idea of the correct error here */
2185 free_a_printer_driver( info_win2k, 3 );
2186 status = WERR_ACCESS_DENIED;
2187 goto done;
2190 /* if we get to here, we now have 2 driver info structures to remove */
2191 /* remove the Win2k driver first*/
2193 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2194 free_a_printer_driver( info_win2k, 3 );
2196 /* this should not have failed---if it did, report to client */
2198 if ( !W_ERROR_IS_OK(status_win2k) )
2199 goto done;
2203 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2205 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2206 status = WERR_OK;
2207 done:
2208 free_a_printer_driver( info, 3 );
2210 return status;
2214 /****************************************************************************
2215 Internal routine for retreiving printerdata
2216 ***************************************************************************/
2218 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2219 const char *key, const char *value, uint32 *type, uint8 **data,
2220 uint32 *needed, uint32 in_size )
2222 REGISTRY_VALUE *val;
2223 uint32 size;
2224 int data_len;
2226 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2227 return WERR_BADFILE;
2229 *type = regval_type( val );
2231 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2233 size = regval_size( val );
2235 /* copy the min(in_size, len) */
2237 if ( in_size ) {
2238 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2240 /* special case for 0 length values */
2241 if ( data_len ) {
2242 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2243 return WERR_NOMEM;
2245 else {
2246 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2247 return WERR_NOMEM;
2250 else
2251 *data = NULL;
2253 *needed = size;
2255 DEBUG(5,("get_printer_dataex: copy done\n"));
2257 return WERR_OK;
2260 /****************************************************************************
2261 Internal routine for removing printerdata
2262 ***************************************************************************/
2264 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2266 return delete_printer_data( printer->info_2, key, value );
2269 /****************************************************************************
2270 Internal routine for storing printerdata
2271 ***************************************************************************/
2273 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2274 uint32 type, uint8 *data, int real_len )
2276 /* the registry objects enforce uniqueness based on value name */
2278 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2281 /********************************************************************
2282 GetPrinterData on a printer server Handle.
2283 ********************************************************************/
2285 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2287 int i;
2289 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2291 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2292 *type = REG_DWORD;
2293 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2294 return WERR_NOMEM;
2295 SIVAL(*data, 0, 0x00);
2296 *needed = 0x4;
2297 return WERR_OK;
2300 if (!StrCaseCmp(value, "BeepEnabled")) {
2301 *type = REG_DWORD;
2302 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2303 return WERR_NOMEM;
2304 SIVAL(*data, 0, 0x00);
2305 *needed = 0x4;
2306 return WERR_OK;
2309 if (!StrCaseCmp(value, "EventLog")) {
2310 *type = REG_DWORD;
2311 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2312 return WERR_NOMEM;
2313 /* formally was 0x1b */
2314 SIVAL(*data, 0, 0x0);
2315 *needed = 0x4;
2316 return WERR_OK;
2319 if (!StrCaseCmp(value, "NetPopup")) {
2320 *type = REG_DWORD;
2321 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2322 return WERR_NOMEM;
2323 SIVAL(*data, 0, 0x00);
2324 *needed = 0x4;
2325 return WERR_OK;
2328 if (!StrCaseCmp(value, "MajorVersion")) {
2329 *type = REG_DWORD;
2330 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2331 return WERR_NOMEM;
2333 /* Windows NT 4.0 seems to not allow uploading of drivers
2334 to a server that reports 0x3 as the MajorVersion.
2335 need to investigate more how Win2k gets around this .
2336 -- jerry */
2338 if ( RA_WINNT == get_remote_arch() )
2339 SIVAL(*data, 0, 2);
2340 else
2341 SIVAL(*data, 0, 3);
2343 *needed = 0x4;
2344 return WERR_OK;
2347 if (!StrCaseCmp(value, "MinorVersion")) {
2348 *type = REG_DWORD;
2349 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2350 return WERR_NOMEM;
2351 SIVAL(*data, 0, 0);
2352 *needed = 0x4;
2353 return WERR_OK;
2356 /* REG_BINARY
2357 * uint32 size = 0x114
2358 * uint32 major = 5
2359 * uint32 minor = [0|1]
2360 * uint32 build = [2195|2600]
2361 * extra unicode string = e.g. "Service Pack 3"
2363 if (!StrCaseCmp(value, "OSVersion")) {
2364 *type = REG_BINARY;
2365 *needed = 0x114;
2367 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2368 return WERR_NOMEM;
2370 SIVAL(*data, 0, *needed); /* size */
2371 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2372 SIVAL(*data, 8, 0);
2373 SIVAL(*data, 12, 2195); /* build */
2375 /* leave extra string empty */
2377 return WERR_OK;
2381 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2382 const char *string="C:\\PRINTERS";
2383 *type = REG_SZ;
2384 *needed = 2*(strlen(string)+1);
2385 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2386 return WERR_NOMEM;
2387 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 /* it's done by hand ready to go on the wire */
2390 for (i=0; i<strlen(string); i++) {
2391 (*data)[2*i]=string[i];
2392 (*data)[2*i+1]='\0';
2394 return WERR_OK;
2397 if (!StrCaseCmp(value, "Architecture")) {
2398 const char *string="Windows NT x86";
2399 *type = REG_SZ;
2400 *needed = 2*(strlen(string)+1);
2401 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2402 return WERR_NOMEM;
2403 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 for (i=0; i<strlen(string); i++) {
2405 (*data)[2*i]=string[i];
2406 (*data)[2*i+1]='\0';
2408 return WERR_OK;
2411 if (!StrCaseCmp(value, "DsPresent")) {
2412 *type = REG_DWORD;
2413 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2414 return WERR_NOMEM;
2416 /* only show the publish check box if we are a
2417 memeber of a AD domain */
2419 if ( lp_security() == SEC_ADS )
2420 SIVAL(*data, 0, 0x01);
2421 else
2422 SIVAL(*data, 0, 0x00);
2424 *needed = 0x4;
2425 return WERR_OK;
2428 if (!StrCaseCmp(value, "DNSMachineName")) {
2429 const char *hostname = get_mydnsfullname();
2431 if (!hostname)
2432 return WERR_BADFILE;
2433 *type = REG_SZ;
2434 *needed = 2*(strlen(hostname)+1);
2435 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2436 return WERR_NOMEM;
2437 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2438 for (i=0; i<strlen(hostname); i++) {
2439 (*data)[2*i]=hostname[i];
2440 (*data)[2*i+1]='\0';
2442 return WERR_OK;
2446 return WERR_BADFILE;
2449 /********************************************************************
2450 * spoolss_getprinterdata
2451 ********************************************************************/
2453 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2455 POLICY_HND *handle = &q_u->handle;
2456 UNISTR2 *valuename = &q_u->valuename;
2457 uint32 in_size = q_u->size;
2458 uint32 *type = &r_u->type;
2459 uint32 *out_size = &r_u->size;
2460 uint8 **data = &r_u->data;
2461 uint32 *needed = &r_u->needed;
2462 WERROR status;
2463 fstring value;
2464 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2465 NT_PRINTER_INFO_LEVEL *printer = NULL;
2466 int snum = 0;
2469 * Reminder: when it's a string, the length is in BYTES
2470 * even if UNICODE is negociated.
2472 * JFM, 4/19/1999
2475 *out_size = in_size;
2477 /* in case of problem, return some default values */
2479 *needed = 0;
2480 *type = 0;
2482 DEBUG(4,("_spoolss_getprinterdata\n"));
2484 if ( !Printer ) {
2485 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2486 status = WERR_BADFID;
2487 goto done;
2490 unistr2_to_ascii(value, valuename, sizeof(value));
2492 if ( Printer->printer_type == SPLHND_SERVER )
2493 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2494 else
2496 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2497 status = WERR_BADFID;
2498 goto done;
2501 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2502 if ( !W_ERROR_IS_OK(status) )
2503 goto done;
2505 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2507 if ( strequal(value, "ChangeId") ) {
2508 *type = REG_DWORD;
2509 *needed = sizeof(uint32);
2510 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2511 status = WERR_NOMEM;
2512 goto done;
2514 SIVAL( *data, 0, printer->info_2->changeid );
2515 status = WERR_OK;
2517 else
2518 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2521 if (*needed > *out_size)
2522 status = WERR_MORE_DATA;
2524 done:
2525 if ( !W_ERROR_IS_OK(status) )
2527 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2529 /* reply this param doesn't exist */
2531 if ( *out_size ) {
2532 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2533 if ( printer )
2534 free_a_printer( &printer, 2 );
2535 return WERR_NOMEM;
2537 } else {
2538 *data = NULL;
2542 /* cleanup & exit */
2544 if ( printer )
2545 free_a_printer( &printer, 2 );
2547 return status;
2550 /*********************************************************
2551 Connect to the client machine.
2552 **********************************************************/
2554 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2555 struct sockaddr_storage *client_ss, const char *remote_machine)
2557 NTSTATUS ret;
2558 struct cli_state *the_cli;
2559 struct sockaddr_storage rm_addr;
2561 if ( is_zero_addr(client_ss) ) {
2562 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2563 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2564 return False;
2567 if (ismyaddr(&rm_addr)) {
2568 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2569 return False;
2571 } else {
2572 char addr[INET6_ADDRSTRLEN];
2573 rm_addr = *client_ss;
2574 print_sockaddr(addr, sizeof(addr), &rm_addr);
2575 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2576 addr));
2579 /* setup the connection */
2581 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2582 &rm_addr, 0, "IPC$", "IPC",
2583 "", /* username */
2584 "", /* domain */
2585 "", /* password */
2586 0, lp_client_signing(), NULL );
2588 if ( !NT_STATUS_IS_OK( ret ) ) {
2589 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2590 remote_machine ));
2591 return False;
2594 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2595 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2596 cli_shutdown(the_cli);
2597 return False;
2601 * Ok - we have an anonymous connection to the IPC$ share.
2602 * Now start the NT Domain stuff :-).
2605 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2606 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2607 remote_machine, nt_errstr(ret)));
2608 cli_shutdown(the_cli);
2609 return False;
2612 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2614 (*pp_pipe)->cli = the_cli;
2616 return True;
2619 /***************************************************************************
2620 Connect to the client.
2621 ****************************************************************************/
2623 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2624 uint32 localprinter, uint32 type,
2625 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2627 WERROR result;
2630 * If it's the first connection, contact the client
2631 * and connect to the IPC$ share anonymously
2633 if (smb_connections==0) {
2634 fstring unix_printer;
2636 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2638 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2639 return False;
2641 messaging_register(smbd_messaging_context(), NULL,
2642 MSG_PRINTER_NOTIFY2,
2643 receive_notify2_message_list);
2644 /* Tell the connections db we're now interested in printer
2645 * notify messages. */
2646 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2650 * Tell the specific printing tdb we want messages for this printer
2651 * by registering our PID.
2654 if (!print_notify_register_pid(snum))
2655 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2657 smb_connections++;
2659 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2660 talloc_tos(),
2661 printer,
2662 localprinter,
2663 type,
2664 handle);
2666 if (!W_ERROR_IS_OK(result))
2667 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2668 dos_errstr(result)));
2670 return (W_ERROR_IS_OK(result));
2673 /********************************************************************
2674 * _spoolss_rffpcnex
2675 * ReplyFindFirstPrinterChangeNotifyEx
2677 * before replying OK: status=0 a rpc call is made to the workstation
2678 * asking ReplyOpenPrinter
2680 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2681 * called from api_spoolss_rffpcnex
2682 ********************************************************************/
2684 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2686 POLICY_HND *handle = &q_u->handle;
2687 uint32 flags = q_u->flags;
2688 uint32 options = q_u->options;
2689 UNISTR2 *localmachine = &q_u->localmachine;
2690 uint32 printerlocal = q_u->printerlocal;
2691 int snum = -1;
2692 SPOOL_NOTIFY_OPTION *option = q_u->option;
2693 struct sockaddr_storage client_ss;
2695 /* store the notify value in the printer struct */
2697 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2699 if (!Printer) {
2700 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2701 return WERR_BADFID;
2704 Printer->notify.flags=flags;
2705 Printer->notify.options=options;
2706 Printer->notify.printerlocal=printerlocal;
2708 if (Printer->notify.option)
2709 free_spool_notify_option(&Printer->notify.option);
2711 Printer->notify.option=dup_spool_notify_option(option);
2713 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2714 sizeof(Printer->notify.localmachine));
2716 /* Connect to the client machine and send a ReplyOpenPrinter */
2718 if ( Printer->printer_type == SPLHND_SERVER)
2719 snum = -1;
2720 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2721 !get_printer_snum(p, handle, &snum, NULL) )
2722 return WERR_BADFID;
2724 if (!interpret_string_addr(&client_ss,
2725 p->conn->client_address,
2726 AI_NUMERICHOST)) {
2727 return WERR_SERVER_UNAVAILABLE;
2730 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2731 Printer->notify.printerlocal, 1,
2732 &Printer->notify.client_hnd, &client_ss))
2733 return WERR_SERVER_UNAVAILABLE;
2735 Printer->notify.client_connected=True;
2737 return WERR_OK;
2740 /*******************************************************************
2741 * fill a notify_info_data with the servername
2742 ********************************************************************/
2744 void spoolss_notify_server_name(int snum,
2745 SPOOL_NOTIFY_INFO_DATA *data,
2746 print_queue_struct *queue,
2747 NT_PRINTER_INFO_LEVEL *printer,
2748 TALLOC_CTX *mem_ctx)
2750 smb_ucs2_t *temp = NULL;
2751 uint32 len;
2753 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2754 if (len == (uint32)-1) {
2755 len = 0;
2758 data->notify_data.data.length = len;
2759 if (len) {
2760 data->notify_data.data.string = (uint16 *)temp;
2761 } else {
2762 data->notify_data.data.string = NULL;
2766 /*******************************************************************
2767 * fill a notify_info_data with the printername (not including the servername).
2768 ********************************************************************/
2770 void spoolss_notify_printer_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2776 smb_ucs2_t *temp = NULL;
2777 uint32 len;
2779 /* the notify name should not contain the \\server\ part */
2780 char *p = strrchr(printer->info_2->printername, '\\');
2782 if (!p) {
2783 p = printer->info_2->printername;
2784 } else {
2785 p++;
2788 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2789 if (len == (uint32)-1) {
2790 len = 0;
2793 data->notify_data.data.length = len;
2794 if (len) {
2795 data->notify_data.data.string = (uint16 *)temp;
2796 } else {
2797 data->notify_data.data.string = NULL;
2801 /*******************************************************************
2802 * fill a notify_info_data with the servicename
2803 ********************************************************************/
2805 void spoolss_notify_share_name(int snum,
2806 SPOOL_NOTIFY_INFO_DATA *data,
2807 print_queue_struct *queue,
2808 NT_PRINTER_INFO_LEVEL *printer,
2809 TALLOC_CTX *mem_ctx)
2811 smb_ucs2_t *temp = NULL;
2812 uint32 len;
2814 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2815 if (len == (uint32)-1) {
2816 len = 0;
2819 data->notify_data.data.length = len;
2820 if (len) {
2821 data->notify_data.data.string = (uint16 *)temp;
2822 } else {
2823 data->notify_data.data.string = NULL;
2828 /*******************************************************************
2829 * fill a notify_info_data with the port name
2830 ********************************************************************/
2832 void spoolss_notify_port_name(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2838 smb_ucs2_t *temp = NULL;
2839 uint32 len;
2841 /* even if it's strange, that's consistant in all the code */
2843 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2844 if (len == (uint32)-1) {
2845 len = 0;
2848 data->notify_data.data.length = len;
2849 if (len) {
2850 data->notify_data.data.string = (uint16 *)temp;
2851 } else {
2852 data->notify_data.data.string = NULL;
2856 /*******************************************************************
2857 * fill a notify_info_data with the printername
2858 * but it doesn't exist, have to see what to do
2859 ********************************************************************/
2861 void spoolss_notify_driver_name(int snum,
2862 SPOOL_NOTIFY_INFO_DATA *data,
2863 print_queue_struct *queue,
2864 NT_PRINTER_INFO_LEVEL *printer,
2865 TALLOC_CTX *mem_ctx)
2867 smb_ucs2_t *temp = NULL;
2868 uint32 len;
2870 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2871 if (len == (uint32)-1) {
2872 len = 0;
2875 data->notify_data.data.length = len;
2876 if (len) {
2877 data->notify_data.data.string = (uint16 *)temp;
2878 } else {
2879 data->notify_data.data.string = NULL;
2883 /*******************************************************************
2884 * fill a notify_info_data with the comment
2885 ********************************************************************/
2887 void spoolss_notify_comment(int snum,
2888 SPOOL_NOTIFY_INFO_DATA *data,
2889 print_queue_struct *queue,
2890 NT_PRINTER_INFO_LEVEL *printer,
2891 TALLOC_CTX *mem_ctx)
2893 smb_ucs2_t *temp = NULL;
2894 uint32 len;
2896 if (*printer->info_2->comment == '\0')
2897 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2898 else
2899 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2901 if (len == (uint32)-1) {
2902 len = 0;
2904 data->notify_data.data.length = len;
2905 if (len) {
2906 data->notify_data.data.string = (uint16 *)temp;
2907 } else {
2908 data->notify_data.data.string = NULL;
2912 /*******************************************************************
2913 * fill a notify_info_data with the comment
2914 * location = "Room 1, floor 2, building 3"
2915 ********************************************************************/
2917 void spoolss_notify_location(int snum,
2918 SPOOL_NOTIFY_INFO_DATA *data,
2919 print_queue_struct *queue,
2920 NT_PRINTER_INFO_LEVEL *printer,
2921 TALLOC_CTX *mem_ctx)
2923 smb_ucs2_t *temp = NULL;
2924 uint32 len;
2926 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2927 if (len == (uint32)-1) {
2928 len = 0;
2931 data->notify_data.data.length = len;
2932 if (len) {
2933 data->notify_data.data.string = (uint16 *)temp;
2934 } else {
2935 data->notify_data.data.string = NULL;
2939 /*******************************************************************
2940 * fill a notify_info_data with the device mode
2941 * jfm:xxxx don't to it for know but that's a real problem !!!
2942 ********************************************************************/
2944 static void spoolss_notify_devmode(int snum,
2945 SPOOL_NOTIFY_INFO_DATA *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2950 /* for a dummy implementation we have to zero the fields */
2951 data->notify_data.data.length = 0;
2952 data->notify_data.data.string = NULL;
2955 /*******************************************************************
2956 * fill a notify_info_data with the separator file name
2957 ********************************************************************/
2959 void spoolss_notify_sepfile(int snum,
2960 SPOOL_NOTIFY_INFO_DATA *data,
2961 print_queue_struct *queue,
2962 NT_PRINTER_INFO_LEVEL *printer,
2963 TALLOC_CTX *mem_ctx)
2965 smb_ucs2_t *temp = NULL;
2966 uint32 len;
2968 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2969 if (len == (uint32)-1) {
2970 len = 0;
2973 data->notify_data.data.length = len;
2974 if (len) {
2975 data->notify_data.data.string = (uint16 *)temp;
2976 } else {
2977 data->notify_data.data.string = NULL;
2981 /*******************************************************************
2982 * fill a notify_info_data with the print processor
2983 * jfm:xxxx return always winprint to indicate we don't do anything to it
2984 ********************************************************************/
2986 void spoolss_notify_print_processor(int snum,
2987 SPOOL_NOTIFY_INFO_DATA *data,
2988 print_queue_struct *queue,
2989 NT_PRINTER_INFO_LEVEL *printer,
2990 TALLOC_CTX *mem_ctx)
2992 smb_ucs2_t *temp = NULL;
2993 uint32 len;
2995 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2996 if (len == (uint32)-1) {
2997 len = 0;
3000 data->notify_data.data.length = len;
3001 if (len) {
3002 data->notify_data.data.string = (uint16 *)temp;
3003 } else {
3004 data->notify_data.data.string = NULL;
3008 /*******************************************************************
3009 * fill a notify_info_data with the print processor options
3010 * jfm:xxxx send an empty string
3011 ********************************************************************/
3013 void spoolss_notify_parameters(int snum,
3014 SPOOL_NOTIFY_INFO_DATA *data,
3015 print_queue_struct *queue,
3016 NT_PRINTER_INFO_LEVEL *printer,
3017 TALLOC_CTX *mem_ctx)
3019 smb_ucs2_t *temp = NULL;
3020 uint32 len;
3022 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3023 if (len == (uint32)-1) {
3024 len = 0;
3027 data->notify_data.data.length = len;
3028 if (len) {
3029 data->notify_data.data.string = (uint16 *)temp;
3030 } else {
3031 data->notify_data.data.string = NULL;
3035 /*******************************************************************
3036 * fill a notify_info_data with the data type
3037 * jfm:xxxx always send RAW as data type
3038 ********************************************************************/
3040 void spoolss_notify_datatype(int snum,
3041 SPOOL_NOTIFY_INFO_DATA *data,
3042 print_queue_struct *queue,
3043 NT_PRINTER_INFO_LEVEL *printer,
3044 TALLOC_CTX *mem_ctx)
3046 smb_ucs2_t *temp = NULL;
3047 uint32 len;
3049 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3050 if (len == (uint32)-1) {
3051 len = 0;
3054 data->notify_data.data.length = len;
3055 if (len) {
3056 data->notify_data.data.string = (uint16 *)temp;
3057 } else {
3058 data->notify_data.data.string = NULL;
3062 /*******************************************************************
3063 * fill a notify_info_data with the security descriptor
3064 * jfm:xxxx send an null pointer to say no security desc
3065 * have to implement security before !
3066 ********************************************************************/
3068 static void spoolss_notify_security_desc(int snum,
3069 SPOOL_NOTIFY_INFO_DATA *data,
3070 print_queue_struct *queue,
3071 NT_PRINTER_INFO_LEVEL *printer,
3072 TALLOC_CTX *mem_ctx)
3074 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3075 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3078 /*******************************************************************
3079 * fill a notify_info_data with the attributes
3080 * jfm:xxxx a samba printer is always shared
3081 ********************************************************************/
3083 void spoolss_notify_attributes(int snum,
3084 SPOOL_NOTIFY_INFO_DATA *data,
3085 print_queue_struct *queue,
3086 NT_PRINTER_INFO_LEVEL *printer,
3087 TALLOC_CTX *mem_ctx)
3089 data->notify_data.value[0] = printer->info_2->attributes;
3090 data->notify_data.value[1] = 0;
3093 /*******************************************************************
3094 * fill a notify_info_data with the priority
3095 ********************************************************************/
3097 static void spoolss_notify_priority(int snum,
3098 SPOOL_NOTIFY_INFO_DATA *data,
3099 print_queue_struct *queue,
3100 NT_PRINTER_INFO_LEVEL *printer,
3101 TALLOC_CTX *mem_ctx)
3103 data->notify_data.value[0] = printer->info_2->priority;
3104 data->notify_data.value[1] = 0;
3107 /*******************************************************************
3108 * fill a notify_info_data with the default priority
3109 ********************************************************************/
3111 static void spoolss_notify_default_priority(int snum,
3112 SPOOL_NOTIFY_INFO_DATA *data,
3113 print_queue_struct *queue,
3114 NT_PRINTER_INFO_LEVEL *printer,
3115 TALLOC_CTX *mem_ctx)
3117 data->notify_data.value[0] = printer->info_2->default_priority;
3118 data->notify_data.value[1] = 0;
3121 /*******************************************************************
3122 * fill a notify_info_data with the start time
3123 ********************************************************************/
3125 static void spoolss_notify_start_time(int snum,
3126 SPOOL_NOTIFY_INFO_DATA *data,
3127 print_queue_struct *queue,
3128 NT_PRINTER_INFO_LEVEL *printer,
3129 TALLOC_CTX *mem_ctx)
3131 data->notify_data.value[0] = printer->info_2->starttime;
3132 data->notify_data.value[1] = 0;
3135 /*******************************************************************
3136 * fill a notify_info_data with the until time
3137 ********************************************************************/
3139 static void spoolss_notify_until_time(int snum,
3140 SPOOL_NOTIFY_INFO_DATA *data,
3141 print_queue_struct *queue,
3142 NT_PRINTER_INFO_LEVEL *printer,
3143 TALLOC_CTX *mem_ctx)
3145 data->notify_data.value[0] = printer->info_2->untiltime;
3146 data->notify_data.value[1] = 0;
3149 /*******************************************************************
3150 * fill a notify_info_data with the status
3151 ********************************************************************/
3153 static void spoolss_notify_status(int snum,
3154 SPOOL_NOTIFY_INFO_DATA *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 print_status_struct status;
3161 print_queue_length(snum, &status);
3162 data->notify_data.value[0]=(uint32) status.status;
3163 data->notify_data.value[1] = 0;
3166 /*******************************************************************
3167 * fill a notify_info_data with the number of jobs queued
3168 ********************************************************************/
3170 void spoolss_notify_cjobs(int snum,
3171 SPOOL_NOTIFY_INFO_DATA *data,
3172 print_queue_struct *queue,
3173 NT_PRINTER_INFO_LEVEL *printer,
3174 TALLOC_CTX *mem_ctx)
3176 data->notify_data.value[0] = print_queue_length(snum, NULL);
3177 data->notify_data.value[1] = 0;
3180 /*******************************************************************
3181 * fill a notify_info_data with the average ppm
3182 ********************************************************************/
3184 static void spoolss_notify_average_ppm(int snum,
3185 SPOOL_NOTIFY_INFO_DATA *data,
3186 print_queue_struct *queue,
3187 NT_PRINTER_INFO_LEVEL *printer,
3188 TALLOC_CTX *mem_ctx)
3190 /* always respond 8 pages per minutes */
3191 /* a little hard ! */
3192 data->notify_data.value[0] = printer->info_2->averageppm;
3193 data->notify_data.value[1] = 0;
3196 /*******************************************************************
3197 * fill a notify_info_data with username
3198 ********************************************************************/
3200 static void spoolss_notify_username(int snum,
3201 SPOOL_NOTIFY_INFO_DATA *data,
3202 print_queue_struct *queue,
3203 NT_PRINTER_INFO_LEVEL *printer,
3204 TALLOC_CTX *mem_ctx)
3206 smb_ucs2_t *temp = NULL;
3207 uint32 len;
3209 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3210 if (len == (uint32)-1) {
3211 len = 0;
3214 data->notify_data.data.length = len;
3215 if (len) {
3216 data->notify_data.data.string = (uint16 *)temp;
3217 } else {
3218 data->notify_data.data.string = NULL;
3222 /*******************************************************************
3223 * fill a notify_info_data with job status
3224 ********************************************************************/
3226 static void spoolss_notify_job_status(int snum,
3227 SPOOL_NOTIFY_INFO_DATA *data,
3228 print_queue_struct *queue,
3229 NT_PRINTER_INFO_LEVEL *printer,
3230 TALLOC_CTX *mem_ctx)
3232 data->notify_data.value[0]=nt_printj_status(queue->status);
3233 data->notify_data.value[1] = 0;
3236 /*******************************************************************
3237 * fill a notify_info_data with job name
3238 ********************************************************************/
3240 static void spoolss_notify_job_name(int snum,
3241 SPOOL_NOTIFY_INFO_DATA *data,
3242 print_queue_struct *queue,
3243 NT_PRINTER_INFO_LEVEL *printer,
3244 TALLOC_CTX *mem_ctx)
3246 smb_ucs2_t *temp = NULL;
3247 uint32 len;
3249 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3250 if (len == (uint32)-1) {
3251 len = 0;
3254 data->notify_data.data.length = len;
3255 if (len) {
3256 data->notify_data.data.string = (uint16 *)temp;
3257 } else {
3258 data->notify_data.data.string = NULL;
3262 /*******************************************************************
3263 * fill a notify_info_data with job status
3264 ********************************************************************/
3266 static void spoolss_notify_job_status_string(int snum,
3267 SPOOL_NOTIFY_INFO_DATA *data,
3268 print_queue_struct *queue,
3269 NT_PRINTER_INFO_LEVEL *printer,
3270 TALLOC_CTX *mem_ctx)
3273 * Now we're returning job status codes we just return a "" here. JRA.
3276 const char *p = "";
3277 smb_ucs2_t *temp = NULL;
3278 uint32 len;
3280 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3281 p = "unknown";
3283 switch (queue->status) {
3284 case LPQ_QUEUED:
3285 p = "Queued";
3286 break;
3287 case LPQ_PAUSED:
3288 p = ""; /* NT provides the paused string */
3289 break;
3290 case LPQ_SPOOLING:
3291 p = "Spooling";
3292 break;
3293 case LPQ_PRINTING:
3294 p = "Printing";
3295 break;
3297 #endif /* NO LONGER NEEDED. */
3299 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3300 if (len == (uint32)-1) {
3301 len = 0;
3304 data->notify_data.data.length = len;
3305 if (len) {
3306 data->notify_data.data.string = (uint16 *)temp;
3307 } else {
3308 data->notify_data.data.string = NULL;
3312 /*******************************************************************
3313 * fill a notify_info_data with job time
3314 ********************************************************************/
3316 static void spoolss_notify_job_time(int snum,
3317 SPOOL_NOTIFY_INFO_DATA *data,
3318 print_queue_struct *queue,
3319 NT_PRINTER_INFO_LEVEL *printer,
3320 TALLOC_CTX *mem_ctx)
3322 data->notify_data.value[0]=0x0;
3323 data->notify_data.value[1]=0;
3326 /*******************************************************************
3327 * fill a notify_info_data with job size
3328 ********************************************************************/
3330 static void spoolss_notify_job_size(int snum,
3331 SPOOL_NOTIFY_INFO_DATA *data,
3332 print_queue_struct *queue,
3333 NT_PRINTER_INFO_LEVEL *printer,
3334 TALLOC_CTX *mem_ctx)
3336 data->notify_data.value[0]=queue->size;
3337 data->notify_data.value[1]=0;
3340 /*******************************************************************
3341 * fill a notify_info_data with page info
3342 ********************************************************************/
3343 static void spoolss_notify_total_pages(int snum,
3344 SPOOL_NOTIFY_INFO_DATA *data,
3345 print_queue_struct *queue,
3346 NT_PRINTER_INFO_LEVEL *printer,
3347 TALLOC_CTX *mem_ctx)
3349 data->notify_data.value[0]=queue->page_count;
3350 data->notify_data.value[1]=0;
3353 /*******************************************************************
3354 * fill a notify_info_data with pages printed info.
3355 ********************************************************************/
3356 static void spoolss_notify_pages_printed(int snum,
3357 SPOOL_NOTIFY_INFO_DATA *data,
3358 print_queue_struct *queue,
3359 NT_PRINTER_INFO_LEVEL *printer,
3360 TALLOC_CTX *mem_ctx)
3362 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3363 data->notify_data.value[1]=0;
3366 /*******************************************************************
3367 Fill a notify_info_data with job position.
3368 ********************************************************************/
3370 static void spoolss_notify_job_position(int snum,
3371 SPOOL_NOTIFY_INFO_DATA *data,
3372 print_queue_struct *queue,
3373 NT_PRINTER_INFO_LEVEL *printer,
3374 TALLOC_CTX *mem_ctx)
3376 data->notify_data.value[0]=queue->job;
3377 data->notify_data.value[1]=0;
3380 /*******************************************************************
3381 Fill a notify_info_data with submitted time.
3382 ********************************************************************/
3384 static void spoolss_notify_submitted_time(int snum,
3385 SPOOL_NOTIFY_INFO_DATA *data,
3386 print_queue_struct *queue,
3387 NT_PRINTER_INFO_LEVEL *printer,
3388 TALLOC_CTX *mem_ctx)
3390 struct tm *t;
3391 uint32 len;
3392 SYSTEMTIME st;
3393 char *p;
3395 t=gmtime(&queue->time);
3397 len = sizeof(SYSTEMTIME);
3399 data->notify_data.data.length = len;
3400 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3402 if (!data->notify_data.data.string) {
3403 data->notify_data.data.length = 0;
3404 return;
3407 make_systemtime(&st, t);
3410 * Systemtime must be linearized as a set of UINT16's.
3411 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3414 p = (char *)data->notify_data.data.string;
3415 SSVAL(p, 0, st.year);
3416 SSVAL(p, 2, st.month);
3417 SSVAL(p, 4, st.dayofweek);
3418 SSVAL(p, 6, st.day);
3419 SSVAL(p, 8, st.hour);
3420 SSVAL(p, 10, st.minute);
3421 SSVAL(p, 12, st.second);
3422 SSVAL(p, 14, st.milliseconds);
3425 struct s_notify_info_data_table
3427 uint16 type;
3428 uint16 field;
3429 const char *name;
3430 uint32 size;
3431 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3432 print_queue_struct *queue,
3433 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3436 /* A table describing the various print notification constants and
3437 whether the notification data is a pointer to a variable sized
3438 buffer, a one value uint32 or a two value uint32. */
3440 static const struct s_notify_info_data_table notify_info_data_table[] =
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3491 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3494 /*******************************************************************
3495 Return the size of info_data structure.
3496 ********************************************************************/
3498 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3500 int i=0;
3502 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3503 if ( (notify_info_data_table[i].type == type)
3504 && (notify_info_data_table[i].field == field) ) {
3505 switch(notify_info_data_table[i].size) {
3506 case NOTIFY_ONE_VALUE:
3507 case NOTIFY_TWO_VALUE:
3508 return 1;
3509 case NOTIFY_STRING:
3510 return 2;
3512 /* The only pointer notify data I have seen on
3513 the wire is the submitted time and this has
3514 the notify size set to 4. -tpot */
3516 case NOTIFY_POINTER:
3517 return 4;
3519 case NOTIFY_SECDESC:
3520 return 5;
3525 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3527 return 0;
3530 /*******************************************************************
3531 Return the type of notify_info_data.
3532 ********************************************************************/
3534 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3536 uint32 i=0;
3538 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3539 if (notify_info_data_table[i].type == type &&
3540 notify_info_data_table[i].field == field)
3541 return notify_info_data_table[i].size;
3544 return 0;
3547 /****************************************************************************
3548 ****************************************************************************/
3550 static bool search_notify(uint16 type, uint16 field, int *value)
3552 int i;
3554 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3555 if (notify_info_data_table[i].type == type &&
3556 notify_info_data_table[i].field == field &&
3557 notify_info_data_table[i].fn != NULL) {
3558 *value = i;
3559 return True;
3563 return False;
3566 /****************************************************************************
3567 ****************************************************************************/
3569 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3571 info_data->type = type;
3572 info_data->field = field;
3573 info_data->reserved = 0;
3575 info_data->size = size_of_notify_info_data(type, field);
3576 info_data->enc_type = type_of_notify_info_data(type, field);
3578 info_data->id = id;
3581 /*******************************************************************
3583 * fill a notify_info struct with info asked
3585 ********************************************************************/
3587 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3588 snum, SPOOL_NOTIFY_OPTION_TYPE
3589 *option_type, uint32 id,
3590 TALLOC_CTX *mem_ctx)
3592 int field_num,j;
3593 uint16 type;
3594 uint16 field;
3596 SPOOL_NOTIFY_INFO_DATA *current_data;
3597 NT_PRINTER_INFO_LEVEL *printer = NULL;
3598 print_queue_struct *queue=NULL;
3600 type=option_type->type;
3602 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3603 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3604 option_type->count, lp_servicename(snum)));
3606 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3607 return False;
3609 for(field_num=0; field_num<option_type->count; field_num++) {
3610 field = option_type->fields[field_num];
3612 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3614 if (!search_notify(type, field, &j) )
3615 continue;
3617 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3618 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3619 free_a_printer(&printer, 2);
3620 return False;
3623 current_data = &info->data[info->count];
3625 construct_info_data(current_data, type, field, id);
3627 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3628 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3630 notify_info_data_table[j].fn(snum, current_data, queue,
3631 printer, mem_ctx);
3633 info->count++;
3636 free_a_printer(&printer, 2);
3637 return True;
3640 /*******************************************************************
3642 * fill a notify_info struct with info asked
3644 ********************************************************************/
3646 static bool construct_notify_jobs_info(print_queue_struct *queue,
3647 SPOOL_NOTIFY_INFO *info,
3648 NT_PRINTER_INFO_LEVEL *printer,
3649 int snum, SPOOL_NOTIFY_OPTION_TYPE
3650 *option_type, uint32 id,
3651 TALLOC_CTX *mem_ctx)
3653 int field_num,j;
3654 uint16 type;
3655 uint16 field;
3657 SPOOL_NOTIFY_INFO_DATA *current_data;
3659 DEBUG(4,("construct_notify_jobs_info\n"));
3661 type = option_type->type;
3663 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3664 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3665 option_type->count));
3667 for(field_num=0; field_num<option_type->count; field_num++) {
3668 field = option_type->fields[field_num];
3670 if (!search_notify(type, field, &j) )
3671 continue;
3673 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3674 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3675 return False;
3678 current_data=&(info->data[info->count]);
3680 construct_info_data(current_data, type, field, id);
3681 notify_info_data_table[j].fn(snum, current_data, queue,
3682 printer, mem_ctx);
3683 info->count++;
3686 return True;
3690 * JFM: The enumeration is not that simple, it's even non obvious.
3692 * let's take an example: I want to monitor the PRINTER SERVER for
3693 * the printer's name and the number of jobs currently queued.
3694 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3695 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3697 * I have 3 printers on the back of my server.
3699 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3700 * structures.
3701 * Number Data Id
3702 * 1 printer 1 name 1
3703 * 2 printer 1 cjob 1
3704 * 3 printer 2 name 2
3705 * 4 printer 2 cjob 2
3706 * 5 printer 3 name 3
3707 * 6 printer 3 name 3
3709 * that's the print server case, the printer case is even worse.
3712 /*******************************************************************
3714 * enumerate all printers on the printserver
3715 * fill a notify_info struct with info asked
3717 ********************************************************************/
3719 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3720 SPOOL_NOTIFY_INFO *info,
3721 TALLOC_CTX *mem_ctx)
3723 int snum;
3724 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3725 int n_services=lp_numservices();
3726 int i;
3727 SPOOL_NOTIFY_OPTION *option;
3728 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3730 DEBUG(4,("printserver_notify_info\n"));
3732 if (!Printer)
3733 return WERR_BADFID;
3735 option=Printer->notify.option;
3736 info->version=2;
3737 info->data=NULL;
3738 info->count=0;
3740 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3741 sending a ffpcn() request first */
3743 if ( !option )
3744 return WERR_BADFID;
3746 for (i=0; i<option->count; i++) {
3747 option_type=&(option->ctr.type[i]);
3749 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3750 continue;
3752 for (snum=0; snum<n_services; snum++)
3754 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3755 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3759 #if 0
3761 * Debugging information, don't delete.
3764 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3765 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3766 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3768 for (i=0; i<info->count; i++) {
3769 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3770 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3771 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3773 #endif
3775 return WERR_OK;
3778 /*******************************************************************
3780 * fill a notify_info struct with info asked
3782 ********************************************************************/
3784 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3785 TALLOC_CTX *mem_ctx)
3787 int snum;
3788 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3789 int i;
3790 uint32 id;
3791 SPOOL_NOTIFY_OPTION *option;
3792 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3793 int count,j;
3794 print_queue_struct *queue=NULL;
3795 print_status_struct status;
3797 DEBUG(4,("printer_notify_info\n"));
3799 if (!Printer)
3800 return WERR_BADFID;
3802 option=Printer->notify.option;
3803 id = 0x0;
3804 info->version=2;
3805 info->data=NULL;
3806 info->count=0;
3808 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3809 sending a ffpcn() request first */
3811 if ( !option )
3812 return WERR_BADFID;
3814 get_printer_snum(p, hnd, &snum, NULL);
3816 for (i=0; i<option->count; i++) {
3817 option_type=&option->ctr.type[i];
3819 switch ( option_type->type ) {
3820 case PRINTER_NOTIFY_TYPE:
3821 if(construct_notify_printer_info(Printer, info, snum,
3822 option_type, id,
3823 mem_ctx))
3824 id--;
3825 break;
3827 case JOB_NOTIFY_TYPE: {
3828 NT_PRINTER_INFO_LEVEL *printer = NULL;
3830 count = print_queue_status(snum, &queue, &status);
3832 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3833 goto done;
3835 for (j=0; j<count; j++) {
3836 construct_notify_jobs_info(&queue[j], info,
3837 printer, snum,
3838 option_type,
3839 queue[j].job,
3840 mem_ctx);
3843 free_a_printer(&printer, 2);
3845 done:
3846 SAFE_FREE(queue);
3847 break;
3853 * Debugging information, don't delete.
3856 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3857 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3858 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3860 for (i=0; i<info->count; i++) {
3861 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3862 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3863 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3866 return WERR_OK;
3869 /********************************************************************
3870 * spoolss_rfnpcnex
3871 ********************************************************************/
3873 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3875 POLICY_HND *handle = &q_u->handle;
3876 SPOOL_NOTIFY_INFO *info = &r_u->info;
3878 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3879 WERROR result = WERR_BADFID;
3881 /* we always have a NOTIFY_INFO struct */
3882 r_u->info_ptr=0x1;
3884 if (!Printer) {
3885 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3886 OUR_HANDLE(handle)));
3887 goto done;
3890 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3893 * We are now using the change value, and
3894 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3895 * I don't have a global notification system, I'm sending back all the
3896 * informations even when _NOTHING_ has changed.
3899 /* We need to keep track of the change value to send back in
3900 RRPCN replies otherwise our updates are ignored. */
3902 Printer->notify.fnpcn = True;
3904 if (Printer->notify.client_connected) {
3905 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3906 Printer->notify.change = q_u->change;
3909 /* just ignore the SPOOL_NOTIFY_OPTION */
3911 switch (Printer->printer_type) {
3912 case SPLHND_SERVER:
3913 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3914 break;
3916 case SPLHND_PRINTER:
3917 result = printer_notify_info(p, handle, info, p->mem_ctx);
3918 break;
3921 Printer->notify.fnpcn = False;
3923 done:
3924 return result;
3927 /********************************************************************
3928 * construct_printer_info_0
3929 * fill a printer_info_0 struct
3930 ********************************************************************/
3932 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3934 char *chaine = NULL;
3935 int count;
3936 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3937 counter_printer_0 *session_counter;
3938 uint32 global_counter;
3939 struct tm *t;
3940 time_t setuptime;
3941 print_status_struct status;
3942 TALLOC_CTX *ctx = talloc_tos();
3944 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3945 return False;
3947 init_unistr(&printer->printername, ntprinter->info_2->printername);
3949 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3950 if (!chaine) {
3951 free_a_printer(&ntprinter,2);
3952 return false;
3955 count = print_queue_length(snum, &status);
3957 /* check if we already have a counter for this printer */
3958 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3959 if (session_counter->snum == snum)
3960 break;
3963 init_unistr(&printer->servername, chaine);
3965 /* it's the first time, add it to the list */
3966 if (session_counter==NULL) {
3967 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3968 free_a_printer(&ntprinter, 2);
3969 return False;
3971 ZERO_STRUCTP(session_counter);
3972 session_counter->snum=snum;
3973 session_counter->counter=0;
3974 DLIST_ADD(counter_list, session_counter);
3977 /* increment it */
3978 session_counter->counter++;
3980 /* JFM:
3981 * the global_counter should be stored in a TDB as it's common to all the clients
3982 * and should be zeroed on samba startup
3984 global_counter=session_counter->counter;
3985 printer->cjobs = count;
3986 printer->total_jobs = 0;
3987 printer->total_bytes = 0;
3989 setuptime = (time_t)ntprinter->info_2->setuptime;
3990 t=gmtime(&setuptime);
3992 printer->year = t->tm_year+1900;
3993 printer->month = t->tm_mon+1;
3994 printer->dayofweek = t->tm_wday;
3995 printer->day = t->tm_mday;
3996 printer->hour = t->tm_hour;
3997 printer->minute = t->tm_min;
3998 printer->second = t->tm_sec;
3999 printer->milliseconds = 0;
4001 printer->global_counter = global_counter;
4002 printer->total_pages = 0;
4004 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4005 printer->major_version = 0x0005; /* NT 5 */
4006 printer->build_version = 0x0893; /* build 2195 */
4008 printer->unknown7 = 0x1;
4009 printer->unknown8 = 0x0;
4010 printer->unknown9 = 0x0;
4011 printer->session_counter = session_counter->counter;
4012 printer->unknown11 = 0x0;
4013 printer->printer_errors = 0x0; /* number of print failure */
4014 printer->unknown13 = 0x0;
4015 printer->unknown14 = 0x1;
4016 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4017 printer->unknown16 = 0x0;
4018 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4019 printer->unknown18 = 0x0;
4020 printer->status = nt_printq_status(status.status);
4021 printer->unknown20 = 0x0;
4022 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4023 printer->unknown22 = 0x0;
4024 printer->unknown23 = 0x6; /* 6 ???*/
4025 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4026 printer->unknown25 = 0;
4027 printer->unknown26 = 0;
4028 printer->unknown27 = 0;
4029 printer->unknown28 = 0;
4030 printer->unknown29 = 0;
4032 free_a_printer(&ntprinter,2);
4033 return (True);
4036 /********************************************************************
4037 * construct_printer_info_1
4038 * fill a printer_info_1 struct
4039 ********************************************************************/
4040 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4042 char *chaine = NULL;
4043 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4044 TALLOC_CTX *ctx = talloc_tos();
4046 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4047 return false;
4049 printer->flags=flags;
4051 if (*ntprinter->info_2->comment == '\0') {
4052 init_unistr(&printer->comment, lp_comment(snum));
4053 chaine = talloc_asprintf(ctx,
4054 "%s,%s,%s", ntprinter->info_2->printername,
4055 ntprinter->info_2->drivername, lp_comment(snum));
4057 else {
4058 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4059 chaine = talloc_asprintf(ctx,
4060 "%s,%s,%s", ntprinter->info_2->printername,
4061 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4064 if (!chaine) {
4065 free_a_printer(&ntprinter,2);
4066 return false;
4069 init_unistr(&printer->description, chaine);
4070 init_unistr(&printer->name, ntprinter->info_2->printername);
4072 free_a_printer(&ntprinter,2);
4074 return True;
4077 /****************************************************************************
4078 Free a DEVMODE struct.
4079 ****************************************************************************/
4081 static void free_dev_mode(DEVICEMODE *dev)
4083 if (dev == NULL)
4084 return;
4086 SAFE_FREE(dev->dev_private);
4087 SAFE_FREE(dev);
4091 /****************************************************************************
4092 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4093 should be valid upon entry
4094 ****************************************************************************/
4096 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4098 if ( !devmode || !ntdevmode )
4099 return False;
4101 init_unistr(&devmode->devicename, ntdevmode->devicename);
4103 init_unistr(&devmode->formname, ntdevmode->formname);
4105 devmode->specversion = ntdevmode->specversion;
4106 devmode->driverversion = ntdevmode->driverversion;
4107 devmode->size = ntdevmode->size;
4108 devmode->driverextra = ntdevmode->driverextra;
4109 devmode->fields = ntdevmode->fields;
4111 devmode->orientation = ntdevmode->orientation;
4112 devmode->papersize = ntdevmode->papersize;
4113 devmode->paperlength = ntdevmode->paperlength;
4114 devmode->paperwidth = ntdevmode->paperwidth;
4115 devmode->scale = ntdevmode->scale;
4116 devmode->copies = ntdevmode->copies;
4117 devmode->defaultsource = ntdevmode->defaultsource;
4118 devmode->printquality = ntdevmode->printquality;
4119 devmode->color = ntdevmode->color;
4120 devmode->duplex = ntdevmode->duplex;
4121 devmode->yresolution = ntdevmode->yresolution;
4122 devmode->ttoption = ntdevmode->ttoption;
4123 devmode->collate = ntdevmode->collate;
4124 devmode->icmmethod = ntdevmode->icmmethod;
4125 devmode->icmintent = ntdevmode->icmintent;
4126 devmode->mediatype = ntdevmode->mediatype;
4127 devmode->dithertype = ntdevmode->dithertype;
4129 if (ntdevmode->nt_dev_private != NULL) {
4130 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4131 return False;
4134 return True;
4137 /****************************************************************************
4138 Create a DEVMODE struct. Returns malloced memory.
4139 ****************************************************************************/
4141 DEVICEMODE *construct_dev_mode(const char *servicename)
4143 NT_PRINTER_INFO_LEVEL *printer = NULL;
4144 DEVICEMODE *devmode = NULL;
4146 DEBUG(7,("construct_dev_mode\n"));
4148 DEBUGADD(8,("getting printer characteristics\n"));
4150 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4151 return NULL;
4153 if ( !printer->info_2->devmode ) {
4154 DEBUG(5, ("BONG! There was no device mode!\n"));
4155 goto done;
4158 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4159 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4160 goto done;
4163 ZERO_STRUCTP(devmode);
4165 DEBUGADD(8,("loading DEVICEMODE\n"));
4167 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4168 free_dev_mode( devmode );
4169 devmode = NULL;
4172 done:
4173 free_a_printer(&printer,2);
4175 return devmode;
4178 /********************************************************************
4179 * construct_printer_info_2
4180 * fill a printer_info_2 struct
4181 ********************************************************************/
4183 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4185 int count;
4186 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4188 print_status_struct status;
4190 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4191 return False;
4193 count = print_queue_length(snum, &status);
4195 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4196 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4197 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4198 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4199 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4201 if (*ntprinter->info_2->comment == '\0')
4202 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4203 else
4204 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4206 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4207 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4208 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4209 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4210 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4212 printer->attributes = ntprinter->info_2->attributes;
4214 printer->priority = ntprinter->info_2->priority; /* priority */
4215 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4216 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4217 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4218 printer->status = nt_printq_status(status.status); /* status */
4219 printer->cjobs = count; /* jobs */
4220 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4222 if ( !(printer->devmode = construct_dev_mode(
4223 lp_const_servicename(snum))) )
4224 DEBUG(8, ("Returning NULL Devicemode!\n"));
4226 printer->secdesc = NULL;
4228 if ( ntprinter->info_2->secdesc_buf
4229 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4231 /* don't use talloc_steal() here unless you do a deep steal of all
4232 the SEC_DESC members */
4234 printer->secdesc = dup_sec_desc( talloc_tos(),
4235 ntprinter->info_2->secdesc_buf->sd );
4238 free_a_printer(&ntprinter, 2);
4240 return True;
4243 /********************************************************************
4244 * construct_printer_info_3
4245 * fill a printer_info_3 struct
4246 ********************************************************************/
4248 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4250 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4251 PRINTER_INFO_3 *printer = NULL;
4253 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4254 return False;
4256 *pp_printer = NULL;
4257 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4258 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4259 free_a_printer(&ntprinter, 2);
4260 return False;
4263 ZERO_STRUCTP(printer);
4265 /* These are the components of the SD we are returning. */
4267 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4268 /* don't use talloc_steal() here unless you do a deep steal of all
4269 the SEC_DESC members */
4271 printer->secdesc = dup_sec_desc( talloc_tos(),
4272 ntprinter->info_2->secdesc_buf->sd );
4275 free_a_printer(&ntprinter, 2);
4277 *pp_printer = printer;
4278 return True;
4281 /********************************************************************
4282 * construct_printer_info_4
4283 * fill a printer_info_4 struct
4284 ********************************************************************/
4286 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4288 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4290 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4291 return False;
4293 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4294 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4295 printer->attributes = ntprinter->info_2->attributes;
4297 free_a_printer(&ntprinter, 2);
4298 return True;
4301 /********************************************************************
4302 * construct_printer_info_5
4303 * fill a printer_info_5 struct
4304 ********************************************************************/
4306 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4308 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4310 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4311 return False;
4313 init_unistr(&printer->printername, ntprinter->info_2->printername);
4314 init_unistr(&printer->portname, ntprinter->info_2->portname);
4315 printer->attributes = ntprinter->info_2->attributes;
4317 /* these two are not used by NT+ according to MSDN */
4319 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4320 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4322 free_a_printer(&ntprinter, 2);
4324 return True;
4327 /********************************************************************
4328 * construct_printer_info_6
4329 * fill a printer_info_6 struct
4330 ********************************************************************/
4332 static bool construct_printer_info_6(Printer_entry *print_hnd,
4333 PRINTER_INFO_6 *printer,
4334 int snum)
4336 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4337 int count;
4338 print_status_struct status;
4340 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4341 lp_const_servicename(snum))))
4342 return False;
4344 count = print_queue_length(snum, &status);
4346 printer->status = nt_printq_status(status.status);
4348 free_a_printer(&ntprinter, 2);
4350 return True;
4353 /********************************************************************
4354 * construct_printer_info_7
4355 * fill a printer_info_7 struct
4356 ********************************************************************/
4358 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4360 char *guid_str = NULL;
4361 struct GUID guid;
4363 if (is_printer_published(print_hnd, snum, &guid)) {
4364 asprintf(&guid_str, "{%s}",
4365 smb_uuid_string(talloc_tos(), guid));
4366 strupper_m(guid_str);
4367 init_unistr(&printer->guid, guid_str);
4368 printer->action = SPOOL_DS_PUBLISH;
4369 } else {
4370 init_unistr(&printer->guid, "");
4371 printer->action = SPOOL_DS_UNPUBLISH;
4374 return True;
4377 /********************************************************************
4378 Spoolss_enumprinters.
4379 ********************************************************************/
4381 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4383 int snum;
4384 int i;
4385 int n_services=lp_numservices();
4386 PRINTER_INFO_1 *printers=NULL;
4387 PRINTER_INFO_1 current_prt;
4388 WERROR result = WERR_OK;
4390 DEBUG(4,("enum_all_printers_info_1\n"));
4392 for (snum=0; snum<n_services; snum++) {
4393 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4394 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4396 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4397 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4398 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4399 *returned=0;
4400 return WERR_NOMEM;
4402 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4404 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4405 (*returned)++;
4410 /* check the required size. */
4411 for (i=0; i<*returned; i++)
4412 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4414 if (*needed > offered) {
4415 result = WERR_INSUFFICIENT_BUFFER;
4416 goto out;
4419 if (!rpcbuf_alloc_size(buffer, *needed)) {
4420 result = WERR_NOMEM;
4421 goto out;
4424 /* fill the buffer with the structures */
4425 for (i=0; i<*returned; i++)
4426 smb_io_printer_info_1("", buffer, &printers[i], 0);
4428 out:
4429 /* clear memory */
4431 SAFE_FREE(printers);
4433 if ( !W_ERROR_IS_OK(result) )
4434 *returned = 0;
4436 return result;
4439 /********************************************************************
4440 enum_all_printers_info_1_local.
4441 *********************************************************************/
4443 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4445 DEBUG(4,("enum_all_printers_info_1_local\n"));
4447 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4450 /********************************************************************
4451 enum_all_printers_info_1_name.
4452 *********************************************************************/
4454 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4456 char *s = name;
4458 DEBUG(4,("enum_all_printers_info_1_name\n"));
4460 if ((name[0] == '\\') && (name[1] == '\\'))
4461 s = name + 2;
4463 if (is_myname_or_ipaddr(s)) {
4464 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4466 else
4467 return WERR_INVALID_NAME;
4470 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4471 /********************************************************************
4472 enum_all_printers_info_1_remote.
4473 *********************************************************************/
4475 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4477 PRINTER_INFO_1 *printer;
4478 fstring printername;
4479 fstring desc;
4480 fstring comment;
4481 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4482 WERROR result = WERR_OK;
4484 /* JFM: currently it's more a place holder than anything else.
4485 * In the spooler world there is a notion of server registration.
4486 * the print servers are registered on the PDC (in the same domain)
4488 * We should have a TDB here. The registration is done thru an
4489 * undocumented RPC call.
4492 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4493 return WERR_NOMEM;
4495 *returned=1;
4497 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4498 slprintf(desc, sizeof(desc)-1,"%s", name);
4499 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4501 init_unistr(&printer->description, desc);
4502 init_unistr(&printer->name, printername);
4503 init_unistr(&printer->comment, comment);
4504 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4506 /* check the required size. */
4507 *needed += spoolss_size_printer_info_1(printer);
4509 if (*needed > offered) {
4510 result = WERR_INSUFFICIENT_BUFFER;
4511 goto out;
4514 if (!rpcbuf_alloc_size(buffer, *needed)) {
4515 result = WERR_NOMEM;
4516 goto out;
4519 /* fill the buffer with the structures */
4520 smb_io_printer_info_1("", buffer, printer, 0);
4522 out:
4523 /* clear memory */
4524 SAFE_FREE(printer);
4526 if ( !W_ERROR_IS_OK(result) )
4527 *returned = 0;
4529 return result;
4532 #endif
4534 /********************************************************************
4535 enum_all_printers_info_1_network.
4536 *********************************************************************/
4538 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4540 char *s = name;
4542 DEBUG(4,("enum_all_printers_info_1_network\n"));
4544 /* If we respond to a enum_printers level 1 on our name with flags
4545 set to PRINTER_ENUM_REMOTE with a list of printers then these
4546 printers incorrectly appear in the APW browse list.
4547 Specifically the printers for the server appear at the workgroup
4548 level where all the other servers in the domain are
4549 listed. Windows responds to this call with a
4550 WERR_CAN_NOT_COMPLETE so we should do the same. */
4552 if (name[0] == '\\' && name[1] == '\\')
4553 s = name + 2;
4555 if (is_myname_or_ipaddr(s))
4556 return WERR_CAN_NOT_COMPLETE;
4558 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4561 /********************************************************************
4562 * api_spoolss_enumprinters
4564 * called from api_spoolss_enumprinters (see this to understand)
4565 ********************************************************************/
4567 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4569 int snum;
4570 int i;
4571 int n_services=lp_numservices();
4572 PRINTER_INFO_2 *printers=NULL;
4573 PRINTER_INFO_2 current_prt;
4574 WERROR result = WERR_OK;
4576 *returned = 0;
4578 for (snum=0; snum<n_services; snum++) {
4579 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4580 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4582 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4583 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4584 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4585 *returned = 0;
4586 return WERR_NOMEM;
4589 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4591 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4593 (*returned)++;
4598 /* check the required size. */
4599 for (i=0; i<*returned; i++)
4600 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4602 if (*needed > offered) {
4603 result = WERR_INSUFFICIENT_BUFFER;
4604 goto out;
4607 if (!rpcbuf_alloc_size(buffer, *needed)) {
4608 result = WERR_NOMEM;
4609 goto out;
4612 /* fill the buffer with the structures */
4613 for (i=0; i<*returned; i++)
4614 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4616 out:
4617 /* clear memory */
4619 for (i=0; i<*returned; i++)
4620 free_devmode(printers[i].devmode);
4622 SAFE_FREE(printers);
4624 if ( !W_ERROR_IS_OK(result) )
4625 *returned = 0;
4627 return result;
4630 /********************************************************************
4631 * handle enumeration of printers at level 1
4632 ********************************************************************/
4634 static WERROR enumprinters_level1( uint32 flags, fstring name,
4635 RPC_BUFFER *buffer, uint32 offered,
4636 uint32 *needed, uint32 *returned)
4638 /* Not all the flags are equals */
4640 if (flags & PRINTER_ENUM_LOCAL)
4641 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4643 if (flags & PRINTER_ENUM_NAME)
4644 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4646 #if 0 /* JERRY - disabled for now */
4647 if (flags & PRINTER_ENUM_REMOTE)
4648 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4649 #endif
4651 if (flags & PRINTER_ENUM_NETWORK)
4652 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4654 return WERR_OK; /* NT4sp5 does that */
4657 /********************************************************************
4658 * handle enumeration of printers at level 2
4659 ********************************************************************/
4661 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4662 RPC_BUFFER *buffer, uint32 offered,
4663 uint32 *needed, uint32 *returned)
4665 char *s = servername;
4667 if (flags & PRINTER_ENUM_LOCAL) {
4668 return enum_all_printers_info_2(buffer, offered, needed, returned);
4671 if (flags & PRINTER_ENUM_NAME) {
4672 if ((servername[0] == '\\') && (servername[1] == '\\'))
4673 s = servername + 2;
4674 if (is_myname_or_ipaddr(s))
4675 return enum_all_printers_info_2(buffer, offered, needed, returned);
4676 else
4677 return WERR_INVALID_NAME;
4680 if (flags & PRINTER_ENUM_REMOTE)
4681 return WERR_UNKNOWN_LEVEL;
4683 return WERR_OK;
4686 /********************************************************************
4687 * handle enumeration of printers at level 5
4688 ********************************************************************/
4690 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4691 RPC_BUFFER *buffer, uint32 offered,
4692 uint32 *needed, uint32 *returned)
4694 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4695 return WERR_OK;
4698 /********************************************************************
4699 * api_spoolss_enumprinters
4701 * called from api_spoolss_enumprinters (see this to understand)
4702 ********************************************************************/
4704 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4706 uint32 flags = q_u->flags;
4707 UNISTR2 *servername = &q_u->servername;
4708 uint32 level = q_u->level;
4709 RPC_BUFFER *buffer = NULL;
4710 uint32 offered = q_u->offered;
4711 uint32 *needed = &r_u->needed;
4712 uint32 *returned = &r_u->returned;
4714 fstring name;
4716 /* that's an [in out] buffer */
4718 if (!q_u->buffer && (offered!=0)) {
4719 return WERR_INVALID_PARAM;
4722 rpcbuf_move(q_u->buffer, &r_u->buffer);
4723 buffer = r_u->buffer;
4725 DEBUG(4,("_spoolss_enumprinters\n"));
4727 *needed=0;
4728 *returned=0;
4731 * Level 1:
4732 * flags==PRINTER_ENUM_NAME
4733 * if name=="" then enumerates all printers
4734 * if name!="" then enumerate the printer
4735 * flags==PRINTER_ENUM_REMOTE
4736 * name is NULL, enumerate printers
4737 * Level 2: name!="" enumerates printers, name can't be NULL
4738 * Level 3: doesn't exist
4739 * Level 4: does a local registry lookup
4740 * Level 5: same as Level 2
4743 unistr2_to_ascii(name, servername, sizeof(name));
4744 strupper_m(name);
4746 switch (level) {
4747 case 1:
4748 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4749 case 2:
4750 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4751 case 5:
4752 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4753 case 3:
4754 case 4:
4755 break;
4757 return WERR_UNKNOWN_LEVEL;
4760 /****************************************************************************
4761 ****************************************************************************/
4763 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4765 PRINTER_INFO_0 *printer=NULL;
4766 WERROR result = WERR_OK;
4768 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4769 return WERR_NOMEM;
4771 construct_printer_info_0(print_hnd, printer, snum);
4773 /* check the required size. */
4774 *needed += spoolss_size_printer_info_0(printer);
4776 if (*needed > offered) {
4777 result = WERR_INSUFFICIENT_BUFFER;
4778 goto out;
4781 if (!rpcbuf_alloc_size(buffer, *needed)) {
4782 result = WERR_NOMEM;
4783 goto out;
4786 /* fill the buffer with the structures */
4787 smb_io_printer_info_0("", buffer, printer, 0);
4789 out:
4790 /* clear memory */
4792 SAFE_FREE(printer);
4794 return result;
4797 /****************************************************************************
4798 ****************************************************************************/
4800 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4802 PRINTER_INFO_1 *printer=NULL;
4803 WERROR result = WERR_OK;
4805 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4806 return WERR_NOMEM;
4808 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4810 /* check the required size. */
4811 *needed += spoolss_size_printer_info_1(printer);
4813 if (*needed > offered) {
4814 result = WERR_INSUFFICIENT_BUFFER;
4815 goto out;
4818 if (!rpcbuf_alloc_size(buffer, *needed)) {
4819 result = WERR_NOMEM;
4820 goto out;
4823 /* fill the buffer with the structures */
4824 smb_io_printer_info_1("", buffer, printer, 0);
4826 out:
4827 /* clear memory */
4828 SAFE_FREE(printer);
4830 return result;
4833 /****************************************************************************
4834 ****************************************************************************/
4836 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4838 PRINTER_INFO_2 *printer=NULL;
4839 WERROR result = WERR_OK;
4841 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4842 return WERR_NOMEM;
4844 construct_printer_info_2(print_hnd, printer, snum);
4846 /* check the required size. */
4847 *needed += spoolss_size_printer_info_2(printer);
4849 if (*needed > offered) {
4850 result = WERR_INSUFFICIENT_BUFFER;
4851 goto out;
4854 if (!rpcbuf_alloc_size(buffer, *needed)) {
4855 result = WERR_NOMEM;
4856 goto out;
4859 /* fill the buffer with the structures */
4860 if (!smb_io_printer_info_2("", buffer, printer, 0))
4861 result = WERR_NOMEM;
4863 out:
4864 /* clear memory */
4865 free_printer_info_2(printer);
4867 return result;
4870 /****************************************************************************
4871 ****************************************************************************/
4873 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4875 PRINTER_INFO_3 *printer=NULL;
4876 WERROR result = WERR_OK;
4878 if (!construct_printer_info_3(print_hnd, &printer, snum))
4879 return WERR_NOMEM;
4881 /* check the required size. */
4882 *needed += spoolss_size_printer_info_3(printer);
4884 if (*needed > offered) {
4885 result = WERR_INSUFFICIENT_BUFFER;
4886 goto out;
4889 if (!rpcbuf_alloc_size(buffer, *needed)) {
4890 result = WERR_NOMEM;
4891 goto out;
4894 /* fill the buffer with the structures */
4895 smb_io_printer_info_3("", buffer, printer, 0);
4897 out:
4898 /* clear memory */
4899 free_printer_info_3(printer);
4901 return result;
4904 /****************************************************************************
4905 ****************************************************************************/
4907 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4909 PRINTER_INFO_4 *printer=NULL;
4910 WERROR result = WERR_OK;
4912 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4913 return WERR_NOMEM;
4915 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4916 SAFE_FREE(printer);
4917 return WERR_NOMEM;
4920 /* check the required size. */
4921 *needed += spoolss_size_printer_info_4(printer);
4923 if (*needed > offered) {
4924 result = WERR_INSUFFICIENT_BUFFER;
4925 goto out;
4928 if (!rpcbuf_alloc_size(buffer, *needed)) {
4929 result = WERR_NOMEM;
4930 goto out;
4933 /* fill the buffer with the structures */
4934 smb_io_printer_info_4("", buffer, printer, 0);
4936 out:
4937 /* clear memory */
4938 free_printer_info_4(printer);
4940 return result;
4943 /****************************************************************************
4944 ****************************************************************************/
4946 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4948 PRINTER_INFO_5 *printer=NULL;
4949 WERROR result = WERR_OK;
4951 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4952 return WERR_NOMEM;
4954 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4955 free_printer_info_5(printer);
4956 return WERR_NOMEM;
4959 /* check the required size. */
4960 *needed += spoolss_size_printer_info_5(printer);
4962 if (*needed > offered) {
4963 result = WERR_INSUFFICIENT_BUFFER;
4964 goto out;
4967 if (!rpcbuf_alloc_size(buffer, *needed)) {
4968 result = WERR_NOMEM;
4969 goto out;
4972 /* fill the buffer with the structures */
4973 smb_io_printer_info_5("", buffer, printer, 0);
4975 out:
4976 /* clear memory */
4977 free_printer_info_5(printer);
4979 return result;
4982 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4983 int snum,
4984 RPC_BUFFER *buffer, uint32 offered,
4985 uint32 *needed)
4987 PRINTER_INFO_6 *printer;
4988 WERROR result = WERR_OK;
4990 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4991 return WERR_NOMEM;
4994 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4995 free_printer_info_6(printer);
4996 return WERR_NOMEM;
4999 /* check the required size. */
5000 *needed += spoolss_size_printer_info_6(printer);
5002 if (*needed > offered) {
5003 result = WERR_INSUFFICIENT_BUFFER;
5004 goto out;
5007 if (!rpcbuf_alloc_size(buffer, *needed)) {
5008 result = WERR_NOMEM;
5009 goto out;
5012 /* fill the buffer with the structures */
5013 smb_io_printer_info_6("", buffer, printer, 0);
5015 out:
5016 /* clear memory */
5017 free_printer_info_6(printer);
5019 return result;
5022 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5024 PRINTER_INFO_7 *printer=NULL;
5025 WERROR result = WERR_OK;
5027 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5028 return WERR_NOMEM;
5030 if (!construct_printer_info_7(print_hnd, printer, snum))
5031 return WERR_NOMEM;
5033 /* check the required size. */
5034 *needed += spoolss_size_printer_info_7(printer);
5036 if (*needed > offered) {
5037 result = WERR_INSUFFICIENT_BUFFER;
5038 goto out;
5041 if (!rpcbuf_alloc_size(buffer, *needed)) {
5042 result = WERR_NOMEM;
5043 goto out;
5047 /* fill the buffer with the structures */
5048 smb_io_printer_info_7("", buffer, printer, 0);
5050 out:
5051 /* clear memory */
5052 free_printer_info_7(printer);
5054 return result;
5057 /****************************************************************************
5058 ****************************************************************************/
5060 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5062 POLICY_HND *handle = &q_u->handle;
5063 uint32 level = q_u->level;
5064 RPC_BUFFER *buffer = NULL;
5065 uint32 offered = q_u->offered;
5066 uint32 *needed = &r_u->needed;
5067 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5069 int snum;
5071 /* that's an [in out] buffer */
5073 if (!q_u->buffer && (offered!=0)) {
5074 return WERR_INVALID_PARAM;
5077 rpcbuf_move(q_u->buffer, &r_u->buffer);
5078 buffer = r_u->buffer;
5080 *needed=0;
5082 if (!get_printer_snum(p, handle, &snum, NULL))
5083 return WERR_BADFID;
5085 switch (level) {
5086 case 0:
5087 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5088 case 1:
5089 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5090 case 2:
5091 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5092 case 3:
5093 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5094 case 4:
5095 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5096 case 5:
5097 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5098 case 6:
5099 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5100 case 7:
5101 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5103 return WERR_UNKNOWN_LEVEL;
5106 /********************************************************************
5107 * fill a DRIVER_INFO_1 struct
5108 ********************************************************************/
5110 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5112 init_unistr( &info->name, driver.info_3->name);
5115 /********************************************************************
5116 * construct_printer_driver_info_1
5117 ********************************************************************/
5119 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5121 NT_PRINTER_INFO_LEVEL *printer = NULL;
5122 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5124 ZERO_STRUCT(driver);
5126 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5127 return WERR_INVALID_PRINTER_NAME;
5129 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5130 free_a_printer(&printer, 2);
5131 return WERR_UNKNOWN_PRINTER_DRIVER;
5134 fill_printer_driver_info_1(info, driver, servername, architecture);
5136 free_a_printer(&printer,2);
5138 return WERR_OK;
5141 /********************************************************************
5142 * construct_printer_driver_info_2
5143 * fill a printer_info_2 struct
5144 ********************************************************************/
5146 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5148 TALLOC_CTX *ctx = talloc_tos();
5149 char *temp = NULL;
5151 info->version=driver.info_3->cversion;
5153 init_unistr( &info->name, driver.info_3->name );
5154 init_unistr( &info->architecture, driver.info_3->environment );
5157 if (strlen(driver.info_3->driverpath)) {
5158 temp = talloc_asprintf(ctx,
5159 "\\\\%s%s",
5160 servername,
5161 driver.info_3->driverpath);
5162 init_unistr( &info->driverpath, temp );
5163 } else {
5164 init_unistr( &info->driverpath, "" );
5167 TALLOC_FREE(temp);
5168 if (strlen(driver.info_3->datafile)) {
5169 temp = talloc_asprintf(ctx,
5170 "\\\\%s%s",
5171 servername,
5172 driver.info_3->datafile);
5173 init_unistr( &info->datafile, temp );
5174 } else
5175 init_unistr( &info->datafile, "" );
5177 TALLOC_FREE(temp);
5178 if (strlen(driver.info_3->configfile)) {
5179 temp = talloc_asprintf(ctx,
5180 "\\\\%s%s",
5181 servername,
5182 driver.info_3->configfile);
5183 init_unistr( &info->configfile, temp );
5184 } else
5185 init_unistr( &info->configfile, "" );
5188 /********************************************************************
5189 * construct_printer_driver_info_2
5190 * fill a printer_info_2 struct
5191 ********************************************************************/
5193 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5195 NT_PRINTER_INFO_LEVEL *printer = NULL;
5196 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5198 ZERO_STRUCT(printer);
5199 ZERO_STRUCT(driver);
5201 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5202 return WERR_INVALID_PRINTER_NAME;
5204 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5205 free_a_printer(&printer, 2);
5206 return WERR_UNKNOWN_PRINTER_DRIVER;
5209 fill_printer_driver_info_2(info, driver, servername);
5211 free_a_printer(&printer,2);
5213 return WERR_OK;
5216 /********************************************************************
5217 * copy a strings array and convert to UNICODE
5219 * convert an array of ascii string to a UNICODE string
5220 ********************************************************************/
5222 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5224 int i=0;
5225 int j=0;
5226 const char *v;
5227 char *line = NULL;
5228 TALLOC_CTX *ctx = talloc_tos();
5230 DEBUG(6,("init_unistr_array\n"));
5231 *uni_array=NULL;
5233 while (true) {
5234 if ( !char_array ) {
5235 v = "";
5236 } else {
5237 v = char_array[i];
5238 if (!v)
5239 v = ""; /* hack to handle null lists */
5242 /* hack to allow this to be used in places other than when generating
5243 the list of dependent files */
5245 TALLOC_FREE(line);
5246 if ( servername ) {
5247 line = talloc_asprintf(ctx,
5248 "\\\\%s%s",
5249 servername,
5251 } else {
5252 line = talloc_strdup(ctx, v);
5255 if (!line) {
5256 SAFE_FREE(*uni_array);
5257 return 0;
5259 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5261 /* add one extra unit16 for the second terminating NULL */
5263 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5264 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5265 return 0;
5268 if ( !strlen(v) )
5269 break;
5271 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5272 i++;
5275 if (*uni_array) {
5276 /* special case for ""; we need to add both NULL's here */
5277 if (!j)
5278 (*uni_array)[j++]=0x0000;
5279 (*uni_array)[j]=0x0000;
5282 DEBUGADD(6,("last one:done\n"));
5284 /* return size of array in uint16's */
5286 return j+1;
5289 /********************************************************************
5290 * construct_printer_info_3
5291 * fill a printer_info_3 struct
5292 ********************************************************************/
5294 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5296 char *temp = NULL;
5297 TALLOC_CTX *ctx = talloc_tos();
5299 ZERO_STRUCTP(info);
5301 info->version=driver.info_3->cversion;
5303 init_unistr( &info->name, driver.info_3->name );
5304 init_unistr( &info->architecture, driver.info_3->environment );
5306 if (strlen(driver.info_3->driverpath)) {
5307 temp = talloc_asprintf(ctx,
5308 "\\\\%s%s",
5309 servername,
5310 driver.info_3->driverpath);
5311 init_unistr( &info->driverpath, temp );
5312 } else
5313 init_unistr( &info->driverpath, "" );
5315 TALLOC_FREE(temp);
5316 if (strlen(driver.info_3->datafile)) {
5317 temp = talloc_asprintf(ctx,
5318 "\\\\%s%s",
5319 servername,
5320 driver.info_3->datafile);
5321 init_unistr( &info->datafile, temp );
5322 } else
5323 init_unistr( &info->datafile, "" );
5325 TALLOC_FREE(temp);
5326 if (strlen(driver.info_3->configfile)) {
5327 temp = talloc_asprintf(ctx,
5328 "\\\\%s%s",
5329 servername,
5330 driver.info_3->configfile);
5331 init_unistr( &info->configfile, temp );
5332 } else
5333 init_unistr( &info->configfile, "" );
5335 TALLOC_FREE(temp);
5336 if (strlen(driver.info_3->helpfile)) {
5337 temp = talloc_asprintf(ctx,
5338 "\\\\%s%s",
5339 servername,
5340 driver.info_3->helpfile);
5341 init_unistr( &info->helpfile, temp );
5342 } else
5343 init_unistr( &info->helpfile, "" );
5345 TALLOC_FREE(temp);
5346 init_unistr( &info->monitorname, driver.info_3->monitorname );
5347 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5349 info->dependentfiles=NULL;
5350 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5353 /********************************************************************
5354 * construct_printer_info_3
5355 * fill a printer_info_3 struct
5356 ********************************************************************/
5358 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5360 NT_PRINTER_INFO_LEVEL *printer = NULL;
5361 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5362 WERROR status;
5363 ZERO_STRUCT(driver);
5365 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5366 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5367 if (!W_ERROR_IS_OK(status))
5368 return WERR_INVALID_PRINTER_NAME;
5370 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5371 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5373 #if 0 /* JERRY */
5376 * I put this code in during testing. Helpful when commenting out the
5377 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5378 * as win2k always queries the driver using an infor level of 6.
5379 * I've left it in (but ifdef'd out) because I'll probably
5380 * use it in experimentation again in the future. --jerry 22/01/2002
5383 if (!W_ERROR_IS_OK(status)) {
5385 * Is this a W2k client ?
5387 if (version == 3) {
5388 /* Yes - try again with a WinNT driver. */
5389 version = 2;
5390 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5391 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5393 #endif
5395 if (!W_ERROR_IS_OK(status)) {
5396 free_a_printer(&printer,2);
5397 return WERR_UNKNOWN_PRINTER_DRIVER;
5400 #if 0 /* JERRY */
5402 #endif
5405 fill_printer_driver_info_3(info, driver, servername);
5407 free_a_printer(&printer,2);
5409 return WERR_OK;
5412 /********************************************************************
5413 * construct_printer_info_6
5414 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5415 ********************************************************************/
5417 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5419 char *temp = NULL;
5420 fstring nullstr;
5421 TALLOC_CTX *ctx = talloc_tos();
5423 ZERO_STRUCTP(info);
5424 memset(&nullstr, '\0', sizeof(fstring));
5426 info->version=driver.info_3->cversion;
5428 init_unistr( &info->name, driver.info_3->name );
5429 init_unistr( &info->architecture, driver.info_3->environment );
5431 if (strlen(driver.info_3->driverpath)) {
5432 temp = talloc_asprintf(ctx,
5433 "\\\\%s%s",
5434 servername,
5435 driver.info_3->driverpath);
5436 init_unistr( &info->driverpath, temp );
5437 } else
5438 init_unistr( &info->driverpath, "" );
5440 TALLOC_FREE(temp);
5441 if (strlen(driver.info_3->datafile)) {
5442 temp = talloc_asprintf(ctx,
5443 "\\\\%s%s",
5444 servername,
5445 driver.info_3->datafile);
5446 init_unistr( &info->datafile, temp );
5447 } else
5448 init_unistr( &info->datafile, "" );
5450 TALLOC_FREE(temp);
5451 if (strlen(driver.info_3->configfile)) {
5452 temp = talloc_asprintf(ctx,
5453 "\\\\%s%s",
5454 servername,
5455 driver.info_3->configfile);
5456 init_unistr( &info->configfile, temp );
5457 } else
5458 init_unistr( &info->configfile, "" );
5460 TALLOC_FREE(temp);
5461 if (strlen(driver.info_3->helpfile)) {
5462 temp = talloc_asprintf(ctx,
5463 "\\\\%s%s",
5464 servername,
5465 driver.info_3->helpfile);
5466 init_unistr( &info->helpfile, temp );
5467 } else
5468 init_unistr( &info->helpfile, "" );
5470 TALLOC_FREE(temp);
5471 init_unistr( &info->monitorname, driver.info_3->monitorname );
5472 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5474 info->dependentfiles = NULL;
5475 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5477 info->previousdrivernames=NULL;
5478 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5480 info->driver_date=0;
5482 info->padding=0;
5483 info->driver_version_low=0;
5484 info->driver_version_high=0;
5486 init_unistr( &info->mfgname, "");
5487 init_unistr( &info->oem_url, "");
5488 init_unistr( &info->hardware_id, "");
5489 init_unistr( &info->provider, "");
5492 /********************************************************************
5493 * construct_printer_info_6
5494 * fill a printer_info_6 struct
5495 ********************************************************************/
5497 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5498 fstring servername, fstring architecture, uint32 version)
5500 NT_PRINTER_INFO_LEVEL *printer = NULL;
5501 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5502 WERROR status;
5504 ZERO_STRUCT(driver);
5506 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5508 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5510 if (!W_ERROR_IS_OK(status))
5511 return WERR_INVALID_PRINTER_NAME;
5513 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5515 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5517 if (!W_ERROR_IS_OK(status))
5520 * Is this a W2k client ?
5523 if (version < 3) {
5524 free_a_printer(&printer,2);
5525 return WERR_UNKNOWN_PRINTER_DRIVER;
5528 /* Yes - try again with a WinNT driver. */
5529 version = 2;
5530 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5531 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5532 if (!W_ERROR_IS_OK(status)) {
5533 free_a_printer(&printer,2);
5534 return WERR_UNKNOWN_PRINTER_DRIVER;
5538 fill_printer_driver_info_6(info, driver, servername);
5540 free_a_printer(&printer,2);
5541 free_a_printer_driver(driver, 3);
5543 return WERR_OK;
5546 /****************************************************************************
5547 ****************************************************************************/
5549 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5551 SAFE_FREE(info->dependentfiles);
5554 /****************************************************************************
5555 ****************************************************************************/
5557 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5559 SAFE_FREE(info->dependentfiles);
5562 /****************************************************************************
5563 ****************************************************************************/
5565 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5567 DRIVER_INFO_1 *info=NULL;
5568 WERROR result;
5570 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5571 return WERR_NOMEM;
5573 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5574 if (!W_ERROR_IS_OK(result))
5575 goto out;
5577 /* check the required size. */
5578 *needed += spoolss_size_printer_driver_info_1(info);
5580 if (*needed > offered) {
5581 result = WERR_INSUFFICIENT_BUFFER;
5582 goto out;
5585 if (!rpcbuf_alloc_size(buffer, *needed)) {
5586 result = WERR_NOMEM;
5587 goto out;
5590 /* fill the buffer with the structures */
5591 smb_io_printer_driver_info_1("", buffer, info, 0);
5593 out:
5594 /* clear memory */
5595 SAFE_FREE(info);
5597 return result;
5600 /****************************************************************************
5601 ****************************************************************************/
5603 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5605 DRIVER_INFO_2 *info=NULL;
5606 WERROR result;
5608 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5609 return WERR_NOMEM;
5611 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5612 if (!W_ERROR_IS_OK(result))
5613 goto out;
5615 /* check the required size. */
5616 *needed += spoolss_size_printer_driver_info_2(info);
5618 if (*needed > offered) {
5619 result = WERR_INSUFFICIENT_BUFFER;
5620 goto out;
5623 if (!rpcbuf_alloc_size(buffer, *needed)) {
5624 result = WERR_NOMEM;
5625 goto out;
5628 /* fill the buffer with the structures */
5629 smb_io_printer_driver_info_2("", buffer, info, 0);
5631 out:
5632 /* clear memory */
5633 SAFE_FREE(info);
5635 return result;
5638 /****************************************************************************
5639 ****************************************************************************/
5641 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5643 DRIVER_INFO_3 info;
5644 WERROR result;
5646 ZERO_STRUCT(info);
5648 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5649 if (!W_ERROR_IS_OK(result))
5650 goto out;
5652 /* check the required size. */
5653 *needed += spoolss_size_printer_driver_info_3(&info);
5655 if (*needed > offered) {
5656 result = WERR_INSUFFICIENT_BUFFER;
5657 goto out;
5660 if (!rpcbuf_alloc_size(buffer, *needed)) {
5661 result = WERR_NOMEM;
5662 goto out;
5665 /* fill the buffer with the structures */
5666 smb_io_printer_driver_info_3("", buffer, &info, 0);
5668 out:
5669 free_printer_driver_info_3(&info);
5671 return result;
5674 /****************************************************************************
5675 ****************************************************************************/
5677 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5679 DRIVER_INFO_6 info;
5680 WERROR result;
5682 ZERO_STRUCT(info);
5684 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5685 if (!W_ERROR_IS_OK(result))
5686 goto out;
5688 /* check the required size. */
5689 *needed += spoolss_size_printer_driver_info_6(&info);
5691 if (*needed > offered) {
5692 result = WERR_INSUFFICIENT_BUFFER;
5693 goto out;
5696 if (!rpcbuf_alloc_size(buffer, *needed)) {
5697 result = WERR_NOMEM;
5698 goto out;
5701 /* fill the buffer with the structures */
5702 smb_io_printer_driver_info_6("", buffer, &info, 0);
5704 out:
5705 free_printer_driver_info_6(&info);
5707 return result;
5710 /****************************************************************************
5711 ****************************************************************************/
5713 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5715 POLICY_HND *handle = &q_u->handle;
5716 UNISTR2 *uni_arch = &q_u->architecture;
5717 uint32 level = q_u->level;
5718 uint32 clientmajorversion = q_u->clientmajorversion;
5719 RPC_BUFFER *buffer = NULL;
5720 uint32 offered = q_u->offered;
5721 uint32 *needed = &r_u->needed;
5722 uint32 *servermajorversion = &r_u->servermajorversion;
5723 uint32 *serverminorversion = &r_u->serverminorversion;
5724 Printer_entry *printer;
5726 fstring servername;
5727 fstring architecture;
5728 int snum;
5730 /* that's an [in out] buffer */
5732 if (!q_u->buffer && (offered!=0)) {
5733 return WERR_INVALID_PARAM;
5736 rpcbuf_move(q_u->buffer, &r_u->buffer);
5737 buffer = r_u->buffer;
5739 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5741 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5742 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5743 return WERR_INVALID_PRINTER_NAME;
5746 *needed = 0;
5747 *servermajorversion = 0;
5748 *serverminorversion = 0;
5750 fstrcpy(servername, get_server_name( printer ));
5751 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5753 if (!get_printer_snum(p, handle, &snum, NULL))
5754 return WERR_BADFID;
5756 switch (level) {
5757 case 1:
5758 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5759 case 2:
5760 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5761 case 3:
5762 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5763 case 6:
5764 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5765 #if 0 /* JERRY */
5766 case 101:
5767 /* apparently this call is the equivalent of
5768 EnumPrinterDataEx() for the DsDriver key */
5769 break;
5770 #endif
5773 return WERR_UNKNOWN_LEVEL;
5776 /****************************************************************************
5777 ****************************************************************************/
5779 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5781 POLICY_HND *handle = &q_u->handle;
5783 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5785 if (!Printer) {
5786 DEBUG(3,("Error in startpageprinter printer handle\n"));
5787 return WERR_BADFID;
5790 Printer->page_started=True;
5791 return WERR_OK;
5794 /****************************************************************************
5795 ****************************************************************************/
5797 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5799 POLICY_HND *handle = &q_u->handle;
5800 int snum;
5802 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5804 if (!Printer) {
5805 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5806 return WERR_BADFID;
5809 if (!get_printer_snum(p, handle, &snum, NULL))
5810 return WERR_BADFID;
5812 Printer->page_started=False;
5813 print_job_endpage(snum, Printer->jobid);
5815 return WERR_OK;
5818 /********************************************************************
5819 * api_spoolss_getprinter
5820 * called from the spoolss dispatcher
5822 ********************************************************************/
5824 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5826 POLICY_HND *handle = &q_u->handle;
5827 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5828 uint32 *jobid = &r_u->jobid;
5829 TALLOC_CTX *ctx = p->mem_ctx;
5830 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5831 int snum;
5832 char *jobname = NULL;
5833 fstring datatype;
5834 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5836 if (!Printer) {
5837 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5838 return WERR_BADFID;
5842 * a nice thing with NT is it doesn't listen to what you tell it.
5843 * when asked to send _only_ RAW datas, it tries to send datas
5844 * in EMF format.
5846 * So I add checks like in NT Server ...
5849 if (info_1->p_datatype != 0) {
5850 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5851 if (strcmp(datatype, "RAW") != 0) {
5852 (*jobid)=0;
5853 return WERR_INVALID_DATATYPE;
5857 /* get the share number of the printer */
5858 if (!get_printer_snum(p, handle, &snum, NULL)) {
5859 return WERR_BADFID;
5862 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5864 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5866 /* An error occured in print_job_start() so return an appropriate
5867 NT error code. */
5869 if (Printer->jobid == -1) {
5870 return map_werror_from_unix(errno);
5873 Printer->document_started=True;
5874 (*jobid) = Printer->jobid;
5876 return WERR_OK;
5879 /********************************************************************
5880 * api_spoolss_getprinter
5881 * called from the spoolss dispatcher
5883 ********************************************************************/
5885 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5887 POLICY_HND *handle = &q_u->handle;
5889 return _spoolss_enddocprinter_internal(p, handle);
5892 /****************************************************************************
5893 ****************************************************************************/
5895 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5897 POLICY_HND *handle = &q_u->handle;
5898 uint32 buffer_size = q_u->buffer_size;
5899 uint8 *buffer = q_u->buffer;
5900 uint32 *buffer_written = &q_u->buffer_size2;
5901 int snum;
5902 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5904 if (!Printer) {
5905 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5906 r_u->buffer_written = q_u->buffer_size2;
5907 return WERR_BADFID;
5910 if (!get_printer_snum(p, handle, &snum, NULL))
5911 return WERR_BADFID;
5913 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5914 (SMB_OFF_T)-1, (size_t)buffer_size);
5915 if (*buffer_written == (uint32)-1) {
5916 r_u->buffer_written = 0;
5917 if (errno == ENOSPC)
5918 return WERR_NO_SPOOL_SPACE;
5919 else
5920 return WERR_ACCESS_DENIED;
5923 r_u->buffer_written = q_u->buffer_size2;
5925 return WERR_OK;
5928 /********************************************************************
5929 * api_spoolss_getprinter
5930 * called from the spoolss dispatcher
5932 ********************************************************************/
5934 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5935 pipes_struct *p)
5937 int snum;
5938 WERROR errcode = WERR_BADFUNC;
5939 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5941 if (!Printer) {
5942 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5943 return WERR_BADFID;
5946 if (!get_printer_snum(p, handle, &snum, NULL))
5947 return WERR_BADFID;
5949 switch (command) {
5950 case PRINTER_CONTROL_PAUSE:
5951 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5952 errcode = WERR_OK;
5954 break;
5955 case PRINTER_CONTROL_RESUME:
5956 case PRINTER_CONTROL_UNPAUSE:
5957 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5958 errcode = WERR_OK;
5960 break;
5961 case PRINTER_CONTROL_PURGE:
5962 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5963 errcode = WERR_OK;
5965 break;
5966 default:
5967 return WERR_UNKNOWN_LEVEL;
5970 return errcode;
5973 /********************************************************************
5974 * api_spoolss_abortprinter
5975 * From MSDN: "Deletes printer's spool file if printer is configured
5976 * for spooling"
5977 ********************************************************************/
5979 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5981 POLICY_HND *handle = &q_u->handle;
5982 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5983 int snum;
5984 WERROR errcode = WERR_OK;
5986 if (!Printer) {
5987 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5988 return WERR_BADFID;
5991 if (!get_printer_snum(p, handle, &snum, NULL))
5992 return WERR_BADFID;
5994 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5996 return errcode;
5999 /********************************************************************
6000 * called by spoolss_api_setprinter
6001 * when updating a printer description
6002 ********************************************************************/
6004 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6005 const SPOOL_PRINTER_INFO_LEVEL *info,
6006 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6008 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6009 WERROR result;
6010 int snum;
6012 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6014 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6015 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6016 OUR_HANDLE(handle)));
6018 result = WERR_BADFID;
6019 goto done;
6022 if (!secdesc_ctr) {
6023 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6024 result = WERR_INVALID_PARAM;
6025 goto done;
6028 /* Check the user has permissions to change the security
6029 descriptor. By experimentation with two NT machines, the user
6030 requires Full Access to the printer to change security
6031 information. */
6033 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6034 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6035 result = WERR_ACCESS_DENIED;
6036 goto done;
6039 /* NT seems to like setting the security descriptor even though
6040 nothing may have actually changed. */
6042 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6043 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6044 result = WERR_BADFID;
6045 goto done;
6048 if (DEBUGLEVEL >= 10) {
6049 SEC_ACL *the_acl;
6050 int i;
6052 the_acl = old_secdesc_ctr->sd->dacl;
6053 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6054 PRINTERNAME(snum), the_acl->num_aces));
6056 for (i = 0; i < the_acl->num_aces; i++) {
6057 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6058 &the_acl->aces[i].trustee),
6059 the_acl->aces[i].access_mask));
6062 the_acl = secdesc_ctr->sd->dacl;
6064 if (the_acl) {
6065 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6066 PRINTERNAME(snum), the_acl->num_aces));
6068 for (i = 0; i < the_acl->num_aces; i++) {
6069 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6070 &the_acl->aces[i].trustee),
6071 the_acl->aces[i].access_mask));
6073 } else {
6074 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6078 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6079 if (!new_secdesc_ctr) {
6080 result = WERR_NOMEM;
6081 goto done;
6084 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6085 result = WERR_OK;
6086 goto done;
6089 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6091 done:
6093 return result;
6096 /********************************************************************
6097 Canonicalize printer info from a client
6099 ATTN: It does not matter what we set the servername to hear
6100 since we do the necessary work in get_a_printer() to set it to
6101 the correct value based on what the client sent in the
6102 _spoolss_open_printer_ex().
6103 ********************************************************************/
6105 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6107 fstring printername;
6108 const char *p;
6110 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6111 "portname=%s drivername=%s comment=%s location=%s\n",
6112 info->servername, info->printername, info->sharename,
6113 info->portname, info->drivername, info->comment, info->location));
6115 /* we force some elements to "correct" values */
6116 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6117 fstrcpy(info->sharename, lp_servicename(snum));
6119 /* check to see if we allow printername != sharename */
6121 if ( lp_force_printername(snum) ) {
6122 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6123 global_myname(), info->sharename );
6124 } else {
6126 /* make sure printername is in \\server\printername format */
6128 fstrcpy( printername, info->printername );
6129 p = printername;
6130 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6131 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6132 p++;
6135 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6136 global_myname(), p );
6139 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6140 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6144 return True;
6147 /****************************************************************************
6148 ****************************************************************************/
6150 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6152 char *cmd = lp_addport_cmd();
6153 char *command = NULL;
6154 int ret;
6155 int fd;
6156 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6157 bool is_print_op = False;
6159 if ( !*cmd ) {
6160 return WERR_ACCESS_DENIED;
6163 command = talloc_asprintf(ctx,
6164 "%s \"%s\" \"%s\"", cmd, portname, uri );
6165 if (!command) {
6166 return WERR_NOMEM;
6169 if ( token )
6170 is_print_op = user_has_privileges( token, &se_printop );
6172 DEBUG(10,("Running [%s]\n", command));
6174 /********* BEGIN SePrintOperatorPrivilege **********/
6176 if ( is_print_op )
6177 become_root();
6179 ret = smbrun(command, &fd);
6181 if ( is_print_op )
6182 unbecome_root();
6184 /********* END SePrintOperatorPrivilege **********/
6186 DEBUGADD(10,("returned [%d]\n", ret));
6188 TALLOC_FREE(command);
6190 if ( ret != 0 ) {
6191 if (fd != -1)
6192 close(fd);
6193 return WERR_ACCESS_DENIED;
6196 return WERR_OK;
6199 /****************************************************************************
6200 ****************************************************************************/
6202 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6204 char *cmd = lp_addprinter_cmd();
6205 char **qlines;
6206 char *command = NULL;
6207 int numlines;
6208 int ret;
6209 int fd;
6210 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6211 bool is_print_op = False;
6212 char *remote_machine = talloc_strdup(ctx, "%m");
6214 if (!remote_machine) {
6215 return false;
6217 remote_machine = talloc_sub_basic(ctx,
6218 current_user_info.smb_name,
6219 current_user_info.domain,
6220 remote_machine);
6221 if (!remote_machine) {
6222 return false;
6225 command = talloc_asprintf(ctx,
6226 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6227 cmd, printer->info_2->printername, printer->info_2->sharename,
6228 printer->info_2->portname, printer->info_2->drivername,
6229 printer->info_2->location, printer->info_2->comment, remote_machine);
6230 if (!command) {
6231 return false;
6234 if ( token )
6235 is_print_op = user_has_privileges( token, &se_printop );
6237 DEBUG(10,("Running [%s]\n", command));
6239 /********* BEGIN SePrintOperatorPrivilege **********/
6241 if ( is_print_op )
6242 become_root();
6244 if ( (ret = smbrun(command, &fd)) == 0 ) {
6245 /* Tell everyone we updated smb.conf. */
6246 message_send_all(smbd_messaging_context(),
6247 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6250 if ( is_print_op )
6251 unbecome_root();
6253 /********* END SePrintOperatorPrivilege **********/
6255 DEBUGADD(10,("returned [%d]\n", ret));
6257 TALLOC_FREE(command);
6258 TALLOC_FREE(remote_machine);
6260 if ( ret != 0 ) {
6261 if (fd != -1)
6262 close(fd);
6263 return False;
6266 /* reload our services immediately */
6267 reload_services( False );
6269 numlines = 0;
6270 /* Get lines and convert them back to dos-codepage */
6271 qlines = fd_lines_load(fd, &numlines, 0);
6272 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6273 close(fd);
6275 /* Set the portname to what the script says the portname should be. */
6276 /* but don't require anything to be return from the script exit a good error code */
6278 if (numlines) {
6279 /* Set the portname to what the script says the portname should be. */
6280 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6281 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6284 file_lines_free(qlines);
6285 return True;
6289 /********************************************************************
6290 * Called by spoolss_api_setprinter
6291 * when updating a printer description.
6292 ********************************************************************/
6294 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6295 const SPOOL_PRINTER_INFO_LEVEL *info,
6296 DEVICEMODE *devmode)
6298 int snum;
6299 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6300 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6301 WERROR result;
6302 UNISTR2 buffer;
6303 fstring asc_buffer;
6305 DEBUG(8,("update_printer\n"));
6307 result = WERR_OK;
6309 if (!Printer) {
6310 result = WERR_BADFID;
6311 goto done;
6314 if (!get_printer_snum(p, handle, &snum, NULL)) {
6315 result = WERR_BADFID;
6316 goto done;
6319 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6320 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6321 result = WERR_BADFID;
6322 goto done;
6325 DEBUGADD(8,("Converting info_2 struct\n"));
6328 * convert_printer_info converts the incoming
6329 * info from the client and overwrites the info
6330 * just read from the tdb in the pointer 'printer'.
6333 if (!convert_printer_info(info, printer, level)) {
6334 result = WERR_NOMEM;
6335 goto done;
6338 if (devmode) {
6339 /* we have a valid devmode
6340 convert it and link it*/
6342 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6343 if (!convert_devicemode(printer->info_2->printername, devmode,
6344 &printer->info_2->devmode)) {
6345 result = WERR_NOMEM;
6346 goto done;
6350 /* Do sanity check on the requested changes for Samba */
6352 if (!check_printer_ok(printer->info_2, snum)) {
6353 result = WERR_INVALID_PARAM;
6354 goto done;
6357 /* FIXME!!! If the driver has changed we really should verify that
6358 it is installed before doing much else --jerry */
6360 /* Check calling user has permission to update printer description */
6362 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6363 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6364 result = WERR_ACCESS_DENIED;
6365 goto done;
6368 /* Call addprinter hook */
6369 /* Check changes to see if this is really needed */
6371 if ( *lp_addprinter_cmd()
6372 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6373 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6374 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6375 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6377 /* add_printer_hook() will call reload_services() */
6379 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6380 result = WERR_ACCESS_DENIED;
6381 goto done;
6386 * When a *new* driver is bound to a printer, the drivername is used to
6387 * lookup previously saved driver initialization info, which is then
6388 * bound to the printer, simulating what happens in the Windows arch.
6390 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6392 if (!set_driver_init(printer, 2))
6394 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6395 printer->info_2->drivername));
6398 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6399 printer->info_2->drivername));
6401 notify_printer_driver(snum, printer->info_2->drivername);
6405 * flag which changes actually occured. This is a small subset of
6406 * all the possible changes. We also have to update things in the
6407 * DsSpooler key.
6410 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6411 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6412 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6413 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6415 notify_printer_comment(snum, printer->info_2->comment);
6418 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6419 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6420 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6421 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6423 notify_printer_sharename(snum, printer->info_2->sharename);
6426 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6427 char *pname;
6429 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6430 pname++;
6431 else
6432 pname = printer->info_2->printername;
6435 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6436 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6437 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6439 notify_printer_printername( snum, pname );
6442 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6443 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6444 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6445 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6447 notify_printer_port(snum, printer->info_2->portname);
6450 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6451 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6452 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6453 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6455 notify_printer_location(snum, printer->info_2->location);
6458 /* here we need to update some more DsSpooler keys */
6459 /* uNCName, serverName, shortServerName */
6461 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6462 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6463 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6464 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6465 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6467 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6468 global_myname(), printer->info_2->sharename );
6469 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6470 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6471 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6473 /* Update printer info */
6474 result = mod_a_printer(printer, 2);
6476 done:
6477 free_a_printer(&printer, 2);
6478 free_a_printer(&old_printer, 2);
6481 return result;
6484 /****************************************************************************
6485 ****************************************************************************/
6486 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6487 const SPOOL_PRINTER_INFO_LEVEL *info)
6489 #ifdef HAVE_ADS
6490 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6491 int snum;
6492 Printer_entry *Printer;
6494 if ( lp_security() != SEC_ADS ) {
6495 return WERR_UNKNOWN_LEVEL;
6498 Printer = find_printer_index_by_hnd(p, handle);
6500 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6502 if (!Printer)
6503 return WERR_BADFID;
6505 if (!get_printer_snum(p, handle, &snum, NULL))
6506 return WERR_BADFID;
6508 nt_printer_publish(Printer, snum, info7->action);
6510 return WERR_OK;
6511 #else
6512 return WERR_UNKNOWN_LEVEL;
6513 #endif
6515 /****************************************************************************
6516 ****************************************************************************/
6518 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6520 POLICY_HND *handle = &q_u->handle;
6521 uint32 level = q_u->level;
6522 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6523 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6524 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6525 uint32 command = q_u->command;
6526 WERROR result;
6528 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6530 if (!Printer) {
6531 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6532 return WERR_BADFID;
6535 /* check the level */
6536 switch (level) {
6537 case 0:
6538 return control_printer(handle, command, p);
6539 case 2:
6540 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6541 if (!W_ERROR_IS_OK(result))
6542 return result;
6543 if (secdesc_ctr)
6544 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6545 return result;
6546 case 3:
6547 return update_printer_sec(handle, level, info, p,
6548 secdesc_ctr);
6549 case 7:
6550 return publish_or_unpublish_printer(p, handle, info);
6551 default:
6552 return WERR_UNKNOWN_LEVEL;
6556 /****************************************************************************
6557 ****************************************************************************/
6559 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6561 POLICY_HND *handle = &q_u->handle;
6562 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6564 if (!Printer) {
6565 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6566 return WERR_BADFID;
6569 if (Printer->notify.client_connected==True) {
6570 int snum = -1;
6572 if ( Printer->printer_type == SPLHND_SERVER)
6573 snum = -1;
6574 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6575 !get_printer_snum(p, handle, &snum, NULL) )
6576 return WERR_BADFID;
6578 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6581 Printer->notify.flags=0;
6582 Printer->notify.options=0;
6583 Printer->notify.localmachine[0]='\0';
6584 Printer->notify.printerlocal=0;
6585 if (Printer->notify.option)
6586 free_spool_notify_option(&Printer->notify.option);
6587 Printer->notify.client_connected=False;
6589 return WERR_OK;
6592 /****************************************************************************
6593 ****************************************************************************/
6595 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6597 /* that's an [in out] buffer */
6599 if (!q_u->buffer && (q_u->offered!=0)) {
6600 return WERR_INVALID_PARAM;
6603 rpcbuf_move(q_u->buffer, &r_u->buffer);
6605 r_u->needed = 0;
6606 return WERR_INVALID_PARAM; /* this is what a NT server
6607 returns for AddJob. AddJob
6608 must fail on non-local
6609 printers */
6612 /****************************************************************************
6613 ****************************************************************************/
6615 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6616 int position, int snum,
6617 const NT_PRINTER_INFO_LEVEL *ntprinter)
6619 struct tm *t;
6621 t=gmtime(&queue->time);
6623 job_info->jobid=queue->job;
6624 init_unistr(&job_info->printername, lp_servicename(snum));
6625 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6626 init_unistr(&job_info->username, queue->fs_user);
6627 init_unistr(&job_info->document, queue->fs_file);
6628 init_unistr(&job_info->datatype, "RAW");
6629 init_unistr(&job_info->text_status, "");
6630 job_info->status=nt_printj_status(queue->status);
6631 job_info->priority=queue->priority;
6632 job_info->position=position;
6633 job_info->totalpages=queue->page_count;
6634 job_info->pagesprinted=0;
6636 make_systemtime(&job_info->submitted, t);
6639 /****************************************************************************
6640 ****************************************************************************/
6642 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6643 int position, int snum,
6644 const NT_PRINTER_INFO_LEVEL *ntprinter,
6645 DEVICEMODE *devmode)
6647 struct tm *t;
6649 t=gmtime(&queue->time);
6651 job_info->jobid=queue->job;
6653 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6655 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6656 init_unistr(&job_info->username, queue->fs_user);
6657 init_unistr(&job_info->document, queue->fs_file);
6658 init_unistr(&job_info->notifyname, queue->fs_user);
6659 init_unistr(&job_info->datatype, "RAW");
6660 init_unistr(&job_info->printprocessor, "winprint");
6661 init_unistr(&job_info->parameters, "");
6662 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6663 init_unistr(&job_info->text_status, "");
6665 /* and here the security descriptor */
6667 job_info->status=nt_printj_status(queue->status);
6668 job_info->priority=queue->priority;
6669 job_info->position=position;
6670 job_info->starttime=0;
6671 job_info->untiltime=0;
6672 job_info->totalpages=queue->page_count;
6673 job_info->size=queue->size;
6674 make_systemtime(&(job_info->submitted), t);
6675 job_info->timeelapsed=0;
6676 job_info->pagesprinted=0;
6678 job_info->devmode = devmode;
6680 return (True);
6683 /****************************************************************************
6684 Enumjobs at level 1.
6685 ****************************************************************************/
6687 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6688 const NT_PRINTER_INFO_LEVEL *ntprinter,
6689 RPC_BUFFER *buffer, uint32 offered,
6690 uint32 *needed, uint32 *returned)
6692 JOB_INFO_1 *info;
6693 int i;
6694 WERROR result = WERR_OK;
6696 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6697 if (info==NULL) {
6698 *returned=0;
6699 return WERR_NOMEM;
6702 for (i=0; i<*returned; i++)
6703 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6705 /* check the required size. */
6706 for (i=0; i<*returned; i++)
6707 (*needed) += spoolss_size_job_info_1(&info[i]);
6709 if (*needed > offered) {
6710 result = WERR_INSUFFICIENT_BUFFER;
6711 goto out;
6714 if (!rpcbuf_alloc_size(buffer, *needed)) {
6715 result = WERR_NOMEM;
6716 goto out;
6719 /* fill the buffer with the structures */
6720 for (i=0; i<*returned; i++)
6721 smb_io_job_info_1("", buffer, &info[i], 0);
6723 out:
6724 /* clear memory */
6725 SAFE_FREE(info);
6727 if ( !W_ERROR_IS_OK(result) )
6728 *returned = 0;
6730 return result;
6733 /****************************************************************************
6734 Enumjobs at level 2.
6735 ****************************************************************************/
6737 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6738 const NT_PRINTER_INFO_LEVEL *ntprinter,
6739 RPC_BUFFER *buffer, uint32 offered,
6740 uint32 *needed, uint32 *returned)
6742 JOB_INFO_2 *info = NULL;
6743 int i;
6744 WERROR result = WERR_OK;
6745 DEVICEMODE *devmode = NULL;
6747 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6748 *returned=0;
6749 return WERR_NOMEM;
6752 /* this should not be a failure condition if the devmode is NULL */
6754 devmode = construct_dev_mode(lp_const_servicename(snum));
6756 for (i=0; i<*returned; i++)
6757 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6759 /* check the required size. */
6760 for (i=0; i<*returned; i++)
6761 (*needed) += spoolss_size_job_info_2(&info[i]);
6763 if (*needed > offered) {
6764 result = WERR_INSUFFICIENT_BUFFER;
6765 goto out;
6768 if (!rpcbuf_alloc_size(buffer, *needed)) {
6769 result = WERR_NOMEM;
6770 goto out;
6773 /* fill the buffer with the structures */
6774 for (i=0; i<*returned; i++)
6775 smb_io_job_info_2("", buffer, &info[i], 0);
6777 out:
6778 free_devmode(devmode);
6779 SAFE_FREE(info);
6781 if ( !W_ERROR_IS_OK(result) )
6782 *returned = 0;
6784 return result;
6788 /****************************************************************************
6789 Enumjobs.
6790 ****************************************************************************/
6792 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6794 POLICY_HND *handle = &q_u->handle;
6795 uint32 level = q_u->level;
6796 RPC_BUFFER *buffer = NULL;
6797 uint32 offered = q_u->offered;
6798 uint32 *needed = &r_u->needed;
6799 uint32 *returned = &r_u->returned;
6800 WERROR wret;
6801 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6802 int snum;
6803 print_status_struct prt_status;
6804 print_queue_struct *queue=NULL;
6806 /* that's an [in out] buffer */
6808 if (!q_u->buffer && (offered!=0)) {
6809 return WERR_INVALID_PARAM;
6812 rpcbuf_move(q_u->buffer, &r_u->buffer);
6813 buffer = r_u->buffer;
6815 DEBUG(4,("_spoolss_enumjobs\n"));
6817 *needed=0;
6818 *returned=0;
6820 /* lookup the printer snum and tdb entry */
6822 if (!get_printer_snum(p, handle, &snum, NULL))
6823 return WERR_BADFID;
6825 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6826 if ( !W_ERROR_IS_OK(wret) )
6827 return wret;
6829 *returned = print_queue_status(snum, &queue, &prt_status);
6830 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6832 if (*returned == 0) {
6833 SAFE_FREE(queue);
6834 free_a_printer(&ntprinter, 2);
6835 return WERR_OK;
6838 switch (level) {
6839 case 1:
6840 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6841 break;
6842 case 2:
6843 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6844 break;
6845 default:
6846 *returned=0;
6847 wret = WERR_UNKNOWN_LEVEL;
6848 break;
6851 SAFE_FREE(queue);
6852 free_a_printer( &ntprinter, 2 );
6853 return wret;
6856 /****************************************************************************
6857 ****************************************************************************/
6859 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6861 return WERR_OK;
6864 /****************************************************************************
6865 ****************************************************************************/
6867 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6869 POLICY_HND *handle = &q_u->handle;
6870 uint32 jobid = q_u->jobid;
6871 uint32 command = q_u->command;
6873 int snum;
6874 WERROR errcode = WERR_BADFUNC;
6876 if (!get_printer_snum(p, handle, &snum, NULL)) {
6877 return WERR_BADFID;
6880 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6881 return WERR_INVALID_PRINTER_NAME;
6884 switch (command) {
6885 case JOB_CONTROL_CANCEL:
6886 case JOB_CONTROL_DELETE:
6887 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6888 errcode = WERR_OK;
6890 break;
6891 case JOB_CONTROL_PAUSE:
6892 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6893 errcode = WERR_OK;
6895 break;
6896 case JOB_CONTROL_RESTART:
6897 case JOB_CONTROL_RESUME:
6898 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6899 errcode = WERR_OK;
6901 break;
6902 default:
6903 return WERR_UNKNOWN_LEVEL;
6906 return errcode;
6909 /****************************************************************************
6910 Enumerates all printer drivers at level 1.
6911 ****************************************************************************/
6913 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6915 int i;
6916 int ndrivers;
6917 uint32 version;
6918 fstring *list = NULL;
6919 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6920 DRIVER_INFO_1 *driver_info_1=NULL;
6921 WERROR result = WERR_OK;
6923 *returned=0;
6925 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6926 list=NULL;
6927 ndrivers=get_ntdrivers(&list, architecture, version);
6928 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6930 if(ndrivers == -1) {
6931 SAFE_FREE(driver_info_1);
6932 return WERR_NOMEM;
6935 if(ndrivers != 0) {
6936 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6937 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6938 SAFE_FREE(list);
6939 return WERR_NOMEM;
6943 for (i=0; i<ndrivers; i++) {
6944 WERROR status;
6945 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6946 ZERO_STRUCT(driver);
6947 status = get_a_printer_driver(&driver, 3, list[i],
6948 architecture, version);
6949 if (!W_ERROR_IS_OK(status)) {
6950 SAFE_FREE(list);
6951 SAFE_FREE(driver_info_1);
6952 return status;
6954 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6955 free_a_printer_driver(driver, 3);
6958 *returned+=ndrivers;
6959 SAFE_FREE(list);
6962 /* check the required size. */
6963 for (i=0; i<*returned; i++) {
6964 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6965 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6968 if (*needed > offered) {
6969 result = WERR_INSUFFICIENT_BUFFER;
6970 goto out;
6973 if (!rpcbuf_alloc_size(buffer, *needed)) {
6974 result = WERR_NOMEM;
6975 goto out;
6978 /* fill the buffer with the driver structures */
6979 for (i=0; i<*returned; i++) {
6980 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6981 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6984 out:
6985 SAFE_FREE(driver_info_1);
6987 if ( !W_ERROR_IS_OK(result) )
6988 *returned = 0;
6990 return result;
6993 /****************************************************************************
6994 Enumerates all printer drivers at level 2.
6995 ****************************************************************************/
6997 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6999 int i;
7000 int ndrivers;
7001 uint32 version;
7002 fstring *list = NULL;
7003 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7004 DRIVER_INFO_2 *driver_info_2=NULL;
7005 WERROR result = WERR_OK;
7007 *returned=0;
7009 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7010 list=NULL;
7011 ndrivers=get_ntdrivers(&list, architecture, version);
7012 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7014 if(ndrivers == -1) {
7015 SAFE_FREE(driver_info_2);
7016 return WERR_NOMEM;
7019 if(ndrivers != 0) {
7020 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7021 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7022 SAFE_FREE(list);
7023 return WERR_NOMEM;
7027 for (i=0; i<ndrivers; i++) {
7028 WERROR status;
7030 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7031 ZERO_STRUCT(driver);
7032 status = get_a_printer_driver(&driver, 3, list[i],
7033 architecture, version);
7034 if (!W_ERROR_IS_OK(status)) {
7035 SAFE_FREE(list);
7036 SAFE_FREE(driver_info_2);
7037 return status;
7039 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7040 free_a_printer_driver(driver, 3);
7043 *returned+=ndrivers;
7044 SAFE_FREE(list);
7047 /* check the required size. */
7048 for (i=0; i<*returned; i++) {
7049 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7050 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7053 if (*needed > offered) {
7054 result = WERR_INSUFFICIENT_BUFFER;
7055 goto out;
7058 if (!rpcbuf_alloc_size(buffer, *needed)) {
7059 result = WERR_NOMEM;
7060 goto out;
7063 /* fill the buffer with the form structures */
7064 for (i=0; i<*returned; i++) {
7065 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7066 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7069 out:
7070 SAFE_FREE(driver_info_2);
7072 if ( !W_ERROR_IS_OK(result) )
7073 *returned = 0;
7075 return result;
7078 /****************************************************************************
7079 Enumerates all printer drivers at level 3.
7080 ****************************************************************************/
7082 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7084 int i;
7085 int ndrivers;
7086 uint32 version;
7087 fstring *list = NULL;
7088 DRIVER_INFO_3 *driver_info_3=NULL;
7089 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7090 WERROR result = WERR_OK;
7092 *returned=0;
7094 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7095 list=NULL;
7096 ndrivers=get_ntdrivers(&list, architecture, version);
7097 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7099 if(ndrivers == -1) {
7100 SAFE_FREE(driver_info_3);
7101 return WERR_NOMEM;
7104 if(ndrivers != 0) {
7105 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7106 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7107 SAFE_FREE(list);
7108 return WERR_NOMEM;
7112 for (i=0; i<ndrivers; i++) {
7113 WERROR status;
7115 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7116 ZERO_STRUCT(driver);
7117 status = get_a_printer_driver(&driver, 3, list[i],
7118 architecture, version);
7119 if (!W_ERROR_IS_OK(status)) {
7120 SAFE_FREE(list);
7121 SAFE_FREE(driver_info_3);
7122 return status;
7124 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7125 free_a_printer_driver(driver, 3);
7128 *returned+=ndrivers;
7129 SAFE_FREE(list);
7132 /* check the required size. */
7133 for (i=0; i<*returned; i++) {
7134 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7135 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7138 if (*needed > offered) {
7139 result = WERR_INSUFFICIENT_BUFFER;
7140 goto out;
7143 if (!rpcbuf_alloc_size(buffer, *needed)) {
7144 result = WERR_NOMEM;
7145 goto out;
7148 /* fill the buffer with the driver structures */
7149 for (i=0; i<*returned; i++) {
7150 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7151 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7154 out:
7155 for (i=0; i<*returned; i++) {
7156 SAFE_FREE(driver_info_3[i].dependentfiles);
7159 SAFE_FREE(driver_info_3);
7161 if ( !W_ERROR_IS_OK(result) )
7162 *returned = 0;
7164 return result;
7167 /****************************************************************************
7168 Enumerates all printer drivers.
7169 ****************************************************************************/
7171 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7173 uint32 level = q_u->level;
7174 RPC_BUFFER *buffer = NULL;
7175 uint32 offered = q_u->offered;
7176 uint32 *needed = &r_u->needed;
7177 uint32 *returned = &r_u->returned;
7179 fstring servername;
7180 fstring architecture;
7182 /* that's an [in out] buffer */
7184 if (!q_u->buffer && (offered!=0)) {
7185 return WERR_INVALID_PARAM;
7188 rpcbuf_move(q_u->buffer, &r_u->buffer);
7189 buffer = r_u->buffer;
7191 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7193 *needed = 0;
7194 *returned = 0;
7196 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7197 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7199 if ( !is_myname_or_ipaddr( servername ) )
7200 return WERR_UNKNOWN_PRINTER_DRIVER;
7202 switch (level) {
7203 case 1:
7204 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7205 case 2:
7206 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7207 case 3:
7208 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7209 default:
7210 return WERR_UNKNOWN_LEVEL;
7214 /****************************************************************************
7215 ****************************************************************************/
7217 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7219 form->flag=list->flag;
7220 init_unistr(&form->name, list->name);
7221 form->width=list->width;
7222 form->length=list->length;
7223 form->left=list->left;
7224 form->top=list->top;
7225 form->right=list->right;
7226 form->bottom=list->bottom;
7229 /****************************************************************************
7230 ****************************************************************************/
7232 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7234 uint32 level = q_u->level;
7235 RPC_BUFFER *buffer = NULL;
7236 uint32 offered = q_u->offered;
7237 uint32 *needed = &r_u->needed;
7238 uint32 *numofforms = &r_u->numofforms;
7239 uint32 numbuiltinforms;
7241 nt_forms_struct *list=NULL;
7242 nt_forms_struct *builtinlist=NULL;
7243 FORM_1 *forms_1;
7244 int buffer_size=0;
7245 int i;
7247 /* that's an [in out] buffer */
7249 if (!q_u->buffer && (offered!=0) ) {
7250 return WERR_INVALID_PARAM;
7253 rpcbuf_move(q_u->buffer, &r_u->buffer);
7254 buffer = r_u->buffer;
7256 DEBUG(4,("_spoolss_enumforms\n"));
7257 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7258 DEBUGADD(5,("Info level [%d]\n", level));
7260 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7261 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7262 *numofforms = get_ntforms(&list);
7263 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7264 *numofforms += numbuiltinforms;
7266 if (*numofforms == 0) {
7267 SAFE_FREE(builtinlist);
7268 SAFE_FREE(list);
7269 return WERR_NO_MORE_ITEMS;
7272 switch (level) {
7273 case 1:
7274 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7275 SAFE_FREE(builtinlist);
7276 SAFE_FREE(list);
7277 *numofforms=0;
7278 return WERR_NOMEM;
7281 /* construct the list of form structures */
7282 for (i=0; i<numbuiltinforms; i++) {
7283 DEBUGADD(6,("Filling form number [%d]\n",i));
7284 fill_form_1(&forms_1[i], &builtinlist[i]);
7287 SAFE_FREE(builtinlist);
7289 for (; i<*numofforms; i++) {
7290 DEBUGADD(6,("Filling form number [%d]\n",i));
7291 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7294 SAFE_FREE(list);
7296 /* check the required size. */
7297 for (i=0; i<numbuiltinforms; i++) {
7298 DEBUGADD(6,("adding form [%d]'s size\n",i));
7299 buffer_size += spoolss_size_form_1(&forms_1[i]);
7301 for (; i<*numofforms; i++) {
7302 DEBUGADD(6,("adding form [%d]'s size\n",i));
7303 buffer_size += spoolss_size_form_1(&forms_1[i]);
7306 *needed=buffer_size;
7308 if (*needed > offered) {
7309 SAFE_FREE(forms_1);
7310 *numofforms=0;
7311 return WERR_INSUFFICIENT_BUFFER;
7314 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7315 SAFE_FREE(forms_1);
7316 *numofforms=0;
7317 return WERR_NOMEM;
7320 /* fill the buffer with the form structures */
7321 for (i=0; i<numbuiltinforms; i++) {
7322 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7323 smb_io_form_1("", buffer, &forms_1[i], 0);
7325 for (; i<*numofforms; i++) {
7326 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7327 smb_io_form_1("", buffer, &forms_1[i], 0);
7330 SAFE_FREE(forms_1);
7332 return WERR_OK;
7334 default:
7335 SAFE_FREE(list);
7336 SAFE_FREE(builtinlist);
7337 return WERR_UNKNOWN_LEVEL;
7341 /****************************************************************************
7342 ****************************************************************************/
7344 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7346 uint32 level = q_u->level;
7347 UNISTR2 *uni_formname = &q_u->formname;
7348 RPC_BUFFER *buffer = NULL;
7349 uint32 offered = q_u->offered;
7350 uint32 *needed = &r_u->needed;
7352 nt_forms_struct *list=NULL;
7353 nt_forms_struct builtin_form;
7354 bool foundBuiltin;
7355 FORM_1 form_1;
7356 fstring form_name;
7357 int buffer_size=0;
7358 int numofforms=0, i=0;
7360 /* that's an [in out] buffer */
7362 if (!q_u->buffer && (offered!=0)) {
7363 return WERR_INVALID_PARAM;
7366 rpcbuf_move(q_u->buffer, &r_u->buffer);
7367 buffer = r_u->buffer;
7369 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7371 DEBUG(4,("_spoolss_getform\n"));
7372 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7373 DEBUGADD(5,("Info level [%d]\n", level));
7375 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7376 if (!foundBuiltin) {
7377 numofforms = get_ntforms(&list);
7378 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7380 if (numofforms == 0)
7381 return WERR_BADFID;
7384 switch (level) {
7385 case 1:
7386 if (foundBuiltin) {
7387 fill_form_1(&form_1, &builtin_form);
7388 } else {
7390 /* Check if the requested name is in the list of form structures */
7391 for (i=0; i<numofforms; i++) {
7393 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7395 if (strequal(form_name, list[i].name)) {
7396 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7397 fill_form_1(&form_1, &list[i]);
7398 break;
7402 SAFE_FREE(list);
7403 if (i == numofforms) {
7404 return WERR_BADFID;
7407 /* check the required size. */
7409 *needed=spoolss_size_form_1(&form_1);
7411 if (*needed > offered)
7412 return WERR_INSUFFICIENT_BUFFER;
7414 if (!rpcbuf_alloc_size(buffer, buffer_size))
7415 return WERR_NOMEM;
7417 /* fill the buffer with the form structures */
7418 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7419 smb_io_form_1("", buffer, &form_1, 0);
7421 return WERR_OK;
7423 default:
7424 SAFE_FREE(list);
7425 return WERR_UNKNOWN_LEVEL;
7429 /****************************************************************************
7430 ****************************************************************************/
7432 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7434 init_unistr(&port->port_name, name);
7437 /****************************************************************************
7438 TODO: This probably needs distinguish between TCP/IP and Local ports
7439 somehow.
7440 ****************************************************************************/
7442 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7444 init_unistr(&port->port_name, name);
7445 init_unistr(&port->monitor_name, "Local Monitor");
7446 init_unistr(&port->description, SPL_LOCAL_PORT );
7447 port->port_type=PORT_TYPE_WRITE;
7448 port->reserved=0x0;
7452 /****************************************************************************
7453 wrapper around the enumer ports command
7454 ****************************************************************************/
7456 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7458 char *cmd = lp_enumports_cmd();
7459 char **qlines = NULL;
7460 char *command = NULL;
7461 int numlines;
7462 int ret;
7463 int fd;
7465 *count = 0;
7466 *lines = NULL;
7468 /* if no hook then just fill in the default port */
7470 if ( !*cmd ) {
7471 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7472 return WERR_NOMEM;
7474 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7475 SAFE_FREE(qlines);
7476 return WERR_NOMEM;
7478 qlines[1] = NULL;
7479 numlines = 1;
7481 else {
7482 /* we have a valid enumport command */
7484 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7485 if (!command) {
7486 return WERR_NOMEM;
7489 DEBUG(10,("Running [%s]\n", command));
7490 ret = smbrun(command, &fd);
7491 DEBUG(10,("Returned [%d]\n", ret));
7492 TALLOC_FREE(command);
7493 if (ret != 0) {
7494 if (fd != -1) {
7495 close(fd);
7497 return WERR_ACCESS_DENIED;
7500 numlines = 0;
7501 qlines = fd_lines_load(fd, &numlines, 0);
7502 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7503 close(fd);
7506 *count = numlines;
7507 *lines = qlines;
7509 return WERR_OK;
7512 /****************************************************************************
7513 enumports level 1.
7514 ****************************************************************************/
7516 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7518 PORT_INFO_1 *ports=NULL;
7519 int i=0;
7520 WERROR result = WERR_OK;
7521 char **qlines = NULL;
7522 int numlines = 0;
7524 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7525 if (!W_ERROR_IS_OK(result)) {
7526 file_lines_free(qlines);
7527 return result;
7530 if(numlines) {
7531 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7532 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7533 dos_errstr(WERR_NOMEM)));
7534 file_lines_free(qlines);
7535 return WERR_NOMEM;
7538 for (i=0; i<numlines; i++) {
7539 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7540 fill_port_1(&ports[i], qlines[i]);
7543 file_lines_free(qlines);
7545 *returned = numlines;
7547 /* check the required size. */
7548 for (i=0; i<*returned; i++) {
7549 DEBUGADD(6,("adding port [%d]'s size\n", i));
7550 *needed += spoolss_size_port_info_1(&ports[i]);
7553 if (*needed > offered) {
7554 result = WERR_INSUFFICIENT_BUFFER;
7555 goto out;
7558 if (!rpcbuf_alloc_size(buffer, *needed)) {
7559 result = WERR_NOMEM;
7560 goto out;
7563 /* fill the buffer with the ports structures */
7564 for (i=0; i<*returned; i++) {
7565 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7566 smb_io_port_1("", buffer, &ports[i], 0);
7569 out:
7570 SAFE_FREE(ports);
7572 if ( !W_ERROR_IS_OK(result) )
7573 *returned = 0;
7575 return result;
7578 /****************************************************************************
7579 enumports level 2.
7580 ****************************************************************************/
7582 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7584 PORT_INFO_2 *ports=NULL;
7585 int i=0;
7586 WERROR result = WERR_OK;
7587 char **qlines = NULL;
7588 int numlines = 0;
7590 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7591 if ( !W_ERROR_IS_OK(result)) {
7592 file_lines_free(qlines);
7593 return result;
7596 if(numlines) {
7597 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7598 file_lines_free(qlines);
7599 return WERR_NOMEM;
7602 for (i=0; i<numlines; i++) {
7603 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7604 fill_port_2(&(ports[i]), qlines[i]);
7608 file_lines_free(qlines);
7610 *returned = numlines;
7612 /* check the required size. */
7613 for (i=0; i<*returned; i++) {
7614 DEBUGADD(6,("adding port [%d]'s size\n", i));
7615 *needed += spoolss_size_port_info_2(&ports[i]);
7618 if (*needed > offered) {
7619 result = WERR_INSUFFICIENT_BUFFER;
7620 goto out;
7623 if (!rpcbuf_alloc_size(buffer, *needed)) {
7624 result = WERR_NOMEM;
7625 goto out;
7628 /* fill the buffer with the ports structures */
7629 for (i=0; i<*returned; i++) {
7630 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7631 smb_io_port_2("", buffer, &ports[i], 0);
7634 out:
7635 SAFE_FREE(ports);
7637 if ( !W_ERROR_IS_OK(result) )
7638 *returned = 0;
7640 return result;
7643 /****************************************************************************
7644 enumports.
7645 ****************************************************************************/
7647 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7649 uint32 level = q_u->level;
7650 RPC_BUFFER *buffer = NULL;
7651 uint32 offered = q_u->offered;
7652 uint32 *needed = &r_u->needed;
7653 uint32 *returned = &r_u->returned;
7655 /* that's an [in out] buffer */
7657 if (!q_u->buffer && (offered!=0)) {
7658 return WERR_INVALID_PARAM;
7661 rpcbuf_move(q_u->buffer, &r_u->buffer);
7662 buffer = r_u->buffer;
7664 DEBUG(4,("_spoolss_enumports\n"));
7666 *returned=0;
7667 *needed=0;
7669 switch (level) {
7670 case 1:
7671 return enumports_level_1(buffer, offered, needed, returned);
7672 case 2:
7673 return enumports_level_2(buffer, offered, needed, returned);
7674 default:
7675 return WERR_UNKNOWN_LEVEL;
7679 /****************************************************************************
7680 ****************************************************************************/
7682 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7683 const SPOOL_PRINTER_INFO_LEVEL *info,
7684 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7685 uint32 user_switch, const SPOOL_USER_CTR *user,
7686 POLICY_HND *handle)
7688 NT_PRINTER_INFO_LEVEL *printer = NULL;
7689 fstring name;
7690 int snum;
7691 WERROR err = WERR_OK;
7693 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7694 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7695 return WERR_NOMEM;
7698 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7699 if (!convert_printer_info(info, printer, 2)) {
7700 free_a_printer(&printer, 2);
7701 return WERR_NOMEM;
7704 /* check to see if the printer already exists */
7706 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7707 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7708 printer->info_2->sharename));
7709 free_a_printer(&printer, 2);
7710 return WERR_PRINTER_ALREADY_EXISTS;
7713 /* FIXME!!! smbd should check to see if the driver is installed before
7714 trying to add a printer like this --jerry */
7716 if (*lp_addprinter_cmd() ) {
7717 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7718 free_a_printer(&printer,2);
7719 return WERR_ACCESS_DENIED;
7721 } else {
7722 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7723 "smb.conf parameter \"addprinter command\" is defined. This"
7724 "parameter must exist for this call to succeed\n",
7725 printer->info_2->sharename ));
7728 /* use our primary netbios name since get_a_printer() will convert
7729 it to what the client expects on a case by case basis */
7731 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7732 printer->info_2->sharename);
7735 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7736 free_a_printer(&printer,2);
7737 return WERR_ACCESS_DENIED;
7740 /* you must be a printer admin to add a new printer */
7741 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7742 free_a_printer(&printer,2);
7743 return WERR_ACCESS_DENIED;
7747 * Do sanity check on the requested changes for Samba.
7750 if (!check_printer_ok(printer->info_2, snum)) {
7751 free_a_printer(&printer,2);
7752 return WERR_INVALID_PARAM;
7756 * When a printer is created, the drivername bound to the printer is used
7757 * to lookup previously saved driver initialization info, which is then
7758 * bound to the new printer, simulating what happens in the Windows arch.
7761 if (!devmode)
7763 set_driver_init(printer, 2);
7765 else
7767 /* A valid devmode was included, convert and link it
7769 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7771 if (!convert_devicemode(printer->info_2->printername, devmode,
7772 &printer->info_2->devmode))
7773 return WERR_NOMEM;
7776 /* write the ASCII on disk */
7777 err = mod_a_printer(printer, 2);
7778 if (!W_ERROR_IS_OK(err)) {
7779 free_a_printer(&printer,2);
7780 return err;
7783 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7784 /* Handle open failed - remove addition. */
7785 del_a_printer(printer->info_2->sharename);
7786 free_a_printer(&printer,2);
7787 return WERR_ACCESS_DENIED;
7790 update_c_setprinter(False);
7791 free_a_printer(&printer,2);
7793 return WERR_OK;
7796 /****************************************************************************
7797 ****************************************************************************/
7799 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7801 UNISTR2 *uni_srv_name = q_u->server_name;
7802 uint32 level = q_u->level;
7803 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7804 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7805 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7806 uint32 user_switch = q_u->user_switch;
7807 SPOOL_USER_CTR *user = &q_u->user_ctr;
7808 POLICY_HND *handle = &r_u->handle;
7810 switch (level) {
7811 case 1:
7812 /* we don't handle yet */
7813 /* but I know what to do ... */
7814 return WERR_UNKNOWN_LEVEL;
7815 case 2:
7816 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7817 devmode, sdb,
7818 user_switch, user, handle);
7819 default:
7820 return WERR_UNKNOWN_LEVEL;
7824 /****************************************************************************
7825 ****************************************************************************/
7827 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7829 uint32 level = q_u->level;
7830 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7831 WERROR err = WERR_OK;
7832 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7833 fstring driver_name;
7834 uint32 version;
7836 ZERO_STRUCT(driver);
7838 if (!convert_printer_driver_info(info, &driver, level)) {
7839 err = WERR_NOMEM;
7840 goto done;
7843 DEBUG(5,("Cleaning driver's information\n"));
7844 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7845 if (!W_ERROR_IS_OK(err))
7846 goto done;
7848 DEBUG(5,("Moving driver to final destination\n"));
7849 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7850 goto done;
7853 if (add_a_printer_driver(driver, level)!=0) {
7854 err = WERR_ACCESS_DENIED;
7855 goto done;
7859 * I think this is where he DrvUpgradePrinter() hook would be
7860 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7861 * server. Right now, we just need to send ourselves a message
7862 * to update each printer bound to this driver. --jerry
7865 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7866 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7867 driver_name));
7871 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7872 * decide if the driver init data should be deleted. The rules are:
7873 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7874 * 2) delete init data only if there is no 2k/Xp driver
7875 * 3) always delete init data
7876 * The generalized rule is always use init data from the highest order driver.
7877 * It is necessary to follow the driver install by an initialization step to
7878 * finish off this process.
7880 if (level == 3)
7881 version = driver.info_3->cversion;
7882 else if (level == 6)
7883 version = driver.info_6->version;
7884 else
7885 version = -1;
7886 switch (version) {
7888 * 9x printer driver - never delete init data
7890 case 0:
7891 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7892 driver_name));
7893 break;
7896 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7897 * there is no 2k/Xp driver init data for this driver name.
7899 case 2:
7901 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7903 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7905 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7907 if (!del_driver_init(driver_name))
7908 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7909 } else {
7911 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7913 free_a_printer_driver(driver1,3);
7914 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7915 driver_name));
7918 break;
7921 * 2k or Xp printer driver - always delete init data
7923 case 3:
7924 if (!del_driver_init(driver_name))
7925 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7926 break;
7928 default:
7929 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7930 break;
7934 done:
7935 free_a_printer_driver(driver, level);
7936 return err;
7939 /********************************************************************
7940 * spoolss_addprinterdriverex
7941 ********************************************************************/
7943 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7945 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7946 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7949 * we only support the semantics of AddPrinterDriver()
7950 * i.e. only copy files that are newer than existing ones
7953 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7954 return WERR_ACCESS_DENIED;
7956 ZERO_STRUCT(q_u_local);
7957 ZERO_STRUCT(r_u_local);
7959 /* just pass the information off to _spoolss_addprinterdriver() */
7960 q_u_local.server_name_ptr = q_u->server_name_ptr;
7961 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7962 q_u_local.level = q_u->level;
7963 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7965 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7968 /****************************************************************************
7969 ****************************************************************************/
7971 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7973 init_unistr(&info->name, name);
7976 /****************************************************************************
7977 ****************************************************************************/
7979 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7981 char *path = NULL;
7982 char *long_archi = NULL;
7983 char *servername = NULL;
7984 char *pservername = NULL;
7985 const char *short_archi;
7986 DRIVER_DIRECTORY_1 *info=NULL;
7987 WERROR result = WERR_OK;
7988 TALLOC_CTX *ctx = talloc_tos();
7990 servername = unistr2_to_ascii_talloc(ctx, name);
7991 if (!servername) {
7992 return WERR_NOMEM;
7994 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
7995 if (!long_archi) {
7996 return WERR_NOMEM;
7999 /* check for beginning double '\'s and that the server
8000 long enough */
8002 pservername = servername;
8003 if ( *pservername == '\\' && strlen(servername)>2 ) {
8004 pservername += 2;
8007 if ( !is_myname_or_ipaddr( pservername ) )
8008 return WERR_INVALID_PARAM;
8010 if (!(short_archi = get_short_archi(long_archi)))
8011 return WERR_INVALID_ENVIRONMENT;
8013 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8014 return WERR_NOMEM;
8016 path = talloc_asprintf(ctx,
8017 "\\\\%s\\print$\\%s", pservername, short_archi);
8018 if (!path) {
8019 result = WERR_NOMEM;
8020 goto out;
8023 DEBUG(4,("printer driver directory: [%s]\n", path));
8025 fill_driverdir_1(info, path);
8027 *needed += spoolss_size_driverdir_info_1(info);
8029 if (*needed > offered) {
8030 result = WERR_INSUFFICIENT_BUFFER;
8031 goto out;
8034 if (!rpcbuf_alloc_size(buffer, *needed)) {
8035 result = WERR_NOMEM;
8036 goto out;
8039 smb_io_driverdir_1("", buffer, info, 0);
8041 out:
8042 SAFE_FREE(info);
8044 return result;
8047 /****************************************************************************
8048 ****************************************************************************/
8050 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8052 UNISTR2 *name = &q_u->name;
8053 UNISTR2 *uni_environment = &q_u->environment;
8054 uint32 level = q_u->level;
8055 RPC_BUFFER *buffer = NULL;
8056 uint32 offered = q_u->offered;
8057 uint32 *needed = &r_u->needed;
8059 /* that's an [in out] buffer */
8061 if (!q_u->buffer && (offered!=0)) {
8062 return WERR_INVALID_PARAM;
8065 rpcbuf_move(q_u->buffer, &r_u->buffer);
8066 buffer = r_u->buffer;
8068 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8070 *needed=0;
8072 switch(level) {
8073 case 1:
8074 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8075 default:
8076 return WERR_UNKNOWN_LEVEL;
8080 /****************************************************************************
8081 ****************************************************************************/
8083 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8085 POLICY_HND *handle = &q_u->handle;
8086 uint32 idx = q_u->index;
8087 uint32 in_value_len = q_u->valuesize;
8088 uint32 in_data_len = q_u->datasize;
8089 uint32 *out_max_value_len = &r_u->valuesize;
8090 uint16 **out_value = &r_u->value;
8091 uint32 *out_value_len = &r_u->realvaluesize;
8092 uint32 *out_type = &r_u->type;
8093 uint32 *out_max_data_len = &r_u->datasize;
8094 uint8 **data_out = &r_u->data;
8095 uint32 *out_data_len = &r_u->realdatasize;
8097 NT_PRINTER_INFO_LEVEL *printer = NULL;
8099 uint32 biggest_valuesize;
8100 uint32 biggest_datasize;
8101 uint32 data_len;
8102 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8103 int snum;
8104 WERROR result;
8105 REGISTRY_VALUE *val = NULL;
8106 NT_PRINTER_DATA *p_data;
8107 int i, key_index, num_values;
8108 int name_length;
8110 *out_type = 0;
8112 *out_max_data_len = 0;
8113 *data_out = NULL;
8114 *out_data_len = 0;
8116 DEBUG(5,("spoolss_enumprinterdata\n"));
8118 if (!Printer) {
8119 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8120 return WERR_BADFID;
8123 if (!get_printer_snum(p,handle, &snum, NULL))
8124 return WERR_BADFID;
8126 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8127 if (!W_ERROR_IS_OK(result))
8128 return result;
8130 p_data = printer->info_2->data;
8131 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8133 result = WERR_OK;
8136 * The NT machine wants to know the biggest size of value and data
8138 * cf: MSDN EnumPrinterData remark section
8141 if ( !in_value_len && !in_data_len && (key_index != -1) )
8143 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8145 biggest_valuesize = 0;
8146 biggest_datasize = 0;
8148 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8150 for ( i=0; i<num_values; i++ )
8152 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8154 name_length = strlen(val->valuename);
8155 if ( strlen(val->valuename) > biggest_valuesize )
8156 biggest_valuesize = name_length;
8158 if ( val->size > biggest_datasize )
8159 biggest_datasize = val->size;
8161 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8162 biggest_datasize));
8165 /* the value is an UNICODE string but real_value_size is the length
8166 in bytes including the trailing 0 */
8168 *out_value_len = 2 * (1+biggest_valuesize);
8169 *out_data_len = biggest_datasize;
8171 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8173 goto done;
8177 * the value len is wrong in NT sp3
8178 * that's the number of bytes not the number of unicode chars
8181 if ( key_index != -1 )
8182 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8184 if ( !val )
8187 /* out_value should default to "" or else NT4 has
8188 problems unmarshalling the response */
8190 *out_max_value_len=(in_value_len/sizeof(uint16));
8192 if (in_value_len) {
8193 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8195 result = WERR_NOMEM;
8196 goto done;
8198 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8199 } else {
8200 *out_value=NULL;
8201 *out_value_len = 0;
8204 /* the data is counted in bytes */
8206 *out_max_data_len = in_data_len;
8207 *out_data_len = in_data_len;
8209 /* only allocate when given a non-zero data_len */
8211 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8213 result = WERR_NOMEM;
8214 goto done;
8217 result = WERR_NO_MORE_ITEMS;
8219 else
8222 * the value is:
8223 * - counted in bytes in the request
8224 * - counted in UNICODE chars in the max reply
8225 * - counted in bytes in the real size
8227 * take a pause *before* coding not *during* coding
8230 /* name */
8231 *out_max_value_len=(in_value_len/sizeof(uint16));
8232 if (in_value_len) {
8233 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8235 result = WERR_NOMEM;
8236 goto done;
8239 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8240 } else {
8241 *out_value = NULL;
8242 *out_value_len = 0;
8245 /* type */
8247 *out_type = regval_type( val );
8249 /* data - counted in bytes */
8251 *out_max_data_len = in_data_len;
8252 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8254 result = WERR_NOMEM;
8255 goto done;
8257 data_len = regval_size(val);
8258 if ( *data_out && data_len )
8259 memcpy( *data_out, regval_data_p(val), data_len );
8260 *out_data_len = data_len;
8263 done:
8264 free_a_printer(&printer, 2);
8265 return result;
8268 /****************************************************************************
8269 ****************************************************************************/
8271 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8273 POLICY_HND *handle = &q_u->handle;
8274 UNISTR2 *value = &q_u->value;
8275 uint32 type = q_u->type;
8276 uint8 *data = q_u->data;
8277 uint32 real_len = q_u->real_len;
8279 NT_PRINTER_INFO_LEVEL *printer = NULL;
8280 int snum=0;
8281 WERROR status = WERR_OK;
8282 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8283 fstring valuename;
8285 DEBUG(5,("spoolss_setprinterdata\n"));
8287 if (!Printer) {
8288 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8289 return WERR_BADFID;
8292 if ( Printer->printer_type == SPLHND_SERVER ) {
8293 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8294 return WERR_INVALID_PARAM;
8297 if (!get_printer_snum(p,handle, &snum, NULL))
8298 return WERR_BADFID;
8301 * Access check : NT returns "access denied" if you make a
8302 * SetPrinterData call without the necessary privildge.
8303 * we were originally returning OK if nothing changed
8304 * which made Win2k issue **a lot** of SetPrinterData
8305 * when connecting to a printer --jerry
8308 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8310 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8311 status = WERR_ACCESS_DENIED;
8312 goto done;
8315 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8316 if (!W_ERROR_IS_OK(status))
8317 return status;
8319 unistr2_to_ascii(valuename, value, sizeof(valuename));
8322 * When client side code sets a magic printer data key, detect it and save
8323 * the current printer data and the magic key's data (its the DEVMODE) for
8324 * future printer/driver initializations.
8326 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8328 /* Set devmode and printer initialization info */
8329 status = save_driver_init( printer, 2, data, real_len );
8331 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8333 else
8335 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8336 type, data, real_len );
8337 if ( W_ERROR_IS_OK(status) )
8338 status = mod_a_printer(printer, 2);
8341 done:
8342 free_a_printer(&printer, 2);
8344 return status;
8347 /****************************************************************************
8348 ****************************************************************************/
8350 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8352 POLICY_HND *handle = &q_u->handle;
8353 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8354 int snum;
8356 DEBUG(5,("_spoolss_resetprinter\n"));
8359 * All we do is to check to see if the handle and queue is valid.
8360 * This call really doesn't mean anything to us because we only
8361 * support RAW printing. --jerry
8364 if (!Printer) {
8365 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8366 return WERR_BADFID;
8369 if (!get_printer_snum(p,handle, &snum, NULL))
8370 return WERR_BADFID;
8373 /* blindly return success */
8374 return WERR_OK;
8378 /****************************************************************************
8379 ****************************************************************************/
8381 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8383 POLICY_HND *handle = &q_u->handle;
8384 UNISTR2 *value = &q_u->valuename;
8386 NT_PRINTER_INFO_LEVEL *printer = NULL;
8387 int snum=0;
8388 WERROR status = WERR_OK;
8389 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8390 char *valuename = NULL;
8391 TALLOC_CTX *ctx = p->mem_ctx;
8393 DEBUG(5,("spoolss_deleteprinterdata\n"));
8395 if (!Printer) {
8396 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8397 return WERR_BADFID;
8400 if (!get_printer_snum(p, handle, &snum, NULL))
8401 return WERR_BADFID;
8403 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8404 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8405 return WERR_ACCESS_DENIED;
8408 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8409 if (!W_ERROR_IS_OK(status))
8410 return status;
8412 valuename = unistr2_to_ascii_talloc(ctx, value);
8413 if (!valuename) {
8414 free_a_printer(&printer, 2);
8415 return WERR_NOMEM;
8418 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8420 if ( W_ERROR_IS_OK(status) )
8421 mod_a_printer( printer, 2 );
8423 free_a_printer(&printer, 2);
8424 TALLOC_FREE(valuename);
8426 return status;
8429 /****************************************************************************
8430 ****************************************************************************/
8432 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8434 POLICY_HND *handle = &q_u->handle;
8435 FORM *form = &q_u->form;
8436 nt_forms_struct tmpForm;
8437 int snum;
8438 WERROR status = WERR_OK;
8439 NT_PRINTER_INFO_LEVEL *printer = NULL;
8441 int count=0;
8442 nt_forms_struct *list=NULL;
8443 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8445 DEBUG(5,("spoolss_addform\n"));
8447 if (!Printer) {
8448 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8449 return WERR_BADFID;
8453 /* forms can be added on printer of on the print server handle */
8455 if ( Printer->printer_type == SPLHND_PRINTER )
8457 if (!get_printer_snum(p,handle, &snum, NULL))
8458 return WERR_BADFID;
8460 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8461 if (!W_ERROR_IS_OK(status))
8462 goto done;
8465 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8466 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8467 status = WERR_ACCESS_DENIED;
8468 goto done;
8471 /* can't add if builtin */
8473 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8474 status = WERR_ALREADY_EXISTS;
8475 goto done;
8478 count = get_ntforms(&list);
8480 if(!add_a_form(&list, form, &count)) {
8481 status = WERR_NOMEM;
8482 goto done;
8485 write_ntforms(&list, count);
8488 * ChangeID must always be set if this is a printer
8491 if ( Printer->printer_type == SPLHND_PRINTER )
8492 status = mod_a_printer(printer, 2);
8494 done:
8495 if ( printer )
8496 free_a_printer(&printer, 2);
8497 SAFE_FREE(list);
8499 return status;
8502 /****************************************************************************
8503 ****************************************************************************/
8505 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8507 POLICY_HND *handle = &q_u->handle;
8508 UNISTR2 *form_name = &q_u->name;
8509 nt_forms_struct tmpForm;
8510 int count=0;
8511 nt_forms_struct *list=NULL;
8512 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8513 int snum;
8514 WERROR status = WERR_OK;
8515 NT_PRINTER_INFO_LEVEL *printer = NULL;
8517 DEBUG(5,("spoolss_deleteform\n"));
8519 if (!Printer) {
8520 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8521 return WERR_BADFID;
8524 /* forms can be deleted on printer of on the print server handle */
8526 if ( Printer->printer_type == SPLHND_PRINTER )
8528 if (!get_printer_snum(p,handle, &snum, NULL))
8529 return WERR_BADFID;
8531 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8532 if (!W_ERROR_IS_OK(status))
8533 goto done;
8536 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8537 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8538 status = WERR_ACCESS_DENIED;
8539 goto done;
8542 /* can't delete if builtin */
8544 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8545 status = WERR_INVALID_PARAM;
8546 goto done;
8549 count = get_ntforms(&list);
8551 if ( !delete_a_form(&list, form_name, &count, &status ))
8552 goto done;
8555 * ChangeID must always be set if this is a printer
8558 if ( Printer->printer_type == SPLHND_PRINTER )
8559 status = mod_a_printer(printer, 2);
8561 done:
8562 if ( printer )
8563 free_a_printer(&printer, 2);
8564 SAFE_FREE(list);
8566 return status;
8569 /****************************************************************************
8570 ****************************************************************************/
8572 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8574 POLICY_HND *handle = &q_u->handle;
8575 FORM *form = &q_u->form;
8576 nt_forms_struct tmpForm;
8577 int snum;
8578 WERROR status = WERR_OK;
8579 NT_PRINTER_INFO_LEVEL *printer = NULL;
8581 int count=0;
8582 nt_forms_struct *list=NULL;
8583 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8585 DEBUG(5,("spoolss_setform\n"));
8587 if (!Printer) {
8588 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8589 return WERR_BADFID;
8592 /* forms can be modified on printer of on the print server handle */
8594 if ( Printer->printer_type == SPLHND_PRINTER )
8596 if (!get_printer_snum(p,handle, &snum, NULL))
8597 return WERR_BADFID;
8599 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8600 if (!W_ERROR_IS_OK(status))
8601 goto done;
8604 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8605 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8606 status = WERR_ACCESS_DENIED;
8607 goto done;
8610 /* can't set if builtin */
8611 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8612 status = WERR_INVALID_PARAM;
8613 goto done;
8616 count = get_ntforms(&list);
8617 update_a_form(&list, form, count);
8618 write_ntforms(&list, count);
8621 * ChangeID must always be set if this is a printer
8624 if ( Printer->printer_type == SPLHND_PRINTER )
8625 status = mod_a_printer(printer, 2);
8628 done:
8629 if ( printer )
8630 free_a_printer(&printer, 2);
8631 SAFE_FREE(list);
8633 return status;
8636 /****************************************************************************
8637 enumprintprocessors level 1.
8638 ****************************************************************************/
8640 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8642 PRINTPROCESSOR_1 *info_1=NULL;
8643 WERROR result = WERR_OK;
8645 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8646 return WERR_NOMEM;
8648 (*returned) = 0x1;
8650 init_unistr(&info_1->name, "winprint");
8652 *needed += spoolss_size_printprocessor_info_1(info_1);
8654 if (*needed > offered) {
8655 result = WERR_INSUFFICIENT_BUFFER;
8656 goto out;
8659 if (!rpcbuf_alloc_size(buffer, *needed)) {
8660 result = WERR_NOMEM;
8661 goto out;
8664 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8666 out:
8667 SAFE_FREE(info_1);
8669 if ( !W_ERROR_IS_OK(result) )
8670 *returned = 0;
8672 return result;
8675 /****************************************************************************
8676 ****************************************************************************/
8678 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8680 uint32 level = q_u->level;
8681 RPC_BUFFER *buffer = NULL;
8682 uint32 offered = q_u->offered;
8683 uint32 *needed = &r_u->needed;
8684 uint32 *returned = &r_u->returned;
8686 /* that's an [in out] buffer */
8688 if (!q_u->buffer && (offered!=0)) {
8689 return WERR_INVALID_PARAM;
8692 rpcbuf_move(q_u->buffer, &r_u->buffer);
8693 buffer = r_u->buffer;
8695 DEBUG(5,("spoolss_enumprintprocessors\n"));
8698 * Enumerate the print processors ...
8700 * Just reply with "winprint", to keep NT happy
8701 * and I can use my nice printer checker.
8704 *returned=0;
8705 *needed=0;
8707 switch (level) {
8708 case 1:
8709 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8710 default:
8711 return WERR_UNKNOWN_LEVEL;
8715 /****************************************************************************
8716 enumprintprocdatatypes level 1.
8717 ****************************************************************************/
8719 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8721 PRINTPROCDATATYPE_1 *info_1=NULL;
8722 WERROR result = WERR_OK;
8724 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8725 return WERR_NOMEM;
8727 (*returned) = 0x1;
8729 init_unistr(&info_1->name, "RAW");
8731 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8733 if (*needed > offered) {
8734 result = WERR_INSUFFICIENT_BUFFER;
8735 goto out;
8738 if (!rpcbuf_alloc_size(buffer, *needed)) {
8739 result = WERR_NOMEM;
8740 goto out;
8743 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8745 out:
8746 SAFE_FREE(info_1);
8748 if ( !W_ERROR_IS_OK(result) )
8749 *returned = 0;
8751 return result;
8754 /****************************************************************************
8755 ****************************************************************************/
8757 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8759 uint32 level = q_u->level;
8760 RPC_BUFFER *buffer = NULL;
8761 uint32 offered = q_u->offered;
8762 uint32 *needed = &r_u->needed;
8763 uint32 *returned = &r_u->returned;
8765 /* that's an [in out] buffer */
8767 if (!q_u->buffer && (offered!=0)) {
8768 return WERR_INVALID_PARAM;
8771 rpcbuf_move(q_u->buffer, &r_u->buffer);
8772 buffer = r_u->buffer;
8774 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8776 *returned=0;
8777 *needed=0;
8779 switch (level) {
8780 case 1:
8781 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8782 default:
8783 return WERR_UNKNOWN_LEVEL;
8787 /****************************************************************************
8788 enumprintmonitors level 1.
8789 ****************************************************************************/
8791 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8793 PRINTMONITOR_1 *info_1;
8794 WERROR result = WERR_OK;
8795 int i;
8797 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8798 return WERR_NOMEM;
8800 *returned = 2;
8802 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8803 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8805 for ( i=0; i<*returned; i++ ) {
8806 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8809 if (*needed > offered) {
8810 result = WERR_INSUFFICIENT_BUFFER;
8811 goto out;
8814 if (!rpcbuf_alloc_size(buffer, *needed)) {
8815 result = WERR_NOMEM;
8816 goto out;
8819 for ( i=0; i<*returned; i++ ) {
8820 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8823 out:
8824 SAFE_FREE(info_1);
8826 if ( !W_ERROR_IS_OK(result) )
8827 *returned = 0;
8829 return result;
8832 /****************************************************************************
8833 enumprintmonitors level 2.
8834 ****************************************************************************/
8836 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8838 PRINTMONITOR_2 *info_2;
8839 WERROR result = WERR_OK;
8840 int i;
8842 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8843 return WERR_NOMEM;
8845 *returned = 2;
8847 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8848 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8849 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8851 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8852 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8853 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8855 for ( i=0; i<*returned; i++ ) {
8856 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8859 if (*needed > offered) {
8860 result = WERR_INSUFFICIENT_BUFFER;
8861 goto out;
8864 if (!rpcbuf_alloc_size(buffer, *needed)) {
8865 result = WERR_NOMEM;
8866 goto out;
8869 for ( i=0; i<*returned; i++ ) {
8870 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8873 out:
8874 SAFE_FREE(info_2);
8876 if ( !W_ERROR_IS_OK(result) )
8877 *returned = 0;
8879 return result;
8882 /****************************************************************************
8883 ****************************************************************************/
8885 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8887 uint32 level = q_u->level;
8888 RPC_BUFFER *buffer = NULL;
8889 uint32 offered = q_u->offered;
8890 uint32 *needed = &r_u->needed;
8891 uint32 *returned = &r_u->returned;
8893 /* that's an [in out] buffer */
8895 if (!q_u->buffer && (offered!=0)) {
8896 return WERR_INVALID_PARAM;
8899 rpcbuf_move(q_u->buffer, &r_u->buffer);
8900 buffer = r_u->buffer;
8902 DEBUG(5,("spoolss_enumprintmonitors\n"));
8905 * Enumerate the print monitors ...
8907 * Just reply with "Local Port", to keep NT happy
8908 * and I can use my nice printer checker.
8911 *returned=0;
8912 *needed=0;
8914 switch (level) {
8915 case 1:
8916 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8917 case 2:
8918 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8919 default:
8920 return WERR_UNKNOWN_LEVEL;
8924 /****************************************************************************
8925 ****************************************************************************/
8927 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8928 NT_PRINTER_INFO_LEVEL *ntprinter,
8929 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8930 uint32 *needed)
8932 int i=0;
8933 bool found=False;
8934 JOB_INFO_1 *info_1=NULL;
8935 WERROR result = WERR_OK;
8937 info_1=SMB_MALLOC_P(JOB_INFO_1);
8939 if (info_1 == NULL) {
8940 return WERR_NOMEM;
8943 for (i=0; i<count && found==False; i++) {
8944 if ((*queue)[i].job==(int)jobid)
8945 found=True;
8948 if (found==False) {
8949 SAFE_FREE(info_1);
8950 /* NT treats not found as bad param... yet another bad choice */
8951 return WERR_INVALID_PARAM;
8954 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8956 *needed += spoolss_size_job_info_1(info_1);
8958 if (*needed > offered) {
8959 result = WERR_INSUFFICIENT_BUFFER;
8960 goto out;
8963 if (!rpcbuf_alloc_size(buffer, *needed)) {
8964 result = WERR_NOMEM;
8965 goto out;
8968 smb_io_job_info_1("", buffer, info_1, 0);
8970 out:
8971 SAFE_FREE(info_1);
8973 return result;
8976 /****************************************************************************
8977 ****************************************************************************/
8979 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8980 NT_PRINTER_INFO_LEVEL *ntprinter,
8981 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8982 uint32 *needed)
8984 int i = 0;
8985 bool found = False;
8986 JOB_INFO_2 *info_2;
8987 WERROR result;
8988 DEVICEMODE *devmode = NULL;
8989 NT_DEVICEMODE *nt_devmode = NULL;
8991 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8992 return WERR_NOMEM;
8994 ZERO_STRUCTP(info_2);
8996 for ( i=0; i<count && found==False; i++ )
8998 if ((*queue)[i].job == (int)jobid)
8999 found = True;
9002 if ( !found ) {
9003 /* NT treats not found as bad param... yet another bad
9004 choice */
9005 result = WERR_INVALID_PARAM;
9006 goto done;
9010 * if the print job does not have a DEVMODE associated with it,
9011 * just use the one for the printer. A NULL devicemode is not
9012 * a failure condition
9015 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9016 devmode = construct_dev_mode(lp_const_servicename(snum));
9017 else {
9018 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9019 ZERO_STRUCTP( devmode );
9020 convert_nt_devicemode( devmode, nt_devmode );
9024 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9026 *needed += spoolss_size_job_info_2(info_2);
9028 if (*needed > offered) {
9029 result = WERR_INSUFFICIENT_BUFFER;
9030 goto done;
9033 if (!rpcbuf_alloc_size(buffer, *needed)) {
9034 result = WERR_NOMEM;
9035 goto done;
9038 smb_io_job_info_2("", buffer, info_2, 0);
9040 result = WERR_OK;
9042 done:
9043 /* Cleanup allocated memory */
9045 free_job_info_2(info_2); /* Also frees devmode */
9046 SAFE_FREE(info_2);
9048 return result;
9051 /****************************************************************************
9052 ****************************************************************************/
9054 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9056 POLICY_HND *handle = &q_u->handle;
9057 uint32 jobid = q_u->jobid;
9058 uint32 level = q_u->level;
9059 RPC_BUFFER *buffer = NULL;
9060 uint32 offered = q_u->offered;
9061 uint32 *needed = &r_u->needed;
9062 WERROR wstatus = WERR_OK;
9063 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9064 int snum;
9065 int count;
9066 print_queue_struct *queue = NULL;
9067 print_status_struct prt_status;
9069 /* that's an [in out] buffer */
9071 if (!q_u->buffer && (offered!=0)) {
9072 return WERR_INVALID_PARAM;
9075 rpcbuf_move(q_u->buffer, &r_u->buffer);
9076 buffer = r_u->buffer;
9078 DEBUG(5,("spoolss_getjob\n"));
9080 *needed = 0;
9082 if (!get_printer_snum(p, handle, &snum, NULL))
9083 return WERR_BADFID;
9085 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9086 if ( !W_ERROR_IS_OK(wstatus) )
9087 return wstatus;
9089 count = print_queue_status(snum, &queue, &prt_status);
9091 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9092 count, prt_status.status, prt_status.message));
9094 switch ( level ) {
9095 case 1:
9096 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9097 buffer, offered, needed);
9098 break;
9099 case 2:
9100 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9101 buffer, offered, needed);
9102 break;
9103 default:
9104 wstatus = WERR_UNKNOWN_LEVEL;
9105 break;
9108 SAFE_FREE(queue);
9109 free_a_printer( &ntprinter, 2 );
9111 return wstatus;
9114 /********************************************************************
9115 spoolss_getprinterdataex
9117 From MSDN documentation of GetPrinterDataEx: pass request
9118 to GetPrinterData if key is "PrinterDriverData".
9119 ********************************************************************/
9121 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9123 POLICY_HND *handle = &q_u->handle;
9124 uint32 in_size = q_u->size;
9125 uint32 *type = &r_u->type;
9126 uint32 *out_size = &r_u->size;
9127 uint8 **data = &r_u->data;
9128 uint32 *needed = &r_u->needed;
9129 fstring keyname, valuename;
9131 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9133 NT_PRINTER_INFO_LEVEL *printer = NULL;
9134 int snum = 0;
9135 WERROR status = WERR_OK;
9137 DEBUG(4,("_spoolss_getprinterdataex\n"));
9139 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9140 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9142 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9143 keyname, valuename));
9145 /* in case of problem, return some default values */
9147 *needed = 0;
9148 *type = 0;
9149 *out_size = in_size;
9151 if (!Printer) {
9152 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9153 status = WERR_BADFID;
9154 goto done;
9157 /* Is the handle to a printer or to the server? */
9159 if (Printer->printer_type == SPLHND_SERVER) {
9160 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9161 status = WERR_INVALID_PARAM;
9162 goto done;
9165 if ( !get_printer_snum(p,handle, &snum, NULL) )
9166 return WERR_BADFID;
9168 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9169 if ( !W_ERROR_IS_OK(status) )
9170 goto done;
9172 /* check to see if the keyname is valid */
9173 if ( !strlen(keyname) ) {
9174 status = WERR_INVALID_PARAM;
9175 goto done;
9178 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9179 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9180 free_a_printer( &printer, 2 );
9181 status = WERR_BADFILE;
9182 goto done;
9185 /* When given a new keyname, we should just create it */
9187 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9189 if (*needed > *out_size)
9190 status = WERR_MORE_DATA;
9192 done:
9193 if ( !W_ERROR_IS_OK(status) )
9195 DEBUG(5, ("error: allocating %d\n", *out_size));
9197 /* reply this param doesn't exist */
9199 if ( *out_size )
9201 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9202 status = WERR_NOMEM;
9203 goto done;
9205 } else {
9206 *data = NULL;
9210 if ( printer )
9211 free_a_printer( &printer, 2 );
9213 return status;
9216 /********************************************************************
9217 * spoolss_setprinterdataex
9218 ********************************************************************/
9220 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9222 POLICY_HND *handle = &q_u->handle;
9223 uint32 type = q_u->type;
9224 uint8 *data = q_u->data;
9225 uint32 real_len = q_u->real_len;
9227 NT_PRINTER_INFO_LEVEL *printer = NULL;
9228 int snum = 0;
9229 WERROR status = WERR_OK;
9230 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9231 fstring valuename;
9232 fstring keyname;
9233 char *oid_string;
9235 DEBUG(4,("_spoolss_setprinterdataex\n"));
9237 /* From MSDN documentation of SetPrinterDataEx: pass request to
9238 SetPrinterData if key is "PrinterDriverData" */
9240 if (!Printer) {
9241 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9242 return WERR_BADFID;
9245 if ( Printer->printer_type == SPLHND_SERVER ) {
9246 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9247 return WERR_INVALID_PARAM;
9250 if ( !get_printer_snum(p,handle, &snum, NULL) )
9251 return WERR_BADFID;
9254 * Access check : NT returns "access denied" if you make a
9255 * SetPrinterData call without the necessary privildge.
9256 * we were originally returning OK if nothing changed
9257 * which made Win2k issue **a lot** of SetPrinterData
9258 * when connecting to a printer --jerry
9261 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9263 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9264 return WERR_ACCESS_DENIED;
9267 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9268 if (!W_ERROR_IS_OK(status))
9269 return status;
9271 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9272 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9274 /* check for OID in valuename */
9276 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9278 *oid_string = '\0';
9279 oid_string++;
9282 /* save the registry data */
9284 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9286 if ( W_ERROR_IS_OK(status) )
9288 /* save the OID if one was specified */
9289 if ( oid_string ) {
9290 fstrcat( keyname, "\\" );
9291 fstrcat( keyname, SPOOL_OID_KEY );
9294 * I'm not checking the status here on purpose. Don't know
9295 * if this is right, but I'm returning the status from the
9296 * previous set_printer_dataex() call. I have no idea if
9297 * this is right. --jerry
9300 set_printer_dataex( printer, keyname, valuename,
9301 REG_SZ, (uint8 *)oid_string,
9302 strlen(oid_string)+1 );
9305 status = mod_a_printer(printer, 2);
9308 free_a_printer(&printer, 2);
9310 return status;
9314 /********************************************************************
9315 * spoolss_deleteprinterdataex
9316 ********************************************************************/
9318 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9320 POLICY_HND *handle = &q_u->handle;
9321 UNISTR2 *value = &q_u->valuename;
9322 UNISTR2 *key = &q_u->keyname;
9324 NT_PRINTER_INFO_LEVEL *printer = NULL;
9325 int snum=0;
9326 WERROR status = WERR_OK;
9327 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9328 char *valuename = NULL;
9329 char *keyname = NULL;
9330 TALLOC_CTX *ctx = p->mem_ctx;
9332 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9334 if (!Printer) {
9335 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9336 return WERR_BADFID;
9339 if (!get_printer_snum(p, handle, &snum, NULL))
9340 return WERR_BADFID;
9342 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9343 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9344 return WERR_ACCESS_DENIED;
9347 valuename = unistr2_to_ascii_talloc(ctx, value);
9348 keyname = unistr2_to_ascii_talloc(ctx, key);
9349 if (!valuename || !keyname) {
9350 return WERR_NOMEM;
9353 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9354 if (!W_ERROR_IS_OK(status))
9355 return status;
9357 status = delete_printer_dataex( printer, keyname, valuename );
9359 if ( W_ERROR_IS_OK(status) )
9360 mod_a_printer( printer, 2 );
9362 free_a_printer(&printer, 2);
9364 return status;
9367 /********************************************************************
9368 * spoolss_enumprinterkey
9369 ********************************************************************/
9372 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9374 fstring key;
9375 fstring *keynames = NULL;
9376 uint16 *enumkeys = NULL;
9377 int num_keys;
9378 int printerkey_len;
9379 POLICY_HND *handle = &q_u->handle;
9380 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9381 NT_PRINTER_DATA *data;
9382 NT_PRINTER_INFO_LEVEL *printer = NULL;
9383 int snum = 0;
9384 WERROR status = WERR_BADFILE;
9387 DEBUG(4,("_spoolss_enumprinterkey\n"));
9389 if (!Printer) {
9390 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9391 return WERR_BADFID;
9394 if ( !get_printer_snum(p,handle, &snum, NULL) )
9395 return WERR_BADFID;
9397 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9398 if (!W_ERROR_IS_OK(status))
9399 return status;
9401 /* get the list of subkey names */
9403 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9404 data = printer->info_2->data;
9406 num_keys = get_printer_subkeys( data, key, &keynames );
9408 if ( num_keys == -1 ) {
9409 status = WERR_BADFILE;
9410 goto done;
9413 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9415 r_u->needed = printerkey_len*2;
9417 if ( q_u->size < r_u->needed ) {
9418 status = WERR_MORE_DATA;
9419 goto done;
9422 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9423 status = WERR_NOMEM;
9424 goto done;
9427 status = WERR_OK;
9429 if ( q_u->size < r_u->needed )
9430 status = WERR_MORE_DATA;
9432 done:
9433 free_a_printer( &printer, 2 );
9434 SAFE_FREE( keynames );
9436 return status;
9439 /********************************************************************
9440 * spoolss_deleteprinterkey
9441 ********************************************************************/
9443 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9445 POLICY_HND *handle = &q_u->handle;
9446 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9447 fstring key;
9448 NT_PRINTER_INFO_LEVEL *printer = NULL;
9449 int snum=0;
9450 WERROR status;
9452 DEBUG(5,("spoolss_deleteprinterkey\n"));
9454 if (!Printer) {
9455 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9456 return WERR_BADFID;
9459 /* if keyname == NULL, return error */
9461 if ( !q_u->keyname.buffer )
9462 return WERR_INVALID_PARAM;
9464 if (!get_printer_snum(p, handle, &snum, NULL))
9465 return WERR_BADFID;
9467 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9468 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9469 return WERR_ACCESS_DENIED;
9472 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9473 if (!W_ERROR_IS_OK(status))
9474 return status;
9476 /* delete the key and all subneys */
9478 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9480 status = delete_all_printer_data( printer->info_2, key );
9482 if ( W_ERROR_IS_OK(status) )
9483 status = mod_a_printer(printer, 2);
9485 free_a_printer( &printer, 2 );
9487 return status;
9491 /********************************************************************
9492 * spoolss_enumprinterdataex
9493 ********************************************************************/
9495 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9497 POLICY_HND *handle = &q_u->handle;
9498 uint32 in_size = q_u->size;
9499 uint32 num_entries,
9500 needed;
9501 NT_PRINTER_INFO_LEVEL *printer = NULL;
9502 PRINTER_ENUM_VALUES *enum_values = NULL;
9503 NT_PRINTER_DATA *p_data;
9504 fstring key;
9505 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9506 int snum;
9507 WERROR result;
9508 int key_index;
9509 int i;
9510 REGISTRY_VALUE *val;
9511 char *value_name;
9512 uint32 data_len;
9515 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9517 if (!Printer) {
9518 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9519 return WERR_BADFID;
9523 * first check for a keyname of NULL or "". Win2k seems to send
9524 * this a lot and we should send back WERR_INVALID_PARAM
9525 * no need to spend time looking up the printer in this case.
9526 * --jerry
9529 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9530 if ( !strlen(key) ) {
9531 result = WERR_INVALID_PARAM;
9532 goto done;
9535 /* get the printer off of disk */
9537 if (!get_printer_snum(p,handle, &snum, NULL))
9538 return WERR_BADFID;
9540 ZERO_STRUCT(printer);
9541 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9542 if (!W_ERROR_IS_OK(result))
9543 return result;
9545 /* now look for a match on the key name */
9547 p_data = printer->info_2->data;
9549 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9550 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9552 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9553 result = WERR_INVALID_PARAM;
9554 goto done;
9557 result = WERR_OK;
9558 needed = 0;
9560 /* allocate the memory for the array of pointers -- if necessary */
9562 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9563 if ( num_entries )
9565 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9567 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9568 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9569 result = WERR_NOMEM;
9570 goto done;
9573 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9577 * loop through all params and build the array to pass
9578 * back to the client
9581 for ( i=0; i<num_entries; i++ )
9583 /* lookup the registry value */
9585 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9586 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9588 /* copy the data */
9590 value_name = regval_name( val );
9591 init_unistr( &enum_values[i].valuename, value_name );
9592 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9593 enum_values[i].type = regval_type( val );
9595 data_len = regval_size( val );
9596 if ( data_len ) {
9597 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9599 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9600 data_len ));
9601 result = WERR_NOMEM;
9602 goto done;
9605 enum_values[i].data_len = data_len;
9607 /* keep track of the size of the array in bytes */
9609 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9612 /* housekeeping information in the reply */
9614 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9615 * the hand marshalled container size is a multiple
9616 * of 4 bytes for RPC alignment.
9619 if (needed % 4) {
9620 needed += 4-(needed % 4);
9623 r_u->needed = needed;
9624 r_u->returned = num_entries;
9626 if (needed > in_size) {
9627 result = WERR_MORE_DATA;
9628 goto done;
9631 /* copy data into the reply */
9633 r_u->ctr.size = r_u->needed;
9635 r_u->ctr.size_of_array = r_u->returned;
9636 r_u->ctr.values = enum_values;
9640 done:
9641 if ( printer )
9642 free_a_printer(&printer, 2);
9644 return result;
9647 /****************************************************************************
9648 ****************************************************************************/
9650 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9652 init_unistr(&info->name, name);
9655 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9656 UNISTR2 *environment,
9657 RPC_BUFFER *buffer,
9658 uint32 offered,
9659 uint32 *needed)
9661 char *long_archi = NULL;
9662 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9663 WERROR result = WERR_OK;
9664 TALLOC_CTX *ctx = talloc_tos();
9666 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9667 if (!long_archi) {
9668 return WERR_NOMEM;
9671 if (!get_short_archi(long_archi))
9672 return WERR_INVALID_ENVIRONMENT;
9674 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9675 return WERR_NOMEM;
9677 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9679 *needed += spoolss_size_printprocessordirectory_info_1(info);
9681 if (*needed > offered) {
9682 result = WERR_INSUFFICIENT_BUFFER;
9683 goto out;
9686 if (!rpcbuf_alloc_size(buffer, *needed)) {
9687 result = WERR_INSUFFICIENT_BUFFER;
9688 goto out;
9691 smb_io_printprocessordirectory_1("", buffer, info, 0);
9693 out:
9694 SAFE_FREE(info);
9696 return result;
9699 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9701 uint32 level = q_u->level;
9702 RPC_BUFFER *buffer = NULL;
9703 uint32 offered = q_u->offered;
9704 uint32 *needed = &r_u->needed;
9705 WERROR result;
9707 /* that's an [in out] buffer */
9709 if (!q_u->buffer && (offered!=0)) {
9710 return WERR_INVALID_PARAM;
9713 rpcbuf_move(q_u->buffer, &r_u->buffer);
9714 buffer = r_u->buffer;
9716 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9718 *needed=0;
9720 switch(level) {
9721 case 1:
9722 result = getprintprocessordirectory_level_1
9723 (&q_u->name, &q_u->environment, buffer, offered, needed);
9724 break;
9725 default:
9726 result = WERR_UNKNOWN_LEVEL;
9729 return result;
9732 /*******************************************************************
9733 Streams the monitor UI DLL name in UNICODE
9734 *******************************************************************/
9736 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9737 RPC_BUFFER *out, uint32 *needed )
9739 const char *dllname = "tcpmonui.dll";
9741 *needed = (strlen(dllname)+1) * 2;
9743 if ( rpcbuf_get_size(out) < *needed ) {
9744 return WERR_INSUFFICIENT_BUFFER;
9747 if ( !make_monitorui_buf( out, dllname ) ) {
9748 return WERR_NOMEM;
9751 return WERR_OK;
9754 /*******************************************************************
9755 Create a new TCP/IP port
9756 *******************************************************************/
9758 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9759 RPC_BUFFER *out, uint32 *needed )
9761 NT_PORT_DATA_1 port1;
9762 TALLOC_CTX *ctx = talloc_tos();
9763 char *device_uri = NULL;
9765 ZERO_STRUCT( port1 );
9767 /* convert to our internal port data structure */
9769 if ( !convert_port_data_1( &port1, in ) ) {
9770 return WERR_NOMEM;
9773 /* create the device URI and call the add_port_hook() */
9775 switch ( port1.protocol ) {
9776 case PORT_PROTOCOL_DIRECT:
9777 device_uri = talloc_asprintf(ctx,
9778 "socket://%s:%d/", port1.hostaddr, port1.port );
9779 break;
9781 case PORT_PROTOCOL_LPR:
9782 device_uri = talloc_asprintf(ctx,
9783 "lpr://%s/%s", port1.hostaddr, port1.queue );
9784 break;
9786 default:
9787 return WERR_UNKNOWN_PORT;
9790 if (!device_uri) {
9791 return WERR_NOMEM;
9794 return add_port_hook(ctx, token, port1.name, device_uri );
9797 /*******************************************************************
9798 *******************************************************************/
9800 struct xcv_api_table xcvtcp_cmds[] = {
9801 { "MonitorUI", xcvtcp_monitorui },
9802 { "AddPort", xcvtcp_addport},
9803 { NULL, NULL }
9806 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9807 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9808 uint32 *needed )
9810 int i;
9812 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9814 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9815 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9816 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9819 return WERR_BADFUNC;
9822 /*******************************************************************
9823 *******************************************************************/
9824 #if 0 /* don't support management using the "Local Port" monitor */
9826 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9827 RPC_BUFFER *out, uint32 *needed )
9829 const char *dllname = "localui.dll";
9831 *needed = (strlen(dllname)+1) * 2;
9833 if ( rpcbuf_get_size(out) < *needed ) {
9834 return WERR_INSUFFICIENT_BUFFER;
9837 if ( !make_monitorui_buf( out, dllname )) {
9838 return WERR_NOMEM;
9841 return WERR_OK;
9844 /*******************************************************************
9845 *******************************************************************/
9847 struct xcv_api_table xcvlocal_cmds[] = {
9848 { "MonitorUI", xcvlocal_monitorui },
9849 { NULL, NULL }
9851 #else
9852 struct xcv_api_table xcvlocal_cmds[] = {
9853 { NULL, NULL }
9855 #endif
9859 /*******************************************************************
9860 *******************************************************************/
9862 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9863 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9864 uint32 *needed )
9866 int i;
9868 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9870 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9871 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9872 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9874 return WERR_BADFUNC;
9877 /*******************************************************************
9878 *******************************************************************/
9880 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9882 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9883 fstring command;
9885 if (!Printer) {
9886 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9887 return WERR_BADFID;
9890 /* Has to be a handle to the TCP/IP port monitor */
9892 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9893 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9894 return WERR_BADFID;
9897 /* requires administrative access to the server */
9899 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9900 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9901 return WERR_ACCESS_DENIED;
9904 /* Get the command name. There's numerous commands supported by the
9905 TCPMON interface. */
9907 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9908 q_u->dataname.uni_str_len*2, 0);
9910 /* Allocate the outgoing buffer */
9912 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9914 switch ( Printer->printer_type ) {
9915 case SPLHND_PORTMON_TCP:
9916 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9917 &q_u->indata, &r_u->outdata, &r_u->needed );
9918 case SPLHND_PORTMON_LOCAL:
9919 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9920 &q_u->indata, &r_u->outdata, &r_u->needed );
9923 return WERR_INVALID_PRINT_MONITOR;