s3-spoolss: make us pass the RPC-SPOOLSS torture test w.r.t. directory calls.
[Samba/gbeck.git] / source3 / rpc_server / srv_spoolss_nt.c
blob2f89775101879364248d508402b0096ddded0aae
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) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
75 /********************************************************************
76 * Canonicalize servername.
77 ********************************************************************/
79 static const char *canon_servername(const char *servername)
81 const char *pservername = servername;
82 while (*pservername == '\\') {
83 pservername++;
85 return pservername;
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
91 switch (v) {
92 case LPQ_QUEUED:
93 return 0;
94 case LPQ_PAUSED:
95 return JOB_STATUS_PAUSED;
96 case LPQ_SPOOLING:
97 return JOB_STATUS_SPOOLING;
98 case LPQ_PRINTING:
99 return JOB_STATUS_PRINTING;
100 case LPQ_ERROR:
101 return JOB_STATUS_ERROR;
102 case LPQ_DELETING:
103 return JOB_STATUS_DELETING;
104 case LPQ_OFFLINE:
105 return JOB_STATUS_OFFLINE;
106 case LPQ_PAPEROUT:
107 return JOB_STATUS_PAPEROUT;
108 case LPQ_PRINTED:
109 return JOB_STATUS_PRINTED;
110 case LPQ_DELETED:
111 return JOB_STATUS_DELETED;
112 case LPQ_BLOCKED:
113 return JOB_STATUS_BLOCKED;
114 case LPQ_USER_INTERVENTION:
115 return JOB_STATUS_USER_INTERVENTION;
117 return 0;
120 static int nt_printq_status(int v)
122 switch (v) {
123 case LPQ_PAUSED:
124 return PRINTER_STATUS_PAUSED;
125 case LPQ_QUEUED:
126 case LPQ_SPOOLING:
127 case LPQ_PRINTING:
128 return 0;
130 return 0;
133 /***************************************************************************
134 Disconnect from the client
135 ****************************************************************************/
137 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
139 WERROR result;
140 NTSTATUS status;
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 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
157 handle,
158 &result);
159 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 win_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 messaging_deregister(smbd_messaging_context(),
170 MSG_PRINTER_NOTIFY2, NULL);
172 /* Tell the connections db we're no longer interested in
173 * printer notify messages. */
175 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
178 smb_connections--;
181 /****************************************************************************
182 Functions to free a printer entry datastruct.
183 ****************************************************************************/
185 static int printer_entry_destructor(Printer_entry *Printer)
187 if (Printer->notify.client_connected==True) {
188 int snum = -1;
190 if ( Printer->printer_type == SPLHND_SERVER) {
191 snum = -1;
192 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
193 } else if (Printer->printer_type == SPLHND_PRINTER) {
194 snum = print_queue_snum(Printer->sharename);
195 if (snum != -1)
196 srv_spoolss_replycloseprinter(snum,
197 &Printer->notify.client_hnd);
201 Printer->notify.flags=0;
202 Printer->notify.options=0;
203 Printer->notify.localmachine[0]='\0';
204 Printer->notify.printerlocal=0;
205 TALLOC_FREE(Printer->notify.option);
206 Printer->notify.client_connected=False;
208 free_nt_devicemode( &Printer->nt_devmode );
209 free_a_printer( &Printer->printer_info, 2 );
211 /* Remove from the internal list. */
212 DLIST_REMOVE(printers_list, Printer);
213 return 0;
216 /****************************************************************************
217 find printer index by handle
218 ****************************************************************************/
220 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
222 Printer_entry *find_printer = NULL;
224 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
225 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
226 return NULL;
229 return find_printer;
232 /****************************************************************************
233 Close printer index by handle.
234 ****************************************************************************/
236 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
238 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
240 if (!Printer) {
241 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
242 return False;
245 close_policy_hnd(p, hnd);
247 return True;
250 /****************************************************************************
251 Delete a printer given a handle.
252 ****************************************************************************/
254 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
256 char *cmd = lp_deleteprinter_cmd();
257 char *command = NULL;
258 int ret;
259 SE_PRIV se_printop = SE_PRINT_OPERATOR;
260 bool is_print_op = False;
262 /* can't fail if we don't try */
264 if ( !*cmd )
265 return WERR_OK;
267 command = talloc_asprintf(ctx,
268 "%s \"%s\"",
269 cmd, sharename);
270 if (!command) {
271 return WERR_NOMEM;
273 if ( token )
274 is_print_op = user_has_privileges( token, &se_printop );
276 DEBUG(10,("Running [%s]\n", command));
278 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
280 if ( is_print_op )
281 become_root();
283 if ( (ret = smbrun(command, NULL)) == 0 ) {
284 /* Tell everyone we updated smb.conf. */
285 message_send_all(smbd_messaging_context(),
286 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
289 if ( is_print_op )
290 unbecome_root();
292 /********** END SePrintOperatorPrivlege BLOCK **********/
294 DEBUGADD(10,("returned [%d]\n", ret));
296 TALLOC_FREE(command);
298 if (ret != 0)
299 return WERR_BADFID; /* What to return here? */
301 /* go ahead and re-read the services immediately */
302 reload_services( False );
304 if ( lp_servicenumber( sharename ) < 0 )
305 return WERR_ACCESS_DENIED;
307 return WERR_OK;
310 /****************************************************************************
311 Delete a printer given a handle.
312 ****************************************************************************/
314 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
316 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
318 if (!Printer) {
319 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
320 return WERR_BADFID;
324 * It turns out that Windows allows delete printer on a handle
325 * opened by an admin user, then used on a pipe handle created
326 * by an anonymous user..... but they're working on security.... riiight !
327 * JRA.
330 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
331 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
332 return WERR_ACCESS_DENIED;
335 /* this does not need a become root since the access check has been
336 done on the handle already */
338 if (del_a_printer( Printer->sharename ) != 0) {
339 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
340 return WERR_BADFID;
343 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
344 Printer->sharename );
347 /****************************************************************************
348 Return the snum of a printer corresponding to an handle.
349 ****************************************************************************/
351 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
352 struct share_params **params)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
356 if (!Printer) {
357 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
358 return False;
361 switch (Printer->printer_type) {
362 case SPLHND_PRINTER:
363 DEBUG(4,("short name:%s\n", Printer->sharename));
364 *number = print_queue_snum(Printer->sharename);
365 return (*number != -1);
366 case SPLHND_SERVER:
367 return False;
368 default:
369 return False;
373 /****************************************************************************
374 Set printer handle type.
375 Check if it's \\server or \\server\printer
376 ****************************************************************************/
378 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
380 DEBUG(3,("Setting printer type=%s\n", handlename));
382 if ( strlen(handlename) < 3 ) {
383 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
384 return False;
387 /* it's a print server */
388 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
389 DEBUGADD(4,("Printer is a print server\n"));
390 Printer->printer_type = SPLHND_SERVER;
392 /* it's a printer (set_printer_hnd_name() will handle port monitors */
393 else {
394 DEBUGADD(4,("Printer is a printer\n"));
395 Printer->printer_type = SPLHND_PRINTER;
398 return True;
401 /****************************************************************************
402 Set printer handle name.. Accept names like \\server, \\server\printer,
403 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
404 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
405 XcvDataPort() interface.
406 ****************************************************************************/
408 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
410 int snum;
411 int n_services=lp_numservices();
412 char *aprinter, *printername;
413 const char *servername;
414 fstring sname;
415 bool found=False;
416 NT_PRINTER_INFO_LEVEL *printer = NULL;
417 WERROR result;
419 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
421 aprinter = handlename;
422 if ( *handlename == '\\' ) {
423 servername = canon_servername(handlename);
424 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
425 *aprinter = '\0';
426 aprinter++;
428 } else {
429 servername = "";
432 /* save the servername to fill in replies on this handle */
434 if ( !is_myname_or_ipaddr( servername ) )
435 return False;
437 fstrcpy( Printer->servername, servername );
439 if ( Printer->printer_type == SPLHND_SERVER )
440 return True;
442 if ( Printer->printer_type != SPLHND_PRINTER )
443 return False;
445 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
447 /* check for the Port Monitor Interface */
449 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
450 Printer->printer_type = SPLHND_PORTMON_TCP;
451 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
452 found = True;
454 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
455 Printer->printer_type = SPLHND_PORTMON_LOCAL;
456 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
457 found = True;
460 /* Search all sharenames first as this is easier than pulling
461 the printer_info_2 off of disk. Don't use find_service() since
462 that calls out to map_username() */
464 /* do another loop to look for printernames */
466 for (snum=0; !found && snum<n_services; snum++) {
468 /* no point going on if this is not a printer */
470 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
471 continue;
473 fstrcpy(sname, lp_servicename(snum));
474 if ( strequal( aprinter, sname ) ) {
475 found = True;
476 break;
479 /* no point looking up the printer object if
480 we aren't allowing printername != sharename */
482 if ( lp_force_printername(snum) )
483 continue;
485 fstrcpy(sname, lp_servicename(snum));
487 printer = NULL;
489 /* This call doesn't fill in the location or comment from
490 * a CUPS server for efficiency with large numbers of printers.
491 * JRA.
494 result = get_a_printer_search( NULL, &printer, 2, sname );
495 if ( !W_ERROR_IS_OK(result) ) {
496 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
497 sname, win_errstr(result)));
498 continue;
501 /* printername is always returned as \\server\printername */
502 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
503 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
504 printer->info_2->printername));
505 free_a_printer( &printer, 2);
506 continue;
509 printername++;
511 if ( strequal(printername, aprinter) ) {
512 free_a_printer( &printer, 2);
513 found = True;
514 break;
517 DEBUGADD(10, ("printername: %s\n", printername));
519 free_a_printer( &printer, 2);
522 free_a_printer( &printer, 2);
524 if ( !found ) {
525 DEBUGADD(4,("Printer not found\n"));
526 return False;
529 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
531 fstrcpy(Printer->sharename, sname);
533 return True;
536 /****************************************************************************
537 Find first available printer slot. creates a printer handle for you.
538 ****************************************************************************/
540 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
542 Printer_entry *new_printer;
544 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
546 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
547 if (new_printer == NULL) {
548 return false;
550 talloc_set_destructor(new_printer, printer_entry_destructor);
552 if (!create_policy_hnd(p, hnd, new_printer)) {
553 TALLOC_FREE(new_printer);
554 return False;
557 /* Add to the internal list. */
558 DLIST_ADD(printers_list, new_printer);
560 new_printer->notify.option=NULL;
562 if (!set_printer_hnd_printertype(new_printer, name)) {
563 close_printer_handle(p, hnd);
564 return False;
567 if (!set_printer_hnd_name(new_printer, name)) {
568 close_printer_handle(p, hnd);
569 return False;
572 new_printer->access_granted = access_granted;
574 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
576 return True;
579 /***************************************************************************
580 check to see if the client motify handle is monitoring the notification
581 given by (notify_type, notify_field).
582 **************************************************************************/
584 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
585 uint16 notify_field)
587 return True;
590 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
591 uint16 notify_field)
593 struct spoolss_NotifyOption *option = p->notify.option;
594 uint32 i, j;
597 * Flags should always be zero when the change notify
598 * is registered by the client's spooler. A user Win32 app
599 * might use the flags though instead of the NOTIFY_OPTION_INFO
600 * --jerry
603 if (!option) {
604 return False;
607 if (p->notify.flags)
608 return is_monitoring_event_flags(
609 p->notify.flags, notify_type, notify_field);
611 for (i = 0; i < option->count; i++) {
613 /* Check match for notify_type */
615 if (option->types[i].type != notify_type)
616 continue;
618 /* Check match for field */
620 for (j = 0; j < option->types[i].count; j++) {
621 if (option->types[i].fields[j] == notify_field) {
622 return True;
627 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
628 p->servername, p->sharename, notify_type, notify_field));
630 return False;
633 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
634 _data->data.integer[0] = _integer; \
635 _data->data.integer[1] = 0;
638 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
639 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
640 if (!_data->data.string.string) {\
641 _data->data.string.size = 0; \
643 _data->data.string.size = strlen_m_term(_p) * 2;
645 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
646 _data->data.devmode.devmode = _devmode;
648 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
649 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
650 if (!_data->data.sd.sd) { \
651 _data->data.sd.sd_size = 0; \
653 _data->data.sd.sd_size = _size;
655 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
656 struct tm *t,
657 const char **pp,
658 uint32_t *plen)
660 struct spoolss_Time st;
661 uint32_t len = 16;
662 char *p;
664 if (!init_systemtime(&st, t)) {
665 return;
668 p = talloc_array(mem_ctx, char, len);
669 if (!p) {
670 return;
674 * Systemtime must be linearized as a set of UINT16's.
675 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
678 SSVAL(p, 0, st.year);
679 SSVAL(p, 2, st.month);
680 SSVAL(p, 4, st.day_of_week);
681 SSVAL(p, 6, st.day);
682 SSVAL(p, 8, st.hour);
683 SSVAL(p, 10, st.minute);
684 SSVAL(p, 12, st.second);
685 SSVAL(p, 14, st.millisecond);
687 *pp = p;
688 *plen = len;
691 /* Convert a notification message to a struct spoolss_Notify */
693 static void notify_one_value(struct spoolss_notify_msg *msg,
694 struct spoolss_Notify *data,
695 TALLOC_CTX *mem_ctx)
697 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
700 static void notify_string(struct spoolss_notify_msg *msg,
701 struct spoolss_Notify *data,
702 TALLOC_CTX *mem_ctx)
704 /* The length of the message includes the trailing \0 */
706 data->data.string.size = msg->len * 2;
707 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
708 if (!data->data.string.string) {
709 data->data.string.size = 0;
710 return;
714 static void notify_system_time(struct spoolss_notify_msg *msg,
715 struct spoolss_Notify *data,
716 TALLOC_CTX *mem_ctx)
718 data->data.string.string = NULL;
719 data->data.string.size = 0;
721 if (msg->len != sizeof(time_t)) {
722 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
723 msg->len));
724 return;
727 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
728 &data->data.string.string,
729 &data->data.string.size);
732 struct notify2_message_table {
733 const char *name;
734 void (*fn)(struct spoolss_notify_msg *msg,
735 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
738 static struct notify2_message_table printer_notify_table[] = {
739 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
740 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
741 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
742 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
743 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
744 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
745 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
746 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
747 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
748 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
749 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
750 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
751 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
752 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
753 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
754 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
755 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
756 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
757 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
760 static struct notify2_message_table job_notify_table[] = {
761 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
762 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
763 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
764 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
765 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
766 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
767 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
768 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
769 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
770 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
771 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
772 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
773 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
774 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
775 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
776 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
777 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
778 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
779 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
780 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
781 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
782 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
783 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
784 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
788 /***********************************************************************
789 Allocate talloc context for container object
790 **********************************************************************/
792 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
794 if ( !ctr )
795 return;
797 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
799 return;
802 /***********************************************************************
803 release all allocated memory and zero out structure
804 **********************************************************************/
806 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
808 if ( !ctr )
809 return;
811 if ( ctr->ctx )
812 talloc_destroy(ctr->ctx);
814 ZERO_STRUCTP(ctr);
816 return;
819 /***********************************************************************
820 **********************************************************************/
822 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
824 if ( !ctr )
825 return NULL;
827 return ctr->ctx;
830 /***********************************************************************
831 **********************************************************************/
833 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
835 if ( !ctr || !ctr->msg_groups )
836 return NULL;
838 if ( idx >= ctr->num_groups )
839 return NULL;
841 return &ctr->msg_groups[idx];
845 /***********************************************************************
846 How many groups of change messages do we have ?
847 **********************************************************************/
849 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
851 if ( !ctr )
852 return 0;
854 return ctr->num_groups;
857 /***********************************************************************
858 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
859 **********************************************************************/
861 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
863 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
864 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
865 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
866 int i, new_slot;
868 if ( !ctr || !msg )
869 return 0;
871 /* loop over all groups looking for a matching printer name */
873 for ( i=0; i<ctr->num_groups; i++ ) {
874 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
875 break;
878 /* add a new group? */
880 if ( i == ctr->num_groups ) {
881 ctr->num_groups++;
883 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
884 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
885 return 0;
887 ctr->msg_groups = groups;
889 /* clear the new entry and set the printer name */
891 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
892 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
895 /* add the change messages; 'i' is the correct index now regardless */
897 msg_grp = &ctr->msg_groups[i];
899 msg_grp->num_msgs++;
901 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
902 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
903 return 0;
905 msg_grp->msgs = msg_list;
907 new_slot = msg_grp->num_msgs-1;
908 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
910 /* need to allocate own copy of data */
912 if ( msg->len != 0 )
913 msg_grp->msgs[new_slot].notify.data = (char *)
914 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
916 return ctr->num_groups;
919 /***********************************************************************
920 Send a change notication message on all handles which have a call
921 back registered
922 **********************************************************************/
924 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
926 Printer_entry *p;
927 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
928 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
929 SPOOLSS_NOTIFY_MSG *messages;
930 int sending_msg_count;
932 if ( !msg_group ) {
933 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
934 return;
937 messages = msg_group->msgs;
939 if ( !messages ) {
940 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
941 return;
944 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
946 /* loop over all printers */
948 for (p = printers_list; p; p = p->next) {
949 struct spoolss_Notify *notifies;
950 uint32_t count = 0;
951 uint32_t id;
952 int i;
954 /* Is there notification on this handle? */
956 if ( !p->notify.client_connected )
957 continue;
959 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
961 /* For this printer? Print servers always receive
962 notifications. */
964 if ( ( p->printer_type == SPLHND_PRINTER ) &&
965 ( !strequal(msg_group->printername, p->sharename) ) )
966 continue;
968 DEBUG(10,("Our printer\n"));
970 /* allocate the max entries possible */
972 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
973 if (!notifies) {
974 return;
977 /* build the array of change notifications */
979 sending_msg_count = 0;
981 for ( i=0; i<msg_group->num_msgs; i++ ) {
982 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
984 /* Are we monitoring this event? */
986 if (!is_monitoring_event(p, msg->type, msg->field))
987 continue;
989 sending_msg_count++;
992 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
993 msg->type, msg->field, p->sharename));
996 * if the is a printer notification handle and not a job notification
997 * type, then set the id to 0. Other wise just use what was specified
998 * in the message.
1000 * When registering change notification on a print server handle
1001 * we always need to send back the id (snum) matching the printer
1002 * for which the change took place. For change notify registered
1003 * on a printer handle, this does not matter and the id should be 0.
1005 * --jerry
1008 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1009 id = 0;
1010 else
1011 id = msg->id;
1014 /* Convert unix jobid to smb jobid */
1016 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1017 id = sysjob_to_jobid(msg->id);
1019 if (id == -1) {
1020 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1021 goto done;
1025 construct_info_data( &notifies[count], msg->type, msg->field, id );
1027 switch(msg->type) {
1028 case PRINTER_NOTIFY_TYPE:
1029 if ( printer_notify_table[msg->field].fn )
1030 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1031 break;
1033 case JOB_NOTIFY_TYPE:
1034 if ( job_notify_table[msg->field].fn )
1035 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1036 break;
1038 default:
1039 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1040 goto done;
1043 count++;
1046 if ( sending_msg_count ) {
1047 NTSTATUS status;
1048 WERROR werr;
1049 union spoolss_ReplyPrinterInfo info;
1050 struct spoolss_NotifyInfo info0;
1051 uint32_t reply_result;
1053 info0.version = 0x2;
1054 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1055 info0.count = count;
1056 info0.notifies = notifies;
1058 info.info0 = &info0;
1060 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1061 &p->notify.client_hnd,
1062 p->notify.change, /* color */
1063 p->notify.flags,
1064 &reply_result,
1065 0, /* reply_type, must be 0 */
1066 info,
1067 &werr);
1068 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1069 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1070 notify_cli_pipe->srv_name_slash,
1071 win_errstr(werr)));
1073 switch (reply_result) {
1074 case 0:
1075 break;
1076 case PRINTER_NOTIFY_INFO_DISCARDED:
1077 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1078 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1079 break;
1080 default:
1081 break;
1086 done:
1087 DEBUG(8,("send_notify2_changes: Exit...\n"));
1088 return;
1091 /***********************************************************************
1092 **********************************************************************/
1094 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1097 uint32 tv_sec, tv_usec;
1098 size_t offset = 0;
1100 /* Unpack message */
1102 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1103 msg->printer);
1105 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1106 &tv_sec, &tv_usec,
1107 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1109 if (msg->len == 0)
1110 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1111 &msg->notify.value[0], &msg->notify.value[1]);
1112 else
1113 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1114 &msg->len, &msg->notify.data);
1116 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1117 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1119 tv->tv_sec = tv_sec;
1120 tv->tv_usec = tv_usec;
1122 if (msg->len == 0)
1123 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1124 msg->notify.value[1]));
1125 else
1126 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1128 return True;
1131 /********************************************************************
1132 Receive a notify2 message list
1133 ********************************************************************/
1135 static void receive_notify2_message_list(struct messaging_context *msg,
1136 void *private_data,
1137 uint32_t msg_type,
1138 struct server_id server_id,
1139 DATA_BLOB *data)
1141 size_t msg_count, i;
1142 char *buf = (char *)data->data;
1143 char *msg_ptr;
1144 size_t msg_len;
1145 SPOOLSS_NOTIFY_MSG notify;
1146 SPOOLSS_NOTIFY_MSG_CTR messages;
1147 int num_groups;
1149 if (data->length < 4) {
1150 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1151 return;
1154 msg_count = IVAL(buf, 0);
1155 msg_ptr = buf + 4;
1157 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1159 if (msg_count == 0) {
1160 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1161 return;
1164 /* initialize the container */
1166 ZERO_STRUCT( messages );
1167 notify_msg_ctr_init( &messages );
1170 * build message groups for each printer identified
1171 * in a change_notify msg. Remember that a PCN message
1172 * includes the handle returned for the srv_spoolss_replyopenprinter()
1173 * call. Therefore messages are grouped according to printer handle.
1176 for ( i=0; i<msg_count; i++ ) {
1177 struct timeval msg_tv;
1179 if (msg_ptr + 4 - buf > data->length) {
1180 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1181 return;
1184 msg_len = IVAL(msg_ptr,0);
1185 msg_ptr += 4;
1187 if (msg_ptr + msg_len - buf > data->length) {
1188 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1189 return;
1192 /* unpack messages */
1194 ZERO_STRUCT( notify );
1195 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1196 msg_ptr += msg_len;
1198 /* add to correct list in container */
1200 notify_msg_ctr_addmsg( &messages, &notify );
1202 /* free memory that might have been allocated by notify2_unpack_msg() */
1204 if ( notify.len != 0 )
1205 SAFE_FREE( notify.notify.data );
1208 /* process each group of messages */
1210 num_groups = notify_msg_ctr_numgroups( &messages );
1211 for ( i=0; i<num_groups; i++ )
1212 send_notify2_changes( &messages, i );
1215 /* cleanup */
1217 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1219 notify_msg_ctr_destroy( &messages );
1221 return;
1224 /********************************************************************
1225 Send a message to ourself about new driver being installed
1226 so we can upgrade the information for each printer bound to this
1227 driver
1228 ********************************************************************/
1230 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1232 int len = strlen(drivername);
1234 if (!len)
1235 return False;
1237 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1238 drivername));
1240 messaging_send_buf(smbd_messaging_context(), procid_self(),
1241 MSG_PRINTER_DRVUPGRADE,
1242 (uint8 *)drivername, len+1);
1244 return True;
1247 /**********************************************************************
1248 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1249 over all printers, upgrading ones as necessary
1250 **********************************************************************/
1252 void do_drv_upgrade_printer(struct messaging_context *msg,
1253 void *private_data,
1254 uint32_t msg_type,
1255 struct server_id server_id,
1256 DATA_BLOB *data)
1258 fstring drivername;
1259 int snum;
1260 int n_services = lp_numservices();
1261 size_t len;
1263 len = MIN(data->length,sizeof(drivername)-1);
1264 strncpy(drivername, (const char *)data->data, len);
1266 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1268 /* Iterate the printer list */
1270 for (snum=0; snum<n_services; snum++)
1272 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1274 WERROR result;
1275 NT_PRINTER_INFO_LEVEL *printer = NULL;
1277 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1278 if (!W_ERROR_IS_OK(result))
1279 continue;
1281 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1283 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1285 /* all we care about currently is the change_id */
1287 result = mod_a_printer(printer, 2);
1288 if (!W_ERROR_IS_OK(result)) {
1289 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1290 win_errstr(result)));
1294 free_a_printer(&printer, 2);
1298 /* all done */
1301 /********************************************************************
1302 Update the cache for all printq's with a registered client
1303 connection
1304 ********************************************************************/
1306 void update_monitored_printq_cache( void )
1308 Printer_entry *printer = printers_list;
1309 int snum;
1311 /* loop through all printers and update the cache where
1312 client_connected == True */
1313 while ( printer )
1315 if ( (printer->printer_type == SPLHND_PRINTER)
1316 && printer->notify.client_connected )
1318 snum = print_queue_snum(printer->sharename);
1319 print_queue_status( snum, NULL, NULL );
1322 printer = printer->next;
1325 return;
1327 /********************************************************************
1328 Send a message to ourself about new driver being installed
1329 so we can upgrade the information for each printer bound to this
1330 driver
1331 ********************************************************************/
1333 static bool srv_spoolss_reset_printerdata(char* drivername)
1335 int len = strlen(drivername);
1337 if (!len)
1338 return False;
1340 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1341 drivername));
1343 messaging_send_buf(smbd_messaging_context(), procid_self(),
1344 MSG_PRINTERDATA_INIT_RESET,
1345 (uint8 *)drivername, len+1);
1347 return True;
1350 /**********************************************************************
1351 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1352 over all printers, resetting printer data as neessary
1353 **********************************************************************/
1355 void reset_all_printerdata(struct messaging_context *msg,
1356 void *private_data,
1357 uint32_t msg_type,
1358 struct server_id server_id,
1359 DATA_BLOB *data)
1361 fstring drivername;
1362 int snum;
1363 int n_services = lp_numservices();
1364 size_t len;
1366 len = MIN( data->length, sizeof(drivername)-1 );
1367 strncpy( drivername, (const char *)data->data, len );
1369 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1371 /* Iterate the printer list */
1373 for ( snum=0; snum<n_services; snum++ )
1375 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1377 WERROR result;
1378 NT_PRINTER_INFO_LEVEL *printer = NULL;
1380 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1381 if ( !W_ERROR_IS_OK(result) )
1382 continue;
1385 * if the printer is bound to the driver,
1386 * then reset to the new driver initdata
1389 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1391 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1393 if ( !set_driver_init(printer, 2) ) {
1394 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1395 printer->info_2->printername, printer->info_2->drivername));
1398 result = mod_a_printer( printer, 2 );
1399 if ( !W_ERROR_IS_OK(result) ) {
1400 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1401 get_dos_error_msg(result)));
1405 free_a_printer( &printer, 2 );
1409 /* all done */
1411 return;
1414 /****************************************************************
1415 _spoolss_OpenPrinter
1416 ****************************************************************/
1418 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1419 struct spoolss_OpenPrinter *r)
1421 struct spoolss_OpenPrinterEx e;
1422 WERROR werr;
1424 ZERO_STRUCT(e.in.userlevel);
1426 e.in.printername = r->in.printername;
1427 e.in.datatype = r->in.datatype;
1428 e.in.devmode_ctr = r->in.devmode_ctr;
1429 e.in.access_mask = r->in.access_mask;
1430 e.in.level = 0;
1432 e.out.handle = r->out.handle;
1434 werr = _spoolss_OpenPrinterEx(p, &e);
1436 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1437 /* OpenPrinterEx returns this for a bad
1438 * printer name. We must return WERR_INVALID_PRINTER_NAME
1439 * instead.
1441 werr = WERR_INVALID_PRINTER_NAME;
1444 return werr;
1447 /********************************************************************
1448 FIXME: temporary convert_devicemode_new function
1449 ********************************************************************/
1451 static bool convert_devicemode_new(const char *printername,
1452 struct spoolss_DeviceMode *devmode,
1453 NT_DEVICEMODE **pp_nt_devmode)
1455 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1458 * Ensure nt_devmode is a valid pointer
1459 * as we will be overwriting it.
1462 if (nt_devmode == NULL) {
1463 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1464 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1465 return false;
1468 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1469 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1471 nt_devmode->specversion = devmode->specversion;
1472 nt_devmode->driverversion = devmode->driverversion;
1473 nt_devmode->size = devmode->size;
1474 nt_devmode->fields = devmode->fields;
1475 nt_devmode->orientation = devmode->orientation;
1476 nt_devmode->papersize = devmode->papersize;
1477 nt_devmode->paperlength = devmode->paperlength;
1478 nt_devmode->paperwidth = devmode->paperwidth;
1479 nt_devmode->scale = devmode->scale;
1480 nt_devmode->copies = devmode->copies;
1481 nt_devmode->defaultsource = devmode->defaultsource;
1482 nt_devmode->printquality = devmode->printquality;
1483 nt_devmode->color = devmode->color;
1484 nt_devmode->duplex = devmode->duplex;
1485 nt_devmode->yresolution = devmode->yresolution;
1486 nt_devmode->ttoption = devmode->ttoption;
1487 nt_devmode->collate = devmode->collate;
1489 nt_devmode->logpixels = devmode->logpixels;
1490 nt_devmode->bitsperpel = devmode->bitsperpel;
1491 nt_devmode->pelswidth = devmode->pelswidth;
1492 nt_devmode->pelsheight = devmode->pelsheight;
1493 nt_devmode->displayflags = devmode->displayflags;
1494 nt_devmode->displayfrequency = devmode->displayfrequency;
1495 nt_devmode->icmmethod = devmode->icmmethod;
1496 nt_devmode->icmintent = devmode->icmintent;
1497 nt_devmode->mediatype = devmode->mediatype;
1498 nt_devmode->dithertype = devmode->dithertype;
1499 nt_devmode->reserved1 = devmode->reserved1;
1500 nt_devmode->reserved2 = devmode->reserved2;
1501 nt_devmode->panningwidth = devmode->panningwidth;
1502 nt_devmode->panningheight = devmode->panningheight;
1505 * Only change private and driverextra if the incoming devmode
1506 * has a new one. JRA.
1509 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1510 SAFE_FREE(nt_devmode->nt_dev_private);
1511 nt_devmode->driverextra = devmode->__driverextra_length;
1512 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1513 return false;
1514 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1517 *pp_nt_devmode = nt_devmode;
1519 return true;
1522 /****************************************************************
1523 _spoolss_OpenPrinterEx
1524 ****************************************************************/
1526 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1527 struct spoolss_OpenPrinterEx *r)
1529 POLICY_HND *handle = r->out.handle;
1530 char *name = CONST_DISCARD(char *, r->in.printername);
1531 int snum;
1532 Printer_entry *Printer=NULL;
1534 if (!name) {
1535 return WERR_INVALID_PARAM;
1538 /* some sanity check because you can open a printer or a print server */
1539 /* aka: \\server\printer or \\server */
1541 DEBUGADD(3,("checking name: %s\n",name));
1543 if (!open_printer_hnd(p, handle, name, 0)) {
1544 ZERO_STRUCTP(r->out.handle);
1545 return WERR_INVALID_PARAM;
1548 Printer=find_printer_index_by_hnd(p, handle);
1549 if ( !Printer ) {
1550 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1551 "handle we created for printer %s\n", name ));
1552 close_printer_handle(p,handle);
1553 ZERO_STRUCTP(r->out.handle);
1554 return WERR_INVALID_PARAM;
1558 * First case: the user is opening the print server:
1560 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1561 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1563 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1564 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1565 * or if the user is listed in the smb.conf printer admin parameter.
1567 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1568 * client view printer folder, but does not show the MSAPW.
1570 * Note: this test needs code to check access rights here too. Jeremy
1571 * could you look at this?
1573 * Second case: the user is opening a printer:
1574 * NT doesn't let us connect to a printer if the connecting user
1575 * doesn't have print permission.
1577 * Third case: user is opening a Port Monitor
1578 * access checks same as opening a handle to the print server.
1581 switch (Printer->printer_type )
1583 case SPLHND_SERVER:
1584 case SPLHND_PORTMON_TCP:
1585 case SPLHND_PORTMON_LOCAL:
1586 /* Printserver handles use global struct... */
1588 snum = -1;
1590 /* Map standard access rights to object specific access rights */
1592 se_map_standard(&r->in.access_mask,
1593 &printserver_std_mapping);
1595 /* Deny any object specific bits that don't apply to print
1596 servers (i.e printer and job specific bits) */
1598 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1600 if (r->in.access_mask &
1601 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1602 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1603 close_printer_handle(p, handle);
1604 ZERO_STRUCTP(r->out.handle);
1605 return WERR_ACCESS_DENIED;
1608 /* Allow admin access */
1610 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1612 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1614 if (!lp_ms_add_printer_wizard()) {
1615 close_printer_handle(p, handle);
1616 ZERO_STRUCTP(r->out.handle);
1617 return WERR_ACCESS_DENIED;
1620 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1621 and not a printer admin, then fail */
1623 if ((p->server_info->utok.uid != 0) &&
1624 !user_has_privileges(p->server_info->ptok,
1625 &se_printop ) &&
1626 !token_contains_name_in_list(
1627 uidtoname(p->server_info->utok.uid),
1628 NULL, NULL,
1629 p->server_info->ptok,
1630 lp_printer_admin(snum))) {
1631 close_printer_handle(p, handle);
1632 ZERO_STRUCTP(r->out.handle);
1633 return WERR_ACCESS_DENIED;
1636 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1638 else
1640 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1643 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1644 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1646 /* We fall through to return WERR_OK */
1647 break;
1649 case SPLHND_PRINTER:
1650 /* NT doesn't let us connect to a printer if the connecting user
1651 doesn't have print permission. */
1653 if (!get_printer_snum(p, handle, &snum, NULL)) {
1654 close_printer_handle(p, handle);
1655 ZERO_STRUCTP(r->out.handle);
1656 return WERR_BADFID;
1659 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1661 /* map an empty access mask to the minimum access mask */
1662 if (r->in.access_mask == 0x0)
1663 r->in.access_mask = PRINTER_ACCESS_USE;
1666 * If we are not serving the printer driver for this printer,
1667 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1668 * will keep NT clients happy --jerry
1671 if (lp_use_client_driver(snum)
1672 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1674 r->in.access_mask = PRINTER_ACCESS_USE;
1677 /* check smb.conf parameters and the the sec_desc */
1679 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1680 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1681 ZERO_STRUCTP(r->out.handle);
1682 return WERR_ACCESS_DENIED;
1685 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1686 p->server_info->ptok, snum) ||
1687 !print_access_check(p->server_info, snum,
1688 r->in.access_mask)) {
1689 DEBUG(3, ("access DENIED for printer open\n"));
1690 close_printer_handle(p, handle);
1691 ZERO_STRUCTP(r->out.handle);
1692 return WERR_ACCESS_DENIED;
1695 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1696 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1697 close_printer_handle(p, handle);
1698 ZERO_STRUCTP(r->out.handle);
1699 return WERR_ACCESS_DENIED;
1702 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1703 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1704 else
1705 r->in.access_mask = PRINTER_ACCESS_USE;
1707 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1708 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1710 break;
1712 default:
1713 /* sanity check to prevent programmer error */
1714 ZERO_STRUCTP(r->out.handle);
1715 return WERR_BADFID;
1718 Printer->access_granted = r->in.access_mask;
1721 * If the client sent a devmode in the OpenPrinter() call, then
1722 * save it here in case we get a job submission on this handle
1725 if ( (Printer->printer_type != SPLHND_SERVER)
1726 && r->in.devmode_ctr.devmode )
1728 convert_devicemode_new(Printer->sharename,
1729 r->in.devmode_ctr.devmode,
1730 &Printer->nt_devmode);
1733 #if 0 /* JERRY -- I'm doubtful this is really effective */
1734 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1735 optimization in Windows 2000 clients --jerry */
1737 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1738 && (RA_WIN2K == get_remote_arch()) )
1740 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1741 sys_usleep( 500000 );
1743 #endif
1745 return WERR_OK;
1748 /****************************************************************************
1749 ****************************************************************************/
1751 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1752 NT_PRINTER_INFO_LEVEL_2 *d)
1754 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1756 if (!r || !d) {
1757 return false;
1760 d->attributes = r->attributes;
1761 d->priority = r->priority;
1762 d->default_priority = r->defaultpriority;
1763 d->starttime = r->starttime;
1764 d->untiltime = r->untiltime;
1765 d->status = r->status;
1766 d->cjobs = r->cjobs;
1768 fstrcpy(d->servername, r->servername);
1769 fstrcpy(d->printername, r->printername);
1770 fstrcpy(d->sharename, r->sharename);
1771 fstrcpy(d->portname, r->portname);
1772 fstrcpy(d->drivername, r->drivername);
1773 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1774 fstrcpy(d->location, r->location);
1775 fstrcpy(d->sepfile, r->sepfile);
1776 fstrcpy(d->printprocessor, r->printprocessor);
1777 fstrcpy(d->datatype, r->datatype);
1778 fstrcpy(d->parameters, r->parameters);
1780 return true;
1783 /****************************************************************************
1784 ****************************************************************************/
1786 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1787 NT_PRINTER_INFO_LEVEL *printer)
1789 bool ret;
1791 switch (info_ctr->level) {
1792 case 2:
1793 /* allocate memory if needed. Messy because
1794 convert_printer_info is used to update an existing
1795 printer or build a new one */
1797 if (!printer->info_2) {
1798 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1799 if (!printer->info_2) {
1800 DEBUG(0,("convert_printer_info_new: "
1801 "talloc() failed!\n"));
1802 return false;
1806 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1807 printer->info_2);
1808 printer->info_2->setuptime = time(NULL);
1809 return ret;
1812 return false;
1815 /*******************************************************************
1816 ********************************************************************/
1818 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1820 int i;
1822 if (!sarray) {
1823 *farray = NULL;
1824 return true;
1827 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1828 if (!*farray) {
1829 return false;
1832 for (i=0; sarray[i] != NULL; i++) {
1833 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1834 if (!*farray) {
1835 return false;
1837 fstrcpy((*farray)[i], sarray[i]);
1840 fstrcpy((*farray)[i], "");
1842 return true;
1845 /*******************************************************************
1846 ********************************************************************/
1848 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1849 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1851 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1853 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1855 if (*p == NULL) {
1856 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1857 if (*p == NULL) {
1858 return false;
1860 ZERO_STRUCTP(*p);
1863 d = *p;
1865 d->cversion = r->version;
1867 fstrcpy(d->name, r->driver_name);
1868 fstrcpy(d->environment, r->architecture);
1869 fstrcpy(d->driverpath, r->driver_path);
1870 fstrcpy(d->datafile, r->data_file);
1871 fstrcpy(d->configfile, r->config_file);
1872 fstrcpy(d->helpfile, r->help_file);
1873 fstrcpy(d->monitorname, r->monitor_name);
1874 fstrcpy(d->defaultdatatype, r->default_datatype);
1876 DEBUGADD(8,( "version: %d\n", d->cversion));
1877 DEBUGADD(8,( "name: %s\n", d->name));
1878 DEBUGADD(8,( "environment: %s\n", d->environment));
1879 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1880 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1881 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1882 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1883 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1884 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1886 if (r->dependent_files) {
1887 if (!string_array_to_fstring_array(r->dependent_files->string,
1888 &d->dependentfiles)) {
1889 SAFE_FREE(*p);
1890 return false;
1894 return true;
1897 /*******************************************************************
1898 ********************************************************************/
1900 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1901 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1903 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1905 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1907 if (*p == NULL) {
1908 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1909 if (*p == NULL) {
1910 return false;
1912 ZERO_STRUCTP(*p);
1915 d = *p;
1917 d->version = r->version;
1919 fstrcpy(d->name, r->driver_name);
1920 fstrcpy(d->environment, r->architecture);
1921 fstrcpy(d->driverpath, r->driver_path);
1922 fstrcpy(d->datafile, r->data_file);
1923 fstrcpy(d->configfile, r->config_file);
1924 fstrcpy(d->helpfile, r->help_file);
1925 fstrcpy(d->monitorname, r->monitor_name);
1926 fstrcpy(d->defaultdatatype, r->default_datatype);
1928 DEBUGADD(8,( "version: %d\n", d->version));
1929 DEBUGADD(8,( "name: %s\n", d->name));
1930 DEBUGADD(8,( "environment: %s\n", d->environment));
1931 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1932 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1933 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1934 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1935 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1936 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1938 if (r->dependent_files) {
1939 if (!string_array_to_fstring_array(r->dependent_files->string,
1940 &d->dependentfiles)) {
1941 goto error;
1945 if (r->previous_names) {
1946 if (!string_array_to_fstring_array(r->previous_names->string,
1947 &d->previousnames)) {
1948 goto error;
1952 return true;
1954 error:
1955 SAFE_FREE(*p);
1956 return false;
1959 /********************************************************************
1960 ********************************************************************/
1962 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1963 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1964 uint32_t level)
1966 switch (level) {
1967 case 3:
1968 printer->info_3 = NULL;
1969 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1970 return false;
1972 break;
1973 case 6:
1974 printer->info_6 = NULL;
1975 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1976 return false;
1978 break;
1979 default:
1980 return false;
1983 return true;
1986 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1987 NT_DEVICEMODE **pp_nt_devmode)
1989 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1992 * Ensure nt_devmode is a valid pointer
1993 * as we will be overwriting it.
1996 if (nt_devmode == NULL) {
1997 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1998 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1999 return False;
2002 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2003 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2005 nt_devmode->specversion=devmode->specversion;
2006 nt_devmode->driverversion=devmode->driverversion;
2007 nt_devmode->size=devmode->size;
2008 nt_devmode->fields=devmode->fields;
2009 nt_devmode->orientation=devmode->orientation;
2010 nt_devmode->papersize=devmode->papersize;
2011 nt_devmode->paperlength=devmode->paperlength;
2012 nt_devmode->paperwidth=devmode->paperwidth;
2013 nt_devmode->scale=devmode->scale;
2014 nt_devmode->copies=devmode->copies;
2015 nt_devmode->defaultsource=devmode->defaultsource;
2016 nt_devmode->printquality=devmode->printquality;
2017 nt_devmode->color=devmode->color;
2018 nt_devmode->duplex=devmode->duplex;
2019 nt_devmode->yresolution=devmode->yresolution;
2020 nt_devmode->ttoption=devmode->ttoption;
2021 nt_devmode->collate=devmode->collate;
2023 nt_devmode->logpixels=devmode->logpixels;
2024 nt_devmode->bitsperpel=devmode->bitsperpel;
2025 nt_devmode->pelswidth=devmode->pelswidth;
2026 nt_devmode->pelsheight=devmode->pelsheight;
2027 nt_devmode->displayflags=devmode->displayflags;
2028 nt_devmode->displayfrequency=devmode->displayfrequency;
2029 nt_devmode->icmmethod=devmode->icmmethod;
2030 nt_devmode->icmintent=devmode->icmintent;
2031 nt_devmode->mediatype=devmode->mediatype;
2032 nt_devmode->dithertype=devmode->dithertype;
2033 nt_devmode->reserved1=devmode->reserved1;
2034 nt_devmode->reserved2=devmode->reserved2;
2035 nt_devmode->panningwidth=devmode->panningwidth;
2036 nt_devmode->panningheight=devmode->panningheight;
2039 * Only change private and driverextra if the incoming devmode
2040 * has a new one. JRA.
2043 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2044 SAFE_FREE(nt_devmode->nt_dev_private);
2045 nt_devmode->driverextra=devmode->driverextra;
2046 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2047 return False;
2048 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2051 *pp_nt_devmode = nt_devmode;
2053 return True;
2056 /********************************************************************
2057 * _spoolss_enddocprinter_internal.
2058 ********************************************************************/
2060 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2062 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2063 int snum;
2065 if (!Printer) {
2066 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2067 return WERR_BADFID;
2070 if (!get_printer_snum(p, handle, &snum, NULL))
2071 return WERR_BADFID;
2073 Printer->document_started=False;
2074 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2075 /* error codes unhandled so far ... */
2077 return WERR_OK;
2080 /****************************************************************
2081 _spoolss_ClosePrinter
2082 ****************************************************************/
2084 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2085 struct spoolss_ClosePrinter *r)
2087 POLICY_HND *handle = r->in.handle;
2089 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2091 if (Printer && Printer->document_started)
2092 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
2094 if (!close_printer_handle(p, handle))
2095 return WERR_BADFID;
2097 /* clear the returned printer handle. Observed behavior
2098 from Win2k server. Don't think this really matters.
2099 Previous code just copied the value of the closed
2100 handle. --jerry */
2102 ZERO_STRUCTP(r->out.handle);
2104 return WERR_OK;
2107 /****************************************************************
2108 _spoolss_DeletePrinter
2109 ****************************************************************/
2111 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2112 struct spoolss_DeletePrinter *r)
2114 POLICY_HND *handle = r->in.handle;
2115 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2116 WERROR result;
2118 if (Printer && Printer->document_started)
2119 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
2121 result = delete_printer_handle(p, handle);
2123 update_c_setprinter(False);
2125 return result;
2128 /*******************************************************************
2129 * static function to lookup the version id corresponding to an
2130 * long architecture string
2131 ******************************************************************/
2133 static int get_version_id (char * arch)
2135 int i;
2136 struct table_node archi_table[]= {
2138 {"Windows 4.0", "WIN40", 0 },
2139 {"Windows NT x86", "W32X86", 2 },
2140 {"Windows NT R4000", "W32MIPS", 2 },
2141 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2142 {"Windows NT PowerPC", "W32PPC", 2 },
2143 {"Windows IA64", "IA64", 3 },
2144 {"Windows x64", "x64", 3 },
2145 {NULL, "", -1 }
2148 for (i=0; archi_table[i].long_archi != NULL; i++)
2150 if (strcmp(arch, archi_table[i].long_archi) == 0)
2151 return (archi_table[i].version);
2154 return -1;
2157 /****************************************************************
2158 _spoolss_DeletePrinterDriver
2159 ****************************************************************/
2161 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2162 struct spoolss_DeletePrinterDriver *r)
2164 char *driver;
2165 char *arch;
2166 NT_PRINTER_DRIVER_INFO_LEVEL info;
2167 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2168 int version;
2169 WERROR status;
2170 WERROR status_win2k = WERR_ACCESS_DENIED;
2171 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2173 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2174 and not a printer admin, then fail */
2176 if ( (p->server_info->utok.uid != 0)
2177 && !user_has_privileges(p->server_info->ptok, &se_printop )
2178 && !token_contains_name_in_list(
2179 uidtoname(p->server_info->utok.uid), NULL,
2180 NULL, p->server_info->ptok,
2181 lp_printer_admin(-1)) )
2183 return WERR_ACCESS_DENIED;
2186 driver = CONST_DISCARD(char *, r->in.driver);
2187 arch = CONST_DISCARD(char *, r->in.architecture);
2189 /* check that we have a valid driver name first */
2191 if ((version=get_version_id(arch)) == -1)
2192 return WERR_INVALID_ENVIRONMENT;
2194 ZERO_STRUCT(info);
2195 ZERO_STRUCT(info_win2k);
2197 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2199 /* try for Win2k driver if "Windows NT x86" */
2201 if ( version == 2 ) {
2202 version = 3;
2203 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2204 status = WERR_UNKNOWN_PRINTER_DRIVER;
2205 goto done;
2208 /* otherwise it was a failure */
2209 else {
2210 status = WERR_UNKNOWN_PRINTER_DRIVER;
2211 goto done;
2216 if (printer_driver_in_use(info.info_3)) {
2217 status = WERR_PRINTER_DRIVER_IN_USE;
2218 goto done;
2221 if ( version == 2 )
2223 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2225 /* if we get to here, we now have 2 driver info structures to remove */
2226 /* remove the Win2k driver first*/
2228 status_win2k = delete_printer_driver(
2229 p, info_win2k.info_3, 3, False );
2230 free_a_printer_driver( info_win2k, 3 );
2232 /* this should not have failed---if it did, report to client */
2233 if ( !W_ERROR_IS_OK(status_win2k) )
2235 status = status_win2k;
2236 goto done;
2241 status = delete_printer_driver(p, info.info_3, version, False);
2243 /* if at least one of the deletes succeeded return OK */
2245 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2246 status = WERR_OK;
2248 done:
2249 free_a_printer_driver( info, 3 );
2251 return status;
2254 /****************************************************************
2255 _spoolss_DeletePrinterDriverEx
2256 ****************************************************************/
2258 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2259 struct spoolss_DeletePrinterDriverEx *r)
2261 char *driver;
2262 char *arch;
2263 NT_PRINTER_DRIVER_INFO_LEVEL info;
2264 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2265 int version;
2266 uint32_t flags = r->in.delete_flags;
2267 bool delete_files;
2268 WERROR status;
2269 WERROR status_win2k = WERR_ACCESS_DENIED;
2270 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2272 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2273 and not a printer admin, then fail */
2275 if ( (p->server_info->utok.uid != 0)
2276 && !user_has_privileges(p->server_info->ptok, &se_printop )
2277 && !token_contains_name_in_list(
2278 uidtoname(p->server_info->utok.uid), NULL, NULL,
2279 p->server_info->ptok, lp_printer_admin(-1)) )
2281 return WERR_ACCESS_DENIED;
2284 driver = CONST_DISCARD(char *, r->in.driver);
2285 arch = CONST_DISCARD(char *, r->in.architecture);
2287 /* check that we have a valid driver name first */
2288 if ((version=get_version_id(arch)) == -1) {
2289 /* this is what NT returns */
2290 return WERR_INVALID_ENVIRONMENT;
2293 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2294 version = r->in.version;
2296 ZERO_STRUCT(info);
2297 ZERO_STRUCT(info_win2k);
2299 status = get_a_printer_driver(&info, 3, driver, arch, version);
2301 if ( !W_ERROR_IS_OK(status) )
2304 * if the client asked for a specific version,
2305 * or this is something other than Windows NT x86,
2306 * then we've failed
2309 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2310 goto done;
2312 /* try for Win2k driver if "Windows NT x86" */
2314 version = 3;
2315 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2316 status = WERR_UNKNOWN_PRINTER_DRIVER;
2317 goto done;
2321 if ( printer_driver_in_use(info.info_3) ) {
2322 status = WERR_PRINTER_DRIVER_IN_USE;
2323 goto done;
2327 * we have a couple of cases to consider.
2328 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2329 * then the delete should fail if **any** files overlap with
2330 * other drivers
2331 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2332 * non-overlapping files
2333 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2334 * is set, the do not delete any files
2335 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2338 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2340 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2342 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2343 /* no idea of the correct error here */
2344 status = WERR_ACCESS_DENIED;
2345 goto done;
2349 /* also check for W32X86/3 if necessary; maybe we already have? */
2351 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2352 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2355 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2356 /* no idea of the correct error here */
2357 free_a_printer_driver( info_win2k, 3 );
2358 status = WERR_ACCESS_DENIED;
2359 goto done;
2362 /* if we get to here, we now have 2 driver info structures to remove */
2363 /* remove the Win2k driver first*/
2365 status_win2k = delete_printer_driver(
2366 p, info_win2k.info_3, 3, delete_files);
2367 free_a_printer_driver( info_win2k, 3 );
2369 /* this should not have failed---if it did, report to client */
2371 if ( !W_ERROR_IS_OK(status_win2k) )
2372 goto done;
2376 status = delete_printer_driver(p, info.info_3, version, delete_files);
2378 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2379 status = WERR_OK;
2380 done:
2381 free_a_printer_driver( info, 3 );
2383 return status;
2387 /****************************************************************************
2388 Internal routine for retreiving printerdata
2389 ***************************************************************************/
2391 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2392 const char *key, const char *value, uint32 *type, uint8 **data,
2393 uint32 *needed, uint32 in_size )
2395 REGISTRY_VALUE *val;
2396 uint32 size;
2397 int data_len;
2399 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2400 return WERR_BADFILE;
2402 *type = regval_type( val );
2404 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2406 size = regval_size( val );
2408 /* copy the min(in_size, len) */
2410 if ( in_size ) {
2411 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2413 /* special case for 0 length values */
2414 if ( data_len ) {
2415 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2416 return WERR_NOMEM;
2418 else {
2419 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2420 return WERR_NOMEM;
2423 else
2424 *data = NULL;
2426 *needed = size;
2428 DEBUG(5,("get_printer_dataex: copy done\n"));
2430 return WERR_OK;
2433 /****************************************************************************
2434 Internal routine for removing printerdata
2435 ***************************************************************************/
2437 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2439 return delete_printer_data( printer->info_2, key, value );
2442 /****************************************************************************
2443 Internal routine for storing printerdata
2444 ***************************************************************************/
2446 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2447 uint32 type, uint8 *data, int real_len )
2449 /* the registry objects enforce uniqueness based on value name */
2451 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2454 /********************************************************************
2455 GetPrinterData on a printer server Handle.
2456 ********************************************************************/
2458 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2460 int i;
2462 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2464 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2465 *type = REG_DWORD;
2466 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2467 return WERR_NOMEM;
2468 SIVAL(*data, 0, 0x00);
2469 *needed = 0x4;
2470 return WERR_OK;
2473 if (!StrCaseCmp(value, "BeepEnabled")) {
2474 *type = REG_DWORD;
2475 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2476 return WERR_NOMEM;
2477 SIVAL(*data, 0, 0x00);
2478 *needed = 0x4;
2479 return WERR_OK;
2482 if (!StrCaseCmp(value, "EventLog")) {
2483 *type = REG_DWORD;
2484 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2485 return WERR_NOMEM;
2486 /* formally was 0x1b */
2487 SIVAL(*data, 0, 0x0);
2488 *needed = 0x4;
2489 return WERR_OK;
2492 if (!StrCaseCmp(value, "NetPopup")) {
2493 *type = REG_DWORD;
2494 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2495 return WERR_NOMEM;
2496 SIVAL(*data, 0, 0x00);
2497 *needed = 0x4;
2498 return WERR_OK;
2501 if (!StrCaseCmp(value, "MajorVersion")) {
2502 *type = REG_DWORD;
2503 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2504 return WERR_NOMEM;
2506 /* Windows NT 4.0 seems to not allow uploading of drivers
2507 to a server that reports 0x3 as the MajorVersion.
2508 need to investigate more how Win2k gets around this .
2509 -- jerry */
2511 if ( RA_WINNT == get_remote_arch() )
2512 SIVAL(*data, 0, 2);
2513 else
2514 SIVAL(*data, 0, 3);
2516 *needed = 0x4;
2517 return WERR_OK;
2520 if (!StrCaseCmp(value, "MinorVersion")) {
2521 *type = REG_DWORD;
2522 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2523 return WERR_NOMEM;
2524 SIVAL(*data, 0, 0);
2525 *needed = 0x4;
2526 return WERR_OK;
2529 /* REG_BINARY
2530 * uint32 size = 0x114
2531 * uint32 major = 5
2532 * uint32 minor = [0|1]
2533 * uint32 build = [2195|2600]
2534 * extra unicode string = e.g. "Service Pack 3"
2536 if (!StrCaseCmp(value, "OSVersion")) {
2537 *type = REG_BINARY;
2538 *needed = 0x114;
2540 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2541 return WERR_NOMEM;
2543 SIVAL(*data, 0, *needed); /* size */
2544 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2545 SIVAL(*data, 8, 0);
2546 SIVAL(*data, 12, 2195); /* build */
2548 /* leave extra string empty */
2550 return WERR_OK;
2554 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2555 const char *string="C:\\PRINTERS";
2556 *type = REG_SZ;
2557 *needed = 2*(strlen(string)+1);
2558 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2559 return WERR_NOMEM;
2560 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2562 /* it's done by hand ready to go on the wire */
2563 for (i=0; i<strlen(string); i++) {
2564 (*data)[2*i]=string[i];
2565 (*data)[2*i+1]='\0';
2567 return WERR_OK;
2570 if (!StrCaseCmp(value, "Architecture")) {
2571 const char *string="Windows NT x86";
2572 *type = REG_SZ;
2573 *needed = 2*(strlen(string)+1);
2574 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2575 return WERR_NOMEM;
2576 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2577 for (i=0; i<strlen(string); i++) {
2578 (*data)[2*i]=string[i];
2579 (*data)[2*i+1]='\0';
2581 return WERR_OK;
2584 if (!StrCaseCmp(value, "DsPresent")) {
2585 *type = REG_DWORD;
2586 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2587 return WERR_NOMEM;
2589 /* only show the publish check box if we are a
2590 memeber of a AD domain */
2592 if ( lp_security() == SEC_ADS )
2593 SIVAL(*data, 0, 0x01);
2594 else
2595 SIVAL(*data, 0, 0x00);
2597 *needed = 0x4;
2598 return WERR_OK;
2601 if (!StrCaseCmp(value, "DNSMachineName")) {
2602 const char *hostname = get_mydnsfullname();
2604 if (!hostname)
2605 return WERR_BADFILE;
2606 *type = REG_SZ;
2607 *needed = 2*(strlen(hostname)+1);
2608 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2609 return WERR_NOMEM;
2610 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2611 for (i=0; i<strlen(hostname); i++) {
2612 (*data)[2*i]=hostname[i];
2613 (*data)[2*i+1]='\0';
2615 return WERR_OK;
2619 return WERR_BADFILE;
2622 /********************************************************************
2623 * spoolss_getprinterdata
2624 ********************************************************************/
2626 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2628 POLICY_HND *handle = &q_u->handle;
2629 UNISTR2 *valuename = &q_u->valuename;
2630 uint32 in_size = q_u->size;
2631 uint32 *type = &r_u->type;
2632 uint32 *out_size = &r_u->size;
2633 uint8 **data = &r_u->data;
2634 uint32 *needed = &r_u->needed;
2635 WERROR status;
2636 fstring value;
2637 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2638 NT_PRINTER_INFO_LEVEL *printer = NULL;
2639 int snum = 0;
2642 * Reminder: when it's a string, the length is in BYTES
2643 * even if UNICODE is negociated.
2645 * JFM, 4/19/1999
2648 *out_size = in_size;
2650 /* in case of problem, return some default values */
2652 *needed = 0;
2653 *type = 0;
2655 DEBUG(4,("_spoolss_getprinterdata\n"));
2657 if ( !Printer ) {
2658 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2659 status = WERR_BADFID;
2660 goto done;
2663 unistr2_to_ascii(value, valuename, sizeof(value));
2665 if ( Printer->printer_type == SPLHND_SERVER )
2666 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2667 else
2669 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2670 status = WERR_BADFID;
2671 goto done;
2674 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2675 if ( !W_ERROR_IS_OK(status) )
2676 goto done;
2678 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2680 if ( strequal(value, "ChangeId") ) {
2681 *type = REG_DWORD;
2682 *needed = sizeof(uint32);
2683 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2684 status = WERR_NOMEM;
2685 goto done;
2687 SIVAL( *data, 0, printer->info_2->changeid );
2688 status = WERR_OK;
2690 else
2691 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2694 if (*needed > *out_size)
2695 status = WERR_MORE_DATA;
2697 done:
2698 if ( !W_ERROR_IS_OK(status) )
2700 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2702 /* reply this param doesn't exist */
2704 if ( *out_size ) {
2705 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2706 if ( printer )
2707 free_a_printer( &printer, 2 );
2708 return WERR_NOMEM;
2710 } else {
2711 *data = NULL;
2715 /* cleanup & exit */
2717 if ( printer )
2718 free_a_printer( &printer, 2 );
2720 return status;
2723 /*********************************************************
2724 Connect to the client machine.
2725 **********************************************************/
2727 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2728 struct sockaddr_storage *client_ss, const char *remote_machine)
2730 NTSTATUS ret;
2731 struct cli_state *the_cli;
2732 struct sockaddr_storage rm_addr;
2734 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2735 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2736 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2737 return False;
2740 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2741 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2742 return False;
2744 } else {
2745 char addr[INET6_ADDRSTRLEN];
2746 rm_addr = *client_ss;
2747 print_sockaddr(addr, sizeof(addr), &rm_addr);
2748 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2749 addr));
2752 /* setup the connection */
2754 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2755 &rm_addr, 0, "IPC$", "IPC",
2756 "", /* username */
2757 "", /* domain */
2758 "", /* password */
2759 0, lp_client_signing(), NULL );
2761 if ( !NT_STATUS_IS_OK( ret ) ) {
2762 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2763 remote_machine ));
2764 return False;
2767 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2768 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2769 cli_shutdown(the_cli);
2770 return False;
2774 * Ok - we have an anonymous connection to the IPC$ share.
2775 * Now start the NT Domain stuff :-).
2778 ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2779 if (!NT_STATUS_IS_OK(ret)) {
2780 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2781 remote_machine, nt_errstr(ret)));
2782 cli_shutdown(the_cli);
2783 return False;
2786 return True;
2789 /***************************************************************************
2790 Connect to the client.
2791 ****************************************************************************/
2793 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2794 uint32 localprinter, uint32 type,
2795 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2797 WERROR result;
2798 NTSTATUS status;
2801 * If it's the first connection, contact the client
2802 * and connect to the IPC$ share anonymously
2804 if (smb_connections==0) {
2805 fstring unix_printer;
2807 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2809 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2810 return False;
2812 messaging_register(smbd_messaging_context(), NULL,
2813 MSG_PRINTER_NOTIFY2,
2814 receive_notify2_message_list);
2815 /* Tell the connections db we're now interested in printer
2816 * notify messages. */
2817 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2821 * Tell the specific printing tdb we want messages for this printer
2822 * by registering our PID.
2825 if (!print_notify_register_pid(snum))
2826 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2828 smb_connections++;
2830 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2831 printer,
2832 localprinter,
2833 type,
2835 NULL,
2836 handle,
2837 &result);
2838 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2839 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2840 win_errstr(result)));
2842 return (W_ERROR_IS_OK(result));
2845 /****************************************************************
2846 ****************************************************************/
2848 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2849 const struct spoolss_NotifyOption *r)
2851 struct spoolss_NotifyOption *option;
2852 uint32_t i,k;
2854 if (!r) {
2855 return NULL;
2858 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2859 if (!option) {
2860 return NULL;
2863 *option = *r;
2865 if (!option->count) {
2866 return option;
2869 option->types = talloc_zero_array(option,
2870 struct spoolss_NotifyOptionType, option->count);
2871 if (!option->types) {
2872 talloc_free(option);
2873 return NULL;
2876 for (i=0; i < option->count; i++) {
2877 option->types[i] = r->types[i];
2879 if (option->types[i].count) {
2880 option->types[i].fields = talloc_zero_array(option,
2881 enum spoolss_Field, option->types[i].count);
2882 if (!option->types[i].fields) {
2883 talloc_free(option);
2884 return NULL;
2886 for (k=0; k<option->types[i].count; k++) {
2887 option->types[i].fields[k] =
2888 r->types[i].fields[k];
2893 return option;
2896 /****************************************************************
2897 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2899 * before replying OK: status=0 a rpc call is made to the workstation
2900 * asking ReplyOpenPrinter
2902 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2903 * called from api_spoolss_rffpcnex
2904 ****************************************************************/
2906 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2907 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2909 POLICY_HND *handle = r->in.handle;
2910 int snum = -1;
2911 struct spoolss_NotifyOption *option = r->in.notify_options;
2912 struct sockaddr_storage client_ss;
2914 /* store the notify value in the printer struct */
2916 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2918 if (!Printer) {
2919 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2920 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2921 return WERR_BADFID;
2924 Printer->notify.flags = r->in.flags;
2925 Printer->notify.options = r->in.options;
2926 Printer->notify.printerlocal = r->in.printer_local;
2928 TALLOC_FREE(Printer->notify.option);
2929 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2931 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2933 /* Connect to the client machine and send a ReplyOpenPrinter */
2935 if ( Printer->printer_type == SPLHND_SERVER)
2936 snum = -1;
2937 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2938 !get_printer_snum(p, handle, &snum, NULL) )
2939 return WERR_BADFID;
2941 if (!interpret_string_addr(&client_ss, p->client_address,
2942 AI_NUMERICHOST)) {
2943 return WERR_SERVER_UNAVAILABLE;
2946 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2947 Printer->notify.printerlocal, 1,
2948 &Printer->notify.client_hnd, &client_ss))
2949 return WERR_SERVER_UNAVAILABLE;
2951 Printer->notify.client_connected=True;
2953 return WERR_OK;
2956 /*******************************************************************
2957 * fill a notify_info_data with the servername
2958 ********************************************************************/
2960 void spoolss_notify_server_name(int snum,
2961 struct spoolss_Notify *data,
2962 print_queue_struct *queue,
2963 NT_PRINTER_INFO_LEVEL *printer,
2964 TALLOC_CTX *mem_ctx)
2966 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2969 /*******************************************************************
2970 * fill a notify_info_data with the printername (not including the servername).
2971 ********************************************************************/
2973 void spoolss_notify_printer_name(int snum,
2974 struct spoolss_Notify *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2979 /* the notify name should not contain the \\server\ part */
2980 char *p = strrchr(printer->info_2->printername, '\\');
2982 if (!p) {
2983 p = printer->info_2->printername;
2984 } else {
2985 p++;
2988 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2991 /*******************************************************************
2992 * fill a notify_info_data with the servicename
2993 ********************************************************************/
2995 void spoolss_notify_share_name(int snum,
2996 struct spoolss_Notify *data,
2997 print_queue_struct *queue,
2998 NT_PRINTER_INFO_LEVEL *printer,
2999 TALLOC_CTX *mem_ctx)
3001 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
3004 /*******************************************************************
3005 * fill a notify_info_data with the port name
3006 ********************************************************************/
3008 void spoolss_notify_port_name(int snum,
3009 struct spoolss_Notify *data,
3010 print_queue_struct *queue,
3011 NT_PRINTER_INFO_LEVEL *printer,
3012 TALLOC_CTX *mem_ctx)
3014 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
3017 /*******************************************************************
3018 * fill a notify_info_data with the printername
3019 * but it doesn't exist, have to see what to do
3020 ********************************************************************/
3022 void spoolss_notify_driver_name(int snum,
3023 struct spoolss_Notify *data,
3024 print_queue_struct *queue,
3025 NT_PRINTER_INFO_LEVEL *printer,
3026 TALLOC_CTX *mem_ctx)
3028 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3031 /*******************************************************************
3032 * fill a notify_info_data with the comment
3033 ********************************************************************/
3035 void spoolss_notify_comment(int snum,
3036 struct spoolss_Notify *data,
3037 print_queue_struct *queue,
3038 NT_PRINTER_INFO_LEVEL *printer,
3039 TALLOC_CTX *mem_ctx)
3041 char *p;
3043 if (*printer->info_2->comment == '\0') {
3044 p = lp_comment(snum);
3045 } else {
3046 p = printer->info_2->comment;
3049 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3052 /*******************************************************************
3053 * fill a notify_info_data with the comment
3054 * location = "Room 1, floor 2, building 3"
3055 ********************************************************************/
3057 void spoolss_notify_location(int snum,
3058 struct spoolss_Notify *data,
3059 print_queue_struct *queue,
3060 NT_PRINTER_INFO_LEVEL *printer,
3061 TALLOC_CTX *mem_ctx)
3063 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3066 /*******************************************************************
3067 * fill a notify_info_data with the device mode
3068 * jfm:xxxx don't to it for know but that's a real problem !!!
3069 ********************************************************************/
3071 static void spoolss_notify_devmode(int snum,
3072 struct spoolss_Notify *data,
3073 print_queue_struct *queue,
3074 NT_PRINTER_INFO_LEVEL *printer,
3075 TALLOC_CTX *mem_ctx)
3077 /* for a dummy implementation we have to zero the fields */
3078 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3081 /*******************************************************************
3082 * fill a notify_info_data with the separator file name
3083 ********************************************************************/
3085 void spoolss_notify_sepfile(int snum,
3086 struct spoolss_Notify *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3091 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3094 /*******************************************************************
3095 * fill a notify_info_data with the print processor
3096 * jfm:xxxx return always winprint to indicate we don't do anything to it
3097 ********************************************************************/
3099 void spoolss_notify_print_processor(int snum,
3100 struct spoolss_Notify *data,
3101 print_queue_struct *queue,
3102 NT_PRINTER_INFO_LEVEL *printer,
3103 TALLOC_CTX *mem_ctx)
3105 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3108 /*******************************************************************
3109 * fill a notify_info_data with the print processor options
3110 * jfm:xxxx send an empty string
3111 ********************************************************************/
3113 void spoolss_notify_parameters(int snum,
3114 struct spoolss_Notify *data,
3115 print_queue_struct *queue,
3116 NT_PRINTER_INFO_LEVEL *printer,
3117 TALLOC_CTX *mem_ctx)
3119 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3122 /*******************************************************************
3123 * fill a notify_info_data with the data type
3124 * jfm:xxxx always send RAW as data type
3125 ********************************************************************/
3127 void spoolss_notify_datatype(int snum,
3128 struct spoolss_Notify *data,
3129 print_queue_struct *queue,
3130 NT_PRINTER_INFO_LEVEL *printer,
3131 TALLOC_CTX *mem_ctx)
3133 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3136 /*******************************************************************
3137 * fill a notify_info_data with the security descriptor
3138 * jfm:xxxx send an null pointer to say no security desc
3139 * have to implement security before !
3140 ********************************************************************/
3142 static void spoolss_notify_security_desc(int snum,
3143 struct spoolss_Notify *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3149 printer->info_2->secdesc_buf->sd_size,
3150 printer->info_2->secdesc_buf->sd);
3153 /*******************************************************************
3154 * fill a notify_info_data with the attributes
3155 * jfm:xxxx a samba printer is always shared
3156 ********************************************************************/
3158 void spoolss_notify_attributes(int snum,
3159 struct spoolss_Notify *data,
3160 print_queue_struct *queue,
3161 NT_PRINTER_INFO_LEVEL *printer,
3162 TALLOC_CTX *mem_ctx)
3164 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3167 /*******************************************************************
3168 * fill a notify_info_data with the priority
3169 ********************************************************************/
3171 static void spoolss_notify_priority(int snum,
3172 struct spoolss_Notify *data,
3173 print_queue_struct *queue,
3174 NT_PRINTER_INFO_LEVEL *printer,
3175 TALLOC_CTX *mem_ctx)
3177 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3180 /*******************************************************************
3181 * fill a notify_info_data with the default priority
3182 ********************************************************************/
3184 static void spoolss_notify_default_priority(int snum,
3185 struct spoolss_Notify *data,
3186 print_queue_struct *queue,
3187 NT_PRINTER_INFO_LEVEL *printer,
3188 TALLOC_CTX *mem_ctx)
3190 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3193 /*******************************************************************
3194 * fill a notify_info_data with the start time
3195 ********************************************************************/
3197 static void spoolss_notify_start_time(int snum,
3198 struct spoolss_Notify *data,
3199 print_queue_struct *queue,
3200 NT_PRINTER_INFO_LEVEL *printer,
3201 TALLOC_CTX *mem_ctx)
3203 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3206 /*******************************************************************
3207 * fill a notify_info_data with the until time
3208 ********************************************************************/
3210 static void spoolss_notify_until_time(int snum,
3211 struct spoolss_Notify *data,
3212 print_queue_struct *queue,
3213 NT_PRINTER_INFO_LEVEL *printer,
3214 TALLOC_CTX *mem_ctx)
3216 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3219 /*******************************************************************
3220 * fill a notify_info_data with the status
3221 ********************************************************************/
3223 static void spoolss_notify_status(int snum,
3224 struct spoolss_Notify *data,
3225 print_queue_struct *queue,
3226 NT_PRINTER_INFO_LEVEL *printer,
3227 TALLOC_CTX *mem_ctx)
3229 print_status_struct status;
3231 print_queue_length(snum, &status);
3232 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3235 /*******************************************************************
3236 * fill a notify_info_data with the number of jobs queued
3237 ********************************************************************/
3239 void spoolss_notify_cjobs(int snum,
3240 struct spoolss_Notify *data,
3241 print_queue_struct *queue,
3242 NT_PRINTER_INFO_LEVEL *printer,
3243 TALLOC_CTX *mem_ctx)
3245 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3248 /*******************************************************************
3249 * fill a notify_info_data with the average ppm
3250 ********************************************************************/
3252 static void spoolss_notify_average_ppm(int snum,
3253 struct spoolss_Notify *data,
3254 print_queue_struct *queue,
3255 NT_PRINTER_INFO_LEVEL *printer,
3256 TALLOC_CTX *mem_ctx)
3258 /* always respond 8 pages per minutes */
3259 /* a little hard ! */
3260 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3263 /*******************************************************************
3264 * fill a notify_info_data with username
3265 ********************************************************************/
3267 static void spoolss_notify_username(int snum,
3268 struct spoolss_Notify *data,
3269 print_queue_struct *queue,
3270 NT_PRINTER_INFO_LEVEL *printer,
3271 TALLOC_CTX *mem_ctx)
3273 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3276 /*******************************************************************
3277 * fill a notify_info_data with job status
3278 ********************************************************************/
3280 static void spoolss_notify_job_status(int snum,
3281 struct spoolss_Notify *data,
3282 print_queue_struct *queue,
3283 NT_PRINTER_INFO_LEVEL *printer,
3284 TALLOC_CTX *mem_ctx)
3286 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3289 /*******************************************************************
3290 * fill a notify_info_data with job name
3291 ********************************************************************/
3293 static void spoolss_notify_job_name(int snum,
3294 struct spoolss_Notify *data,
3295 print_queue_struct *queue,
3296 NT_PRINTER_INFO_LEVEL *printer,
3297 TALLOC_CTX *mem_ctx)
3299 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3302 /*******************************************************************
3303 * fill a notify_info_data with job status
3304 ********************************************************************/
3306 static void spoolss_notify_job_status_string(int snum,
3307 struct spoolss_Notify *data,
3308 print_queue_struct *queue,
3309 NT_PRINTER_INFO_LEVEL *printer,
3310 TALLOC_CTX *mem_ctx)
3313 * Now we're returning job status codes we just return a "" here. JRA.
3316 const char *p = "";
3318 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3319 p = "unknown";
3321 switch (queue->status) {
3322 case LPQ_QUEUED:
3323 p = "Queued";
3324 break;
3325 case LPQ_PAUSED:
3326 p = ""; /* NT provides the paused string */
3327 break;
3328 case LPQ_SPOOLING:
3329 p = "Spooling";
3330 break;
3331 case LPQ_PRINTING:
3332 p = "Printing";
3333 break;
3335 #endif /* NO LONGER NEEDED. */
3337 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3340 /*******************************************************************
3341 * fill a notify_info_data with job time
3342 ********************************************************************/
3344 static void spoolss_notify_job_time(int snum,
3345 struct spoolss_Notify *data,
3346 print_queue_struct *queue,
3347 NT_PRINTER_INFO_LEVEL *printer,
3348 TALLOC_CTX *mem_ctx)
3350 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3353 /*******************************************************************
3354 * fill a notify_info_data with job size
3355 ********************************************************************/
3357 static void spoolss_notify_job_size(int snum,
3358 struct spoolss_Notify *data,
3359 print_queue_struct *queue,
3360 NT_PRINTER_INFO_LEVEL *printer,
3361 TALLOC_CTX *mem_ctx)
3363 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3366 /*******************************************************************
3367 * fill a notify_info_data with page info
3368 ********************************************************************/
3369 static void spoolss_notify_total_pages(int snum,
3370 struct spoolss_Notify *data,
3371 print_queue_struct *queue,
3372 NT_PRINTER_INFO_LEVEL *printer,
3373 TALLOC_CTX *mem_ctx)
3375 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3378 /*******************************************************************
3379 * fill a notify_info_data with pages printed info.
3380 ********************************************************************/
3381 static void spoolss_notify_pages_printed(int snum,
3382 struct spoolss_Notify *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer,
3385 TALLOC_CTX *mem_ctx)
3387 /* Add code when back-end tracks this */
3388 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3391 /*******************************************************************
3392 Fill a notify_info_data with job position.
3393 ********************************************************************/
3395 static void spoolss_notify_job_position(int snum,
3396 struct spoolss_Notify *data,
3397 print_queue_struct *queue,
3398 NT_PRINTER_INFO_LEVEL *printer,
3399 TALLOC_CTX *mem_ctx)
3401 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3404 /*******************************************************************
3405 Fill a notify_info_data with submitted time.
3406 ********************************************************************/
3408 static void spoolss_notify_submitted_time(int snum,
3409 struct spoolss_Notify *data,
3410 print_queue_struct *queue,
3411 NT_PRINTER_INFO_LEVEL *printer,
3412 TALLOC_CTX *mem_ctx)
3414 data->data.string.string = NULL;
3415 data->data.string.size = 0;
3417 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3418 &data->data.string.string,
3419 &data->data.string.size);
3423 struct s_notify_info_data_table
3425 enum spoolss_NotifyType type;
3426 enum spoolss_Field field;
3427 const char *name;
3428 enum spoolss_NotifyTable variable_type;
3429 void (*fn) (int snum, struct spoolss_Notify *data,
3430 print_queue_struct *queue,
3431 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3434 /* A table describing the various print notification constants and
3435 whether the notification data is a pointer to a variable sized
3436 buffer, a one value uint32 or a two value uint32. */
3438 static const struct s_notify_info_data_table notify_info_data_table[] =
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3489 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3492 /*******************************************************************
3493 Return the variable_type of info_data structure.
3494 ********************************************************************/
3496 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3497 enum spoolss_Field field)
3499 int i=0;
3501 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3502 if ( (notify_info_data_table[i].type == type) &&
3503 (notify_info_data_table[i].field == field) ) {
3504 return notify_info_data_table[i].variable_type;
3508 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3510 return 0;
3513 /****************************************************************************
3514 ****************************************************************************/
3516 static bool search_notify(enum spoolss_NotifyType type,
3517 enum spoolss_Field field,
3518 int *value)
3520 int i;
3522 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3523 if (notify_info_data_table[i].type == type &&
3524 notify_info_data_table[i].field == field &&
3525 notify_info_data_table[i].fn != NULL) {
3526 *value = i;
3527 return True;
3531 return False;
3534 /****************************************************************************
3535 ****************************************************************************/
3537 void construct_info_data(struct spoolss_Notify *info_data,
3538 enum spoolss_NotifyType type,
3539 enum spoolss_Field field,
3540 int id)
3542 info_data->type = type;
3543 info_data->field = field;
3544 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3545 info_data->job_id = id;
3548 /*******************************************************************
3550 * fill a notify_info struct with info asked
3552 ********************************************************************/
3554 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3555 struct spoolss_NotifyInfo *info,
3556 int snum,
3557 const struct spoolss_NotifyOptionType *option_type,
3558 uint32_t id,
3559 TALLOC_CTX *mem_ctx)
3561 int field_num,j;
3562 enum spoolss_NotifyType type;
3563 enum spoolss_Field field;
3565 struct spoolss_Notify *current_data;
3566 NT_PRINTER_INFO_LEVEL *printer = NULL;
3567 print_queue_struct *queue=NULL;
3569 type = option_type->type;
3571 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3572 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3573 option_type->count, lp_servicename(snum)));
3575 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3576 return False;
3578 for(field_num=0; field_num < option_type->count; field_num++) {
3579 field = option_type->fields[field_num];
3581 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3583 if (!search_notify(type, field, &j) )
3584 continue;
3586 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3587 struct spoolss_Notify,
3588 info->count + 1);
3589 if (info->notifies == NULL) {
3590 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3591 free_a_printer(&printer, 2);
3592 return False;
3595 current_data = &info->notifies[info->count];
3597 construct_info_data(current_data, type, field, id);
3599 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3600 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3602 notify_info_data_table[j].fn(snum, current_data, queue,
3603 printer, mem_ctx);
3605 info->count++;
3608 free_a_printer(&printer, 2);
3609 return True;
3612 /*******************************************************************
3614 * fill a notify_info struct with info asked
3616 ********************************************************************/
3618 static bool construct_notify_jobs_info(print_queue_struct *queue,
3619 struct spoolss_NotifyInfo *info,
3620 NT_PRINTER_INFO_LEVEL *printer,
3621 int snum,
3622 const struct spoolss_NotifyOptionType *option_type,
3623 uint32_t id,
3624 TALLOC_CTX *mem_ctx)
3626 int field_num,j;
3627 enum spoolss_NotifyType type;
3628 enum spoolss_Field field;
3629 struct spoolss_Notify *current_data;
3631 DEBUG(4,("construct_notify_jobs_info\n"));
3633 type = option_type->type;
3635 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3636 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3637 option_type->count));
3639 for(field_num=0; field_num<option_type->count; field_num++) {
3640 field = option_type->fields[field_num];
3642 if (!search_notify(type, field, &j) )
3643 continue;
3645 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3646 struct spoolss_Notify,
3647 info->count + 1);
3648 if (info->notifies == NULL) {
3649 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3650 return False;
3653 current_data=&(info->notifies[info->count]);
3655 construct_info_data(current_data, type, field, id);
3656 notify_info_data_table[j].fn(snum, current_data, queue,
3657 printer, mem_ctx);
3658 info->count++;
3661 return True;
3665 * JFM: The enumeration is not that simple, it's even non obvious.
3667 * let's take an example: I want to monitor the PRINTER SERVER for
3668 * the printer's name and the number of jobs currently queued.
3669 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3670 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3672 * I have 3 printers on the back of my server.
3674 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3675 * structures.
3676 * Number Data Id
3677 * 1 printer 1 name 1
3678 * 2 printer 1 cjob 1
3679 * 3 printer 2 name 2
3680 * 4 printer 2 cjob 2
3681 * 5 printer 3 name 3
3682 * 6 printer 3 name 3
3684 * that's the print server case, the printer case is even worse.
3687 /*******************************************************************
3689 * enumerate all printers on the printserver
3690 * fill a notify_info struct with info asked
3692 ********************************************************************/
3694 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3695 struct spoolss_NotifyInfo *info,
3696 TALLOC_CTX *mem_ctx)
3698 int snum;
3699 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3700 int n_services=lp_numservices();
3701 int i;
3702 struct spoolss_NotifyOption *option;
3703 struct spoolss_NotifyOptionType option_type;
3705 DEBUG(4,("printserver_notify_info\n"));
3707 if (!Printer)
3708 return WERR_BADFID;
3710 option = Printer->notify.option;
3712 info->version = 2;
3713 info->notifies = NULL;
3714 info->count = 0;
3716 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3717 sending a ffpcn() request first */
3719 if ( !option )
3720 return WERR_BADFID;
3722 for (i=0; i<option->count; i++) {
3723 option_type = option->types[i];
3725 if (option_type.type != PRINTER_NOTIFY_TYPE)
3726 continue;
3728 for (snum=0; snum<n_services; snum++)
3730 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3731 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3735 #if 0
3737 * Debugging information, don't delete.
3740 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3741 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3742 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3744 for (i=0; i<info->count; i++) {
3745 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3746 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3747 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3749 #endif
3751 return WERR_OK;
3754 /*******************************************************************
3756 * fill a notify_info struct with info asked
3758 ********************************************************************/
3760 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3761 TALLOC_CTX *mem_ctx)
3763 int snum;
3764 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3765 int i;
3766 uint32 id;
3767 struct spoolss_NotifyOption *option;
3768 struct spoolss_NotifyOptionType option_type;
3769 int count,j;
3770 print_queue_struct *queue=NULL;
3771 print_status_struct status;
3773 DEBUG(4,("printer_notify_info\n"));
3775 if (!Printer)
3776 return WERR_BADFID;
3778 option = Printer->notify.option;
3779 id = 0x0;
3781 info->version = 2;
3782 info->notifies = NULL;
3783 info->count = 0;
3785 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3786 sending a ffpcn() request first */
3788 if ( !option )
3789 return WERR_BADFID;
3791 get_printer_snum(p, hnd, &snum, NULL);
3793 for (i=0; i<option->count; i++) {
3794 option_type = option->types[i];
3796 switch (option_type.type) {
3797 case PRINTER_NOTIFY_TYPE:
3798 if(construct_notify_printer_info(Printer, info, snum,
3799 &option_type, id,
3800 mem_ctx))
3801 id--;
3802 break;
3804 case JOB_NOTIFY_TYPE: {
3805 NT_PRINTER_INFO_LEVEL *printer = NULL;
3807 count = print_queue_status(snum, &queue, &status);
3809 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3810 goto done;
3812 for (j=0; j<count; j++) {
3813 construct_notify_jobs_info(&queue[j], info,
3814 printer, snum,
3815 &option_type,
3816 queue[j].job,
3817 mem_ctx);
3820 free_a_printer(&printer, 2);
3822 done:
3823 SAFE_FREE(queue);
3824 break;
3830 * Debugging information, don't delete.
3833 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3834 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3835 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3837 for (i=0; i<info->count; i++) {
3838 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3839 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3840 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3843 return WERR_OK;
3846 /****************************************************************
3847 _spoolss_RouterRefreshPrinterChangeNotify
3848 ****************************************************************/
3850 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3851 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3853 POLICY_HND *handle = r->in.handle;
3854 struct spoolss_NotifyInfo *info;
3856 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3857 WERROR result = WERR_BADFID;
3859 /* we always have a spoolss_NotifyInfo struct */
3860 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3861 if (!info) {
3862 result = WERR_NOMEM;
3863 goto done;
3866 *r->out.info = info;
3868 if (!Printer) {
3869 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3870 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3871 goto done;
3874 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3877 * We are now using the change value, and
3878 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3879 * I don't have a global notification system, I'm sending back all the
3880 * informations even when _NOTHING_ has changed.
3883 /* We need to keep track of the change value to send back in
3884 RRPCN replies otherwise our updates are ignored. */
3886 Printer->notify.fnpcn = True;
3888 if (Printer->notify.client_connected) {
3889 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3890 "Saving change value in request [%x]\n",
3891 r->in.change_low));
3892 Printer->notify.change = r->in.change_low;
3895 /* just ignore the spoolss_NotifyOption */
3897 switch (Printer->printer_type) {
3898 case SPLHND_SERVER:
3899 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3900 break;
3902 case SPLHND_PRINTER:
3903 result = printer_notify_info(p, handle, info, p->mem_ctx);
3904 break;
3907 Printer->notify.fnpcn = False;
3909 done:
3910 return result;
3913 /********************************************************************
3914 * construct_printer_info_0
3915 * fill a printer_info_0 struct
3916 ********************************************************************/
3918 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3920 char *chaine = NULL;
3921 int count;
3922 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3923 counter_printer_0 *session_counter;
3924 uint32 global_counter;
3925 struct tm *t;
3926 time_t setuptime;
3927 print_status_struct status;
3928 TALLOC_CTX *ctx = talloc_tos();
3930 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3931 return False;
3933 init_unistr(&printer->printername, ntprinter->info_2->printername);
3935 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3936 if (!chaine) {
3937 free_a_printer(&ntprinter,2);
3938 return false;
3941 count = print_queue_length(snum, &status);
3943 /* check if we already have a counter for this printer */
3944 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3945 if (session_counter->snum == snum)
3946 break;
3949 init_unistr(&printer->servername, chaine);
3951 /* it's the first time, add it to the list */
3952 if (session_counter==NULL) {
3953 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3954 free_a_printer(&ntprinter, 2);
3955 return False;
3957 ZERO_STRUCTP(session_counter);
3958 session_counter->snum=snum;
3959 session_counter->counter=0;
3960 DLIST_ADD(counter_list, session_counter);
3963 /* increment it */
3964 session_counter->counter++;
3966 /* JFM:
3967 * the global_counter should be stored in a TDB as it's common to all the clients
3968 * and should be zeroed on samba startup
3970 global_counter=session_counter->counter;
3971 printer->cjobs = count;
3972 printer->total_jobs = 0;
3973 printer->total_bytes = 0;
3975 setuptime = (time_t)ntprinter->info_2->setuptime;
3976 t=gmtime(&setuptime);
3978 printer->year = t->tm_year+1900;
3979 printer->month = t->tm_mon+1;
3980 printer->dayofweek = t->tm_wday;
3981 printer->day = t->tm_mday;
3982 printer->hour = t->tm_hour;
3983 printer->minute = t->tm_min;
3984 printer->second = t->tm_sec;
3985 printer->milliseconds = 0;
3987 printer->global_counter = global_counter;
3988 printer->total_pages = 0;
3990 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3991 printer->major_version = 0x0005; /* NT 5 */
3992 printer->build_version = 0x0893; /* build 2195 */
3994 printer->unknown7 = 0x1;
3995 printer->unknown8 = 0x0;
3996 printer->unknown9 = 0x0;
3997 printer->session_counter = session_counter->counter;
3998 printer->unknown11 = 0x0;
3999 printer->printer_errors = 0x0; /* number of print failure */
4000 printer->unknown13 = 0x0;
4001 printer->unknown14 = 0x1;
4002 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4003 printer->unknown16 = 0x0;
4004 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4005 printer->unknown18 = 0x0;
4006 printer->status = nt_printq_status(status.status);
4007 printer->unknown20 = 0x0;
4008 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4009 printer->unknown22 = 0x0;
4010 printer->unknown23 = 0x6; /* 6 ???*/
4011 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4012 printer->unknown25 = 0;
4013 printer->unknown26 = 0;
4014 printer->unknown27 = 0;
4015 printer->unknown28 = 0;
4016 printer->unknown29 = 0;
4018 free_a_printer(&ntprinter,2);
4019 return (True);
4022 /********************************************************************
4023 * construct_printer_info_1
4024 * fill a printer_info_1 struct
4025 ********************************************************************/
4026 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4028 char *chaine = NULL;
4029 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4030 TALLOC_CTX *ctx = talloc_tos();
4032 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4033 return false;
4035 printer->flags=flags;
4037 if (*ntprinter->info_2->comment == '\0') {
4038 init_unistr(&printer->comment, lp_comment(snum));
4039 chaine = talloc_asprintf(ctx,
4040 "%s,%s,%s", ntprinter->info_2->printername,
4041 ntprinter->info_2->drivername, lp_comment(snum));
4043 else {
4044 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4045 chaine = talloc_asprintf(ctx,
4046 "%s,%s,%s", ntprinter->info_2->printername,
4047 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4050 if (!chaine) {
4051 free_a_printer(&ntprinter,2);
4052 return false;
4055 init_unistr(&printer->description, chaine);
4056 init_unistr(&printer->name, ntprinter->info_2->printername);
4058 free_a_printer(&ntprinter,2);
4060 return True;
4063 /****************************************************************************
4064 Free a DEVMODE struct.
4065 ****************************************************************************/
4067 static void free_dev_mode(DEVICEMODE *dev)
4069 if (dev == NULL)
4070 return;
4072 SAFE_FREE(dev->dev_private);
4073 SAFE_FREE(dev);
4077 /****************************************************************************
4078 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4079 should be valid upon entry
4080 ****************************************************************************/
4082 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4084 if ( !devmode || !ntdevmode )
4085 return False;
4087 init_unistr(&devmode->devicename, ntdevmode->devicename);
4089 init_unistr(&devmode->formname, ntdevmode->formname);
4091 devmode->specversion = ntdevmode->specversion;
4092 devmode->driverversion = ntdevmode->driverversion;
4093 devmode->size = ntdevmode->size;
4094 devmode->driverextra = ntdevmode->driverextra;
4095 devmode->fields = ntdevmode->fields;
4097 devmode->orientation = ntdevmode->orientation;
4098 devmode->papersize = ntdevmode->papersize;
4099 devmode->paperlength = ntdevmode->paperlength;
4100 devmode->paperwidth = ntdevmode->paperwidth;
4101 devmode->scale = ntdevmode->scale;
4102 devmode->copies = ntdevmode->copies;
4103 devmode->defaultsource = ntdevmode->defaultsource;
4104 devmode->printquality = ntdevmode->printquality;
4105 devmode->color = ntdevmode->color;
4106 devmode->duplex = ntdevmode->duplex;
4107 devmode->yresolution = ntdevmode->yresolution;
4108 devmode->ttoption = ntdevmode->ttoption;
4109 devmode->collate = ntdevmode->collate;
4110 devmode->icmmethod = ntdevmode->icmmethod;
4111 devmode->icmintent = ntdevmode->icmintent;
4112 devmode->mediatype = ntdevmode->mediatype;
4113 devmode->dithertype = ntdevmode->dithertype;
4115 if (ntdevmode->nt_dev_private != NULL) {
4116 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4117 return False;
4120 return True;
4123 /****************************************************************************
4124 Create a DEVMODE struct. Returns malloced memory.
4125 ****************************************************************************/
4127 DEVICEMODE *construct_dev_mode(const char *servicename)
4129 NT_PRINTER_INFO_LEVEL *printer = NULL;
4130 DEVICEMODE *devmode = NULL;
4132 DEBUG(7,("construct_dev_mode\n"));
4134 DEBUGADD(8,("getting printer characteristics\n"));
4136 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4137 return NULL;
4139 if ( !printer->info_2->devmode ) {
4140 DEBUG(5, ("BONG! There was no device mode!\n"));
4141 goto done;
4144 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4145 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4146 goto done;
4149 ZERO_STRUCTP(devmode);
4151 DEBUGADD(8,("loading DEVICEMODE\n"));
4153 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4154 free_dev_mode( devmode );
4155 devmode = NULL;
4158 done:
4159 free_a_printer(&printer,2);
4161 return devmode;
4164 /********************************************************************
4165 * construct_printer_info_2
4166 * fill a printer_info_2 struct
4167 ********************************************************************/
4169 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4171 int count;
4172 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4174 print_status_struct status;
4176 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4177 return False;
4179 count = print_queue_length(snum, &status);
4181 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4182 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4183 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4184 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4185 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4187 if (*ntprinter->info_2->comment == '\0')
4188 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4189 else
4190 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4192 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4193 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4194 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4195 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4196 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4198 printer->attributes = ntprinter->info_2->attributes;
4200 printer->priority = ntprinter->info_2->priority; /* priority */
4201 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4202 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4203 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4204 printer->status = nt_printq_status(status.status); /* status */
4205 printer->cjobs = count; /* jobs */
4206 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4208 if ( !(printer->devmode = construct_dev_mode(
4209 lp_const_servicename(snum))) )
4210 DEBUG(8, ("Returning NULL Devicemode!\n"));
4212 printer->secdesc = NULL;
4214 if ( ntprinter->info_2->secdesc_buf
4215 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4217 /* don't use talloc_steal() here unless you do a deep steal of all
4218 the SEC_DESC members */
4220 printer->secdesc = dup_sec_desc( talloc_tos(),
4221 ntprinter->info_2->secdesc_buf->sd );
4224 free_a_printer(&ntprinter, 2);
4226 return True;
4229 /********************************************************************
4230 * construct_printer_info_3
4231 * fill a printer_info_3 struct
4232 ********************************************************************/
4234 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4236 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4237 PRINTER_INFO_3 *printer = NULL;
4239 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4240 return False;
4242 *pp_printer = NULL;
4243 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4244 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4245 free_a_printer(&ntprinter, 2);
4246 return False;
4249 ZERO_STRUCTP(printer);
4251 /* These are the components of the SD we are returning. */
4253 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4254 /* don't use talloc_steal() here unless you do a deep steal of all
4255 the SEC_DESC members */
4257 printer->secdesc = dup_sec_desc( talloc_tos(),
4258 ntprinter->info_2->secdesc_buf->sd );
4261 free_a_printer(&ntprinter, 2);
4263 *pp_printer = printer;
4264 return True;
4267 /********************************************************************
4268 * construct_printer_info_4
4269 * fill a printer_info_4 struct
4270 ********************************************************************/
4272 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4274 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4276 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4277 return False;
4279 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4280 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4281 printer->attributes = ntprinter->info_2->attributes;
4283 free_a_printer(&ntprinter, 2);
4284 return True;
4287 /********************************************************************
4288 * construct_printer_info_5
4289 * fill a printer_info_5 struct
4290 ********************************************************************/
4292 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4294 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4296 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4297 return False;
4299 init_unistr(&printer->printername, ntprinter->info_2->printername);
4300 init_unistr(&printer->portname, ntprinter->info_2->portname);
4301 printer->attributes = ntprinter->info_2->attributes;
4303 /* these two are not used by NT+ according to MSDN */
4305 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4306 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4308 free_a_printer(&ntprinter, 2);
4310 return True;
4313 /********************************************************************
4314 * construct_printer_info_6
4315 * fill a printer_info_6 struct
4316 ********************************************************************/
4318 static bool construct_printer_info_6(Printer_entry *print_hnd,
4319 PRINTER_INFO_6 *printer,
4320 int snum)
4322 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4323 int count;
4324 print_status_struct status;
4326 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4327 lp_const_servicename(snum))))
4328 return False;
4330 count = print_queue_length(snum, &status);
4332 printer->status = nt_printq_status(status.status);
4334 free_a_printer(&ntprinter, 2);
4336 return True;
4339 /********************************************************************
4340 * construct_printer_info_7
4341 * fill a printer_info_7 struct
4342 ********************************************************************/
4344 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4346 char *guid_str = NULL;
4347 struct GUID guid;
4349 if (is_printer_published(print_hnd, snum, &guid)) {
4350 if (asprintf(&guid_str, "{%s}",
4351 GUID_string(talloc_tos(), &guid)) == -1) {
4352 return false;
4354 strupper_m(guid_str);
4355 init_unistr(&printer->guid, guid_str);
4356 SAFE_FREE(guid_str);
4357 printer->action = SPOOL_DS_PUBLISH;
4358 } else {
4359 init_unistr(&printer->guid, "");
4360 printer->action = SPOOL_DS_UNPUBLISH;
4363 return True;
4366 /********************************************************************
4367 Spoolss_enumprinters.
4368 ********************************************************************/
4370 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4372 int snum;
4373 int i;
4374 int n_services=lp_numservices();
4375 PRINTER_INFO_1 *printers=NULL;
4376 PRINTER_INFO_1 current_prt;
4377 WERROR result = WERR_OK;
4379 DEBUG(4,("enum_all_printers_info_1\n"));
4381 for (snum=0; snum<n_services; snum++) {
4382 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4383 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4385 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4386 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4387 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4388 *returned=0;
4389 return WERR_NOMEM;
4391 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4393 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4394 (*returned)++;
4399 /* check the required size. */
4400 for (i=0; i<*returned; i++)
4401 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4403 if (*needed > offered) {
4404 result = WERR_INSUFFICIENT_BUFFER;
4405 goto out;
4408 if (!rpcbuf_alloc_size(buffer, *needed)) {
4409 result = WERR_NOMEM;
4410 goto out;
4413 /* fill the buffer with the structures */
4414 for (i=0; i<*returned; i++)
4415 smb_io_printer_info_1("", buffer, &printers[i], 0);
4417 out:
4418 /* clear memory */
4420 SAFE_FREE(printers);
4422 if ( !W_ERROR_IS_OK(result) )
4423 *returned = 0;
4425 return result;
4428 /********************************************************************
4429 enum_all_printers_info_1_local.
4430 *********************************************************************/
4432 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4434 DEBUG(4,("enum_all_printers_info_1_local\n"));
4436 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4439 /********************************************************************
4440 enum_all_printers_info_1_name.
4441 *********************************************************************/
4443 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4445 char *s = name;
4447 DEBUG(4,("enum_all_printers_info_1_name\n"));
4449 if ((name[0] == '\\') && (name[1] == '\\'))
4450 s = name + 2;
4452 if (is_myname_or_ipaddr(s)) {
4453 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4455 else
4456 return WERR_INVALID_NAME;
4459 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4460 /********************************************************************
4461 enum_all_printers_info_1_remote.
4462 *********************************************************************/
4464 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4466 PRINTER_INFO_1 *printer;
4467 fstring printername;
4468 fstring desc;
4469 fstring comment;
4470 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4471 WERROR result = WERR_OK;
4473 /* JFM: currently it's more a place holder than anything else.
4474 * In the spooler world there is a notion of server registration.
4475 * the print servers are registered on the PDC (in the same domain)
4477 * We should have a TDB here. The registration is done thru an
4478 * undocumented RPC call.
4481 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4482 return WERR_NOMEM;
4484 *returned=1;
4486 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4487 slprintf(desc, sizeof(desc)-1,"%s", name);
4488 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4490 init_unistr(&printer->description, desc);
4491 init_unistr(&printer->name, printername);
4492 init_unistr(&printer->comment, comment);
4493 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4495 /* check the required size. */
4496 *needed += spoolss_size_printer_info_1(printer);
4498 if (*needed > offered) {
4499 result = WERR_INSUFFICIENT_BUFFER;
4500 goto out;
4503 if (!rpcbuf_alloc_size(buffer, *needed)) {
4504 result = WERR_NOMEM;
4505 goto out;
4508 /* fill the buffer with the structures */
4509 smb_io_printer_info_1("", buffer, printer, 0);
4511 out:
4512 /* clear memory */
4513 SAFE_FREE(printer);
4515 if ( !W_ERROR_IS_OK(result) )
4516 *returned = 0;
4518 return result;
4521 #endif
4523 /********************************************************************
4524 enum_all_printers_info_1_network.
4525 *********************************************************************/
4527 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4529 char *s = name;
4531 DEBUG(4,("enum_all_printers_info_1_network\n"));
4533 /* If we respond to a enum_printers level 1 on our name with flags
4534 set to PRINTER_ENUM_REMOTE with a list of printers then these
4535 printers incorrectly appear in the APW browse list.
4536 Specifically the printers for the server appear at the workgroup
4537 level where all the other servers in the domain are
4538 listed. Windows responds to this call with a
4539 WERR_CAN_NOT_COMPLETE so we should do the same. */
4541 if (name[0] == '\\' && name[1] == '\\')
4542 s = name + 2;
4544 if (is_myname_or_ipaddr(s))
4545 return WERR_CAN_NOT_COMPLETE;
4547 return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4550 /********************************************************************
4551 * api_spoolss_enumprinters
4553 * called from api_spoolss_enumprinters (see this to understand)
4554 ********************************************************************/
4556 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4558 int snum;
4559 int i;
4560 int n_services=lp_numservices();
4561 PRINTER_INFO_2 *printers=NULL;
4562 PRINTER_INFO_2 current_prt;
4563 WERROR result = WERR_OK;
4565 *returned = 0;
4567 for (snum=0; snum<n_services; snum++) {
4568 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4569 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4571 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4572 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4573 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4574 *returned = 0;
4575 return WERR_NOMEM;
4578 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4580 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4582 (*returned)++;
4587 /* check the required size. */
4588 for (i=0; i<*returned; i++)
4589 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4591 if (*needed > offered) {
4592 result = WERR_INSUFFICIENT_BUFFER;
4593 goto out;
4596 if (!rpcbuf_alloc_size(buffer, *needed)) {
4597 result = WERR_NOMEM;
4598 goto out;
4601 /* fill the buffer with the structures */
4602 for (i=0; i<*returned; i++)
4603 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4605 out:
4606 /* clear memory */
4608 for (i=0; i<*returned; i++)
4609 free_devmode(printers[i].devmode);
4611 SAFE_FREE(printers);
4613 if ( !W_ERROR_IS_OK(result) )
4614 *returned = 0;
4616 return result;
4619 /********************************************************************
4620 * handle enumeration of printers at level 1
4621 ********************************************************************/
4623 static WERROR enumprinters_level1( uint32 flags, fstring name,
4624 RPC_BUFFER *buffer, uint32 offered,
4625 uint32 *needed, uint32 *returned)
4627 /* Not all the flags are equals */
4629 if (flags & PRINTER_ENUM_LOCAL)
4630 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4632 if (flags & PRINTER_ENUM_NAME)
4633 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4635 #if 0 /* JERRY - disabled for now */
4636 if (flags & PRINTER_ENUM_REMOTE)
4637 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4638 #endif
4640 if (flags & PRINTER_ENUM_NETWORK)
4641 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4643 return WERR_OK; /* NT4sp5 does that */
4646 /********************************************************************
4647 * handle enumeration of printers at level 2
4648 ********************************************************************/
4650 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4651 RPC_BUFFER *buffer, uint32 offered,
4652 uint32 *needed, uint32 *returned)
4654 if (flags & PRINTER_ENUM_LOCAL) {
4655 return enum_all_printers_info_2(buffer, offered, needed, returned);
4658 if (flags & PRINTER_ENUM_NAME) {
4659 if (is_myname_or_ipaddr(canon_servername(servername)))
4660 return enum_all_printers_info_2(buffer, offered, needed, returned);
4661 else
4662 return WERR_INVALID_NAME;
4665 if (flags & PRINTER_ENUM_REMOTE)
4666 return WERR_UNKNOWN_LEVEL;
4668 return WERR_OK;
4671 /********************************************************************
4672 * handle enumeration of printers at level 5
4673 ********************************************************************/
4675 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4676 RPC_BUFFER *buffer, uint32 offered,
4677 uint32 *needed, uint32 *returned)
4679 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4680 return WERR_OK;
4683 /********************************************************************
4684 * api_spoolss_enumprinters
4686 * called from api_spoolss_enumprinters (see this to understand)
4687 ********************************************************************/
4689 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4691 uint32 flags = q_u->flags;
4692 UNISTR2 *servername = &q_u->servername;
4693 uint32 level = q_u->level;
4694 RPC_BUFFER *buffer = NULL;
4695 uint32 offered = q_u->offered;
4696 uint32 *needed = &r_u->needed;
4697 uint32 *returned = &r_u->returned;
4699 fstring name;
4701 /* that's an [in out] buffer */
4703 if (!q_u->buffer && (offered!=0)) {
4704 return WERR_INVALID_PARAM;
4707 if (offered > MAX_RPC_DATA_SIZE) {
4708 return WERR_INVALID_PARAM;
4711 rpcbuf_move(q_u->buffer, &r_u->buffer);
4712 buffer = r_u->buffer;
4714 DEBUG(4,("_spoolss_enumprinters\n"));
4716 *needed=0;
4717 *returned=0;
4720 * Level 1:
4721 * flags==PRINTER_ENUM_NAME
4722 * if name=="" then enumerates all printers
4723 * if name!="" then enumerate the printer
4724 * flags==PRINTER_ENUM_REMOTE
4725 * name is NULL, enumerate printers
4726 * Level 2: name!="" enumerates printers, name can't be NULL
4727 * Level 3: doesn't exist
4728 * Level 4: does a local registry lookup
4729 * Level 5: same as Level 2
4732 unistr2_to_ascii(name, servername, sizeof(name));
4733 strupper_m(name);
4735 switch (level) {
4736 case 1:
4737 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4738 case 2:
4739 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4740 case 5:
4741 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4742 case 3:
4743 case 4:
4744 break;
4746 return WERR_UNKNOWN_LEVEL;
4749 /****************************************************************************
4750 ****************************************************************************/
4752 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4754 PRINTER_INFO_0 *printer=NULL;
4755 WERROR result = WERR_OK;
4757 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4758 return WERR_NOMEM;
4760 construct_printer_info_0(print_hnd, printer, snum);
4762 /* check the required size. */
4763 *needed += spoolss_size_printer_info_0(printer);
4765 if (*needed > offered) {
4766 result = WERR_INSUFFICIENT_BUFFER;
4767 goto out;
4770 if (!rpcbuf_alloc_size(buffer, *needed)) {
4771 result = WERR_NOMEM;
4772 goto out;
4775 /* fill the buffer with the structures */
4776 smb_io_printer_info_0("", buffer, printer, 0);
4778 out:
4779 /* clear memory */
4781 SAFE_FREE(printer);
4783 return result;
4786 /****************************************************************************
4787 ****************************************************************************/
4789 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4791 PRINTER_INFO_1 *printer=NULL;
4792 WERROR result = WERR_OK;
4794 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4795 return WERR_NOMEM;
4797 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4799 /* check the required size. */
4800 *needed += spoolss_size_printer_info_1(printer);
4802 if (*needed > offered) {
4803 result = WERR_INSUFFICIENT_BUFFER;
4804 goto out;
4807 if (!rpcbuf_alloc_size(buffer, *needed)) {
4808 result = WERR_NOMEM;
4809 goto out;
4812 /* fill the buffer with the structures */
4813 smb_io_printer_info_1("", buffer, printer, 0);
4815 out:
4816 /* clear memory */
4817 SAFE_FREE(printer);
4819 return result;
4822 /****************************************************************************
4823 ****************************************************************************/
4825 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4827 PRINTER_INFO_2 *printer=NULL;
4828 WERROR result = WERR_OK;
4830 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4831 return WERR_NOMEM;
4833 construct_printer_info_2(print_hnd, printer, snum);
4835 /* check the required size. */
4836 *needed += spoolss_size_printer_info_2(printer);
4838 if (*needed > offered) {
4839 result = WERR_INSUFFICIENT_BUFFER;
4840 goto out;
4843 if (!rpcbuf_alloc_size(buffer, *needed)) {
4844 result = WERR_NOMEM;
4845 goto out;
4848 /* fill the buffer with the structures */
4849 if (!smb_io_printer_info_2("", buffer, printer, 0))
4850 result = WERR_NOMEM;
4852 out:
4853 /* clear memory */
4854 free_printer_info_2(printer);
4856 return result;
4859 /****************************************************************************
4860 ****************************************************************************/
4862 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4864 PRINTER_INFO_3 *printer=NULL;
4865 WERROR result = WERR_OK;
4867 if (!construct_printer_info_3(print_hnd, &printer, snum))
4868 return WERR_NOMEM;
4870 /* check the required size. */
4871 *needed += spoolss_size_printer_info_3(printer);
4873 if (*needed > offered) {
4874 result = WERR_INSUFFICIENT_BUFFER;
4875 goto out;
4878 if (!rpcbuf_alloc_size(buffer, *needed)) {
4879 result = WERR_NOMEM;
4880 goto out;
4883 /* fill the buffer with the structures */
4884 smb_io_printer_info_3("", buffer, printer, 0);
4886 out:
4887 /* clear memory */
4888 free_printer_info_3(printer);
4890 return result;
4893 /****************************************************************************
4894 ****************************************************************************/
4896 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4898 PRINTER_INFO_4 *printer=NULL;
4899 WERROR result = WERR_OK;
4901 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4902 return WERR_NOMEM;
4904 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4905 SAFE_FREE(printer);
4906 return WERR_NOMEM;
4909 /* check the required size. */
4910 *needed += spoolss_size_printer_info_4(printer);
4912 if (*needed > offered) {
4913 result = WERR_INSUFFICIENT_BUFFER;
4914 goto out;
4917 if (!rpcbuf_alloc_size(buffer, *needed)) {
4918 result = WERR_NOMEM;
4919 goto out;
4922 /* fill the buffer with the structures */
4923 smb_io_printer_info_4("", buffer, printer, 0);
4925 out:
4926 /* clear memory */
4927 free_printer_info_4(printer);
4929 return result;
4932 /****************************************************************************
4933 ****************************************************************************/
4935 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4937 PRINTER_INFO_5 *printer=NULL;
4938 WERROR result = WERR_OK;
4940 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4941 return WERR_NOMEM;
4943 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4944 free_printer_info_5(printer);
4945 return WERR_NOMEM;
4948 /* check the required size. */
4949 *needed += spoolss_size_printer_info_5(printer);
4951 if (*needed > offered) {
4952 result = WERR_INSUFFICIENT_BUFFER;
4953 goto out;
4956 if (!rpcbuf_alloc_size(buffer, *needed)) {
4957 result = WERR_NOMEM;
4958 goto out;
4961 /* fill the buffer with the structures */
4962 smb_io_printer_info_5("", buffer, printer, 0);
4964 out:
4965 /* clear memory */
4966 free_printer_info_5(printer);
4968 return result;
4971 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4972 int snum,
4973 RPC_BUFFER *buffer, uint32 offered,
4974 uint32 *needed)
4976 PRINTER_INFO_6 *printer;
4977 WERROR result = WERR_OK;
4979 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4980 return WERR_NOMEM;
4983 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4984 free_printer_info_6(printer);
4985 return WERR_NOMEM;
4988 /* check the required size. */
4989 *needed += spoolss_size_printer_info_6(printer);
4991 if (*needed > offered) {
4992 result = WERR_INSUFFICIENT_BUFFER;
4993 goto out;
4996 if (!rpcbuf_alloc_size(buffer, *needed)) {
4997 result = WERR_NOMEM;
4998 goto out;
5001 /* fill the buffer with the structures */
5002 smb_io_printer_info_6("", buffer, printer, 0);
5004 out:
5005 /* clear memory */
5006 free_printer_info_6(printer);
5008 return result;
5011 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5013 PRINTER_INFO_7 *printer=NULL;
5014 WERROR result = WERR_OK;
5016 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5017 return WERR_NOMEM;
5019 if (!construct_printer_info_7(print_hnd, printer, snum)) {
5020 result = WERR_NOMEM;
5021 goto out;
5024 /* check the required size. */
5025 *needed += spoolss_size_printer_info_7(printer);
5027 if (*needed > offered) {
5028 result = WERR_INSUFFICIENT_BUFFER;
5029 goto out;
5032 if (!rpcbuf_alloc_size(buffer, *needed)) {
5033 result = WERR_NOMEM;
5034 goto out;
5038 /* fill the buffer with the structures */
5039 smb_io_printer_info_7("", buffer, printer, 0);
5041 out:
5042 /* clear memory */
5043 free_printer_info_7(printer);
5045 return result;
5048 /****************************************************************************
5049 ****************************************************************************/
5051 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5053 POLICY_HND *handle = &q_u->handle;
5054 uint32 level = q_u->level;
5055 RPC_BUFFER *buffer = NULL;
5056 uint32 offered = q_u->offered;
5057 uint32 *needed = &r_u->needed;
5058 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5060 int snum;
5062 /* that's an [in out] buffer */
5064 if (!q_u->buffer && (offered!=0)) {
5065 return WERR_INVALID_PARAM;
5068 if (offered > MAX_RPC_DATA_SIZE) {
5069 return WERR_INVALID_PARAM;
5072 rpcbuf_move(q_u->buffer, &r_u->buffer);
5073 buffer = r_u->buffer;
5075 *needed=0;
5077 if (!get_printer_snum(p, handle, &snum, NULL))
5078 return WERR_BADFID;
5080 switch (level) {
5081 case 0:
5082 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5083 case 1:
5084 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5085 case 2:
5086 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5087 case 3:
5088 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5089 case 4:
5090 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5091 case 5:
5092 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5093 case 6:
5094 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5095 case 7:
5096 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5098 return WERR_UNKNOWN_LEVEL;
5101 /********************************************************************
5102 * fill a DRIVER_INFO_1 struct
5103 ********************************************************************/
5105 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5107 init_unistr( &info->name, driver.info_3->name);
5110 /********************************************************************
5111 * construct_printer_driver_info_1
5112 ********************************************************************/
5114 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5116 NT_PRINTER_INFO_LEVEL *printer = NULL;
5117 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5119 ZERO_STRUCT(driver);
5121 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5122 return WERR_INVALID_PRINTER_NAME;
5124 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5125 free_a_printer(&printer, 2);
5126 return WERR_UNKNOWN_PRINTER_DRIVER;
5129 fill_printer_driver_info_1(info, driver, servername, architecture);
5131 free_a_printer(&printer,2);
5133 return WERR_OK;
5136 /********************************************************************
5137 * construct_printer_driver_info_2
5138 * fill a printer_info_2 struct
5139 ********************************************************************/
5141 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5143 TALLOC_CTX *ctx = talloc_tos();
5144 char *temp = NULL;
5145 const char *cservername = canon_servername(servername);
5147 info->version=driver.info_3->cversion;
5149 init_unistr( &info->name, driver.info_3->name );
5150 init_unistr( &info->architecture, driver.info_3->environment );
5152 if (strlen(driver.info_3->driverpath)) {
5153 temp = talloc_asprintf(ctx,
5154 "\\\\%s%s",
5155 cservername,
5156 driver.info_3->driverpath);
5157 init_unistr( &info->driverpath, temp );
5158 } else {
5159 init_unistr( &info->driverpath, "" );
5162 TALLOC_FREE(temp);
5163 if (strlen(driver.info_3->datafile)) {
5164 temp = talloc_asprintf(ctx,
5165 "\\\\%s%s",
5166 cservername,
5167 driver.info_3->datafile);
5168 init_unistr( &info->datafile, temp );
5169 } else
5170 init_unistr( &info->datafile, "" );
5172 TALLOC_FREE(temp);
5173 if (strlen(driver.info_3->configfile)) {
5174 temp = talloc_asprintf(ctx,
5175 "\\\\%s%s",
5176 cservername,
5177 driver.info_3->configfile);
5178 init_unistr( &info->configfile, temp );
5179 } else
5180 init_unistr( &info->configfile, "" );
5183 /********************************************************************
5184 * construct_printer_driver_info_2
5185 * fill a printer_info_2 struct
5186 ********************************************************************/
5188 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5190 NT_PRINTER_INFO_LEVEL *printer = NULL;
5191 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5193 ZERO_STRUCT(printer);
5194 ZERO_STRUCT(driver);
5196 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5197 return WERR_INVALID_PRINTER_NAME;
5199 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5200 free_a_printer(&printer, 2);
5201 return WERR_UNKNOWN_PRINTER_DRIVER;
5204 fill_printer_driver_info_2(info, driver, servername);
5206 free_a_printer(&printer,2);
5208 return WERR_OK;
5211 /********************************************************************
5212 * copy a strings array and convert to UNICODE
5214 * convert an array of ascii string to a UNICODE string
5215 ********************************************************************/
5217 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5219 int i=0;
5220 int j=0;
5221 const char *v;
5222 char *line = NULL;
5223 TALLOC_CTX *ctx = talloc_tos();
5225 DEBUG(6,("init_unistr_array\n"));
5226 *uni_array=NULL;
5228 while (true) {
5229 if ( !char_array ) {
5230 v = "";
5231 } else {
5232 v = char_array[i];
5233 if (!v)
5234 v = ""; /* hack to handle null lists */
5237 /* hack to allow this to be used in places other than when generating
5238 the list of dependent files */
5240 TALLOC_FREE(line);
5241 if ( servername ) {
5242 line = talloc_asprintf(ctx,
5243 "\\\\%s%s",
5244 canon_servername(servername),
5246 } else {
5247 line = talloc_strdup(ctx, v);
5250 if (!line) {
5251 SAFE_FREE(*uni_array);
5252 return 0;
5254 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5256 /* add one extra unit16 for the second terminating NULL */
5258 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5259 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5260 return 0;
5263 if ( !strlen(v) )
5264 break;
5266 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5267 i++;
5270 if (*uni_array) {
5271 /* special case for ""; we need to add both NULL's here */
5272 if (!j)
5273 (*uni_array)[j++]=0x0000;
5274 (*uni_array)[j]=0x0000;
5277 DEBUGADD(6,("last one:done\n"));
5279 /* return size of array in uint16's */
5281 return j+1;
5284 /********************************************************************
5285 * construct_printer_info_3
5286 * fill a printer_info_3 struct
5287 ********************************************************************/
5289 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5291 char *temp = NULL;
5292 TALLOC_CTX *ctx = talloc_tos();
5293 const char *cservername = canon_servername(servername);
5295 ZERO_STRUCTP(info);
5297 info->version=driver.info_3->cversion;
5299 init_unistr( &info->name, driver.info_3->name );
5300 init_unistr( &info->architecture, driver.info_3->environment );
5302 if (strlen(driver.info_3->driverpath)) {
5303 temp = talloc_asprintf(ctx,
5304 "\\\\%s%s",
5305 cservername,
5306 driver.info_3->driverpath);
5307 init_unistr( &info->driverpath, temp );
5308 } else
5309 init_unistr( &info->driverpath, "" );
5311 TALLOC_FREE(temp);
5312 if (strlen(driver.info_3->datafile)) {
5313 temp = talloc_asprintf(ctx,
5314 "\\\\%s%s",
5315 cservername,
5316 driver.info_3->datafile);
5317 init_unistr( &info->datafile, temp );
5318 } else
5319 init_unistr( &info->datafile, "" );
5321 TALLOC_FREE(temp);
5322 if (strlen(driver.info_3->configfile)) {
5323 temp = talloc_asprintf(ctx,
5324 "\\\\%s%s",
5325 cservername,
5326 driver.info_3->configfile);
5327 init_unistr( &info->configfile, temp );
5328 } else
5329 init_unistr( &info->configfile, "" );
5331 TALLOC_FREE(temp);
5332 if (strlen(driver.info_3->helpfile)) {
5333 temp = talloc_asprintf(ctx,
5334 "\\\\%s%s",
5335 cservername,
5336 driver.info_3->helpfile);
5337 init_unistr( &info->helpfile, temp );
5338 } else
5339 init_unistr( &info->helpfile, "" );
5341 TALLOC_FREE(temp);
5342 init_unistr( &info->monitorname, driver.info_3->monitorname );
5343 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5345 info->dependentfiles=NULL;
5346 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5349 /********************************************************************
5350 * construct_printer_info_3
5351 * fill a printer_info_3 struct
5352 ********************************************************************/
5354 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5356 NT_PRINTER_INFO_LEVEL *printer = NULL;
5357 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5358 WERROR status;
5359 ZERO_STRUCT(driver);
5361 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5362 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5363 if (!W_ERROR_IS_OK(status))
5364 return WERR_INVALID_PRINTER_NAME;
5366 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5367 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5369 #if 0 /* JERRY */
5372 * I put this code in during testing. Helpful when commenting out the
5373 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5374 * as win2k always queries the driver using an infor level of 6.
5375 * I've left it in (but ifdef'd out) because I'll probably
5376 * use it in experimentation again in the future. --jerry 22/01/2002
5379 if (!W_ERROR_IS_OK(status)) {
5381 * Is this a W2k client ?
5383 if (version == 3) {
5384 /* Yes - try again with a WinNT driver. */
5385 version = 2;
5386 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5387 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5389 #endif
5391 if (!W_ERROR_IS_OK(status)) {
5392 free_a_printer(&printer,2);
5393 return WERR_UNKNOWN_PRINTER_DRIVER;
5396 #if 0 /* JERRY */
5398 #endif
5401 fill_printer_driver_info_3(info, driver, servername);
5403 free_a_printer(&printer,2);
5405 return WERR_OK;
5408 /********************************************************************
5409 * construct_printer_info_6
5410 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5411 ********************************************************************/
5413 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5415 char *temp = NULL;
5416 fstring nullstr;
5417 TALLOC_CTX *ctx = talloc_tos();
5418 const char *cservername = canon_servername(servername);
5420 ZERO_STRUCTP(info);
5421 memset(&nullstr, '\0', sizeof(fstring));
5423 info->version=driver.info_3->cversion;
5425 init_unistr( &info->name, driver.info_3->name );
5426 init_unistr( &info->architecture, driver.info_3->environment );
5428 if (strlen(driver.info_3->driverpath)) {
5429 temp = talloc_asprintf(ctx,
5430 "\\\\%s%s",
5431 cservername,
5432 driver.info_3->driverpath);
5433 init_unistr( &info->driverpath, temp );
5434 } else
5435 init_unistr( &info->driverpath, "" );
5437 TALLOC_FREE(temp);
5438 if (strlen(driver.info_3->datafile)) {
5439 temp = talloc_asprintf(ctx,
5440 "\\\\%s%s",
5441 cservername,
5442 driver.info_3->datafile);
5443 init_unistr( &info->datafile, temp );
5444 } else
5445 init_unistr( &info->datafile, "" );
5447 TALLOC_FREE(temp);
5448 if (strlen(driver.info_3->configfile)) {
5449 temp = talloc_asprintf(ctx,
5450 "\\\\%s%s",
5451 cservername,
5452 driver.info_3->configfile);
5453 init_unistr( &info->configfile, temp );
5454 } else
5455 init_unistr( &info->configfile, "" );
5457 TALLOC_FREE(temp);
5458 if (strlen(driver.info_3->helpfile)) {
5459 temp = talloc_asprintf(ctx,
5460 "\\\\%s%s",
5461 cservername,
5462 driver.info_3->helpfile);
5463 init_unistr( &info->helpfile, temp );
5464 } else
5465 init_unistr( &info->helpfile, "" );
5467 TALLOC_FREE(temp);
5468 init_unistr( &info->monitorname, driver.info_3->monitorname );
5469 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5471 info->dependentfiles = NULL;
5472 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5474 info->previousdrivernames=NULL;
5475 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5477 info->driver_date=0;
5479 info->padding=0;
5480 info->driver_version_low=0;
5481 info->driver_version_high=0;
5483 init_unistr( &info->mfgname, "");
5484 init_unistr( &info->oem_url, "");
5485 init_unistr( &info->hardware_id, "");
5486 init_unistr( &info->provider, "");
5489 /********************************************************************
5490 * construct_printer_info_6
5491 * fill a printer_info_6 struct
5492 ********************************************************************/
5494 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5495 const char *servername, fstring architecture, uint32 version)
5497 NT_PRINTER_INFO_LEVEL *printer = NULL;
5498 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5499 WERROR status;
5501 ZERO_STRUCT(driver);
5503 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5505 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5507 if (!W_ERROR_IS_OK(status))
5508 return WERR_INVALID_PRINTER_NAME;
5510 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5512 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5514 if (!W_ERROR_IS_OK(status))
5517 * Is this a W2k client ?
5520 if (version < 3) {
5521 free_a_printer(&printer,2);
5522 return WERR_UNKNOWN_PRINTER_DRIVER;
5525 /* Yes - try again with a WinNT driver. */
5526 version = 2;
5527 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5528 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5529 if (!W_ERROR_IS_OK(status)) {
5530 free_a_printer(&printer,2);
5531 return WERR_UNKNOWN_PRINTER_DRIVER;
5535 fill_printer_driver_info_6(info, driver, servername);
5537 free_a_printer(&printer,2);
5538 free_a_printer_driver(driver, 3);
5540 return WERR_OK;
5543 /****************************************************************************
5544 ****************************************************************************/
5546 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5548 SAFE_FREE(info->dependentfiles);
5551 /****************************************************************************
5552 ****************************************************************************/
5554 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5556 SAFE_FREE(info->dependentfiles);
5559 /****************************************************************************
5560 ****************************************************************************/
5562 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5564 DRIVER_INFO_1 *info=NULL;
5565 WERROR result;
5567 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5568 return WERR_NOMEM;
5570 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5571 if (!W_ERROR_IS_OK(result))
5572 goto out;
5574 /* check the required size. */
5575 *needed += spoolss_size_printer_driver_info_1(info);
5577 if (*needed > offered) {
5578 result = WERR_INSUFFICIENT_BUFFER;
5579 goto out;
5582 if (!rpcbuf_alloc_size(buffer, *needed)) {
5583 result = WERR_NOMEM;
5584 goto out;
5587 /* fill the buffer with the structures */
5588 smb_io_printer_driver_info_1("", buffer, info, 0);
5590 out:
5591 /* clear memory */
5592 SAFE_FREE(info);
5594 return result;
5597 /****************************************************************************
5598 ****************************************************************************/
5600 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5602 DRIVER_INFO_2 *info=NULL;
5603 WERROR result;
5605 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5606 return WERR_NOMEM;
5608 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5609 if (!W_ERROR_IS_OK(result))
5610 goto out;
5612 /* check the required size. */
5613 *needed += spoolss_size_printer_driver_info_2(info);
5615 if (*needed > offered) {
5616 result = WERR_INSUFFICIENT_BUFFER;
5617 goto out;
5620 if (!rpcbuf_alloc_size(buffer, *needed)) {
5621 result = WERR_NOMEM;
5622 goto out;
5625 /* fill the buffer with the structures */
5626 smb_io_printer_driver_info_2("", buffer, info, 0);
5628 out:
5629 /* clear memory */
5630 SAFE_FREE(info);
5632 return result;
5635 /****************************************************************************
5636 ****************************************************************************/
5638 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5640 DRIVER_INFO_3 info;
5641 WERROR result;
5643 ZERO_STRUCT(info);
5645 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5646 if (!W_ERROR_IS_OK(result))
5647 goto out;
5649 /* check the required size. */
5650 *needed += spoolss_size_printer_driver_info_3(&info);
5652 if (*needed > offered) {
5653 result = WERR_INSUFFICIENT_BUFFER;
5654 goto out;
5657 if (!rpcbuf_alloc_size(buffer, *needed)) {
5658 result = WERR_NOMEM;
5659 goto out;
5662 /* fill the buffer with the structures */
5663 smb_io_printer_driver_info_3("", buffer, &info, 0);
5665 out:
5666 free_printer_driver_info_3(&info);
5668 return result;
5671 /****************************************************************************
5672 ****************************************************************************/
5674 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5676 DRIVER_INFO_6 info;
5677 WERROR result;
5679 ZERO_STRUCT(info);
5681 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5682 if (!W_ERROR_IS_OK(result))
5683 goto out;
5685 /* check the required size. */
5686 *needed += spoolss_size_printer_driver_info_6(&info);
5688 if (*needed > offered) {
5689 result = WERR_INSUFFICIENT_BUFFER;
5690 goto out;
5693 if (!rpcbuf_alloc_size(buffer, *needed)) {
5694 result = WERR_NOMEM;
5695 goto out;
5698 /* fill the buffer with the structures */
5699 smb_io_printer_driver_info_6("", buffer, &info, 0);
5701 out:
5702 free_printer_driver_info_6(&info);
5704 return result;
5707 /****************************************************************************
5708 ****************************************************************************/
5710 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5712 POLICY_HND *handle = &q_u->handle;
5713 UNISTR2 *uni_arch = &q_u->architecture;
5714 uint32 level = q_u->level;
5715 uint32 clientmajorversion = q_u->clientmajorversion;
5716 RPC_BUFFER *buffer = NULL;
5717 uint32 offered = q_u->offered;
5718 uint32 *needed = &r_u->needed;
5719 uint32 *servermajorversion = &r_u->servermajorversion;
5720 uint32 *serverminorversion = &r_u->serverminorversion;
5721 Printer_entry *printer;
5723 fstring servername;
5724 fstring architecture;
5725 int snum;
5727 /* that's an [in out] buffer */
5729 if (!q_u->buffer && (offered!=0)) {
5730 return WERR_INVALID_PARAM;
5733 if (offered > MAX_RPC_DATA_SIZE) {
5734 return WERR_INVALID_PARAM;
5737 rpcbuf_move(q_u->buffer, &r_u->buffer);
5738 buffer = r_u->buffer;
5740 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5742 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5743 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5744 return WERR_INVALID_PRINTER_NAME;
5747 *needed = 0;
5748 *servermajorversion = 0;
5749 *serverminorversion = 0;
5751 fstrcpy(servername, get_server_name( printer ));
5752 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5754 if (!get_printer_snum(p, handle, &snum, NULL))
5755 return WERR_BADFID;
5757 switch (level) {
5758 case 1:
5759 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5760 case 2:
5761 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5762 case 3:
5763 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5764 case 6:
5765 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5766 #if 0 /* JERRY */
5767 case 101:
5768 /* apparently this call is the equivalent of
5769 EnumPrinterDataEx() for the DsDriver key */
5770 break;
5771 #endif
5774 return WERR_UNKNOWN_LEVEL;
5778 /****************************************************************
5779 _spoolss_StartPagePrinter
5780 ****************************************************************/
5782 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5783 struct spoolss_StartPagePrinter *r)
5785 POLICY_HND *handle = r->in.handle;
5787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5789 if (!Printer) {
5790 DEBUG(3,("_spoolss_StartPagePrinter: "
5791 "Error in startpageprinter printer handle\n"));
5792 return WERR_BADFID;
5795 Printer->page_started=True;
5796 return WERR_OK;
5799 /****************************************************************
5800 _spoolss_EndPagePrinter
5801 ****************************************************************/
5803 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5804 struct spoolss_EndPagePrinter *r)
5806 POLICY_HND *handle = r->in.handle;
5807 int snum;
5809 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5811 if (!Printer) {
5812 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5813 OUR_HANDLE(handle)));
5814 return WERR_BADFID;
5817 if (!get_printer_snum(p, handle, &snum, NULL))
5818 return WERR_BADFID;
5820 Printer->page_started=False;
5821 print_job_endpage(snum, Printer->jobid);
5823 return WERR_OK;
5826 /****************************************************************
5827 _spoolss_StartDocPrinter
5828 ****************************************************************/
5830 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5831 struct spoolss_StartDocPrinter *r)
5833 POLICY_HND *handle = r->in.handle;
5834 uint32_t *jobid = r->out.job_id;
5835 struct spoolss_DocumentInfo1 *info_1;
5836 int snum;
5837 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5839 if (!Printer) {
5840 DEBUG(2,("_spoolss_StartDocPrinter: "
5841 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5842 return WERR_BADFID;
5845 if (r->in.level != 1) {
5846 return WERR_UNKNOWN_LEVEL;
5849 info_1 = r->in.info.info1;
5852 * a nice thing with NT is it doesn't listen to what you tell it.
5853 * when asked to send _only_ RAW datas, it tries to send datas
5854 * in EMF format.
5856 * So I add checks like in NT Server ...
5859 if (info_1->datatype) {
5860 if (strcmp(info_1->datatype, "RAW") != 0) {
5861 (*jobid)=0;
5862 return WERR_INVALID_DATATYPE;
5866 /* get the share number of the printer */
5867 if (!get_printer_snum(p, handle, &snum, NULL)) {
5868 return WERR_BADFID;
5871 Printer->jobid = print_job_start(p->server_info, snum,
5872 CONST_DISCARD(char *,info_1->document_name),
5873 Printer->nt_devmode);
5875 /* An error occured in print_job_start() so return an appropriate
5876 NT error code. */
5878 if (Printer->jobid == -1) {
5879 return map_werror_from_unix(errno);
5882 Printer->document_started=True;
5883 (*jobid) = Printer->jobid;
5885 return WERR_OK;
5888 /****************************************************************
5889 _spoolss_EndDocPrinter
5890 ****************************************************************/
5892 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5893 struct spoolss_EndDocPrinter *r)
5895 POLICY_HND *handle = r->in.handle;
5897 return _spoolss_enddocprinter_internal(p, handle);
5900 /****************************************************************
5901 _spoolss_WritePrinter
5902 ****************************************************************/
5904 WERROR _spoolss_WritePrinter(pipes_struct *p,
5905 struct spoolss_WritePrinter *r)
5907 POLICY_HND *handle = r->in.handle;
5908 uint32 buffer_size = r->in._data_size;
5909 uint8 *buffer = r->in.data.data;
5910 uint32 *buffer_written = &r->in._data_size;
5911 int snum;
5912 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5914 if (!Printer) {
5915 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5916 OUR_HANDLE(handle)));
5917 *r->out.num_written = r->in._data_size;
5918 return WERR_BADFID;
5921 if (!get_printer_snum(p, handle, &snum, NULL))
5922 return WERR_BADFID;
5924 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5925 (SMB_OFF_T)-1, (size_t)buffer_size);
5926 if (*buffer_written == (uint32)-1) {
5927 *r->out.num_written = 0;
5928 if (errno == ENOSPC)
5929 return WERR_NO_SPOOL_SPACE;
5930 else
5931 return WERR_ACCESS_DENIED;
5934 *r->out.num_written = r->in._data_size;
5936 return WERR_OK;
5939 /********************************************************************
5940 * api_spoolss_getprinter
5941 * called from the spoolss dispatcher
5943 ********************************************************************/
5945 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5946 pipes_struct *p)
5948 int snum;
5949 WERROR errcode = WERR_BADFUNC;
5950 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5952 if (!Printer) {
5953 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5954 return WERR_BADFID;
5957 if (!get_printer_snum(p, handle, &snum, NULL))
5958 return WERR_BADFID;
5960 switch (command) {
5961 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5962 if (print_queue_pause(p->server_info, snum, &errcode)) {
5963 errcode = WERR_OK;
5965 break;
5966 case SPOOLSS_PRINTER_CONTROL_RESUME:
5967 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5968 if (print_queue_resume(p->server_info, snum, &errcode)) {
5969 errcode = WERR_OK;
5971 break;
5972 case SPOOLSS_PRINTER_CONTROL_PURGE:
5973 if (print_queue_purge(p->server_info, snum, &errcode)) {
5974 errcode = WERR_OK;
5976 break;
5977 default:
5978 return WERR_UNKNOWN_LEVEL;
5981 return errcode;
5985 /****************************************************************
5986 _spoolss_AbortPrinter
5987 * From MSDN: "Deletes printer's spool file if printer is configured
5988 * for spooling"
5989 ****************************************************************/
5991 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5992 struct spoolss_AbortPrinter *r)
5994 POLICY_HND *handle = r->in.handle;
5995 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5996 int snum;
5997 WERROR errcode = WERR_OK;
5999 if (!Printer) {
6000 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6001 OUR_HANDLE(handle)));
6002 return WERR_BADFID;
6005 if (!get_printer_snum(p, handle, &snum, NULL))
6006 return WERR_BADFID;
6008 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6010 return errcode;
6013 /********************************************************************
6014 * called by spoolss_api_setprinter
6015 * when updating a printer description
6016 ********************************************************************/
6018 static WERROR update_printer_sec(POLICY_HND *handle,
6019 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6021 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6022 WERROR result;
6023 int snum;
6025 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6027 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6028 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6029 OUR_HANDLE(handle)));
6031 result = WERR_BADFID;
6032 goto done;
6035 if (!secdesc_ctr) {
6036 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6037 result = WERR_INVALID_PARAM;
6038 goto done;
6041 /* Check the user has permissions to change the security
6042 descriptor. By experimentation with two NT machines, the user
6043 requires Full Access to the printer to change security
6044 information. */
6046 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6047 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6048 result = WERR_ACCESS_DENIED;
6049 goto done;
6052 /* NT seems to like setting the security descriptor even though
6053 nothing may have actually changed. */
6055 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6056 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6057 result = WERR_BADFID;
6058 goto done;
6061 if (DEBUGLEVEL >= 10) {
6062 SEC_ACL *the_acl;
6063 int i;
6065 the_acl = old_secdesc_ctr->sd->dacl;
6066 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6067 PRINTERNAME(snum), the_acl->num_aces));
6069 for (i = 0; i < the_acl->num_aces; i++) {
6070 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6071 &the_acl->aces[i].trustee),
6072 the_acl->aces[i].access_mask));
6075 the_acl = secdesc_ctr->sd->dacl;
6077 if (the_acl) {
6078 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6079 PRINTERNAME(snum), the_acl->num_aces));
6081 for (i = 0; i < the_acl->num_aces; i++) {
6082 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6083 &the_acl->aces[i].trustee),
6084 the_acl->aces[i].access_mask));
6086 } else {
6087 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6091 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6092 if (!new_secdesc_ctr) {
6093 result = WERR_NOMEM;
6094 goto done;
6097 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6098 result = WERR_OK;
6099 goto done;
6102 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6104 done:
6106 return result;
6109 /********************************************************************
6110 Canonicalize printer info from a client
6112 ATTN: It does not matter what we set the servername to hear
6113 since we do the necessary work in get_a_printer() to set it to
6114 the correct value based on what the client sent in the
6115 _spoolss_open_printer_ex().
6116 ********************************************************************/
6118 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6120 fstring printername;
6121 const char *p;
6123 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6124 "portname=%s drivername=%s comment=%s location=%s\n",
6125 info->servername, info->printername, info->sharename,
6126 info->portname, info->drivername, info->comment, info->location));
6128 /* we force some elements to "correct" values */
6129 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6130 fstrcpy(info->sharename, lp_servicename(snum));
6132 /* check to see if we allow printername != sharename */
6134 if ( lp_force_printername(snum) ) {
6135 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6136 global_myname(), info->sharename );
6137 } else {
6139 /* make sure printername is in \\server\printername format */
6141 fstrcpy( printername, info->printername );
6142 p = printername;
6143 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6144 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6145 p++;
6148 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6149 global_myname(), p );
6152 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6153 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6157 return True;
6160 /****************************************************************************
6161 ****************************************************************************/
6163 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6165 char *cmd = lp_addport_cmd();
6166 char *command = NULL;
6167 int ret;
6168 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6169 bool is_print_op = False;
6171 if ( !*cmd ) {
6172 return WERR_ACCESS_DENIED;
6175 command = talloc_asprintf(ctx,
6176 "%s \"%s\" \"%s\"", cmd, portname, uri );
6177 if (!command) {
6178 return WERR_NOMEM;
6181 if ( token )
6182 is_print_op = user_has_privileges( token, &se_printop );
6184 DEBUG(10,("Running [%s]\n", command));
6186 /********* BEGIN SePrintOperatorPrivilege **********/
6188 if ( is_print_op )
6189 become_root();
6191 ret = smbrun(command, NULL);
6193 if ( is_print_op )
6194 unbecome_root();
6196 /********* END SePrintOperatorPrivilege **********/
6198 DEBUGADD(10,("returned [%d]\n", ret));
6200 TALLOC_FREE(command);
6202 if ( ret != 0 ) {
6203 return WERR_ACCESS_DENIED;
6206 return WERR_OK;
6209 /****************************************************************************
6210 ****************************************************************************/
6212 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6214 char *cmd = lp_addprinter_cmd();
6215 char **qlines;
6216 char *command = NULL;
6217 int numlines;
6218 int ret;
6219 int fd;
6220 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6221 bool is_print_op = False;
6222 char *remote_machine = talloc_strdup(ctx, "%m");
6224 if (!remote_machine) {
6225 return false;
6227 remote_machine = talloc_sub_basic(ctx,
6228 current_user_info.smb_name,
6229 current_user_info.domain,
6230 remote_machine);
6231 if (!remote_machine) {
6232 return false;
6235 command = talloc_asprintf(ctx,
6236 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6237 cmd, printer->info_2->printername, printer->info_2->sharename,
6238 printer->info_2->portname, printer->info_2->drivername,
6239 printer->info_2->location, printer->info_2->comment, remote_machine);
6240 if (!command) {
6241 return false;
6244 if ( token )
6245 is_print_op = user_has_privileges( token, &se_printop );
6247 DEBUG(10,("Running [%s]\n", command));
6249 /********* BEGIN SePrintOperatorPrivilege **********/
6251 if ( is_print_op )
6252 become_root();
6254 if ( (ret = smbrun(command, &fd)) == 0 ) {
6255 /* Tell everyone we updated smb.conf. */
6256 message_send_all(smbd_messaging_context(),
6257 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6260 if ( is_print_op )
6261 unbecome_root();
6263 /********* END SePrintOperatorPrivilege **********/
6265 DEBUGADD(10,("returned [%d]\n", ret));
6267 TALLOC_FREE(command);
6268 TALLOC_FREE(remote_machine);
6270 if ( ret != 0 ) {
6271 if (fd != -1)
6272 close(fd);
6273 return False;
6276 /* reload our services immediately */
6277 reload_services( False );
6279 numlines = 0;
6280 /* Get lines and convert them back to dos-codepage */
6281 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6282 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6283 close(fd);
6285 /* Set the portname to what the script says the portname should be. */
6286 /* but don't require anything to be return from the script exit a good error code */
6288 if (numlines) {
6289 /* Set the portname to what the script says the portname should be. */
6290 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6291 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6294 TALLOC_FREE(qlines);
6295 return True;
6299 /********************************************************************
6300 * Called by spoolss_api_setprinter
6301 * when updating a printer description.
6302 ********************************************************************/
6304 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6305 struct spoolss_SetPrinterInfoCtr *info_ctr,
6306 struct spoolss_DeviceMode *devmode)
6308 int snum;
6309 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6310 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6311 WERROR result;
6312 UNISTR2 buffer;
6313 fstring asc_buffer;
6315 DEBUG(8,("update_printer\n"));
6317 result = WERR_OK;
6319 if (!Printer) {
6320 result = WERR_BADFID;
6321 goto done;
6324 if (!get_printer_snum(p, handle, &snum, NULL)) {
6325 result = WERR_BADFID;
6326 goto done;
6329 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6330 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6331 result = WERR_BADFID;
6332 goto done;
6335 DEBUGADD(8,("Converting info_2 struct\n"));
6338 * convert_printer_info converts the incoming
6339 * info from the client and overwrites the info
6340 * just read from the tdb in the pointer 'printer'.
6343 if (!convert_printer_info_new(info_ctr, printer)) {
6344 result = WERR_NOMEM;
6345 goto done;
6348 if (devmode) {
6349 /* we have a valid devmode
6350 convert it and link it*/
6352 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6353 if (!convert_devicemode_new(printer->info_2->printername,
6354 devmode,
6355 &printer->info_2->devmode)) {
6356 result = WERR_NOMEM;
6357 goto done;
6361 /* Do sanity check on the requested changes for Samba */
6363 if (!check_printer_ok(printer->info_2, snum)) {
6364 result = WERR_INVALID_PARAM;
6365 goto done;
6368 /* FIXME!!! If the driver has changed we really should verify that
6369 it is installed before doing much else --jerry */
6371 /* Check calling user has permission to update printer description */
6373 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6374 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6375 result = WERR_ACCESS_DENIED;
6376 goto done;
6379 /* Call addprinter hook */
6380 /* Check changes to see if this is really needed */
6382 if ( *lp_addprinter_cmd()
6383 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6384 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6385 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6386 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6388 /* add_printer_hook() will call reload_services() */
6390 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6391 printer) ) {
6392 result = WERR_ACCESS_DENIED;
6393 goto done;
6398 * When a *new* driver is bound to a printer, the drivername is used to
6399 * lookup previously saved driver initialization info, which is then
6400 * bound to the printer, simulating what happens in the Windows arch.
6402 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6404 if (!set_driver_init(printer, 2))
6406 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6407 printer->info_2->drivername));
6410 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6411 printer->info_2->drivername));
6413 notify_printer_driver(snum, printer->info_2->drivername);
6417 * flag which changes actually occured. This is a small subset of
6418 * all the possible changes. We also have to update things in the
6419 * DsSpooler key.
6422 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6423 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6424 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6425 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6427 notify_printer_comment(snum, printer->info_2->comment);
6430 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6431 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6432 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6433 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6435 notify_printer_sharename(snum, printer->info_2->sharename);
6438 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6439 char *pname;
6441 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6442 pname++;
6443 else
6444 pname = printer->info_2->printername;
6447 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6448 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6449 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6451 notify_printer_printername( snum, pname );
6454 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6455 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6456 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6457 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6459 notify_printer_port(snum, printer->info_2->portname);
6462 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6463 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6464 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6465 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6467 notify_printer_location(snum, printer->info_2->location);
6470 /* here we need to update some more DsSpooler keys */
6471 /* uNCName, serverName, shortServerName */
6473 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6474 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6475 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6476 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6477 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6479 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6480 global_myname(), printer->info_2->sharename );
6481 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6482 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6483 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6485 /* Update printer info */
6486 result = mod_a_printer(printer, 2);
6488 done:
6489 free_a_printer(&printer, 2);
6490 free_a_printer(&old_printer, 2);
6493 return result;
6496 /****************************************************************************
6497 ****************************************************************************/
6498 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6499 struct spoolss_SetPrinterInfo7 *info7)
6501 #ifdef HAVE_ADS
6502 int snum;
6503 Printer_entry *Printer;
6505 if ( lp_security() != SEC_ADS ) {
6506 return WERR_UNKNOWN_LEVEL;
6509 Printer = find_printer_index_by_hnd(p, handle);
6511 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6513 if (!Printer)
6514 return WERR_BADFID;
6516 if (!get_printer_snum(p, handle, &snum, NULL))
6517 return WERR_BADFID;
6519 nt_printer_publish(Printer, snum, info7->action);
6521 return WERR_OK;
6522 #else
6523 return WERR_UNKNOWN_LEVEL;
6524 #endif
6527 /****************************************************************
6528 _spoolss_SetPrinter
6529 ****************************************************************/
6531 WERROR _spoolss_SetPrinter(pipes_struct *p,
6532 struct spoolss_SetPrinter *r)
6534 POLICY_HND *handle = r->in.handle;
6535 WERROR result;
6537 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6539 if (!Printer) {
6540 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6541 OUR_HANDLE(handle)));
6542 return WERR_BADFID;
6545 /* check the level */
6546 switch (r->in.info_ctr->level) {
6547 case 0:
6548 return control_printer(handle, r->in.command, p);
6549 case 2:
6550 result = update_printer(p, handle,
6551 r->in.info_ctr,
6552 r->in.devmode_ctr->devmode);
6553 if (!W_ERROR_IS_OK(result))
6554 return result;
6555 if (r->in.secdesc_ctr->sd)
6556 result = update_printer_sec(handle, p,
6557 r->in.secdesc_ctr);
6558 return result;
6559 case 3:
6560 return update_printer_sec(handle, p,
6561 r->in.secdesc_ctr);
6562 case 7:
6563 return publish_or_unpublish_printer(p, handle,
6564 r->in.info_ctr->info.info7);
6565 default:
6566 return WERR_UNKNOWN_LEVEL;
6570 /****************************************************************
6571 _spoolss_FindClosePrinterNotify
6572 ****************************************************************/
6574 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6575 struct spoolss_FindClosePrinterNotify *r)
6577 POLICY_HND *handle = r->in.handle;
6578 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6580 if (!Printer) {
6581 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6582 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6583 return WERR_BADFID;
6586 if (Printer->notify.client_connected==True) {
6587 int snum = -1;
6589 if ( Printer->printer_type == SPLHND_SERVER)
6590 snum = -1;
6591 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6592 !get_printer_snum(p, handle, &snum, NULL) )
6593 return WERR_BADFID;
6595 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6598 Printer->notify.flags=0;
6599 Printer->notify.options=0;
6600 Printer->notify.localmachine[0]='\0';
6601 Printer->notify.printerlocal=0;
6602 TALLOC_FREE(Printer->notify.option);
6603 Printer->notify.client_connected=False;
6605 return WERR_OK;
6608 /****************************************************************
6609 _spoolss_AddJob
6610 ****************************************************************/
6612 WERROR _spoolss_AddJob(pipes_struct *p,
6613 struct spoolss_AddJob *r)
6615 if (!r->in.buffer && (r->in.offered != 0)) {
6616 return WERR_INVALID_PARAM;
6619 /* this is what a NT server returns for AddJob. AddJob must fail on
6620 * non-local printers */
6622 return WERR_INVALID_PARAM;
6625 /****************************************************************************
6626 ****************************************************************************/
6628 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6629 int position, int snum,
6630 const NT_PRINTER_INFO_LEVEL *ntprinter)
6632 struct tm *t;
6634 t=gmtime(&queue->time);
6636 job_info->jobid=queue->job;
6637 init_unistr(&job_info->printername, lp_servicename(snum));
6638 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6639 init_unistr(&job_info->username, queue->fs_user);
6640 init_unistr(&job_info->document, queue->fs_file);
6641 init_unistr(&job_info->datatype, "RAW");
6642 init_unistr(&job_info->text_status, "");
6643 job_info->status=nt_printj_status(queue->status);
6644 job_info->priority=queue->priority;
6645 job_info->position=position;
6646 job_info->totalpages=queue->page_count;
6647 job_info->pagesprinted=0;
6649 make_systemtime(&job_info->submitted, t);
6652 /****************************************************************************
6653 ****************************************************************************/
6655 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6656 int position, int snum,
6657 const NT_PRINTER_INFO_LEVEL *ntprinter,
6658 DEVICEMODE *devmode)
6660 struct tm *t;
6662 t=gmtime(&queue->time);
6664 job_info->jobid=queue->job;
6666 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6668 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6669 init_unistr(&job_info->username, queue->fs_user);
6670 init_unistr(&job_info->document, queue->fs_file);
6671 init_unistr(&job_info->notifyname, queue->fs_user);
6672 init_unistr(&job_info->datatype, "RAW");
6673 init_unistr(&job_info->printprocessor, "winprint");
6674 init_unistr(&job_info->parameters, "");
6675 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6676 init_unistr(&job_info->text_status, "");
6678 /* and here the security descriptor */
6680 job_info->status=nt_printj_status(queue->status);
6681 job_info->priority=queue->priority;
6682 job_info->position=position;
6683 job_info->starttime=0;
6684 job_info->untiltime=0;
6685 job_info->totalpages=queue->page_count;
6686 job_info->size=queue->size;
6687 make_systemtime(&(job_info->submitted), t);
6688 job_info->timeelapsed=0;
6689 job_info->pagesprinted=0;
6691 job_info->devmode = devmode;
6693 return (True);
6696 /****************************************************************************
6697 Enumjobs at level 1.
6698 ****************************************************************************/
6700 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6701 const NT_PRINTER_INFO_LEVEL *ntprinter,
6702 RPC_BUFFER *buffer, uint32 offered,
6703 uint32 *needed, uint32 *returned)
6705 JOB_INFO_1 *info;
6706 int i;
6707 WERROR result = WERR_OK;
6709 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6710 if (info==NULL) {
6711 *returned=0;
6712 return WERR_NOMEM;
6715 for (i=0; i<*returned; i++)
6716 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6718 /* check the required size. */
6719 for (i=0; i<*returned; i++)
6720 (*needed) += spoolss_size_job_info_1(&info[i]);
6722 if (*needed > offered) {
6723 result = WERR_INSUFFICIENT_BUFFER;
6724 goto out;
6727 if (!rpcbuf_alloc_size(buffer, *needed)) {
6728 result = WERR_NOMEM;
6729 goto out;
6732 /* fill the buffer with the structures */
6733 for (i=0; i<*returned; i++)
6734 smb_io_job_info_1("", buffer, &info[i], 0);
6736 out:
6737 /* clear memory */
6738 SAFE_FREE(info);
6740 if ( !W_ERROR_IS_OK(result) )
6741 *returned = 0;
6743 return result;
6746 /****************************************************************************
6747 Enumjobs at level 2.
6748 ****************************************************************************/
6750 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6751 const NT_PRINTER_INFO_LEVEL *ntprinter,
6752 RPC_BUFFER *buffer, uint32 offered,
6753 uint32 *needed, uint32 *returned)
6755 JOB_INFO_2 *info = NULL;
6756 int i;
6757 WERROR result = WERR_OK;
6758 DEVICEMODE *devmode = NULL;
6760 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6761 *returned=0;
6762 return WERR_NOMEM;
6765 /* this should not be a failure condition if the devmode is NULL */
6767 devmode = construct_dev_mode(lp_const_servicename(snum));
6769 for (i=0; i<*returned; i++)
6770 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6772 /* check the required size. */
6773 for (i=0; i<*returned; i++)
6774 (*needed) += spoolss_size_job_info_2(&info[i]);
6776 if (*needed > offered) {
6777 result = WERR_INSUFFICIENT_BUFFER;
6778 goto out;
6781 if (!rpcbuf_alloc_size(buffer, *needed)) {
6782 result = WERR_NOMEM;
6783 goto out;
6786 /* fill the buffer with the structures */
6787 for (i=0; i<*returned; i++)
6788 smb_io_job_info_2("", buffer, &info[i], 0);
6790 out:
6791 free_devmode(devmode);
6792 SAFE_FREE(info);
6794 if ( !W_ERROR_IS_OK(result) )
6795 *returned = 0;
6797 return result;
6801 /****************************************************************************
6802 Enumjobs.
6803 ****************************************************************************/
6805 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6807 POLICY_HND *handle = &q_u->handle;
6808 uint32 level = q_u->level;
6809 RPC_BUFFER *buffer = NULL;
6810 uint32 offered = q_u->offered;
6811 uint32 *needed = &r_u->needed;
6812 uint32 *returned = &r_u->returned;
6813 WERROR wret;
6814 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6815 int snum;
6816 print_status_struct prt_status;
6817 print_queue_struct *queue=NULL;
6819 /* that's an [in out] buffer */
6821 if (!q_u->buffer && (offered!=0)) {
6822 return WERR_INVALID_PARAM;
6825 if (offered > MAX_RPC_DATA_SIZE) {
6826 return WERR_INVALID_PARAM;
6829 rpcbuf_move(q_u->buffer, &r_u->buffer);
6830 buffer = r_u->buffer;
6832 DEBUG(4,("_spoolss_enumjobs\n"));
6834 *needed=0;
6835 *returned=0;
6837 /* lookup the printer snum and tdb entry */
6839 if (!get_printer_snum(p, handle, &snum, NULL))
6840 return WERR_BADFID;
6842 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6843 if ( !W_ERROR_IS_OK(wret) )
6844 return wret;
6846 *returned = print_queue_status(snum, &queue, &prt_status);
6847 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6849 if (*returned == 0) {
6850 SAFE_FREE(queue);
6851 free_a_printer(&ntprinter, 2);
6852 return WERR_OK;
6855 switch (level) {
6856 case 1:
6857 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6858 break;
6859 case 2:
6860 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6861 break;
6862 default:
6863 *returned=0;
6864 wret = WERR_UNKNOWN_LEVEL;
6865 break;
6868 SAFE_FREE(queue);
6869 free_a_printer( &ntprinter, 2 );
6870 return wret;
6873 /****************************************************************
6874 _spoolss_ScheduleJob
6875 ****************************************************************/
6877 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6878 struct spoolss_ScheduleJob *r)
6880 return WERR_OK;
6883 /****************************************************************
6884 _spoolss_SetJob
6885 ****************************************************************/
6887 WERROR _spoolss_SetJob(pipes_struct *p,
6888 struct spoolss_SetJob *r)
6890 POLICY_HND *handle = r->in.handle;
6891 uint32 jobid = r->in.job_id;
6892 uint32 command = r->in.command;
6894 int snum;
6895 WERROR errcode = WERR_BADFUNC;
6897 if (!get_printer_snum(p, handle, &snum, NULL)) {
6898 return WERR_BADFID;
6901 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6902 return WERR_INVALID_PRINTER_NAME;
6905 switch (command) {
6906 case SPOOLSS_JOB_CONTROL_CANCEL:
6907 case SPOOLSS_JOB_CONTROL_DELETE:
6908 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6909 errcode = WERR_OK;
6911 break;
6912 case SPOOLSS_JOB_CONTROL_PAUSE:
6913 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6914 errcode = WERR_OK;
6916 break;
6917 case SPOOLSS_JOB_CONTROL_RESTART:
6918 case SPOOLSS_JOB_CONTROL_RESUME:
6919 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6920 errcode = WERR_OK;
6922 break;
6923 default:
6924 return WERR_UNKNOWN_LEVEL;
6927 return errcode;
6930 /****************************************************************************
6931 Enumerates all printer drivers at level 1.
6932 ****************************************************************************/
6934 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6936 int i;
6937 int ndrivers;
6938 uint32 version;
6939 fstring *list = NULL;
6940 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6941 DRIVER_INFO_1 *driver_info_1=NULL;
6942 WERROR result = WERR_OK;
6944 *returned=0;
6946 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6947 list=NULL;
6948 ndrivers=get_ntdrivers(&list, architecture, version);
6949 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6951 if(ndrivers == -1) {
6952 SAFE_FREE(driver_info_1);
6953 return WERR_NOMEM;
6956 if(ndrivers != 0) {
6957 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6958 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6959 SAFE_FREE(list);
6960 return WERR_NOMEM;
6964 for (i=0; i<ndrivers; i++) {
6965 WERROR status;
6966 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6967 ZERO_STRUCT(driver);
6968 status = get_a_printer_driver(&driver, 3, list[i],
6969 architecture, version);
6970 if (!W_ERROR_IS_OK(status)) {
6971 SAFE_FREE(list);
6972 SAFE_FREE(driver_info_1);
6973 return status;
6975 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6976 free_a_printer_driver(driver, 3);
6979 *returned+=ndrivers;
6980 SAFE_FREE(list);
6983 /* check the required size. */
6984 for (i=0; i<*returned; i++) {
6985 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6986 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6989 if (*needed > offered) {
6990 result = WERR_INSUFFICIENT_BUFFER;
6991 goto out;
6994 if (!rpcbuf_alloc_size(buffer, *needed)) {
6995 result = WERR_NOMEM;
6996 goto out;
6999 /* fill the buffer with the driver structures */
7000 for (i=0; i<*returned; i++) {
7001 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7002 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7005 out:
7006 SAFE_FREE(driver_info_1);
7008 if ( !W_ERROR_IS_OK(result) )
7009 *returned = 0;
7011 return result;
7014 /****************************************************************************
7015 Enumerates all printer drivers at level 2.
7016 ****************************************************************************/
7018 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7020 int i;
7021 int ndrivers;
7022 uint32 version;
7023 fstring *list = NULL;
7024 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7025 DRIVER_INFO_2 *driver_info_2=NULL;
7026 WERROR result = WERR_OK;
7028 *returned=0;
7030 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7031 list=NULL;
7032 ndrivers=get_ntdrivers(&list, architecture, version);
7033 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7035 if(ndrivers == -1) {
7036 SAFE_FREE(driver_info_2);
7037 return WERR_NOMEM;
7040 if(ndrivers != 0) {
7041 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7042 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7043 SAFE_FREE(list);
7044 return WERR_NOMEM;
7048 for (i=0; i<ndrivers; i++) {
7049 WERROR status;
7051 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7052 ZERO_STRUCT(driver);
7053 status = get_a_printer_driver(&driver, 3, list[i],
7054 architecture, version);
7055 if (!W_ERROR_IS_OK(status)) {
7056 SAFE_FREE(list);
7057 SAFE_FREE(driver_info_2);
7058 return status;
7060 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7061 free_a_printer_driver(driver, 3);
7064 *returned+=ndrivers;
7065 SAFE_FREE(list);
7068 /* check the required size. */
7069 for (i=0; i<*returned; i++) {
7070 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7071 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7074 if (*needed > offered) {
7075 result = WERR_INSUFFICIENT_BUFFER;
7076 goto out;
7079 if (!rpcbuf_alloc_size(buffer, *needed)) {
7080 result = WERR_NOMEM;
7081 goto out;
7084 /* fill the buffer with the form structures */
7085 for (i=0; i<*returned; i++) {
7086 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7087 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7090 out:
7091 SAFE_FREE(driver_info_2);
7093 if ( !W_ERROR_IS_OK(result) )
7094 *returned = 0;
7096 return result;
7099 /****************************************************************************
7100 Enumerates all printer drivers at level 3.
7101 ****************************************************************************/
7103 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7105 int i;
7106 int ndrivers;
7107 uint32 version;
7108 fstring *list = NULL;
7109 DRIVER_INFO_3 *driver_info_3=NULL;
7110 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7111 WERROR result = WERR_OK;
7113 *returned=0;
7115 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7116 list=NULL;
7117 ndrivers=get_ntdrivers(&list, architecture, version);
7118 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7120 if(ndrivers == -1) {
7121 SAFE_FREE(driver_info_3);
7122 return WERR_NOMEM;
7125 if(ndrivers != 0) {
7126 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7127 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7128 SAFE_FREE(list);
7129 return WERR_NOMEM;
7133 for (i=0; i<ndrivers; i++) {
7134 WERROR status;
7136 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7137 ZERO_STRUCT(driver);
7138 status = get_a_printer_driver(&driver, 3, list[i],
7139 architecture, version);
7140 if (!W_ERROR_IS_OK(status)) {
7141 SAFE_FREE(list);
7142 SAFE_FREE(driver_info_3);
7143 return status;
7145 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7146 free_a_printer_driver(driver, 3);
7149 *returned+=ndrivers;
7150 SAFE_FREE(list);
7153 /* check the required size. */
7154 for (i=0; i<*returned; i++) {
7155 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7156 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7159 if (*needed > offered) {
7160 result = WERR_INSUFFICIENT_BUFFER;
7161 goto out;
7164 if (!rpcbuf_alloc_size(buffer, *needed)) {
7165 result = WERR_NOMEM;
7166 goto out;
7169 /* fill the buffer with the driver structures */
7170 for (i=0; i<*returned; i++) {
7171 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7172 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7175 out:
7176 for (i=0; i<*returned; i++) {
7177 SAFE_FREE(driver_info_3[i].dependentfiles);
7180 SAFE_FREE(driver_info_3);
7182 if ( !W_ERROR_IS_OK(result) )
7183 *returned = 0;
7185 return result;
7188 /****************************************************************************
7189 Enumerates all printer drivers.
7190 ****************************************************************************/
7192 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7194 uint32 level = q_u->level;
7195 RPC_BUFFER *buffer = NULL;
7196 uint32 offered = q_u->offered;
7197 uint32 *needed = &r_u->needed;
7198 uint32 *returned = &r_u->returned;
7199 const char *cservername;
7200 fstring servername;
7201 fstring architecture;
7203 /* that's an [in out] buffer */
7205 if (!q_u->buffer && (offered!=0)) {
7206 return WERR_INVALID_PARAM;
7209 if (offered > MAX_RPC_DATA_SIZE) {
7210 return WERR_INVALID_PARAM;
7213 rpcbuf_move(q_u->buffer, &r_u->buffer);
7214 buffer = r_u->buffer;
7216 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7218 *needed = 0;
7219 *returned = 0;
7221 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7222 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7224 cservername = canon_servername(servername);
7226 if (!is_myname_or_ipaddr(cservername))
7227 return WERR_UNKNOWN_PRINTER_DRIVER;
7229 switch (level) {
7230 case 1:
7231 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7232 case 2:
7233 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7234 case 3:
7235 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7236 default:
7237 return WERR_UNKNOWN_LEVEL;
7241 /****************************************************************************
7242 ****************************************************************************/
7244 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7246 form->flag=list->flag;
7247 init_unistr(&form->name, list->name);
7248 form->width=list->width;
7249 form->length=list->length;
7250 form->left=list->left;
7251 form->top=list->top;
7252 form->right=list->right;
7253 form->bottom=list->bottom;
7256 /****************************************************************************
7257 ****************************************************************************/
7259 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7260 struct spoolss_FormInfo1 *form,
7261 nt_forms_struct *list)
7263 form->form_name = talloc_strdup(mem_ctx, list->name);
7264 W_ERROR_HAVE_NO_MEMORY(form->form_name);
7266 form->flags = list->flag;
7267 form->size.width = list->width;
7268 form->size.height = list->length;
7269 form->area.left = list->left;
7270 form->area.top = list->top;
7271 form->area.right = list->right;
7272 form->area.bottom = list->bottom;
7274 return WERR_OK;
7277 /****************************************************************************
7278 ****************************************************************************/
7280 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7282 uint32 level = q_u->level;
7283 RPC_BUFFER *buffer = NULL;
7284 uint32 offered = q_u->offered;
7285 uint32 *needed = &r_u->needed;
7286 uint32 *numofforms = &r_u->numofforms;
7287 uint32 numbuiltinforms;
7289 nt_forms_struct *list=NULL;
7290 nt_forms_struct *builtinlist=NULL;
7291 FORM_1 *forms_1;
7292 int buffer_size=0;
7293 int i;
7295 /* that's an [in out] buffer */
7297 if (!q_u->buffer && (offered!=0) ) {
7298 return WERR_INVALID_PARAM;
7301 if (offered > MAX_RPC_DATA_SIZE) {
7302 return WERR_INVALID_PARAM;
7305 rpcbuf_move(q_u->buffer, &r_u->buffer);
7306 buffer = r_u->buffer;
7308 DEBUG(4,("_spoolss_enumforms\n"));
7309 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7310 DEBUGADD(5,("Info level [%d]\n", level));
7312 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7313 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7314 *numofforms = get_ntforms(&list);
7315 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7316 *numofforms += numbuiltinforms;
7318 if (*numofforms == 0) {
7319 SAFE_FREE(builtinlist);
7320 SAFE_FREE(list);
7321 return WERR_NO_MORE_ITEMS;
7324 switch (level) {
7325 case 1:
7326 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7327 SAFE_FREE(builtinlist);
7328 SAFE_FREE(list);
7329 *numofforms=0;
7330 return WERR_NOMEM;
7333 /* construct the list of form structures */
7334 for (i=0; i<numbuiltinforms; i++) {
7335 DEBUGADD(6,("Filling form number [%d]\n",i));
7336 fill_form_1(&forms_1[i], &builtinlist[i]);
7339 SAFE_FREE(builtinlist);
7341 for (; i<*numofforms; i++) {
7342 DEBUGADD(6,("Filling form number [%d]\n",i));
7343 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7346 SAFE_FREE(list);
7348 /* check the required size. */
7349 for (i=0; i<numbuiltinforms; i++) {
7350 DEBUGADD(6,("adding form [%d]'s size\n",i));
7351 buffer_size += spoolss_size_form_1(&forms_1[i]);
7353 for (; i<*numofforms; i++) {
7354 DEBUGADD(6,("adding form [%d]'s size\n",i));
7355 buffer_size += spoolss_size_form_1(&forms_1[i]);
7358 *needed=buffer_size;
7360 if (*needed > offered) {
7361 SAFE_FREE(forms_1);
7362 *numofforms=0;
7363 return WERR_INSUFFICIENT_BUFFER;
7366 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7367 SAFE_FREE(forms_1);
7368 *numofforms=0;
7369 return WERR_NOMEM;
7372 /* fill the buffer with the form structures */
7373 for (i=0; i<numbuiltinforms; i++) {
7374 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7375 smb_io_form_1("", buffer, &forms_1[i], 0);
7377 for (; i<*numofforms; i++) {
7378 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7379 smb_io_form_1("", buffer, &forms_1[i], 0);
7382 SAFE_FREE(forms_1);
7384 return WERR_OK;
7386 default:
7387 SAFE_FREE(list);
7388 SAFE_FREE(builtinlist);
7389 return WERR_UNKNOWN_LEVEL;
7393 /****************************************************************
7394 _spoolss_GetForm
7395 ****************************************************************/
7397 WERROR _spoolss_GetForm(pipes_struct *p,
7398 struct spoolss_GetForm *r)
7400 uint32 level = r->in.level;
7401 uint32 offered = r->in.offered;
7402 uint32 *needed = r->out.needed;
7404 nt_forms_struct *list=NULL;
7405 nt_forms_struct builtin_form;
7406 bool foundBuiltin;
7407 union spoolss_FormInfo info;
7408 struct spoolss_FormInfo1 form_1;
7409 int numofforms=0, i=0;
7411 /* that's an [in out] buffer */
7413 if (!r->in.buffer && (offered!=0)) {
7414 return WERR_INVALID_PARAM;
7417 DEBUG(4,("_spoolss_GetForm\n"));
7418 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7419 DEBUGADD(5,("Info level [%d]\n", level));
7421 foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7422 if (!foundBuiltin) {
7423 numofforms = get_ntforms(&list);
7424 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7426 if (numofforms == 0)
7427 return WERR_BADFID;
7430 ZERO_STRUCT(form_1);
7432 switch (level) {
7433 case 1:
7434 if (foundBuiltin) {
7435 fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7436 } else {
7438 /* Check if the requested name is in the list of form structures */
7439 for (i=0; i<numofforms; i++) {
7441 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7442 list[i].name, r->in.form_name));
7444 if (strequal(r->in.form_name, list[i].name)) {
7445 DEBUGADD(6,("Found form %s number [%d]\n",
7446 r->in.form_name, i));
7447 fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7448 break;
7452 SAFE_FREE(list);
7453 if (i == numofforms) {
7454 return WERR_BADFID;
7457 /* check the required size. */
7459 info.info1 = form_1;
7461 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7463 if (*needed > offered) {
7464 r->out.info = NULL;
7465 return WERR_INSUFFICIENT_BUFFER;
7468 r->out.info->info1 = form_1;
7470 /* fill the buffer with the form structures */
7471 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7472 r->in.form_name, i));
7474 return WERR_OK;
7476 default:
7477 SAFE_FREE(list);
7478 return WERR_UNKNOWN_LEVEL;
7482 /****************************************************************************
7483 ****************************************************************************/
7485 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7487 init_unistr(&port->port_name, name);
7490 /****************************************************************************
7491 TODO: This probably needs distinguish between TCP/IP and Local ports
7492 somehow.
7493 ****************************************************************************/
7495 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7497 init_unistr(&port->port_name, name);
7498 init_unistr(&port->monitor_name, "Local Monitor");
7499 init_unistr(&port->description, SPL_LOCAL_PORT );
7500 port->port_type=PORT_TYPE_WRITE;
7501 port->reserved=0x0;
7505 /****************************************************************************
7506 wrapper around the enumer ports command
7507 ****************************************************************************/
7509 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7511 char *cmd = lp_enumports_cmd();
7512 char **qlines = NULL;
7513 char *command = NULL;
7514 int numlines;
7515 int ret;
7516 int fd;
7518 *count = 0;
7519 *lines = NULL;
7521 /* if no hook then just fill in the default port */
7523 if ( !*cmd ) {
7524 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7525 return WERR_NOMEM;
7527 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7528 TALLOC_FREE(qlines);
7529 return WERR_NOMEM;
7531 qlines[1] = NULL;
7532 numlines = 1;
7534 else {
7535 /* we have a valid enumport command */
7537 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7538 if (!command) {
7539 return WERR_NOMEM;
7542 DEBUG(10,("Running [%s]\n", command));
7543 ret = smbrun(command, &fd);
7544 DEBUG(10,("Returned [%d]\n", ret));
7545 TALLOC_FREE(command);
7546 if (ret != 0) {
7547 if (fd != -1) {
7548 close(fd);
7550 return WERR_ACCESS_DENIED;
7553 numlines = 0;
7554 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7555 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7556 close(fd);
7559 *count = numlines;
7560 *lines = qlines;
7562 return WERR_OK;
7565 /****************************************************************************
7566 enumports level 1.
7567 ****************************************************************************/
7569 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7571 PORT_INFO_1 *ports=NULL;
7572 int i=0;
7573 WERROR result = WERR_OK;
7574 char **qlines = NULL;
7575 int numlines = 0;
7577 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7578 if (!W_ERROR_IS_OK(result)) {
7579 TALLOC_FREE(qlines);
7580 return result;
7583 if(numlines) {
7584 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7585 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7586 win_errstr(WERR_NOMEM)));
7587 TALLOC_FREE(qlines);
7588 return WERR_NOMEM;
7591 for (i=0; i<numlines; i++) {
7592 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7593 fill_port_1(&ports[i], qlines[i]);
7596 TALLOC_FREE(qlines);
7598 *returned = numlines;
7600 /* check the required size. */
7601 for (i=0; i<*returned; i++) {
7602 DEBUGADD(6,("adding port [%d]'s size\n", i));
7603 *needed += spoolss_size_port_info_1(&ports[i]);
7606 if (*needed > offered) {
7607 result = WERR_INSUFFICIENT_BUFFER;
7608 goto out;
7611 if (!rpcbuf_alloc_size(buffer, *needed)) {
7612 result = WERR_NOMEM;
7613 goto out;
7616 /* fill the buffer with the ports structures */
7617 for (i=0; i<*returned; i++) {
7618 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7619 smb_io_port_1("", buffer, &ports[i], 0);
7622 out:
7623 SAFE_FREE(ports);
7625 if ( !W_ERROR_IS_OK(result) )
7626 *returned = 0;
7628 return result;
7631 /****************************************************************************
7632 enumports level 2.
7633 ****************************************************************************/
7635 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7637 PORT_INFO_2 *ports=NULL;
7638 int i=0;
7639 WERROR result = WERR_OK;
7640 char **qlines = NULL;
7641 int numlines = 0;
7643 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7644 if ( !W_ERROR_IS_OK(result)) {
7645 TALLOC_FREE(qlines);
7646 return result;
7649 if(numlines) {
7650 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7651 TALLOC_FREE(qlines);
7652 return WERR_NOMEM;
7655 for (i=0; i<numlines; i++) {
7656 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7657 fill_port_2(&(ports[i]), qlines[i]);
7661 TALLOC_FREE(qlines);
7663 *returned = numlines;
7665 /* check the required size. */
7666 for (i=0; i<*returned; i++) {
7667 DEBUGADD(6,("adding port [%d]'s size\n", i));
7668 *needed += spoolss_size_port_info_2(&ports[i]);
7671 if (*needed > offered) {
7672 result = WERR_INSUFFICIENT_BUFFER;
7673 goto out;
7676 if (!rpcbuf_alloc_size(buffer, *needed)) {
7677 result = WERR_NOMEM;
7678 goto out;
7681 /* fill the buffer with the ports structures */
7682 for (i=0; i<*returned; i++) {
7683 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7684 smb_io_port_2("", buffer, &ports[i], 0);
7687 out:
7688 SAFE_FREE(ports);
7690 if ( !W_ERROR_IS_OK(result) )
7691 *returned = 0;
7693 return result;
7696 /****************************************************************************
7697 enumports.
7698 ****************************************************************************/
7700 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7702 uint32 level = q_u->level;
7703 RPC_BUFFER *buffer = NULL;
7704 uint32 offered = q_u->offered;
7705 uint32 *needed = &r_u->needed;
7706 uint32 *returned = &r_u->returned;
7708 /* that's an [in out] buffer */
7710 if (!q_u->buffer && (offered!=0)) {
7711 return WERR_INVALID_PARAM;
7714 if (offered > MAX_RPC_DATA_SIZE) {
7715 return WERR_INVALID_PARAM;
7718 rpcbuf_move(q_u->buffer, &r_u->buffer);
7719 buffer = r_u->buffer;
7721 DEBUG(4,("_spoolss_enumports\n"));
7723 *returned=0;
7724 *needed=0;
7726 switch (level) {
7727 case 1:
7728 return enumports_level_1(buffer, offered, needed, returned);
7729 case 2:
7730 return enumports_level_2(buffer, offered, needed, returned);
7731 default:
7732 return WERR_UNKNOWN_LEVEL;
7736 /****************************************************************************
7737 ****************************************************************************/
7739 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7740 const char *server,
7741 struct spoolss_SetPrinterInfoCtr *info_ctr,
7742 struct spoolss_DeviceMode *devmode,
7743 struct security_descriptor *sec_desc,
7744 struct spoolss_UserLevelCtr *user_ctr,
7745 POLICY_HND *handle)
7747 NT_PRINTER_INFO_LEVEL *printer = NULL;
7748 fstring name;
7749 int snum;
7750 WERROR err = WERR_OK;
7752 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7753 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7754 return WERR_NOMEM;
7757 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7758 if (!convert_printer_info_new(info_ctr, printer)) {
7759 free_a_printer(&printer, 2);
7760 return WERR_NOMEM;
7763 /* check to see if the printer already exists */
7765 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7766 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7767 printer->info_2->sharename));
7768 free_a_printer(&printer, 2);
7769 return WERR_PRINTER_ALREADY_EXISTS;
7772 /* FIXME!!! smbd should check to see if the driver is installed before
7773 trying to add a printer like this --jerry */
7775 if (*lp_addprinter_cmd() ) {
7776 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7777 printer) ) {
7778 free_a_printer(&printer,2);
7779 return WERR_ACCESS_DENIED;
7781 } else {
7782 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7783 "smb.conf parameter \"addprinter command\" is defined. This"
7784 "parameter must exist for this call to succeed\n",
7785 printer->info_2->sharename ));
7788 /* use our primary netbios name since get_a_printer() will convert
7789 it to what the client expects on a case by case basis */
7791 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7792 printer->info_2->sharename);
7795 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7796 free_a_printer(&printer,2);
7797 return WERR_ACCESS_DENIED;
7800 /* you must be a printer admin to add a new printer */
7801 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7802 free_a_printer(&printer,2);
7803 return WERR_ACCESS_DENIED;
7807 * Do sanity check on the requested changes for Samba.
7810 if (!check_printer_ok(printer->info_2, snum)) {
7811 free_a_printer(&printer,2);
7812 return WERR_INVALID_PARAM;
7816 * When a printer is created, the drivername bound to the printer is used
7817 * to lookup previously saved driver initialization info, which is then
7818 * bound to the new printer, simulating what happens in the Windows arch.
7821 if (!devmode)
7823 set_driver_init(printer, 2);
7825 else
7827 /* A valid devmode was included, convert and link it
7829 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7831 if (!convert_devicemode_new(printer->info_2->printername,
7832 devmode,
7833 &printer->info_2->devmode))
7834 return WERR_NOMEM;
7837 /* write the ASCII on disk */
7838 err = mod_a_printer(printer, 2);
7839 if (!W_ERROR_IS_OK(err)) {
7840 free_a_printer(&printer,2);
7841 return err;
7844 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7845 /* Handle open failed - remove addition. */
7846 del_a_printer(printer->info_2->sharename);
7847 free_a_printer(&printer,2);
7848 ZERO_STRUCTP(handle);
7849 return WERR_ACCESS_DENIED;
7852 update_c_setprinter(False);
7853 free_a_printer(&printer,2);
7855 return WERR_OK;
7858 /****************************************************************
7859 _spoolss_AddPrinterEx
7860 ****************************************************************/
7862 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7863 struct spoolss_AddPrinterEx *r)
7865 switch (r->in.info_ctr->level) {
7866 case 1:
7867 /* we don't handle yet */
7868 /* but I know what to do ... */
7869 return WERR_UNKNOWN_LEVEL;
7870 case 2:
7871 return spoolss_addprinterex_level_2(p, r->in.server,
7872 r->in.info_ctr,
7873 r->in.devmode_ctr->devmode,
7874 r->in.secdesc_ctr->sd,
7875 r->in.userlevel_ctr,
7876 r->out.handle);
7877 default:
7878 return WERR_UNKNOWN_LEVEL;
7882 /****************************************************************
7883 _spoolss_AddPrinterDriver
7884 ****************************************************************/
7886 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7887 struct spoolss_AddPrinterDriver *r)
7889 uint32_t level = r->in.info_ctr->level;
7890 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7891 WERROR err = WERR_OK;
7892 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7893 fstring driver_name;
7894 uint32 version;
7895 const char *fn;
7897 switch (p->hdr_req.opnum) {
7898 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7899 fn = "_spoolss_AddPrinterDriver";
7900 break;
7901 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7902 fn = "_spoolss_AddPrinterDriverEx";
7903 break;
7904 default:
7905 return WERR_INVALID_PARAM;
7909 /* FIXME */
7910 if (level != 3 && level != 6) {
7911 /* Clever hack from Martin Zielinski <mz@seh.de>
7912 * to allow downgrade from level 8 (Vista).
7914 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7915 return WERR_UNKNOWN_LEVEL;
7918 ZERO_STRUCT(driver);
7920 if (!convert_printer_driver_info(info, &driver, level)) {
7921 err = WERR_NOMEM;
7922 goto done;
7925 DEBUG(5,("Cleaning driver's information\n"));
7926 err = clean_up_driver_struct(p, driver, level);
7927 if (!W_ERROR_IS_OK(err))
7928 goto done;
7930 DEBUG(5,("Moving driver to final destination\n"));
7931 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7932 &err)) ) {
7933 goto done;
7936 if (add_a_printer_driver(driver, level)!=0) {
7937 err = WERR_ACCESS_DENIED;
7938 goto done;
7941 switch(level) {
7942 case 3:
7943 fstrcpy(driver_name,
7944 driver.info_3->name ? driver.info_3->name : "");
7945 break;
7946 case 6:
7947 fstrcpy(driver_name,
7948 driver.info_6->name ? driver.info_6->name : "");
7949 break;
7953 * I think this is where he DrvUpgradePrinter() hook would be
7954 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7955 * server. Right now, we just need to send ourselves a message
7956 * to update each printer bound to this driver. --jerry
7959 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7960 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7961 fn, driver_name));
7965 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7966 * decide if the driver init data should be deleted. The rules are:
7967 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7968 * 2) delete init data only if there is no 2k/Xp driver
7969 * 3) always delete init data
7970 * The generalized rule is always use init data from the highest order driver.
7971 * It is necessary to follow the driver install by an initialization step to
7972 * finish off this process.
7974 if (level == 3)
7975 version = driver.info_3->cversion;
7976 else if (level == 6)
7977 version = driver.info_6->version;
7978 else
7979 version = -1;
7980 switch (version) {
7982 * 9x printer driver - never delete init data
7984 case 0:
7985 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7986 fn, driver_name));
7987 break;
7990 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7991 * there is no 2k/Xp driver init data for this driver name.
7993 case 2:
7995 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7997 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7999 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
8001 if (!del_driver_init(driver_name))
8002 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
8003 fn, driver_name));
8004 } else {
8006 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
8008 free_a_printer_driver(driver1,3);
8009 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
8010 fn, driver_name));
8013 break;
8016 * 2k or Xp printer driver - always delete init data
8018 case 3:
8019 if (!del_driver_init(driver_name))
8020 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
8021 fn, driver_name));
8022 break;
8024 default:
8025 DEBUG(0,("%s: invalid level=%d\n", fn, level));
8026 break;
8030 done:
8031 free_a_printer_driver(driver, level);
8032 return err;
8035 /****************************************************************
8036 _spoolss_AddPrinterDriverEx
8037 ****************************************************************/
8039 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8040 struct spoolss_AddPrinterDriverEx *r)
8042 struct spoolss_AddPrinterDriver a;
8045 * we only support the semantics of AddPrinterDriver()
8046 * i.e. only copy files that are newer than existing ones
8049 if (r->in.flags != APD_COPY_NEW_FILES) {
8050 return WERR_ACCESS_DENIED;
8053 a.in.servername = r->in.servername;
8054 a.in.info_ctr = r->in.info_ctr;
8056 return _spoolss_AddPrinterDriver(p, &a);
8059 /****************************************************************************
8060 ****************************************************************************/
8062 struct _spoolss_paths {
8063 int type;
8064 const char *share;
8065 const char *dir;
8068 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8070 static const struct _spoolss_paths spoolss_paths[]= {
8071 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8072 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8075 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8076 const char *servername,
8077 const char *environment,
8078 int component,
8079 char **path)
8081 const char *pservername = NULL;
8082 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8083 const char *short_archi;
8085 *path = NULL;
8087 /* environment may be empty */
8088 if (environment && strlen(environment)) {
8089 long_archi = environment;
8092 /* servername may be empty */
8093 if (servername && strlen(servername)) {
8094 pservername = canon_servername(servername);
8096 if (!is_myname_or_ipaddr(pservername)) {
8097 return WERR_INVALID_PARAM;
8101 if (!(short_archi = get_short_archi(long_archi))) {
8102 return WERR_INVALID_ENVIRONMENT;
8105 switch (component) {
8106 case SPOOLSS_PRTPROCS_PATH:
8107 case SPOOLSS_DRIVER_PATH:
8108 if (pservername) {
8109 *path = talloc_asprintf(mem_ctx,
8110 "\\\\%s\\%s\\%s",
8111 pservername,
8112 spoolss_paths[component].share,
8113 short_archi);
8114 } else {
8115 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8116 SPOOLSS_DEFAULT_SERVER_PATH,
8117 spoolss_paths[component].dir,
8118 short_archi);
8120 break;
8121 default:
8122 return WERR_INVALID_PARAM;
8125 if (!*path) {
8126 return WERR_NOMEM;
8129 return WERR_OK;
8132 /****************************************************************************
8133 ****************************************************************************/
8135 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8136 const char *servername,
8137 const char *environment,
8138 struct spoolss_DriverDirectoryInfo1 *r,
8139 uint32_t offered,
8140 uint32_t *needed)
8142 WERROR werr;
8143 char *path = NULL;
8145 werr = compose_spoolss_server_path(mem_ctx,
8146 servername,
8147 environment,
8148 SPOOLSS_DRIVER_PATH,
8149 &path);
8150 if (!W_ERROR_IS_OK(werr)) {
8151 return werr;
8154 DEBUG(4,("printer driver directory: [%s]\n", path));
8156 r->directory_name = path;
8158 *needed += ndr_size_spoolss_DriverDirectoryInfo1(r, NULL, 0);
8160 if (*needed > offered) {
8161 talloc_free(path);
8162 return WERR_INSUFFICIENT_BUFFER;
8165 return WERR_OK;
8168 /****************************************************************
8169 _spoolss_GetPrinterDriverDirectory
8170 ****************************************************************/
8172 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8173 struct spoolss_GetPrinterDriverDirectory *r)
8175 WERROR werror;
8177 /* that's an [in out] buffer */
8179 if (!r->in.buffer && (r->in.offered != 0)) {
8180 return WERR_INVALID_PARAM;
8183 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8184 r->in.level));
8186 *r->out.needed = 0;
8188 /* r->in.level is ignored */
8190 werror = getprinterdriverdir_level_1(p->mem_ctx,
8191 r->in.server,
8192 r->in.environment,
8193 &r->out.info->info1,
8194 r->in.offered,
8195 r->out.needed);
8196 if (!W_ERROR_IS_OK(werror)) {
8197 TALLOC_FREE(r->out.info);
8200 return werror;
8203 /****************************************************************************
8204 ****************************************************************************/
8206 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8208 POLICY_HND *handle = &q_u->handle;
8209 uint32 idx = q_u->index;
8210 uint32 in_value_len = q_u->valuesize;
8211 uint32 in_data_len = q_u->datasize;
8212 uint32 *out_max_value_len = &r_u->valuesize;
8213 uint16 **out_value = &r_u->value;
8214 uint32 *out_value_len = &r_u->realvaluesize;
8215 uint32 *out_type = &r_u->type;
8216 uint32 *out_max_data_len = &r_u->datasize;
8217 uint8 **data_out = &r_u->data;
8218 uint32 *out_data_len = &r_u->realdatasize;
8220 NT_PRINTER_INFO_LEVEL *printer = NULL;
8222 uint32 biggest_valuesize;
8223 uint32 biggest_datasize;
8224 uint32 data_len;
8225 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8226 int snum;
8227 WERROR result;
8228 REGISTRY_VALUE *val = NULL;
8229 NT_PRINTER_DATA *p_data;
8230 int i, key_index, num_values;
8231 int name_length;
8233 *out_type = 0;
8235 *out_max_data_len = 0;
8236 *data_out = NULL;
8237 *out_data_len = 0;
8239 DEBUG(5,("spoolss_enumprinterdata\n"));
8241 if (!Printer) {
8242 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8243 return WERR_BADFID;
8246 if (!get_printer_snum(p,handle, &snum, NULL))
8247 return WERR_BADFID;
8249 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8250 if (!W_ERROR_IS_OK(result))
8251 return result;
8253 p_data = printer->info_2->data;
8254 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8256 result = WERR_OK;
8259 * The NT machine wants to know the biggest size of value and data
8261 * cf: MSDN EnumPrinterData remark section
8264 if ( !in_value_len && !in_data_len && (key_index != -1) )
8266 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8268 biggest_valuesize = 0;
8269 biggest_datasize = 0;
8271 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8273 for ( i=0; i<num_values; i++ )
8275 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8277 name_length = strlen(val->valuename);
8278 if ( strlen(val->valuename) > biggest_valuesize )
8279 biggest_valuesize = name_length;
8281 if ( val->size > biggest_datasize )
8282 biggest_datasize = val->size;
8284 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8285 biggest_datasize));
8288 /* the value is an UNICODE string but real_value_size is the length
8289 in bytes including the trailing 0 */
8291 *out_value_len = 2 * (1+biggest_valuesize);
8292 *out_data_len = biggest_datasize;
8294 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8296 goto done;
8300 * the value len is wrong in NT sp3
8301 * that's the number of bytes not the number of unicode chars
8304 if ( key_index != -1 )
8305 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8307 if ( !val )
8310 /* out_value should default to "" or else NT4 has
8311 problems unmarshalling the response */
8313 *out_max_value_len=(in_value_len/sizeof(uint16));
8315 if (in_value_len) {
8316 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8318 result = WERR_NOMEM;
8319 goto done;
8321 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8322 } else {
8323 *out_value=NULL;
8324 *out_value_len = 0;
8327 /* the data is counted in bytes */
8329 *out_max_data_len = in_data_len;
8330 *out_data_len = in_data_len;
8332 /* only allocate when given a non-zero data_len */
8334 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8336 result = WERR_NOMEM;
8337 goto done;
8340 result = WERR_NO_MORE_ITEMS;
8342 else
8345 * the value is:
8346 * - counted in bytes in the request
8347 * - counted in UNICODE chars in the max reply
8348 * - counted in bytes in the real size
8350 * take a pause *before* coding not *during* coding
8353 /* name */
8354 *out_max_value_len=(in_value_len/sizeof(uint16));
8355 if (in_value_len) {
8356 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8358 result = WERR_NOMEM;
8359 goto done;
8362 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8363 } else {
8364 *out_value = NULL;
8365 *out_value_len = 0;
8368 /* type */
8370 *out_type = regval_type( val );
8372 /* data - counted in bytes */
8374 *out_max_data_len = in_data_len;
8375 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8377 result = WERR_NOMEM;
8378 goto done;
8380 data_len = regval_size(val);
8381 if ( *data_out && data_len )
8382 memcpy( *data_out, regval_data_p(val), data_len );
8383 *out_data_len = data_len;
8386 done:
8387 free_a_printer(&printer, 2);
8388 return result;
8391 /****************************************************************************
8392 ****************************************************************************/
8394 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8396 POLICY_HND *handle = &q_u->handle;
8397 UNISTR2 *value = &q_u->value;
8398 uint32 type = q_u->type;
8399 uint8 *data = q_u->data;
8400 uint32 real_len = q_u->real_len;
8402 NT_PRINTER_INFO_LEVEL *printer = NULL;
8403 int snum=0;
8404 WERROR status = WERR_OK;
8405 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8406 fstring valuename;
8408 DEBUG(5,("spoolss_setprinterdata\n"));
8410 if (!Printer) {
8411 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8412 return WERR_BADFID;
8415 if ( Printer->printer_type == SPLHND_SERVER ) {
8416 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8417 return WERR_INVALID_PARAM;
8420 if (!get_printer_snum(p,handle, &snum, NULL))
8421 return WERR_BADFID;
8424 * Access check : NT returns "access denied" if you make a
8425 * SetPrinterData call without the necessary privildge.
8426 * we were originally returning OK if nothing changed
8427 * which made Win2k issue **a lot** of SetPrinterData
8428 * when connecting to a printer --jerry
8431 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8433 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8434 status = WERR_ACCESS_DENIED;
8435 goto done;
8438 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8439 if (!W_ERROR_IS_OK(status))
8440 return status;
8442 unistr2_to_ascii(valuename, value, sizeof(valuename));
8445 * When client side code sets a magic printer data key, detect it and save
8446 * the current printer data and the magic key's data (its the DEVMODE) for
8447 * future printer/driver initializations.
8449 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8451 /* Set devmode and printer initialization info */
8452 status = save_driver_init( printer, 2, data, real_len );
8454 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8456 else
8458 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8459 type, data, real_len );
8460 if ( W_ERROR_IS_OK(status) )
8461 status = mod_a_printer(printer, 2);
8464 done:
8465 free_a_printer(&printer, 2);
8467 return status;
8470 /****************************************************************
8471 _spoolss_ResetPrinter
8472 ****************************************************************/
8474 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8475 struct spoolss_ResetPrinter *r)
8477 POLICY_HND *handle = r->in.handle;
8478 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8479 int snum;
8481 DEBUG(5,("_spoolss_ResetPrinter\n"));
8484 * All we do is to check to see if the handle and queue is valid.
8485 * This call really doesn't mean anything to us because we only
8486 * support RAW printing. --jerry
8489 if (!Printer) {
8490 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8491 OUR_HANDLE(handle)));
8492 return WERR_BADFID;
8495 if (!get_printer_snum(p,handle, &snum, NULL))
8496 return WERR_BADFID;
8499 /* blindly return success */
8500 return WERR_OK;
8503 /****************************************************************
8504 _spoolss_DeletePrinterData
8505 ****************************************************************/
8507 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8508 struct spoolss_DeletePrinterData *r)
8510 POLICY_HND *handle = r->in.handle;
8511 NT_PRINTER_INFO_LEVEL *printer = NULL;
8512 int snum=0;
8513 WERROR status = WERR_OK;
8514 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8516 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8518 if (!Printer) {
8519 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8520 OUR_HANDLE(handle)));
8521 return WERR_BADFID;
8524 if (!get_printer_snum(p, handle, &snum, NULL))
8525 return WERR_BADFID;
8527 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8528 DEBUG(3, ("_spoolss_DeletePrinterData: "
8529 "printer properties change denied by handle\n"));
8530 return WERR_ACCESS_DENIED;
8533 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8534 if (!W_ERROR_IS_OK(status))
8535 return status;
8537 if (!r->in.value_name) {
8538 free_a_printer(&printer, 2);
8539 return WERR_NOMEM;
8542 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8543 r->in.value_name );
8545 if ( W_ERROR_IS_OK(status) )
8546 mod_a_printer( printer, 2 );
8548 free_a_printer(&printer, 2);
8550 return status;
8553 /****************************************************************
8554 _spoolss_AddForm
8555 ****************************************************************/
8557 WERROR _spoolss_AddForm(pipes_struct *p,
8558 struct spoolss_AddForm *r)
8560 POLICY_HND *handle = r->in.handle;
8561 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8562 nt_forms_struct tmpForm;
8563 int snum;
8564 WERROR status = WERR_OK;
8565 NT_PRINTER_INFO_LEVEL *printer = NULL;
8567 int count=0;
8568 nt_forms_struct *list=NULL;
8569 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8571 DEBUG(5,("_spoolss_AddForm\n"));
8573 if (!Printer) {
8574 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8575 OUR_HANDLE(handle)));
8576 return WERR_BADFID;
8580 /* forms can be added on printer of on the print server handle */
8582 if ( Printer->printer_type == SPLHND_PRINTER )
8584 if (!get_printer_snum(p,handle, &snum, NULL))
8585 return WERR_BADFID;
8587 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8588 if (!W_ERROR_IS_OK(status))
8589 goto done;
8592 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8593 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8594 status = WERR_ACCESS_DENIED;
8595 goto done;
8598 /* can't add if builtin */
8600 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8601 status = WERR_FILE_EXISTS;
8602 goto done;
8605 count = get_ntforms(&list);
8607 if(!add_a_form(&list, form, &count)) {
8608 status = WERR_NOMEM;
8609 goto done;
8612 write_ntforms(&list, count);
8615 * ChangeID must always be set if this is a printer
8618 if ( Printer->printer_type == SPLHND_PRINTER )
8619 status = mod_a_printer(printer, 2);
8621 done:
8622 if ( printer )
8623 free_a_printer(&printer, 2);
8624 SAFE_FREE(list);
8626 return status;
8629 /****************************************************************
8630 _spoolss_DeleteForm
8631 ****************************************************************/
8633 WERROR _spoolss_DeleteForm(pipes_struct *p,
8634 struct spoolss_DeleteForm *r)
8636 POLICY_HND *handle = r->in.handle;
8637 const char *form_name = r->in.form_name;
8638 nt_forms_struct tmpForm;
8639 int count=0;
8640 nt_forms_struct *list=NULL;
8641 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8642 int snum;
8643 WERROR status = WERR_OK;
8644 NT_PRINTER_INFO_LEVEL *printer = NULL;
8646 DEBUG(5,("_spoolss_DeleteForm\n"));
8648 if (!Printer) {
8649 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8650 OUR_HANDLE(handle)));
8651 return WERR_BADFID;
8654 /* forms can be deleted on printer of on the print server handle */
8656 if ( Printer->printer_type == SPLHND_PRINTER )
8658 if (!get_printer_snum(p,handle, &snum, NULL))
8659 return WERR_BADFID;
8661 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8662 if (!W_ERROR_IS_OK(status))
8663 goto done;
8666 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8667 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8668 status = WERR_ACCESS_DENIED;
8669 goto done;
8672 /* can't delete if builtin */
8674 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8675 status = WERR_INVALID_PARAM;
8676 goto done;
8679 count = get_ntforms(&list);
8681 if ( !delete_a_form(&list, form_name, &count, &status ))
8682 goto done;
8685 * ChangeID must always be set if this is a printer
8688 if ( Printer->printer_type == SPLHND_PRINTER )
8689 status = mod_a_printer(printer, 2);
8691 done:
8692 if ( printer )
8693 free_a_printer(&printer, 2);
8694 SAFE_FREE(list);
8696 return status;
8699 /****************************************************************
8700 _spoolss_SetForm
8701 ****************************************************************/
8703 WERROR _spoolss_SetForm(pipes_struct *p,
8704 struct spoolss_SetForm *r)
8706 POLICY_HND *handle = r->in.handle;
8707 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8708 nt_forms_struct tmpForm;
8709 int snum;
8710 WERROR status = WERR_OK;
8711 NT_PRINTER_INFO_LEVEL *printer = NULL;
8713 int count=0;
8714 nt_forms_struct *list=NULL;
8715 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8717 DEBUG(5,("_spoolss_SetForm\n"));
8719 if (!Printer) {
8720 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8721 OUR_HANDLE(handle)));
8722 return WERR_BADFID;
8725 /* forms can be modified on printer of on the print server handle */
8727 if ( Printer->printer_type == SPLHND_PRINTER )
8729 if (!get_printer_snum(p,handle, &snum, NULL))
8730 return WERR_BADFID;
8732 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8733 if (!W_ERROR_IS_OK(status))
8734 goto done;
8737 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8738 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8739 status = WERR_ACCESS_DENIED;
8740 goto done;
8743 /* can't set if builtin */
8744 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8745 status = WERR_INVALID_PARAM;
8746 goto done;
8749 count = get_ntforms(&list);
8750 update_a_form(&list, form, count);
8751 write_ntforms(&list, count);
8754 * ChangeID must always be set if this is a printer
8757 if ( Printer->printer_type == SPLHND_PRINTER )
8758 status = mod_a_printer(printer, 2);
8761 done:
8762 if ( printer )
8763 free_a_printer(&printer, 2);
8764 SAFE_FREE(list);
8766 return status;
8769 /****************************************************************************
8770 enumprintprocessors level 1.
8771 ****************************************************************************/
8773 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8775 PRINTPROCESSOR_1 *info_1=NULL;
8776 WERROR result = WERR_OK;
8778 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8779 return WERR_NOMEM;
8781 (*returned) = 0x1;
8783 init_unistr(&info_1->name, "winprint");
8785 *needed += spoolss_size_printprocessor_info_1(info_1);
8787 if (*needed > offered) {
8788 result = WERR_INSUFFICIENT_BUFFER;
8789 goto out;
8792 if (!rpcbuf_alloc_size(buffer, *needed)) {
8793 result = WERR_NOMEM;
8794 goto out;
8797 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8799 out:
8800 SAFE_FREE(info_1);
8802 if ( !W_ERROR_IS_OK(result) )
8803 *returned = 0;
8805 return result;
8808 /****************************************************************************
8809 ****************************************************************************/
8811 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8813 uint32 level = q_u->level;
8814 RPC_BUFFER *buffer = NULL;
8815 uint32 offered = q_u->offered;
8816 uint32 *needed = &r_u->needed;
8817 uint32 *returned = &r_u->returned;
8819 /* that's an [in out] buffer */
8821 if (!q_u->buffer && (offered!=0)) {
8822 return WERR_INVALID_PARAM;
8825 if (offered > MAX_RPC_DATA_SIZE) {
8826 return WERR_INVALID_PARAM;
8829 rpcbuf_move(q_u->buffer, &r_u->buffer);
8830 buffer = r_u->buffer;
8832 DEBUG(5,("spoolss_enumprintprocessors\n"));
8835 * Enumerate the print processors ...
8837 * Just reply with "winprint", to keep NT happy
8838 * and I can use my nice printer checker.
8841 *returned=0;
8842 *needed=0;
8844 switch (level) {
8845 case 1:
8846 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8847 default:
8848 return WERR_UNKNOWN_LEVEL;
8852 /****************************************************************************
8853 enumprintprocdatatypes level 1.
8854 ****************************************************************************/
8856 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8858 PRINTPROCDATATYPE_1 *info_1=NULL;
8859 WERROR result = WERR_OK;
8861 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8862 return WERR_NOMEM;
8864 (*returned) = 0x1;
8866 init_unistr(&info_1->name, "RAW");
8868 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8870 if (*needed > offered) {
8871 result = WERR_INSUFFICIENT_BUFFER;
8872 goto out;
8875 if (!rpcbuf_alloc_size(buffer, *needed)) {
8876 result = WERR_NOMEM;
8877 goto out;
8880 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8882 out:
8883 SAFE_FREE(info_1);
8885 if ( !W_ERROR_IS_OK(result) )
8886 *returned = 0;
8888 return result;
8891 /****************************************************************************
8892 ****************************************************************************/
8894 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8896 uint32 level = q_u->level;
8897 RPC_BUFFER *buffer = NULL;
8898 uint32 offered = q_u->offered;
8899 uint32 *needed = &r_u->needed;
8900 uint32 *returned = &r_u->returned;
8902 /* that's an [in out] buffer */
8904 if (!q_u->buffer && (offered!=0)) {
8905 return WERR_INVALID_PARAM;
8908 if (offered > MAX_RPC_DATA_SIZE) {
8909 return WERR_INVALID_PARAM;
8912 rpcbuf_move(q_u->buffer, &r_u->buffer);
8913 buffer = r_u->buffer;
8915 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8917 *returned=0;
8918 *needed=0;
8920 switch (level) {
8921 case 1:
8922 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8923 default:
8924 return WERR_UNKNOWN_LEVEL;
8928 /****************************************************************************
8929 enumprintmonitors level 1.
8930 ****************************************************************************/
8932 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8934 PRINTMONITOR_1 *info_1;
8935 WERROR result = WERR_OK;
8936 int i;
8938 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8939 return WERR_NOMEM;
8941 *returned = 2;
8943 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8944 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8946 for ( i=0; i<*returned; i++ ) {
8947 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8950 if (*needed > offered) {
8951 result = WERR_INSUFFICIENT_BUFFER;
8952 goto out;
8955 if (!rpcbuf_alloc_size(buffer, *needed)) {
8956 result = WERR_NOMEM;
8957 goto out;
8960 for ( i=0; i<*returned; i++ ) {
8961 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8964 out:
8965 SAFE_FREE(info_1);
8967 if ( !W_ERROR_IS_OK(result) )
8968 *returned = 0;
8970 return result;
8973 /****************************************************************************
8974 enumprintmonitors level 2.
8975 ****************************************************************************/
8977 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8979 PRINTMONITOR_2 *info_2;
8980 WERROR result = WERR_OK;
8981 int i;
8983 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8984 return WERR_NOMEM;
8986 *returned = 2;
8988 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8989 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8990 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8992 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8993 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8994 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8996 for ( i=0; i<*returned; i++ ) {
8997 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
9000 if (*needed > offered) {
9001 result = WERR_INSUFFICIENT_BUFFER;
9002 goto out;
9005 if (!rpcbuf_alloc_size(buffer, *needed)) {
9006 result = WERR_NOMEM;
9007 goto out;
9010 for ( i=0; i<*returned; i++ ) {
9011 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
9014 out:
9015 SAFE_FREE(info_2);
9017 if ( !W_ERROR_IS_OK(result) )
9018 *returned = 0;
9020 return result;
9023 /****************************************************************************
9024 ****************************************************************************/
9026 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
9028 uint32 level = q_u->level;
9029 RPC_BUFFER *buffer = NULL;
9030 uint32 offered = q_u->offered;
9031 uint32 *needed = &r_u->needed;
9032 uint32 *returned = &r_u->returned;
9034 /* that's an [in out] buffer */
9036 if (!q_u->buffer && (offered!=0)) {
9037 return WERR_INVALID_PARAM;
9040 if (offered > MAX_RPC_DATA_SIZE) {
9041 return WERR_INVALID_PARAM;
9044 rpcbuf_move(q_u->buffer, &r_u->buffer);
9045 buffer = r_u->buffer;
9047 DEBUG(5,("spoolss_enumprintmonitors\n"));
9050 * Enumerate the print monitors ...
9052 * Just reply with "Local Port", to keep NT happy
9053 * and I can use my nice printer checker.
9056 *returned=0;
9057 *needed=0;
9059 switch (level) {
9060 case 1:
9061 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9062 case 2:
9063 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9064 default:
9065 return WERR_UNKNOWN_LEVEL;
9069 /****************************************************************************
9070 ****************************************************************************/
9072 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9073 NT_PRINTER_INFO_LEVEL *ntprinter,
9074 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9075 uint32 *needed)
9077 int i=0;
9078 bool found=False;
9079 JOB_INFO_1 *info_1=NULL;
9080 WERROR result = WERR_OK;
9082 info_1=SMB_MALLOC_P(JOB_INFO_1);
9084 if (info_1 == NULL) {
9085 return WERR_NOMEM;
9088 for (i=0; i<count && found==False; i++) {
9089 if ((*queue)[i].job==(int)jobid)
9090 found=True;
9093 if (found==False) {
9094 SAFE_FREE(info_1);
9095 /* NT treats not found as bad param... yet another bad choice */
9096 return WERR_INVALID_PARAM;
9099 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9101 *needed += spoolss_size_job_info_1(info_1);
9103 if (*needed > offered) {
9104 result = WERR_INSUFFICIENT_BUFFER;
9105 goto out;
9108 if (!rpcbuf_alloc_size(buffer, *needed)) {
9109 result = WERR_NOMEM;
9110 goto out;
9113 smb_io_job_info_1("", buffer, info_1, 0);
9115 out:
9116 SAFE_FREE(info_1);
9118 return result;
9121 /****************************************************************************
9122 ****************************************************************************/
9124 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9125 NT_PRINTER_INFO_LEVEL *ntprinter,
9126 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9127 uint32 *needed)
9129 int i = 0;
9130 bool found = False;
9131 JOB_INFO_2 *info_2;
9132 WERROR result;
9133 DEVICEMODE *devmode = NULL;
9134 NT_DEVICEMODE *nt_devmode = NULL;
9136 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9137 return WERR_NOMEM;
9139 ZERO_STRUCTP(info_2);
9141 for ( i=0; i<count && found==False; i++ )
9143 if ((*queue)[i].job == (int)jobid)
9144 found = True;
9147 if ( !found ) {
9148 /* NT treats not found as bad param... yet another bad
9149 choice */
9150 result = WERR_INVALID_PARAM;
9151 goto done;
9155 * if the print job does not have a DEVMODE associated with it,
9156 * just use the one for the printer. A NULL devicemode is not
9157 * a failure condition
9160 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9161 devmode = construct_dev_mode(lp_const_servicename(snum));
9162 else {
9163 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9164 ZERO_STRUCTP( devmode );
9165 convert_nt_devicemode( devmode, nt_devmode );
9169 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9171 *needed += spoolss_size_job_info_2(info_2);
9173 if (*needed > offered) {
9174 result = WERR_INSUFFICIENT_BUFFER;
9175 goto done;
9178 if (!rpcbuf_alloc_size(buffer, *needed)) {
9179 result = WERR_NOMEM;
9180 goto done;
9183 smb_io_job_info_2("", buffer, info_2, 0);
9185 result = WERR_OK;
9187 done:
9188 /* Cleanup allocated memory */
9190 free_job_info_2(info_2); /* Also frees devmode */
9191 SAFE_FREE(info_2);
9193 return result;
9196 /****************************************************************************
9197 ****************************************************************************/
9199 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9201 POLICY_HND *handle = &q_u->handle;
9202 uint32 jobid = q_u->jobid;
9203 uint32 level = q_u->level;
9204 RPC_BUFFER *buffer = NULL;
9205 uint32 offered = q_u->offered;
9206 uint32 *needed = &r_u->needed;
9207 WERROR wstatus = WERR_OK;
9208 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9209 int snum;
9210 int count;
9211 print_queue_struct *queue = NULL;
9212 print_status_struct prt_status;
9214 /* that's an [in out] buffer */
9216 if (!q_u->buffer && (offered!=0)) {
9217 return WERR_INVALID_PARAM;
9220 if (offered > MAX_RPC_DATA_SIZE) {
9221 return WERR_INVALID_PARAM;
9224 rpcbuf_move(q_u->buffer, &r_u->buffer);
9225 buffer = r_u->buffer;
9227 DEBUG(5,("spoolss_getjob\n"));
9229 *needed = 0;
9231 if (!get_printer_snum(p, handle, &snum, NULL))
9232 return WERR_BADFID;
9234 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9235 if ( !W_ERROR_IS_OK(wstatus) )
9236 return wstatus;
9238 count = print_queue_status(snum, &queue, &prt_status);
9240 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9241 count, prt_status.status, prt_status.message));
9243 switch ( level ) {
9244 case 1:
9245 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9246 buffer, offered, needed);
9247 break;
9248 case 2:
9249 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9250 buffer, offered, needed);
9251 break;
9252 default:
9253 wstatus = WERR_UNKNOWN_LEVEL;
9254 break;
9257 SAFE_FREE(queue);
9258 free_a_printer( &ntprinter, 2 );
9260 return wstatus;
9263 /****************************************************************
9264 _spoolss_GetPrinterDataEx
9266 From MSDN documentation of GetPrinterDataEx: pass request
9267 to GetPrinterData if key is "PrinterDriverData".
9268 ****************************************************************/
9270 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9271 struct spoolss_GetPrinterDataEx *r)
9273 POLICY_HND *handle = r->in.handle;
9274 uint8 *data = NULL;
9275 const char *keyname = r->in.key_name;
9276 const char *valuename = r->in.value_name;
9278 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9280 NT_PRINTER_INFO_LEVEL *printer = NULL;
9281 int snum = 0;
9282 WERROR status = WERR_OK;
9284 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9286 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9287 keyname, valuename));
9289 /* in case of problem, return some default values */
9291 *r->out.needed = 0;
9292 *r->out.type = 0;
9294 if (!Printer) {
9295 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9296 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9297 status = WERR_BADFID;
9298 goto done;
9301 /* Is the handle to a printer or to the server? */
9303 if (Printer->printer_type == SPLHND_SERVER) {
9304 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9305 "Not implemented for server handles yet\n"));
9306 status = WERR_INVALID_PARAM;
9307 goto done;
9310 if ( !get_printer_snum(p,handle, &snum, NULL) )
9311 return WERR_BADFID;
9313 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9314 if ( !W_ERROR_IS_OK(status) )
9315 goto done;
9317 /* check to see if the keyname is valid */
9318 if ( !strlen(keyname) ) {
9319 status = WERR_INVALID_PARAM;
9320 goto done;
9323 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9324 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9325 "Invalid keyname [%s]\n", keyname ));
9326 free_a_printer( &printer, 2 );
9327 status = WERR_BADFILE;
9328 goto done;
9331 /* When given a new keyname, we should just create it */
9333 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9334 r->out.type, &data, r->out.needed,
9335 r->in.offered );
9337 if (*r->out.needed > r->in.offered) {
9338 status = WERR_MORE_DATA;
9341 if (W_ERROR_IS_OK(status)) {
9342 memcpy(r->out.buffer, data, r->in.offered);
9345 done:
9346 if ( printer )
9347 free_a_printer( &printer, 2 );
9349 return status;
9352 /****************************************************************
9353 _spoolss_SetPrinterDataEx
9354 ****************************************************************/
9356 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9357 struct spoolss_SetPrinterDataEx *r)
9359 POLICY_HND *handle = r->in.handle;
9360 NT_PRINTER_INFO_LEVEL *printer = NULL;
9361 int snum = 0;
9362 WERROR status = WERR_OK;
9363 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9364 char *oid_string;
9366 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9368 /* From MSDN documentation of SetPrinterDataEx: pass request to
9369 SetPrinterData if key is "PrinterDriverData" */
9371 if (!Printer) {
9372 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9373 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9374 return WERR_BADFID;
9377 if ( Printer->printer_type == SPLHND_SERVER ) {
9378 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9379 "Not implemented for server handles yet\n"));
9380 return WERR_INVALID_PARAM;
9383 if ( !get_printer_snum(p,handle, &snum, NULL) )
9384 return WERR_BADFID;
9387 * Access check : NT returns "access denied" if you make a
9388 * SetPrinterData call without the necessary privildge.
9389 * we were originally returning OK if nothing changed
9390 * which made Win2k issue **a lot** of SetPrinterData
9391 * when connecting to a printer --jerry
9394 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9396 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9397 "change denied by handle access permissions\n"));
9398 return WERR_ACCESS_DENIED;
9401 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9402 if (!W_ERROR_IS_OK(status))
9403 return status;
9405 /* check for OID in valuename */
9407 if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9409 *oid_string = '\0';
9410 oid_string++;
9413 /* save the registry data */
9415 status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9416 r->in.type, r->in.buffer, r->in.offered );
9418 if ( W_ERROR_IS_OK(status) )
9420 /* save the OID if one was specified */
9421 if ( oid_string ) {
9422 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9423 r->in.key_name, SPOOL_OID_KEY);
9424 if (!str) {
9425 return WERR_NOMEM;
9429 * I'm not checking the status here on purpose. Don't know
9430 * if this is right, but I'm returning the status from the
9431 * previous set_printer_dataex() call. I have no idea if
9432 * this is right. --jerry
9435 set_printer_dataex( printer, str, r->in.value_name,
9436 REG_SZ, (uint8 *)oid_string,
9437 strlen(oid_string)+1 );
9440 status = mod_a_printer(printer, 2);
9443 free_a_printer(&printer, 2);
9445 return status;
9448 /****************************************************************
9449 _spoolss_DeletePrinterDataEx
9450 ****************************************************************/
9452 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9453 struct spoolss_DeletePrinterDataEx *r)
9455 POLICY_HND *handle = r->in.handle;
9456 NT_PRINTER_INFO_LEVEL *printer = NULL;
9457 int snum=0;
9458 WERROR status = WERR_OK;
9459 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9461 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9463 if (!Printer) {
9464 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9465 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9466 return WERR_BADFID;
9469 if (!get_printer_snum(p, handle, &snum, NULL))
9470 return WERR_BADFID;
9472 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9473 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9474 "printer properties change denied by handle\n"));
9475 return WERR_ACCESS_DENIED;
9478 if (!r->in.value_name || !r->in.key_name) {
9479 return WERR_NOMEM;
9482 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9483 if (!W_ERROR_IS_OK(status))
9484 return status;
9486 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9488 if ( W_ERROR_IS_OK(status) )
9489 mod_a_printer( printer, 2 );
9491 free_a_printer(&printer, 2);
9493 return status;
9496 /********************************************************************
9497 * spoolss_enumprinterkey
9498 ********************************************************************/
9501 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9503 fstring key;
9504 fstring *keynames = NULL;
9505 uint16 *enumkeys = NULL;
9506 int num_keys;
9507 int printerkey_len;
9508 POLICY_HND *handle = &q_u->handle;
9509 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9510 NT_PRINTER_DATA *data;
9511 NT_PRINTER_INFO_LEVEL *printer = NULL;
9512 int snum = 0;
9513 WERROR status = WERR_BADFILE;
9516 DEBUG(4,("_spoolss_enumprinterkey\n"));
9518 if (!Printer) {
9519 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9520 return WERR_BADFID;
9523 if ( !get_printer_snum(p,handle, &snum, NULL) )
9524 return WERR_BADFID;
9526 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9527 if (!W_ERROR_IS_OK(status))
9528 return status;
9530 /* get the list of subkey names */
9532 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9533 data = printer->info_2->data;
9535 num_keys = get_printer_subkeys( data, key, &keynames );
9537 if ( num_keys == -1 ) {
9538 status = WERR_BADFILE;
9539 goto done;
9542 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9544 r_u->needed = printerkey_len*2;
9546 if ( q_u->size < r_u->needed ) {
9547 status = WERR_MORE_DATA;
9548 goto done;
9551 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9552 status = WERR_NOMEM;
9553 goto done;
9556 status = WERR_OK;
9558 if ( q_u->size < r_u->needed )
9559 status = WERR_MORE_DATA;
9561 done:
9562 free_a_printer( &printer, 2 );
9563 SAFE_FREE( keynames );
9565 return status;
9568 /****************************************************************
9569 _spoolss_DeletePrinterKey
9570 ****************************************************************/
9572 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9573 struct spoolss_DeletePrinterKey *r)
9575 POLICY_HND *handle = r->in.handle;
9576 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9577 NT_PRINTER_INFO_LEVEL *printer = NULL;
9578 int snum=0;
9579 WERROR status;
9581 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9583 if (!Printer) {
9584 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9585 OUR_HANDLE(handle)));
9586 return WERR_BADFID;
9589 /* if keyname == NULL, return error */
9591 if ( !r->in.key_name )
9592 return WERR_INVALID_PARAM;
9594 if (!get_printer_snum(p, handle, &snum, NULL))
9595 return WERR_BADFID;
9597 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9598 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9599 "printer properties change denied by handle\n"));
9600 return WERR_ACCESS_DENIED;
9603 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9604 if (!W_ERROR_IS_OK(status))
9605 return status;
9607 /* delete the key and all subneys */
9609 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9611 if ( W_ERROR_IS_OK(status) )
9612 status = mod_a_printer(printer, 2);
9614 free_a_printer( &printer, 2 );
9616 return status;
9620 /********************************************************************
9621 * spoolss_enumprinterdataex
9622 ********************************************************************/
9624 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9626 POLICY_HND *handle = &q_u->handle;
9627 uint32 in_size = q_u->size;
9628 uint32 num_entries,
9629 needed;
9630 NT_PRINTER_INFO_LEVEL *printer = NULL;
9631 PRINTER_ENUM_VALUES *enum_values = NULL;
9632 NT_PRINTER_DATA *p_data;
9633 fstring key;
9634 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9635 int snum;
9636 WERROR result;
9637 int key_index;
9638 int i;
9639 REGISTRY_VALUE *val;
9640 char *value_name;
9641 uint32 data_len;
9644 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9646 if (!Printer) {
9647 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9648 return WERR_BADFID;
9652 * first check for a keyname of NULL or "". Win2k seems to send
9653 * this a lot and we should send back WERR_INVALID_PARAM
9654 * no need to spend time looking up the printer in this case.
9655 * --jerry
9658 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9659 if ( !strlen(key) ) {
9660 result = WERR_INVALID_PARAM;
9661 goto done;
9664 /* get the printer off of disk */
9666 if (!get_printer_snum(p,handle, &snum, NULL))
9667 return WERR_BADFID;
9669 ZERO_STRUCT(printer);
9670 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9671 if (!W_ERROR_IS_OK(result))
9672 return result;
9674 /* now look for a match on the key name */
9676 p_data = printer->info_2->data;
9678 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9679 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9681 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9682 result = WERR_INVALID_PARAM;
9683 goto done;
9686 result = WERR_OK;
9687 needed = 0;
9689 /* allocate the memory for the array of pointers -- if necessary */
9691 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9692 if ( num_entries )
9694 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9696 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9697 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9698 result = WERR_NOMEM;
9699 goto done;
9702 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9706 * loop through all params and build the array to pass
9707 * back to the client
9710 for ( i=0; i<num_entries; i++ )
9712 /* lookup the registry value */
9714 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9715 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9717 /* copy the data */
9719 value_name = regval_name( val );
9720 init_unistr( &enum_values[i].valuename, value_name );
9721 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9722 enum_values[i].type = regval_type( val );
9724 data_len = regval_size( val );
9725 if ( data_len ) {
9726 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9728 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9729 data_len ));
9730 result = WERR_NOMEM;
9731 goto done;
9734 enum_values[i].data_len = data_len;
9736 /* keep track of the size of the array in bytes */
9738 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9741 /* housekeeping information in the reply */
9743 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9744 * the hand marshalled container size is a multiple
9745 * of 4 bytes for RPC alignment.
9748 if (needed % 4) {
9749 needed += 4-(needed % 4);
9752 r_u->needed = needed;
9753 r_u->returned = num_entries;
9755 if (needed > in_size) {
9756 result = WERR_MORE_DATA;
9757 goto done;
9760 /* copy data into the reply */
9762 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9763 response buffer size is != the offered buffer size
9765 r_u->ctr.size = r_u->needed;
9767 r_u->ctr.size = in_size;
9769 r_u->ctr.size_of_array = r_u->returned;
9770 r_u->ctr.values = enum_values;
9772 done:
9773 if ( printer )
9774 free_a_printer(&printer, 2);
9776 return result;
9779 /****************************************************************************
9780 ****************************************************************************/
9782 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9783 const char *servername,
9784 const char *environment,
9785 struct spoolss_PrintProcessorDirectoryInfo1 *r,
9786 uint32_t offered,
9787 uint32_t *needed)
9789 WERROR werr;
9790 char *path = NULL;
9792 werr = compose_spoolss_server_path(mem_ctx,
9793 servername,
9794 environment,
9795 SPOOLSS_PRTPROCS_PATH,
9796 &path);
9797 if (!W_ERROR_IS_OK(werr)) {
9798 return werr;
9801 DEBUG(4,("print processor directory: [%s]\n", path));
9803 r->directory_name = path;
9805 *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(r, NULL, 0);
9807 if (*needed > offered) {
9808 talloc_free(path);
9809 return WERR_INSUFFICIENT_BUFFER;
9812 return WERR_OK;
9815 /****************************************************************
9816 _spoolss_GetPrintProcessorDirectory
9817 ****************************************************************/
9819 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9820 struct spoolss_GetPrintProcessorDirectory *r)
9822 WERROR result;
9824 /* that's an [in out] buffer */
9826 if (!r->in.buffer && (r->in.offered != 0)) {
9827 return WERR_INVALID_PARAM;
9830 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9831 r->in.level));
9833 *r->out.needed = 0;
9835 /* r->in.level is ignored */
9837 result = getprintprocessordirectory_level_1(p->mem_ctx,
9838 r->in.server,
9839 r->in.environment,
9840 &r->out.info->info1,
9841 r->in.offered,
9842 r->out.needed);
9843 if (!W_ERROR_IS_OK(result)) {
9844 TALLOC_FREE(r->out.info);
9847 return result;
9850 /*******************************************************************
9851 ********************************************************************/
9853 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9854 const char *dllname)
9856 enum ndr_err_code ndr_err;
9857 struct spoolss_MonitorUi ui;
9859 ui.dll_name = dllname;
9861 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9862 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9863 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9864 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9866 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9869 /*******************************************************************
9870 Streams the monitor UI DLL name in UNICODE
9871 *******************************************************************/
9873 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9874 NT_USER_TOKEN *token, DATA_BLOB *in,
9875 DATA_BLOB *out, uint32_t *needed)
9877 const char *dllname = "tcpmonui.dll";
9879 *needed = (strlen(dllname)+1) * 2;
9881 if (out->length < *needed) {
9882 return WERR_INSUFFICIENT_BUFFER;
9885 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9886 return WERR_NOMEM;
9889 return WERR_OK;
9892 /*******************************************************************
9893 ********************************************************************/
9895 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9896 struct spoolss_PortData1 *port1,
9897 const DATA_BLOB *buf)
9899 enum ndr_err_code ndr_err;
9900 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9901 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9902 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9903 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9905 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9908 /*******************************************************************
9909 ********************************************************************/
9911 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9912 struct spoolss_PortData2 *port2,
9913 const DATA_BLOB *buf)
9915 enum ndr_err_code ndr_err;
9916 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9917 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9918 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9919 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9921 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9924 /*******************************************************************
9925 Create a new TCP/IP port
9926 *******************************************************************/
9928 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9929 NT_USER_TOKEN *token, DATA_BLOB *in,
9930 DATA_BLOB *out, uint32_t *needed)
9932 struct spoolss_PortData1 port1;
9933 struct spoolss_PortData2 port2;
9934 char *device_uri = NULL;
9935 uint32_t version;
9937 const char *portname;
9938 const char *hostaddress;
9939 const char *queue;
9940 uint32_t port_number;
9941 uint32_t protocol;
9943 /* peek for spoolss_PortData version */
9945 if (!in || (in->length < (128 + 4))) {
9946 return WERR_GENERAL_FAILURE;
9949 version = IVAL(in->data, 128);
9951 switch (version) {
9952 case 1:
9953 ZERO_STRUCT(port1);
9955 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9956 return WERR_NOMEM;
9959 portname = port1.portname;
9960 hostaddress = port1.hostaddress;
9961 queue = port1.queue;
9962 protocol = port1.protocol;
9963 port_number = port1.port_number;
9965 break;
9966 case 2:
9967 ZERO_STRUCT(port2);
9969 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9970 return WERR_NOMEM;
9973 portname = port2.portname;
9974 hostaddress = port2.hostaddress;
9975 queue = port2.queue;
9976 protocol = port2.protocol;
9977 port_number = port2.port_number;
9979 break;
9980 default:
9981 DEBUG(1,("xcvtcp_addport: "
9982 "unknown version of port_data: %d\n", version));
9983 return WERR_UNKNOWN_PORT;
9986 /* create the device URI and call the add_port_hook() */
9988 switch (protocol) {
9989 case PROTOCOL_RAWTCP_TYPE:
9990 device_uri = talloc_asprintf(mem_ctx,
9991 "socket://%s:%d/", hostaddress,
9992 port_number);
9993 break;
9995 case PROTOCOL_LPR_TYPE:
9996 device_uri = talloc_asprintf(mem_ctx,
9997 "lpr://%s/%s", hostaddress, queue );
9998 break;
10000 default:
10001 return WERR_UNKNOWN_PORT;
10004 if (!device_uri) {
10005 return WERR_NOMEM;
10008 return add_port_hook(mem_ctx, token, portname, device_uri);
10011 /*******************************************************************
10012 *******************************************************************/
10014 struct xcv_api_table xcvtcp_cmds[] = {
10015 { "MonitorUI", xcvtcp_monitorui },
10016 { "AddPort", xcvtcp_addport},
10017 { NULL, NULL }
10020 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10021 NT_USER_TOKEN *token, const char *command,
10022 DATA_BLOB *inbuf,
10023 DATA_BLOB *outbuf,
10024 uint32_t *needed )
10026 int i;
10028 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10030 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10031 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10032 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10035 return WERR_BADFUNC;
10038 /*******************************************************************
10039 *******************************************************************/
10040 #if 0 /* don't support management using the "Local Port" monitor */
10042 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10043 NT_USER_TOKEN *token, DATA_BLOB *in,
10044 DATA_BLOB *out, uint32_t *needed)
10046 const char *dllname = "localui.dll";
10048 *needed = (strlen(dllname)+1) * 2;
10050 if (out->length < *needed) {
10051 return WERR_INSUFFICIENT_BUFFER;
10054 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10055 return WERR_NOMEM;
10058 return WERR_OK;
10061 /*******************************************************************
10062 *******************************************************************/
10064 struct xcv_api_table xcvlocal_cmds[] = {
10065 { "MonitorUI", xcvlocal_monitorui },
10066 { NULL, NULL }
10068 #else
10069 struct xcv_api_table xcvlocal_cmds[] = {
10070 { NULL, NULL }
10072 #endif
10076 /*******************************************************************
10077 *******************************************************************/
10079 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10080 NT_USER_TOKEN *token, const char *command,
10081 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10082 uint32_t *needed)
10084 int i;
10086 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10088 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10089 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10090 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10092 return WERR_BADFUNC;
10095 /****************************************************************
10096 _spoolss_XcvData
10097 ****************************************************************/
10099 WERROR _spoolss_XcvData(pipes_struct *p,
10100 struct spoolss_XcvData *r)
10102 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10103 DATA_BLOB out_data;
10104 WERROR werror;
10106 if (!Printer) {
10107 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10108 OUR_HANDLE(r->in.handle)));
10109 return WERR_BADFID;
10112 /* Has to be a handle to the TCP/IP port monitor */
10114 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10115 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10116 return WERR_BADFID;
10119 /* requires administrative access to the server */
10121 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10122 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10123 return WERR_ACCESS_DENIED;
10126 /* Allocate the outgoing buffer */
10128 if (r->in.out_data_size) {
10129 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10130 if (out_data.data == NULL) {
10131 return WERR_NOMEM;
10135 switch ( Printer->printer_type ) {
10136 case SPLHND_PORTMON_TCP:
10137 werror = process_xcvtcp_command(p->mem_ctx,
10138 p->server_info->ptok,
10139 r->in.function_name,
10140 &r->in.in_data, &out_data,
10141 r->out.needed);
10142 break;
10143 case SPLHND_PORTMON_LOCAL:
10144 werror = process_xcvlocal_command(p->mem_ctx,
10145 p->server_info->ptok,
10146 r->in.function_name,
10147 &r->in.in_data, &out_data,
10148 r->out.needed);
10149 break;
10150 default:
10151 werror = WERR_INVALID_PRINT_MONITOR;
10154 if (!W_ERROR_IS_OK(werror)) {
10155 return werror;
10158 *r->out.status_code = 0;
10160 memcpy(r->out.out_data, out_data.data, out_data.length);
10162 return WERR_OK;
10165 /****************************************************************
10166 _spoolss_AddPrintProcessor
10167 ****************************************************************/
10169 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10170 struct spoolss_AddPrintProcessor *r)
10172 /* for now, just indicate success and ignore the add. We'll
10173 automatically set the winprint processor for printer
10174 entries later. Used to debug the LexMark Optra S 1855 PCL
10175 driver --jerry */
10177 return WERR_OK;
10180 /****************************************************************
10181 _spoolss_EnumPrinters
10182 ****************************************************************/
10184 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10185 struct spoolss_EnumPrinters *r)
10187 p->rng_fault_state = true;
10188 return WERR_NOT_SUPPORTED;
10191 /****************************************************************
10192 _spoolss_GetJob
10193 ****************************************************************/
10195 WERROR _spoolss_GetJob(pipes_struct *p,
10196 struct spoolss_GetJob *r)
10198 p->rng_fault_state = true;
10199 return WERR_NOT_SUPPORTED;
10202 /****************************************************************
10203 _spoolss_EnumJobs
10204 ****************************************************************/
10206 WERROR _spoolss_EnumJobs(pipes_struct *p,
10207 struct spoolss_EnumJobs *r)
10209 p->rng_fault_state = true;
10210 return WERR_NOT_SUPPORTED;
10213 /****************************************************************
10214 _spoolss_AddPrinter
10215 ****************************************************************/
10217 WERROR _spoolss_AddPrinter(pipes_struct *p,
10218 struct spoolss_AddPrinter *r)
10220 p->rng_fault_state = true;
10221 return WERR_NOT_SUPPORTED;
10224 /****************************************************************
10225 _spoolss_GetPrinter
10226 ****************************************************************/
10228 WERROR _spoolss_GetPrinter(pipes_struct *p,
10229 struct spoolss_GetPrinter *r)
10231 p->rng_fault_state = true;
10232 return WERR_NOT_SUPPORTED;
10235 /****************************************************************
10236 _spoolss_EnumPrinterDrivers
10237 ****************************************************************/
10239 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10240 struct spoolss_EnumPrinterDrivers *r)
10242 p->rng_fault_state = true;
10243 return WERR_NOT_SUPPORTED;
10246 /****************************************************************
10247 _spoolss_GetPrinterDriver
10248 ****************************************************************/
10250 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10251 struct spoolss_GetPrinterDriver *r)
10253 p->rng_fault_state = true;
10254 return WERR_NOT_SUPPORTED;
10257 /****************************************************************
10258 _spoolss_EnumPrintProcessors
10259 ****************************************************************/
10261 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10262 struct spoolss_EnumPrintProcessors *r)
10264 p->rng_fault_state = true;
10265 return WERR_NOT_SUPPORTED;
10268 /****************************************************************
10269 _spoolss_ReadPrinter
10270 ****************************************************************/
10272 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10273 struct spoolss_ReadPrinter *r)
10275 p->rng_fault_state = true;
10276 return WERR_NOT_SUPPORTED;
10279 /****************************************************************
10280 _spoolss_GetPrinterData
10281 ****************************************************************/
10283 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10284 struct spoolss_GetPrinterData *r)
10286 p->rng_fault_state = true;
10287 return WERR_NOT_SUPPORTED;
10290 /****************************************************************
10291 _spoolss_SetPrinterData
10292 ****************************************************************/
10294 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10295 struct spoolss_SetPrinterData *r)
10297 p->rng_fault_state = true;
10298 return WERR_NOT_SUPPORTED;
10301 /****************************************************************
10302 _spoolss_WaitForPrinterChange
10303 ****************************************************************/
10305 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10306 struct spoolss_WaitForPrinterChange *r)
10308 p->rng_fault_state = true;
10309 return WERR_NOT_SUPPORTED;
10312 /****************************************************************
10313 _spoolss_EnumForms
10314 ****************************************************************/
10316 WERROR _spoolss_EnumForms(pipes_struct *p,
10317 struct spoolss_EnumForms *r)
10319 p->rng_fault_state = true;
10320 return WERR_NOT_SUPPORTED;
10323 /****************************************************************
10324 _spoolss_EnumPorts
10325 ****************************************************************/
10327 WERROR _spoolss_EnumPorts(pipes_struct *p,
10328 struct spoolss_EnumPorts *r)
10330 p->rng_fault_state = true;
10331 return WERR_NOT_SUPPORTED;
10334 /****************************************************************
10335 _spoolss_EnumMonitors
10336 ****************************************************************/
10338 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10339 struct spoolss_EnumMonitors *r)
10341 p->rng_fault_state = true;
10342 return WERR_NOT_SUPPORTED;
10345 /****************************************************************
10346 _spoolss_AddPort
10347 ****************************************************************/
10349 WERROR _spoolss_AddPort(pipes_struct *p,
10350 struct spoolss_AddPort *r)
10352 p->rng_fault_state = true;
10353 return WERR_NOT_SUPPORTED;
10356 /****************************************************************
10357 _spoolss_ConfigurePort
10358 ****************************************************************/
10360 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10361 struct spoolss_ConfigurePort *r)
10363 p->rng_fault_state = true;
10364 return WERR_NOT_SUPPORTED;
10367 /****************************************************************
10368 _spoolss_DeletePort
10369 ****************************************************************/
10371 WERROR _spoolss_DeletePort(pipes_struct *p,
10372 struct spoolss_DeletePort *r)
10374 p->rng_fault_state = true;
10375 return WERR_NOT_SUPPORTED;
10378 /****************************************************************
10379 _spoolss_CreatePrinterIC
10380 ****************************************************************/
10382 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10383 struct spoolss_CreatePrinterIC *r)
10385 p->rng_fault_state = true;
10386 return WERR_NOT_SUPPORTED;
10389 /****************************************************************
10390 _spoolss_PlayGDIScriptOnPrinterIC
10391 ****************************************************************/
10393 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10394 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10396 p->rng_fault_state = true;
10397 return WERR_NOT_SUPPORTED;
10400 /****************************************************************
10401 _spoolss_DeletePrinterIC
10402 ****************************************************************/
10404 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10405 struct spoolss_DeletePrinterIC *r)
10407 p->rng_fault_state = true;
10408 return WERR_NOT_SUPPORTED;
10411 /****************************************************************
10412 _spoolss_AddPrinterConnection
10413 ****************************************************************/
10415 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10416 struct spoolss_AddPrinterConnection *r)
10418 p->rng_fault_state = true;
10419 return WERR_NOT_SUPPORTED;
10422 /****************************************************************
10423 _spoolss_DeletePrinterConnection
10424 ****************************************************************/
10426 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10427 struct spoolss_DeletePrinterConnection *r)
10429 p->rng_fault_state = true;
10430 return WERR_NOT_SUPPORTED;
10433 /****************************************************************
10434 _spoolss_PrinterMessageBox
10435 ****************************************************************/
10437 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10438 struct spoolss_PrinterMessageBox *r)
10440 p->rng_fault_state = true;
10441 return WERR_NOT_SUPPORTED;
10444 /****************************************************************
10445 _spoolss_AddMonitor
10446 ****************************************************************/
10448 WERROR _spoolss_AddMonitor(pipes_struct *p,
10449 struct spoolss_AddMonitor *r)
10451 p->rng_fault_state = true;
10452 return WERR_NOT_SUPPORTED;
10455 /****************************************************************
10456 _spoolss_DeleteMonitor
10457 ****************************************************************/
10459 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10460 struct spoolss_DeleteMonitor *r)
10462 p->rng_fault_state = true;
10463 return WERR_NOT_SUPPORTED;
10466 /****************************************************************
10467 _spoolss_DeletePrintProcessor
10468 ****************************************************************/
10470 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10471 struct spoolss_DeletePrintProcessor *r)
10473 p->rng_fault_state = true;
10474 return WERR_NOT_SUPPORTED;
10477 /****************************************************************
10478 _spoolss_AddPrintProvidor
10479 ****************************************************************/
10481 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10482 struct spoolss_AddPrintProvidor *r)
10484 p->rng_fault_state = true;
10485 return WERR_NOT_SUPPORTED;
10488 /****************************************************************
10489 _spoolss_DeletePrintProvidor
10490 ****************************************************************/
10492 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10493 struct spoolss_DeletePrintProvidor *r)
10495 p->rng_fault_state = true;
10496 return WERR_NOT_SUPPORTED;
10499 /****************************************************************
10500 _spoolss_EnumPrintProcDataTypes
10501 ****************************************************************/
10503 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10504 struct spoolss_EnumPrintProcDataTypes *r)
10506 p->rng_fault_state = true;
10507 return WERR_NOT_SUPPORTED;
10510 /****************************************************************
10511 _spoolss_GetPrinterDriver2
10512 ****************************************************************/
10514 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10515 struct spoolss_GetPrinterDriver2 *r)
10517 p->rng_fault_state = true;
10518 return WERR_NOT_SUPPORTED;
10521 /****************************************************************
10522 _spoolss_FindFirstPrinterChangeNotification
10523 ****************************************************************/
10525 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10526 struct spoolss_FindFirstPrinterChangeNotification *r)
10528 p->rng_fault_state = true;
10529 return WERR_NOT_SUPPORTED;
10532 /****************************************************************
10533 _spoolss_FindNextPrinterChangeNotification
10534 ****************************************************************/
10536 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10537 struct spoolss_FindNextPrinterChangeNotification *r)
10539 p->rng_fault_state = true;
10540 return WERR_NOT_SUPPORTED;
10543 /****************************************************************
10544 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10545 ****************************************************************/
10547 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10548 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10550 p->rng_fault_state = true;
10551 return WERR_NOT_SUPPORTED;
10554 /****************************************************************
10555 _spoolss_ReplyOpenPrinter
10556 ****************************************************************/
10558 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10559 struct spoolss_ReplyOpenPrinter *r)
10561 p->rng_fault_state = true;
10562 return WERR_NOT_SUPPORTED;
10565 /****************************************************************
10566 _spoolss_RouterReplyPrinter
10567 ****************************************************************/
10569 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10570 struct spoolss_RouterReplyPrinter *r)
10572 p->rng_fault_state = true;
10573 return WERR_NOT_SUPPORTED;
10576 /****************************************************************
10577 _spoolss_ReplyClosePrinter
10578 ****************************************************************/
10580 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10581 struct spoolss_ReplyClosePrinter *r)
10583 p->rng_fault_state = true;
10584 return WERR_NOT_SUPPORTED;
10587 /****************************************************************
10588 _spoolss_AddPortEx
10589 ****************************************************************/
10591 WERROR _spoolss_AddPortEx(pipes_struct *p,
10592 struct spoolss_AddPortEx *r)
10594 p->rng_fault_state = true;
10595 return WERR_NOT_SUPPORTED;
10598 /****************************************************************
10599 _spoolss_RouterFindFirstPrinterChangeNotification
10600 ****************************************************************/
10602 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10603 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10605 p->rng_fault_state = true;
10606 return WERR_NOT_SUPPORTED;
10609 /****************************************************************
10610 _spoolss_SpoolerInit
10611 ****************************************************************/
10613 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10614 struct spoolss_SpoolerInit *r)
10616 p->rng_fault_state = true;
10617 return WERR_NOT_SUPPORTED;
10620 /****************************************************************
10621 _spoolss_ResetPrinterEx
10622 ****************************************************************/
10624 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10625 struct spoolss_ResetPrinterEx *r)
10627 p->rng_fault_state = true;
10628 return WERR_NOT_SUPPORTED;
10631 /****************************************************************
10632 _spoolss_RouterReplyPrinterEx
10633 ****************************************************************/
10635 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10636 struct spoolss_RouterReplyPrinterEx *r)
10638 p->rng_fault_state = true;
10639 return WERR_NOT_SUPPORTED;
10642 /****************************************************************
10643 _spoolss_44
10644 ****************************************************************/
10646 WERROR _spoolss_44(pipes_struct *p,
10647 struct spoolss_44 *r)
10649 p->rng_fault_state = true;
10650 return WERR_NOT_SUPPORTED;
10653 /****************************************************************
10654 _spoolss_47
10655 ****************************************************************/
10657 WERROR _spoolss_47(pipes_struct *p,
10658 struct spoolss_47 *r)
10660 p->rng_fault_state = true;
10661 return WERR_NOT_SUPPORTED;
10664 /****************************************************************
10665 _spoolss_EnumPrinterData
10666 ****************************************************************/
10668 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10669 struct spoolss_EnumPrinterData *r)
10671 p->rng_fault_state = true;
10672 return WERR_NOT_SUPPORTED;
10675 /****************************************************************
10676 _spoolss_4a
10677 ****************************************************************/
10679 WERROR _spoolss_4a(pipes_struct *p,
10680 struct spoolss_4a *r)
10682 p->rng_fault_state = true;
10683 return WERR_NOT_SUPPORTED;
10686 /****************************************************************
10687 _spoolss_4b
10688 ****************************************************************/
10690 WERROR _spoolss_4b(pipes_struct *p,
10691 struct spoolss_4b *r)
10693 p->rng_fault_state = true;
10694 return WERR_NOT_SUPPORTED;
10697 /****************************************************************
10698 _spoolss_4c
10699 ****************************************************************/
10701 WERROR _spoolss_4c(pipes_struct *p,
10702 struct spoolss_4c *r)
10704 p->rng_fault_state = true;
10705 return WERR_NOT_SUPPORTED;
10708 /****************************************************************
10709 _spoolss_EnumPrinterDataEx
10710 ****************************************************************/
10712 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10713 struct spoolss_EnumPrinterDataEx *r)
10715 p->rng_fault_state = true;
10716 return WERR_NOT_SUPPORTED;
10719 /****************************************************************
10720 _spoolss_EnumPrinterKey
10721 ****************************************************************/
10723 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10724 struct spoolss_EnumPrinterKey *r)
10726 p->rng_fault_state = true;
10727 return WERR_NOT_SUPPORTED;
10730 /****************************************************************
10731 _spoolss_53
10732 ****************************************************************/
10734 WERROR _spoolss_53(pipes_struct *p,
10735 struct spoolss_53 *r)
10737 p->rng_fault_state = true;
10738 return WERR_NOT_SUPPORTED;
10741 /****************************************************************
10742 _spoolss_55
10743 ****************************************************************/
10745 WERROR _spoolss_55(pipes_struct *p,
10746 struct spoolss_55 *r)
10748 p->rng_fault_state = true;
10749 return WERR_NOT_SUPPORTED;
10752 /****************************************************************
10753 _spoolss_56
10754 ****************************************************************/
10756 WERROR _spoolss_56(pipes_struct *p,
10757 struct spoolss_56 *r)
10759 p->rng_fault_state = true;
10760 return WERR_NOT_SUPPORTED;
10763 /****************************************************************
10764 _spoolss_57
10765 ****************************************************************/
10767 WERROR _spoolss_57(pipes_struct *p,
10768 struct spoolss_57 *r)
10770 p->rng_fault_state = true;
10771 return WERR_NOT_SUPPORTED;
10774 /****************************************************************
10775 _spoolss_5a
10776 ****************************************************************/
10778 WERROR _spoolss_5a(pipes_struct *p,
10779 struct spoolss_5a *r)
10781 p->rng_fault_state = true;
10782 return WERR_NOT_SUPPORTED;
10785 /****************************************************************
10786 _spoolss_5b
10787 ****************************************************************/
10789 WERROR _spoolss_5b(pipes_struct *p,
10790 struct spoolss_5b *r)
10792 p->rng_fault_state = true;
10793 return WERR_NOT_SUPPORTED;
10796 /****************************************************************
10797 _spoolss_5c
10798 ****************************************************************/
10800 WERROR _spoolss_5c(pipes_struct *p,
10801 struct spoolss_5c *r)
10803 p->rng_fault_state = true;
10804 return WERR_NOT_SUPPORTED;
10807 /****************************************************************
10808 _spoolss_5d
10809 ****************************************************************/
10811 WERROR _spoolss_5d(pipes_struct *p,
10812 struct spoolss_5d *r)
10814 p->rng_fault_state = true;
10815 return WERR_NOT_SUPPORTED;
10818 /****************************************************************
10819 _spoolss_5e
10820 ****************************************************************/
10822 WERROR _spoolss_5e(pipes_struct *p,
10823 struct spoolss_5e *r)
10825 p->rng_fault_state = true;
10826 return WERR_NOT_SUPPORTED;
10829 /****************************************************************
10830 _spoolss_5f
10831 ****************************************************************/
10833 WERROR _spoolss_5f(pipes_struct *p,
10834 struct spoolss_5f *r)
10836 p->rng_fault_state = true;
10837 return WERR_NOT_SUPPORTED;