s3-rpc_client: move protos to cli_lsarpc.h
[Samba/ekacnet.git] / source3 / rpc_server / srv_spoolss_nt.c
bloba9935150150771c845a7955b8afe773833592744
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.
10 * Copyright (C) Guenther Deschner 2009-2010.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "librpc/gen_ndr/messaging.h"
33 #include "registry.h"
35 /* macros stolen from s4 spoolss server */
36 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
37 ((info)?ndr_size_##fn(info, level, 0):0)
39 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
40 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
42 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
43 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
45 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
48 extern userdom_struct current_user_info;
50 #undef DBGC_CLASS
51 #define DBGC_CLASS DBGC_RPC_SRV
53 #ifndef MAX_OPEN_PRINTER_EXS
54 #define MAX_OPEN_PRINTER_EXS 50
55 #endif
57 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
59 static Printer_entry *printers_list;
61 typedef struct _counter_printer_0 {
62 struct _counter_printer_0 *next;
63 struct _counter_printer_0 *prev;
65 int snum;
66 uint32_t counter;
67 } counter_printer_0;
69 static counter_printer_0 *counter_list;
71 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
72 static uint32_t smb_connections = 0;
75 /* in printing/nt_printing.c */
77 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
79 /* API table for Xcv Monitor functions */
81 struct xcv_api_table {
82 const char *name;
83 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
86 /********************************************************************
87 * Canonicalize servername.
88 ********************************************************************/
90 static const char *canon_servername(const char *servername)
92 const char *pservername = servername;
93 while (*pservername == '\\') {
94 pservername++;
96 return pservername;
99 /* translate between internal status numbers and NT status numbers */
100 static int nt_printj_status(int v)
102 switch (v) {
103 case LPQ_QUEUED:
104 return 0;
105 case LPQ_PAUSED:
106 return JOB_STATUS_PAUSED;
107 case LPQ_SPOOLING:
108 return JOB_STATUS_SPOOLING;
109 case LPQ_PRINTING:
110 return JOB_STATUS_PRINTING;
111 case LPQ_ERROR:
112 return JOB_STATUS_ERROR;
113 case LPQ_DELETING:
114 return JOB_STATUS_DELETING;
115 case LPQ_OFFLINE:
116 return JOB_STATUS_OFFLINE;
117 case LPQ_PAPEROUT:
118 return JOB_STATUS_PAPEROUT;
119 case LPQ_PRINTED:
120 return JOB_STATUS_PRINTED;
121 case LPQ_DELETED:
122 return JOB_STATUS_DELETED;
123 case LPQ_BLOCKED:
124 return JOB_STATUS_BLOCKED_DEVQ;
125 case LPQ_USER_INTERVENTION:
126 return JOB_STATUS_USER_INTERVENTION;
128 return 0;
131 static int nt_printq_status(int v)
133 switch (v) {
134 case LPQ_PAUSED:
135 return PRINTER_STATUS_PAUSED;
136 case LPQ_QUEUED:
137 case LPQ_SPOOLING:
138 case LPQ_PRINTING:
139 return 0;
141 return 0;
144 /***************************************************************************
145 Disconnect from the client
146 ****************************************************************************/
148 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
150 WERROR result;
151 NTSTATUS status;
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 return;
167 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
168 handle,
169 &result);
170 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
171 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
172 win_errstr(result)));
174 /* if it's the last connection, deconnect the IPC$ share */
175 if (smb_connections==1) {
177 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
178 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
180 messaging_deregister(smbd_messaging_context(),
181 MSG_PRINTER_NOTIFY2, NULL);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
189 smb_connections--;
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static int printer_entry_destructor(Printer_entry *Printer)
198 if (Printer->notify.client_connected == true) {
199 int snum = -1;
201 if ( Printer->printer_type == SPLHND_SERVER) {
202 snum = -1;
203 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
204 } else if (Printer->printer_type == SPLHND_PRINTER) {
205 snum = print_queue_snum(Printer->sharename);
206 if (snum != -1)
207 srv_spoolss_replycloseprinter(snum,
208 &Printer->notify.client_hnd);
212 Printer->notify.flags=0;
213 Printer->notify.options=0;
214 Printer->notify.localmachine[0]='\0';
215 Printer->notify.printerlocal=0;
216 TALLOC_FREE(Printer->notify.option);
217 Printer->notify.client_connected = false;
219 free_nt_devicemode( &Printer->nt_devmode );
220 free_a_printer( &Printer->printer_info, 2 );
222 /* Remove from the internal list. */
223 DLIST_REMOVE(printers_list, Printer);
224 return 0;
227 /****************************************************************************
228 find printer index by handle
229 ****************************************************************************/
231 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
232 struct policy_handle *hnd)
234 Printer_entry *find_printer = NULL;
236 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
237 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
238 return NULL;
241 return find_printer;
244 /****************************************************************************
245 Close printer index by handle.
246 ****************************************************************************/
248 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
250 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
252 if (!Printer) {
253 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
254 OUR_HANDLE(hnd)));
255 return false;
258 close_policy_hnd(p, hnd);
260 return true;
263 /****************************************************************************
264 Delete a printer given a handle.
265 ****************************************************************************/
267 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
269 char *cmd = lp_deleteprinter_cmd();
270 char *command = NULL;
271 int ret;
272 SE_PRIV se_printop = SE_PRINT_OPERATOR;
273 bool is_print_op = false;
275 /* can't fail if we don't try */
277 if ( !*cmd )
278 return WERR_OK;
280 command = talloc_asprintf(ctx,
281 "%s \"%s\"",
282 cmd, sharename);
283 if (!command) {
284 return WERR_NOMEM;
286 if ( token )
287 is_print_op = user_has_privileges( token, &se_printop );
289 DEBUG(10,("Running [%s]\n", command));
291 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
293 if ( is_print_op )
294 become_root();
296 if ( (ret = smbrun(command, NULL)) == 0 ) {
297 /* Tell everyone we updated smb.conf. */
298 message_send_all(smbd_messaging_context(),
299 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
302 if ( is_print_op )
303 unbecome_root();
305 /********** END SePrintOperatorPrivlege BLOCK **********/
307 DEBUGADD(10,("returned [%d]\n", ret));
309 TALLOC_FREE(command);
311 if (ret != 0)
312 return WERR_BADFID; /* What to return here? */
314 /* go ahead and re-read the services immediately */
315 become_root();
316 reload_services(false);
317 unbecome_root();
319 if ( lp_servicenumber( sharename ) > 0 )
320 return WERR_ACCESS_DENIED;
322 return WERR_OK;
325 /****************************************************************************
326 Delete a printer given a handle.
327 ****************************************************************************/
329 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
331 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
333 if (!Printer) {
334 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
335 OUR_HANDLE(hnd)));
336 return WERR_BADFID;
340 * It turns out that Windows allows delete printer on a handle
341 * opened by an admin user, then used on a pipe handle created
342 * by an anonymous user..... but they're working on security.... riiight !
343 * JRA.
346 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
347 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
348 return WERR_ACCESS_DENIED;
351 /* this does not need a become root since the access check has been
352 done on the handle already */
354 if (del_a_printer( Printer->sharename ) != 0) {
355 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
356 return WERR_BADFID;
359 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
360 Printer->sharename );
363 /****************************************************************************
364 Return the snum of a printer corresponding to an handle.
365 ****************************************************************************/
367 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
368 int *number, struct share_params **params)
370 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
372 if (!Printer) {
373 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
374 OUR_HANDLE(hnd)));
375 return false;
378 switch (Printer->printer_type) {
379 case SPLHND_PRINTER:
380 DEBUG(4,("short name:%s\n", Printer->sharename));
381 *number = print_queue_snum(Printer->sharename);
382 return (*number != -1);
383 case SPLHND_SERVER:
384 return false;
385 default:
386 return false;
390 /****************************************************************************
391 Set printer handle type.
392 Check if it's \\server or \\server\printer
393 ****************************************************************************/
395 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
397 DEBUG(3,("Setting printer type=%s\n", handlename));
399 if ( strlen(handlename) < 3 ) {
400 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
401 return false;
404 /* it's a print server */
405 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
406 DEBUGADD(4,("Printer is a print server\n"));
407 Printer->printer_type = SPLHND_SERVER;
409 /* it's a printer (set_printer_hnd_name() will handle port monitors */
410 else {
411 DEBUGADD(4,("Printer is a printer\n"));
412 Printer->printer_type = SPLHND_PRINTER;
415 return true;
418 /****************************************************************************
419 Set printer handle name.. Accept names like \\server, \\server\printer,
420 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
421 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
422 XcvDataPort() interface.
423 ****************************************************************************/
425 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
427 int snum;
428 int n_services=lp_numservices();
429 char *aprinter, *printername;
430 const char *servername;
431 fstring sname;
432 bool found = false;
433 NT_PRINTER_INFO_LEVEL *printer = NULL;
434 WERROR result;
436 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
437 (unsigned long)strlen(handlename)));
439 aprinter = CONST_DISCARD(char *, handlename);
440 if ( *handlename == '\\' ) {
441 servername = canon_servername(handlename);
442 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
443 *aprinter = '\0';
444 aprinter++;
446 } else {
447 servername = global_myname();
450 /* save the servername to fill in replies on this handle */
452 if ( !is_myname_or_ipaddr( servername ) )
453 return false;
455 fstrcpy( Printer->servername, servername );
457 if ( Printer->printer_type == SPLHND_SERVER )
458 return true;
460 if ( Printer->printer_type != SPLHND_PRINTER )
461 return false;
463 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
465 /* check for the Port Monitor Interface */
467 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
468 Printer->printer_type = SPLHND_PORTMON_TCP;
469 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
470 found = true;
472 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
473 Printer->printer_type = SPLHND_PORTMON_LOCAL;
474 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
475 found = true;
478 /* Search all sharenames first as this is easier than pulling
479 the printer_info_2 off of disk. Don't use find_service() since
480 that calls out to map_username() */
482 /* do another loop to look for printernames */
484 for (snum=0; !found && snum<n_services; snum++) {
486 /* no point going on if this is not a printer */
488 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
489 continue;
491 fstrcpy(sname, lp_servicename(snum));
492 if ( strequal( aprinter, sname ) ) {
493 found = true;
494 break;
497 /* no point looking up the printer object if
498 we aren't allowing printername != sharename */
500 if ( lp_force_printername(snum) )
501 continue;
503 fstrcpy(sname, lp_servicename(snum));
505 printer = NULL;
507 /* This call doesn't fill in the location or comment from
508 * a CUPS server for efficiency with large numbers of printers.
509 * JRA.
512 result = get_a_printer_search( NULL, &printer, 2, sname );
513 if ( !W_ERROR_IS_OK(result) ) {
514 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
515 sname, win_errstr(result)));
516 continue;
519 /* printername is always returned as \\server\printername */
520 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
521 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
522 printer->info_2->printername));
523 free_a_printer( &printer, 2);
524 continue;
527 printername++;
529 if ( strequal(printername, aprinter) ) {
530 free_a_printer( &printer, 2);
531 found = true;
532 break;
535 DEBUGADD(10, ("printername: %s\n", printername));
537 free_a_printer( &printer, 2);
540 free_a_printer( &printer, 2);
542 if ( !found ) {
543 DEBUGADD(4,("Printer not found\n"));
544 return false;
547 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
549 fstrcpy(Printer->sharename, sname);
551 return true;
554 /****************************************************************************
555 Find first available printer slot. creates a printer handle for you.
556 ****************************************************************************/
558 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
559 const char *name, uint32_t access_granted)
561 Printer_entry *new_printer;
563 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
565 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
566 if (new_printer == NULL) {
567 return false;
569 talloc_set_destructor(new_printer, printer_entry_destructor);
571 if (!create_policy_hnd(p, hnd, new_printer)) {
572 TALLOC_FREE(new_printer);
573 return false;
576 /* Add to the internal list. */
577 DLIST_ADD(printers_list, new_printer);
579 new_printer->notify.option=NULL;
581 if (!set_printer_hnd_printertype(new_printer, name)) {
582 close_printer_handle(p, hnd);
583 return false;
586 if (!set_printer_hnd_name(new_printer, name)) {
587 close_printer_handle(p, hnd);
588 return false;
591 new_printer->access_granted = access_granted;
593 DEBUG(5, ("%d printer handles active\n",
594 (int)num_pipe_handles(p->pipe_handles)));
596 return true;
599 /***************************************************************************
600 check to see if the client motify handle is monitoring the notification
601 given by (notify_type, notify_field).
602 **************************************************************************/
604 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
605 uint16_t notify_field)
607 return true;
610 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
611 uint16_t notify_field)
613 struct spoolss_NotifyOption *option = p->notify.option;
614 uint32_t i, j;
617 * Flags should always be zero when the change notify
618 * is registered by the client's spooler. A user Win32 app
619 * might use the flags though instead of the NOTIFY_OPTION_INFO
620 * --jerry
623 if (!option) {
624 return false;
627 if (p->notify.flags)
628 return is_monitoring_event_flags(
629 p->notify.flags, notify_type, notify_field);
631 for (i = 0; i < option->count; i++) {
633 /* Check match for notify_type */
635 if (option->types[i].type != notify_type)
636 continue;
638 /* Check match for field */
640 for (j = 0; j < option->types[i].count; j++) {
641 if (option->types[i].fields[j].field == notify_field) {
642 return true;
647 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
648 p->servername, p->sharename, notify_type, notify_field));
650 return false;
653 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
654 _data->data.integer[0] = _integer; \
655 _data->data.integer[1] = 0;
658 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
659 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
660 if (!_data->data.string.string) {\
661 _data->data.string.size = 0; \
663 _data->data.string.size = strlen_m_term(_p) * 2;
665 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
666 _data->data.devmode.devmode = _devmode;
668 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
669 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
670 if (!_data->data.sd.sd) { \
671 _data->data.sd.sd_size = 0; \
673 _data->data.sd.sd_size = _size;
675 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
676 struct tm *t,
677 const char **pp,
678 uint32_t *plen)
680 struct spoolss_Time st;
681 uint32_t len = 16;
682 char *p;
684 if (!init_systemtime(&st, t)) {
685 return;
688 p = talloc_array(mem_ctx, char, len);
689 if (!p) {
690 return;
694 * Systemtime must be linearized as a set of UINT16's.
695 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
698 SSVAL(p, 0, st.year);
699 SSVAL(p, 2, st.month);
700 SSVAL(p, 4, st.day_of_week);
701 SSVAL(p, 6, st.day);
702 SSVAL(p, 8, st.hour);
703 SSVAL(p, 10, st.minute);
704 SSVAL(p, 12, st.second);
705 SSVAL(p, 14, st.millisecond);
707 *pp = p;
708 *plen = len;
711 /* Convert a notification message to a struct spoolss_Notify */
713 static void notify_one_value(struct spoolss_notify_msg *msg,
714 struct spoolss_Notify *data,
715 TALLOC_CTX *mem_ctx)
717 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
720 static void notify_string(struct spoolss_notify_msg *msg,
721 struct spoolss_Notify *data,
722 TALLOC_CTX *mem_ctx)
724 /* The length of the message includes the trailing \0 */
726 data->data.string.size = msg->len * 2;
727 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
728 if (!data->data.string.string) {
729 data->data.string.size = 0;
730 return;
734 static void notify_system_time(struct spoolss_notify_msg *msg,
735 struct spoolss_Notify *data,
736 TALLOC_CTX *mem_ctx)
738 data->data.string.string = NULL;
739 data->data.string.size = 0;
741 if (msg->len != sizeof(time_t)) {
742 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
743 msg->len));
744 return;
747 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
748 &data->data.string.string,
749 &data->data.string.size);
752 struct notify2_message_table {
753 const char *name;
754 void (*fn)(struct spoolss_notify_msg *msg,
755 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
758 static struct notify2_message_table printer_notify_table[] = {
759 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
760 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
761 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
762 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
763 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
764 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
765 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
766 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
767 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
768 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
769 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
770 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
771 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
772 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
773 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
774 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
775 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
776 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
777 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
780 static struct notify2_message_table job_notify_table[] = {
781 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
782 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
783 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
784 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
785 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
786 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
787 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
788 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
789 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
790 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
791 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
792 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
793 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
794 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
795 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
796 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
797 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
798 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
799 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
800 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
801 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
802 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
803 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
804 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
808 /***********************************************************************
809 Allocate talloc context for container object
810 **********************************************************************/
812 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 if ( !ctr )
815 return;
817 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
819 return;
822 /***********************************************************************
823 release all allocated memory and zero out structure
824 **********************************************************************/
826 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
828 if ( !ctr )
829 return;
831 if ( ctr->ctx )
832 talloc_destroy(ctr->ctx);
834 ZERO_STRUCTP(ctr);
836 return;
839 /***********************************************************************
840 **********************************************************************/
842 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
844 if ( !ctr )
845 return NULL;
847 return ctr->ctx;
850 /***********************************************************************
851 **********************************************************************/
853 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
855 if ( !ctr || !ctr->msg_groups )
856 return NULL;
858 if ( idx >= ctr->num_groups )
859 return NULL;
861 return &ctr->msg_groups[idx];
865 /***********************************************************************
866 How many groups of change messages do we have ?
867 **********************************************************************/
869 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
871 if ( !ctr )
872 return 0;
874 return ctr->num_groups;
877 /***********************************************************************
878 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
879 **********************************************************************/
881 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
883 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
884 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
885 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
886 int i, new_slot;
888 if ( !ctr || !msg )
889 return 0;
891 /* loop over all groups looking for a matching printer name */
893 for ( i=0; i<ctr->num_groups; i++ ) {
894 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
895 break;
898 /* add a new group? */
900 if ( i == ctr->num_groups ) {
901 ctr->num_groups++;
903 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
904 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
905 return 0;
907 ctr->msg_groups = groups;
909 /* clear the new entry and set the printer name */
911 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
912 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
915 /* add the change messages; 'i' is the correct index now regardless */
917 msg_grp = &ctr->msg_groups[i];
919 msg_grp->num_msgs++;
921 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
922 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
923 return 0;
925 msg_grp->msgs = msg_list;
927 new_slot = msg_grp->num_msgs-1;
928 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
930 /* need to allocate own copy of data */
932 if ( msg->len != 0 )
933 msg_grp->msgs[new_slot].notify.data = (char *)
934 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
936 return ctr->num_groups;
939 void construct_info_data(struct spoolss_Notify *info_data,
940 enum spoolss_NotifyType type,
941 uint16_t field,
942 int id);
944 /***********************************************************************
945 Send a change notication message on all handles which have a call
946 back registered
947 **********************************************************************/
949 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
951 Printer_entry *p;
952 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
953 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
954 SPOOLSS_NOTIFY_MSG *messages;
955 int sending_msg_count;
957 if ( !msg_group ) {
958 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
959 return;
962 messages = msg_group->msgs;
964 if ( !messages ) {
965 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
966 return;
969 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
971 /* loop over all printers */
973 for (p = printers_list; p; p = p->next) {
974 struct spoolss_Notify *notifies;
975 uint32_t count = 0;
976 uint32_t id;
977 int i;
979 /* Is there notification on this handle? */
981 if ( !p->notify.client_connected )
982 continue;
984 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
986 /* For this printer? Print servers always receive
987 notifications. */
989 if ( ( p->printer_type == SPLHND_PRINTER ) &&
990 ( !strequal(msg_group->printername, p->sharename) ) )
991 continue;
993 DEBUG(10,("Our printer\n"));
995 /* allocate the max entries possible */
997 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
998 if (!notifies) {
999 return;
1002 /* build the array of change notifications */
1004 sending_msg_count = 0;
1006 for ( i=0; i<msg_group->num_msgs; i++ ) {
1007 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1009 /* Are we monitoring this event? */
1011 if (!is_monitoring_event(p, msg->type, msg->field))
1012 continue;
1014 sending_msg_count++;
1017 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1018 msg->type, msg->field, p->sharename));
1021 * if the is a printer notification handle and not a job notification
1022 * type, then set the id to 0. Other wise just use what was specified
1023 * in the message.
1025 * When registering change notification on a print server handle
1026 * we always need to send back the id (snum) matching the printer
1027 * for which the change took place. For change notify registered
1028 * on a printer handle, this does not matter and the id should be 0.
1030 * --jerry
1033 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1034 id = 0;
1035 else
1036 id = msg->id;
1039 /* Convert unix jobid to smb jobid */
1041 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1042 id = sysjob_to_jobid(msg->id);
1044 if (id == -1) {
1045 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1046 goto done;
1050 construct_info_data( &notifies[count], msg->type, msg->field, id );
1052 switch(msg->type) {
1053 case PRINTER_NOTIFY_TYPE:
1054 if ( printer_notify_table[msg->field].fn )
1055 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1056 break;
1058 case JOB_NOTIFY_TYPE:
1059 if ( job_notify_table[msg->field].fn )
1060 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1061 break;
1063 default:
1064 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1065 goto done;
1068 count++;
1071 if ( sending_msg_count ) {
1072 NTSTATUS status;
1073 WERROR werr;
1074 union spoolss_ReplyPrinterInfo info;
1075 struct spoolss_NotifyInfo info0;
1076 uint32_t reply_result;
1078 info0.version = 0x2;
1079 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1080 info0.count = count;
1081 info0.notifies = notifies;
1083 info.info0 = &info0;
1085 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1086 &p->notify.client_hnd,
1087 p->notify.change, /* color */
1088 p->notify.flags,
1089 &reply_result,
1090 0, /* reply_type, must be 0 */
1091 info,
1092 &werr);
1093 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1094 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1095 notify_cli_pipe->srv_name_slash,
1096 win_errstr(werr)));
1098 switch (reply_result) {
1099 case 0:
1100 break;
1101 case PRINTER_NOTIFY_INFO_DISCARDED:
1102 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1103 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1104 break;
1105 default:
1106 break;
1111 done:
1112 DEBUG(8,("send_notify2_changes: Exit...\n"));
1113 return;
1116 /***********************************************************************
1117 **********************************************************************/
1119 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1122 uint32_t tv_sec, tv_usec;
1123 size_t offset = 0;
1125 /* Unpack message */
1127 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1128 msg->printer);
1130 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1131 &tv_sec, &tv_usec,
1132 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1134 if (msg->len == 0)
1135 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1136 &msg->notify.value[0], &msg->notify.value[1]);
1137 else
1138 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1139 &msg->len, &msg->notify.data);
1141 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1142 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1144 tv->tv_sec = tv_sec;
1145 tv->tv_usec = tv_usec;
1147 if (msg->len == 0)
1148 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1149 msg->notify.value[1]));
1150 else
1151 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1153 return true;
1156 /********************************************************************
1157 Receive a notify2 message list
1158 ********************************************************************/
1160 static void receive_notify2_message_list(struct messaging_context *msg,
1161 void *private_data,
1162 uint32_t msg_type,
1163 struct server_id server_id,
1164 DATA_BLOB *data)
1166 size_t msg_count, i;
1167 char *buf = (char *)data->data;
1168 char *msg_ptr;
1169 size_t msg_len;
1170 SPOOLSS_NOTIFY_MSG notify;
1171 SPOOLSS_NOTIFY_MSG_CTR messages;
1172 int num_groups;
1174 if (data->length < 4) {
1175 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1176 return;
1179 msg_count = IVAL(buf, 0);
1180 msg_ptr = buf + 4;
1182 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1184 if (msg_count == 0) {
1185 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1186 return;
1189 /* initialize the container */
1191 ZERO_STRUCT( messages );
1192 notify_msg_ctr_init( &messages );
1195 * build message groups for each printer identified
1196 * in a change_notify msg. Remember that a PCN message
1197 * includes the handle returned for the srv_spoolss_replyopenprinter()
1198 * call. Therefore messages are grouped according to printer handle.
1201 for ( i=0; i<msg_count; i++ ) {
1202 struct timeval msg_tv;
1204 if (msg_ptr + 4 - buf > data->length) {
1205 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1206 return;
1209 msg_len = IVAL(msg_ptr,0);
1210 msg_ptr += 4;
1212 if (msg_ptr + msg_len - buf > data->length) {
1213 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1214 return;
1217 /* unpack messages */
1219 ZERO_STRUCT( notify );
1220 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1221 msg_ptr += msg_len;
1223 /* add to correct list in container */
1225 notify_msg_ctr_addmsg( &messages, &notify );
1227 /* free memory that might have been allocated by notify2_unpack_msg() */
1229 if ( notify.len != 0 )
1230 SAFE_FREE( notify.notify.data );
1233 /* process each group of messages */
1235 num_groups = notify_msg_ctr_numgroups( &messages );
1236 for ( i=0; i<num_groups; i++ )
1237 send_notify2_changes( &messages, i );
1240 /* cleanup */
1242 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1243 (uint32_t)msg_count ));
1245 notify_msg_ctr_destroy( &messages );
1247 return;
1250 /********************************************************************
1251 Send a message to ourself about new driver being installed
1252 so we can upgrade the information for each printer bound to this
1253 driver
1254 ********************************************************************/
1256 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1258 int len = strlen(drivername);
1260 if (!len)
1261 return false;
1263 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1264 drivername));
1266 messaging_send_buf(smbd_messaging_context(), procid_self(),
1267 MSG_PRINTER_DRVUPGRADE,
1268 (uint8_t *)drivername, len+1);
1270 return true;
1273 /**********************************************************************
1274 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1275 over all printers, upgrading ones as necessary
1276 **********************************************************************/
1278 void do_drv_upgrade_printer(struct messaging_context *msg,
1279 void *private_data,
1280 uint32_t msg_type,
1281 struct server_id server_id,
1282 DATA_BLOB *data)
1284 fstring drivername;
1285 int snum;
1286 int n_services = lp_numservices();
1287 size_t len;
1289 len = MIN(data->length,sizeof(drivername)-1);
1290 strncpy(drivername, (const char *)data->data, len);
1292 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1294 /* Iterate the printer list */
1296 for (snum=0; snum<n_services; snum++)
1298 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1300 WERROR result;
1301 NT_PRINTER_INFO_LEVEL *printer = NULL;
1303 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1304 if (!W_ERROR_IS_OK(result))
1305 continue;
1307 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1309 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1311 /* all we care about currently is the change_id */
1313 result = mod_a_printer(printer, 2);
1314 if (!W_ERROR_IS_OK(result)) {
1315 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1316 win_errstr(result)));
1320 free_a_printer(&printer, 2);
1324 /* all done */
1327 /********************************************************************
1328 Update the cache for all printq's with a registered client
1329 connection
1330 ********************************************************************/
1332 void update_monitored_printq_cache( void )
1334 Printer_entry *printer = printers_list;
1335 int snum;
1337 /* loop through all printers and update the cache where
1338 client_connected == true */
1339 while ( printer )
1341 if ( (printer->printer_type == SPLHND_PRINTER)
1342 && printer->notify.client_connected )
1344 snum = print_queue_snum(printer->sharename);
1345 print_queue_status( snum, NULL, NULL );
1348 printer = printer->next;
1351 return;
1354 /****************************************************************
1355 _spoolss_OpenPrinter
1356 ****************************************************************/
1358 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1359 struct spoolss_OpenPrinter *r)
1361 struct spoolss_OpenPrinterEx e;
1362 WERROR werr;
1364 ZERO_STRUCT(e.in.userlevel);
1366 e.in.printername = r->in.printername;
1367 e.in.datatype = r->in.datatype;
1368 e.in.devmode_ctr = r->in.devmode_ctr;
1369 e.in.access_mask = r->in.access_mask;
1370 e.in.level = 0;
1372 e.out.handle = r->out.handle;
1374 werr = _spoolss_OpenPrinterEx(p, &e);
1376 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1377 /* OpenPrinterEx returns this for a bad
1378 * printer name. We must return WERR_INVALID_PRINTER_NAME
1379 * instead.
1381 werr = WERR_INVALID_PRINTER_NAME;
1384 return werr;
1387 /********************************************************************
1388 ********************************************************************/
1390 bool convert_devicemode(const char *printername,
1391 const struct spoolss_DeviceMode *devmode,
1392 NT_DEVICEMODE **pp_nt_devmode)
1394 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1397 * Ensure nt_devmode is a valid pointer
1398 * as we will be overwriting it.
1401 if (nt_devmode == NULL) {
1402 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1403 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1404 return false;
1407 fstrcpy(nt_devmode->devicename, devmode->devicename);
1408 fstrcpy(nt_devmode->formname, devmode->formname);
1410 nt_devmode->devicename[31] = '\0';
1411 nt_devmode->formname[31] = '\0';
1413 nt_devmode->specversion = devmode->specversion;
1414 nt_devmode->driverversion = devmode->driverversion;
1415 nt_devmode->size = devmode->size;
1416 nt_devmode->fields = devmode->fields;
1417 nt_devmode->orientation = devmode->orientation;
1418 nt_devmode->papersize = devmode->papersize;
1419 nt_devmode->paperlength = devmode->paperlength;
1420 nt_devmode->paperwidth = devmode->paperwidth;
1421 nt_devmode->scale = devmode->scale;
1422 nt_devmode->copies = devmode->copies;
1423 nt_devmode->defaultsource = devmode->defaultsource;
1424 nt_devmode->printquality = devmode->printquality;
1425 nt_devmode->color = devmode->color;
1426 nt_devmode->duplex = devmode->duplex;
1427 nt_devmode->yresolution = devmode->yresolution;
1428 nt_devmode->ttoption = devmode->ttoption;
1429 nt_devmode->collate = devmode->collate;
1431 nt_devmode->logpixels = devmode->logpixels;
1432 nt_devmode->bitsperpel = devmode->bitsperpel;
1433 nt_devmode->pelswidth = devmode->pelswidth;
1434 nt_devmode->pelsheight = devmode->pelsheight;
1435 nt_devmode->displayflags = devmode->displayflags;
1436 nt_devmode->displayfrequency = devmode->displayfrequency;
1437 nt_devmode->icmmethod = devmode->icmmethod;
1438 nt_devmode->icmintent = devmode->icmintent;
1439 nt_devmode->mediatype = devmode->mediatype;
1440 nt_devmode->dithertype = devmode->dithertype;
1441 nt_devmode->reserved1 = devmode->reserved1;
1442 nt_devmode->reserved2 = devmode->reserved2;
1443 nt_devmode->panningwidth = devmode->panningwidth;
1444 nt_devmode->panningheight = devmode->panningheight;
1447 * Only change private and driverextra if the incoming devmode
1448 * has a new one. JRA.
1451 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1452 SAFE_FREE(nt_devmode->nt_dev_private);
1453 nt_devmode->driverextra = devmode->__driverextra_length;
1454 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1455 return false;
1456 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1459 *pp_nt_devmode = nt_devmode;
1461 return true;
1464 /****************************************************************
1465 _spoolss_OpenPrinterEx
1466 ****************************************************************/
1468 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1469 struct spoolss_OpenPrinterEx *r)
1471 int snum;
1472 Printer_entry *Printer=NULL;
1474 if (!r->in.printername) {
1475 return WERR_INVALID_PARAM;
1478 /* some sanity check because you can open a printer or a print server */
1479 /* aka: \\server\printer or \\server */
1481 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1483 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1484 ZERO_STRUCTP(r->out.handle);
1485 return WERR_INVALID_PARAM;
1488 Printer = find_printer_index_by_hnd(p, r->out.handle);
1489 if ( !Printer ) {
1490 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1491 "handle we created for printer %s\n", r->in.printername));
1492 close_printer_handle(p, r->out.handle);
1493 ZERO_STRUCTP(r->out.handle);
1494 return WERR_INVALID_PARAM;
1498 * First case: the user is opening the print server:
1500 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1501 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1503 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1504 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1505 * or if the user is listed in the smb.conf printer admin parameter.
1507 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1508 * client view printer folder, but does not show the MSAPW.
1510 * Note: this test needs code to check access rights here too. Jeremy
1511 * could you look at this?
1513 * Second case: the user is opening a printer:
1514 * NT doesn't let us connect to a printer if the connecting user
1515 * doesn't have print permission.
1517 * Third case: user is opening a Port Monitor
1518 * access checks same as opening a handle to the print server.
1521 switch (Printer->printer_type )
1523 case SPLHND_SERVER:
1524 case SPLHND_PORTMON_TCP:
1525 case SPLHND_PORTMON_LOCAL:
1526 /* Printserver handles use global struct... */
1528 snum = -1;
1530 /* Map standard access rights to object specific access rights */
1532 se_map_standard(&r->in.access_mask,
1533 &printserver_std_mapping);
1535 /* Deny any object specific bits that don't apply to print
1536 servers (i.e printer and job specific bits) */
1538 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1540 if (r->in.access_mask &
1541 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1542 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1543 close_printer_handle(p, r->out.handle);
1544 ZERO_STRUCTP(r->out.handle);
1545 return WERR_ACCESS_DENIED;
1548 /* Allow admin access */
1550 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1552 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1554 if (!lp_ms_add_printer_wizard()) {
1555 close_printer_handle(p, r->out.handle);
1556 ZERO_STRUCTP(r->out.handle);
1557 return WERR_ACCESS_DENIED;
1560 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1561 and not a printer admin, then fail */
1563 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1564 !user_has_privileges(p->server_info->ptok,
1565 &se_printop ) &&
1566 !token_contains_name_in_list(
1567 uidtoname(p->server_info->utok.uid),
1568 NULL, NULL,
1569 p->server_info->ptok,
1570 lp_printer_admin(snum))) {
1571 close_printer_handle(p, r->out.handle);
1572 ZERO_STRUCTP(r->out.handle);
1573 return WERR_ACCESS_DENIED;
1576 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1578 else
1580 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1583 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1584 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1586 /* We fall through to return WERR_OK */
1587 break;
1589 case SPLHND_PRINTER:
1590 /* NT doesn't let us connect to a printer if the connecting user
1591 doesn't have print permission. */
1593 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1594 close_printer_handle(p, r->out.handle);
1595 ZERO_STRUCTP(r->out.handle);
1596 return WERR_BADFID;
1599 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1600 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1603 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1605 /* map an empty access mask to the minimum access mask */
1606 if (r->in.access_mask == 0x0)
1607 r->in.access_mask = PRINTER_ACCESS_USE;
1610 * If we are not serving the printer driver for this printer,
1611 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1612 * will keep NT clients happy --jerry
1615 if (lp_use_client_driver(snum)
1616 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1618 r->in.access_mask = PRINTER_ACCESS_USE;
1621 /* check smb.conf parameters and the the sec_desc */
1623 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1624 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1625 ZERO_STRUCTP(r->out.handle);
1626 return WERR_ACCESS_DENIED;
1629 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1630 p->server_info->ptok, snum) ||
1631 !print_access_check(p->server_info, snum,
1632 r->in.access_mask)) {
1633 DEBUG(3, ("access DENIED for printer open\n"));
1634 close_printer_handle(p, r->out.handle);
1635 ZERO_STRUCTP(r->out.handle);
1636 return WERR_ACCESS_DENIED;
1639 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1640 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1641 close_printer_handle(p, r->out.handle);
1642 ZERO_STRUCTP(r->out.handle);
1643 return WERR_ACCESS_DENIED;
1646 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1647 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1648 else
1649 r->in.access_mask = PRINTER_ACCESS_USE;
1651 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1652 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1654 break;
1656 default:
1657 /* sanity check to prevent programmer error */
1658 ZERO_STRUCTP(r->out.handle);
1659 return WERR_BADFID;
1662 Printer->access_granted = r->in.access_mask;
1665 * If the client sent a devmode in the OpenPrinter() call, then
1666 * save it here in case we get a job submission on this handle
1669 if ((Printer->printer_type != SPLHND_SERVER) &&
1670 r->in.devmode_ctr.devmode) {
1671 convert_devicemode(Printer->sharename,
1672 r->in.devmode_ctr.devmode,
1673 &Printer->nt_devmode);
1676 #if 0 /* JERRY -- I'm doubtful this is really effective */
1677 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1678 optimization in Windows 2000 clients --jerry */
1680 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1681 && (RA_WIN2K == get_remote_arch()) )
1683 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1684 sys_usleep( 500000 );
1686 #endif
1688 return WERR_OK;
1691 /****************************************************************************
1692 ****************************************************************************/
1694 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1695 NT_PRINTER_INFO_LEVEL_2 *d)
1697 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1699 if (!r || !d) {
1700 return false;
1703 d->attributes = r->attributes;
1704 d->priority = r->priority;
1705 d->default_priority = r->defaultpriority;
1706 d->starttime = r->starttime;
1707 d->untiltime = r->untiltime;
1708 d->status = r->status;
1709 d->cjobs = r->cjobs;
1711 fstrcpy(d->servername, r->servername);
1712 fstrcpy(d->printername, r->printername);
1713 fstrcpy(d->sharename, r->sharename);
1714 fstrcpy(d->portname, r->portname);
1715 fstrcpy(d->drivername, r->drivername);
1716 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1717 fstrcpy(d->location, r->location);
1718 fstrcpy(d->sepfile, r->sepfile);
1719 fstrcpy(d->printprocessor, r->printprocessor);
1720 fstrcpy(d->datatype, r->datatype);
1721 fstrcpy(d->parameters, r->parameters);
1723 return true;
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1730 NT_PRINTER_INFO_LEVEL *printer)
1732 bool ret;
1734 switch (info_ctr->level) {
1735 case 2:
1736 /* allocate memory if needed. Messy because
1737 convert_printer_info is used to update an existing
1738 printer or build a new one */
1740 if (!printer->info_2) {
1741 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1742 if (!printer->info_2) {
1743 DEBUG(0,("convert_printer_info: "
1744 "talloc() failed!\n"));
1745 return false;
1749 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1750 printer->info_2);
1751 printer->info_2->setuptime = time(NULL);
1752 return ret;
1755 return false;
1758 /****************************************************************
1759 _spoolss_ClosePrinter
1760 ****************************************************************/
1762 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1763 struct spoolss_ClosePrinter *r)
1765 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1767 if (Printer && Printer->document_started) {
1768 struct spoolss_EndDocPrinter e;
1770 e.in.handle = r->in.handle;
1772 _spoolss_EndDocPrinter(p, &e);
1775 if (!close_printer_handle(p, r->in.handle))
1776 return WERR_BADFID;
1778 /* clear the returned printer handle. Observed behavior
1779 from Win2k server. Don't think this really matters.
1780 Previous code just copied the value of the closed
1781 handle. --jerry */
1783 ZERO_STRUCTP(r->out.handle);
1785 return WERR_OK;
1788 /****************************************************************
1789 _spoolss_DeletePrinter
1790 ****************************************************************/
1792 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1793 struct spoolss_DeletePrinter *r)
1795 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1796 WERROR result;
1798 if (Printer && Printer->document_started) {
1799 struct spoolss_EndDocPrinter e;
1801 e.in.handle = r->in.handle;
1803 _spoolss_EndDocPrinter(p, &e);
1806 result = delete_printer_handle(p, r->in.handle);
1808 update_c_setprinter(false);
1810 return result;
1813 /*******************************************************************
1814 * static function to lookup the version id corresponding to an
1815 * long architecture string
1816 ******************************************************************/
1818 static const struct print_architecture_table_node archi_table[]= {
1820 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1821 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1822 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1823 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1824 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1825 {"Windows IA64", SPL_ARCH_IA64, 3 },
1826 {"Windows x64", SPL_ARCH_X64, 3 },
1827 {NULL, "", -1 }
1830 static int get_version_id(const char *arch)
1832 int i;
1834 for (i=0; archi_table[i].long_archi != NULL; i++)
1836 if (strcmp(arch, archi_table[i].long_archi) == 0)
1837 return (archi_table[i].version);
1840 return -1;
1843 /****************************************************************
1844 _spoolss_DeletePrinterDriver
1845 ****************************************************************/
1847 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1848 struct spoolss_DeletePrinterDriver *r)
1851 struct spoolss_DriverInfo8 *info = NULL;
1852 struct spoolss_DriverInfo8 *info_win2k = NULL;
1853 int version;
1854 WERROR status;
1855 WERROR status_win2k = WERR_ACCESS_DENIED;
1856 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1858 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1859 and not a printer admin, then fail */
1861 if ( (p->server_info->utok.uid != sec_initial_uid())
1862 && !user_has_privileges(p->server_info->ptok, &se_printop )
1863 && !token_contains_name_in_list(
1864 uidtoname(p->server_info->utok.uid), NULL,
1865 NULL, p->server_info->ptok,
1866 lp_printer_admin(-1)) )
1868 return WERR_ACCESS_DENIED;
1871 /* check that we have a valid driver name first */
1873 if ((version = get_version_id(r->in.architecture)) == -1)
1874 return WERR_INVALID_ENVIRONMENT;
1876 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1877 r->in.architecture,
1878 version)))
1880 /* try for Win2k driver if "Windows NT x86" */
1882 if ( version == 2 ) {
1883 version = 3;
1884 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1885 &info,
1886 r->in.driver,
1887 r->in.architecture,
1888 version))) {
1889 status = WERR_UNKNOWN_PRINTER_DRIVER;
1890 goto done;
1893 /* otherwise it was a failure */
1894 else {
1895 status = WERR_UNKNOWN_PRINTER_DRIVER;
1896 goto done;
1901 if (printer_driver_in_use(info)) {
1902 status = WERR_PRINTER_DRIVER_IN_USE;
1903 goto done;
1906 if ( version == 2 )
1908 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1909 &info_win2k,
1910 r->in.driver,
1911 r->in.architecture, 3)))
1913 /* if we get to here, we now have 2 driver info structures to remove */
1914 /* remove the Win2k driver first*/
1916 status_win2k = delete_printer_driver(
1917 p, info_win2k, 3, false);
1918 free_a_printer_driver(info_win2k);
1920 /* this should not have failed---if it did, report to client */
1921 if ( !W_ERROR_IS_OK(status_win2k) )
1923 status = status_win2k;
1924 goto done;
1929 status = delete_printer_driver(p, info, version, false);
1931 /* if at least one of the deletes succeeded return OK */
1933 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1934 status = WERR_OK;
1936 done:
1937 free_a_printer_driver(info);
1939 return status;
1942 /****************************************************************
1943 _spoolss_DeletePrinterDriverEx
1944 ****************************************************************/
1946 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1947 struct spoolss_DeletePrinterDriverEx *r)
1949 struct spoolss_DriverInfo8 *info = NULL;
1950 struct spoolss_DriverInfo8 *info_win2k = NULL;
1951 int version;
1952 bool delete_files;
1953 WERROR status;
1954 WERROR status_win2k = WERR_ACCESS_DENIED;
1955 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1957 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1958 and not a printer admin, then fail */
1960 if ( (p->server_info->utok.uid != sec_initial_uid())
1961 && !user_has_privileges(p->server_info->ptok, &se_printop )
1962 && !token_contains_name_in_list(
1963 uidtoname(p->server_info->utok.uid), NULL, NULL,
1964 p->server_info->ptok, lp_printer_admin(-1)) )
1966 return WERR_ACCESS_DENIED;
1969 /* check that we have a valid driver name first */
1970 if ((version = get_version_id(r->in.architecture)) == -1) {
1971 /* this is what NT returns */
1972 return WERR_INVALID_ENVIRONMENT;
1975 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1976 version = r->in.version;
1978 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1979 r->in.architecture, version);
1981 if ( !W_ERROR_IS_OK(status) )
1984 * if the client asked for a specific version,
1985 * or this is something other than Windows NT x86,
1986 * then we've failed
1989 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1990 goto done;
1992 /* try for Win2k driver if "Windows NT x86" */
1994 version = 3;
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1996 r->in.architecture,
1997 version))) {
1998 status = WERR_UNKNOWN_PRINTER_DRIVER;
1999 goto done;
2003 if (printer_driver_in_use(info)) {
2004 status = WERR_PRINTER_DRIVER_IN_USE;
2005 goto done;
2009 * we have a couple of cases to consider.
2010 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2011 * then the delete should fail if **any** files overlap with
2012 * other drivers
2013 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2014 * non-overlapping files
2015 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2016 * is set, the do not delete any files
2017 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2020 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2022 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2024 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2025 /* no idea of the correct error here */
2026 status = WERR_ACCESS_DENIED;
2027 goto done;
2031 /* also check for W32X86/3 if necessary; maybe we already have? */
2033 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2034 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2035 r->in.driver,
2036 r->in.architecture, 3)))
2039 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2040 /* no idea of the correct error here */
2041 free_a_printer_driver(info_win2k);
2042 status = WERR_ACCESS_DENIED;
2043 goto done;
2046 /* if we get to here, we now have 2 driver info structures to remove */
2047 /* remove the Win2k driver first*/
2049 status_win2k = delete_printer_driver(
2050 p, info_win2k, 3, delete_files);
2051 free_a_printer_driver(info_win2k);
2053 /* this should not have failed---if it did, report to client */
2055 if ( !W_ERROR_IS_OK(status_win2k) )
2056 goto done;
2060 status = delete_printer_driver(p, info, version, delete_files);
2062 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2063 status = WERR_OK;
2064 done:
2065 free_a_printer_driver(info);
2067 return status;
2071 /****************************************************************************
2072 Internal routine for removing printerdata
2073 ***************************************************************************/
2075 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2077 return delete_printer_data( printer->info_2, key, value );
2080 /****************************************************************************
2081 Internal routine for storing printerdata
2082 ***************************************************************************/
2084 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2085 const char *key, const char *value,
2086 uint32_t type, uint8_t *data, int real_len)
2088 /* the registry objects enforce uniqueness based on value name */
2090 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2093 /********************************************************************
2094 GetPrinterData on a printer server Handle.
2095 ********************************************************************/
2097 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2098 const char *value,
2099 enum winreg_Type *type,
2100 union spoolss_PrinterData *data)
2102 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2104 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2105 *type = REG_DWORD;
2106 data->value = 0x00;
2107 return WERR_OK;
2110 if (!StrCaseCmp(value, "BeepEnabled")) {
2111 *type = REG_DWORD;
2112 data->value = 0x00;
2113 return WERR_OK;
2116 if (!StrCaseCmp(value, "EventLog")) {
2117 *type = REG_DWORD;
2118 /* formally was 0x1b */
2119 data->value = 0x00;
2120 return WERR_OK;
2123 if (!StrCaseCmp(value, "NetPopup")) {
2124 *type = REG_DWORD;
2125 data->value = 0x00;
2126 return WERR_OK;
2129 if (!StrCaseCmp(value, "MajorVersion")) {
2130 *type = REG_DWORD;
2132 /* Windows NT 4.0 seems to not allow uploading of drivers
2133 to a server that reports 0x3 as the MajorVersion.
2134 need to investigate more how Win2k gets around this .
2135 -- jerry */
2137 if (RA_WINNT == get_remote_arch()) {
2138 data->value = 0x02;
2139 } else {
2140 data->value = 0x03;
2143 return WERR_OK;
2146 if (!StrCaseCmp(value, "MinorVersion")) {
2147 *type = REG_DWORD;
2148 data->value = 0x00;
2149 return WERR_OK;
2152 /* REG_BINARY
2153 * uint32_t size = 0x114
2154 * uint32_t major = 5
2155 * uint32_t minor = [0|1]
2156 * uint32_t build = [2195|2600]
2157 * extra unicode string = e.g. "Service Pack 3"
2159 if (!StrCaseCmp(value, "OSVersion")) {
2160 DATA_BLOB blob;
2161 enum ndr_err_code ndr_err;
2162 struct spoolss_OSVersion os;
2164 os.major = 5; /* Windows 2000 == 5.0 */
2165 os.minor = 0;
2166 os.build = 2195; /* build */
2167 os.extra_string = ""; /* leave extra string empty */
2169 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2170 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2171 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2172 return WERR_GENERAL_FAILURE;
2175 *type = REG_BINARY;
2176 data->binary = blob;
2178 return WERR_OK;
2182 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2183 *type = REG_SZ;
2185 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2186 W_ERROR_HAVE_NO_MEMORY(data->string);
2188 return WERR_OK;
2191 if (!StrCaseCmp(value, "Architecture")) {
2192 *type = REG_SZ;
2193 data->string = talloc_strdup(mem_ctx,
2194 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2195 W_ERROR_HAVE_NO_MEMORY(data->string);
2197 return WERR_OK;
2200 if (!StrCaseCmp(value, "DsPresent")) {
2201 *type = REG_DWORD;
2203 /* only show the publish check box if we are a
2204 member of a AD domain */
2206 if (lp_security() == SEC_ADS) {
2207 data->value = 0x01;
2208 } else {
2209 data->value = 0x00;
2211 return WERR_OK;
2214 if (!StrCaseCmp(value, "DNSMachineName")) {
2215 const char *hostname = get_mydnsfullname();
2217 if (!hostname) {
2218 return WERR_BADFILE;
2221 *type = REG_SZ;
2222 data->string = talloc_strdup(mem_ctx, hostname);
2223 W_ERROR_HAVE_NO_MEMORY(data->string);
2225 return WERR_OK;
2228 *type = REG_NONE;
2230 return WERR_INVALID_PARAM;
2233 /****************************************************************
2234 _spoolss_GetPrinterData
2235 ****************************************************************/
2237 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2238 struct spoolss_GetPrinterData *r)
2240 struct spoolss_GetPrinterDataEx r2;
2242 r2.in.handle = r->in.handle;
2243 r2.in.key_name = "PrinterDriverData";
2244 r2.in.value_name = r->in.value_name;
2245 r2.in.offered = r->in.offered;
2246 r2.out.type = r->out.type;
2247 r2.out.data = r->out.data;
2248 r2.out.needed = r->out.needed;
2250 return _spoolss_GetPrinterDataEx(p, &r2);
2253 /*********************************************************
2254 Connect to the client machine.
2255 **********************************************************/
2257 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2258 struct sockaddr_storage *client_ss, const char *remote_machine)
2260 NTSTATUS ret;
2261 struct cli_state *the_cli;
2262 struct sockaddr_storage rm_addr;
2263 char addr[INET6_ADDRSTRLEN];
2265 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2266 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2267 remote_machine));
2268 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2269 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2270 return false;
2272 print_sockaddr(addr, sizeof(addr), &rm_addr);
2273 } else {
2274 rm_addr = *client_ss;
2275 print_sockaddr(addr, sizeof(addr), &rm_addr);
2276 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2277 addr));
2280 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2281 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2282 addr));
2283 return false;
2286 /* setup the connection */
2287 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2288 &rm_addr, 0, "IPC$", "IPC",
2289 "", /* username */
2290 "", /* domain */
2291 "", /* password */
2292 0, lp_client_signing(), NULL );
2294 if ( !NT_STATUS_IS_OK( ret ) ) {
2295 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2296 remote_machine ));
2297 return false;
2300 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2301 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2302 cli_shutdown(the_cli);
2303 return false;
2307 * Ok - we have an anonymous connection to the IPC$ share.
2308 * Now start the NT Domain stuff :-).
2311 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2312 if (!NT_STATUS_IS_OK(ret)) {
2313 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2314 remote_machine, nt_errstr(ret)));
2315 cli_shutdown(the_cli);
2316 return false;
2319 return true;
2322 /***************************************************************************
2323 Connect to the client.
2324 ****************************************************************************/
2326 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2327 uint32_t localprinter, uint32_t type,
2328 struct policy_handle *handle,
2329 struct sockaddr_storage *client_ss)
2331 WERROR result;
2332 NTSTATUS status;
2335 * If it's the first connection, contact the client
2336 * and connect to the IPC$ share anonymously
2338 if (smb_connections==0) {
2339 fstring unix_printer;
2341 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2343 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2344 return false;
2346 messaging_register(smbd_messaging_context(), NULL,
2347 MSG_PRINTER_NOTIFY2,
2348 receive_notify2_message_list);
2349 /* Tell the connections db we're now interested in printer
2350 * notify messages. */
2351 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2355 * Tell the specific printing tdb we want messages for this printer
2356 * by registering our PID.
2359 if (!print_notify_register_pid(snum))
2360 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2362 smb_connections++;
2364 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2365 printer,
2366 localprinter,
2367 type,
2369 NULL,
2370 handle,
2371 &result);
2372 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2373 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2374 win_errstr(result)));
2376 return (W_ERROR_IS_OK(result));
2379 /****************************************************************
2380 ****************************************************************/
2382 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2383 const struct spoolss_NotifyOption *r)
2385 struct spoolss_NotifyOption *option;
2386 uint32_t i,k;
2388 if (!r) {
2389 return NULL;
2392 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2393 if (!option) {
2394 return NULL;
2397 *option = *r;
2399 if (!option->count) {
2400 return option;
2403 option->types = talloc_zero_array(option,
2404 struct spoolss_NotifyOptionType, option->count);
2405 if (!option->types) {
2406 talloc_free(option);
2407 return NULL;
2410 for (i=0; i < option->count; i++) {
2411 option->types[i] = r->types[i];
2413 if (option->types[i].count) {
2414 option->types[i].fields = talloc_zero_array(option,
2415 union spoolss_Field, option->types[i].count);
2416 if (!option->types[i].fields) {
2417 talloc_free(option);
2418 return NULL;
2420 for (k=0; k<option->types[i].count; k++) {
2421 option->types[i].fields[k] =
2422 r->types[i].fields[k];
2427 return option;
2430 /****************************************************************
2431 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2433 * before replying OK: status=0 a rpc call is made to the workstation
2434 * asking ReplyOpenPrinter
2436 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2437 * called from api_spoolss_rffpcnex
2438 ****************************************************************/
2440 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2441 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2443 int snum = -1;
2444 struct spoolss_NotifyOption *option = r->in.notify_options;
2445 struct sockaddr_storage client_ss;
2447 /* store the notify value in the printer struct */
2449 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2451 if (!Printer) {
2452 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2453 "Invalid handle (%s:%u:%u).\n",
2454 OUR_HANDLE(r->in.handle)));
2455 return WERR_BADFID;
2458 Printer->notify.flags = r->in.flags;
2459 Printer->notify.options = r->in.options;
2460 Printer->notify.printerlocal = r->in.printer_local;
2462 TALLOC_FREE(Printer->notify.option);
2463 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2465 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2467 /* Connect to the client machine and send a ReplyOpenPrinter */
2469 if ( Printer->printer_type == SPLHND_SERVER)
2470 snum = -1;
2471 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2472 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2473 return WERR_BADFID;
2475 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2476 "client_address is %s\n", p->client_address));
2478 if (!interpret_string_addr(&client_ss, p->client_address,
2479 AI_NUMERICHOST)) {
2480 return WERR_SERVER_UNAVAILABLE;
2483 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2484 Printer->notify.printerlocal, 1,
2485 &Printer->notify.client_hnd, &client_ss))
2486 return WERR_SERVER_UNAVAILABLE;
2488 Printer->notify.client_connected = true;
2490 return WERR_OK;
2493 /*******************************************************************
2494 * fill a notify_info_data with the servername
2495 ********************************************************************/
2497 static void spoolss_notify_server_name(int snum,
2498 struct spoolss_Notify *data,
2499 print_queue_struct *queue,
2500 NT_PRINTER_INFO_LEVEL *printer,
2501 TALLOC_CTX *mem_ctx)
2503 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2506 /*******************************************************************
2507 * fill a notify_info_data with the printername (not including the servername).
2508 ********************************************************************/
2510 static void spoolss_notify_printer_name(int snum,
2511 struct spoolss_Notify *data,
2512 print_queue_struct *queue,
2513 NT_PRINTER_INFO_LEVEL *printer,
2514 TALLOC_CTX *mem_ctx)
2516 /* the notify name should not contain the \\server\ part */
2517 char *p = strrchr(printer->info_2->printername, '\\');
2519 if (!p) {
2520 p = printer->info_2->printername;
2521 } else {
2522 p++;
2525 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2528 /*******************************************************************
2529 * fill a notify_info_data with the servicename
2530 ********************************************************************/
2532 static void spoolss_notify_share_name(int snum,
2533 struct spoolss_Notify *data,
2534 print_queue_struct *queue,
2535 NT_PRINTER_INFO_LEVEL *printer,
2536 TALLOC_CTX *mem_ctx)
2538 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2541 /*******************************************************************
2542 * fill a notify_info_data with the port name
2543 ********************************************************************/
2545 static void spoolss_notify_port_name(int snum,
2546 struct spoolss_Notify *data,
2547 print_queue_struct *queue,
2548 NT_PRINTER_INFO_LEVEL *printer,
2549 TALLOC_CTX *mem_ctx)
2551 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2554 /*******************************************************************
2555 * fill a notify_info_data with the printername
2556 * but it doesn't exist, have to see what to do
2557 ********************************************************************/
2559 static void spoolss_notify_driver_name(int snum,
2560 struct spoolss_Notify *data,
2561 print_queue_struct *queue,
2562 NT_PRINTER_INFO_LEVEL *printer,
2563 TALLOC_CTX *mem_ctx)
2565 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2568 /*******************************************************************
2569 * fill a notify_info_data with the comment
2570 ********************************************************************/
2572 static void spoolss_notify_comment(int snum,
2573 struct spoolss_Notify *data,
2574 print_queue_struct *queue,
2575 NT_PRINTER_INFO_LEVEL *printer,
2576 TALLOC_CTX *mem_ctx)
2578 char *p;
2580 if (*printer->info_2->comment == '\0') {
2581 p = lp_comment(snum);
2582 } else {
2583 p = printer->info_2->comment;
2586 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2589 /*******************************************************************
2590 * fill a notify_info_data with the comment
2591 * location = "Room 1, floor 2, building 3"
2592 ********************************************************************/
2594 static void spoolss_notify_location(int snum,
2595 struct spoolss_Notify *data,
2596 print_queue_struct *queue,
2597 NT_PRINTER_INFO_LEVEL *printer,
2598 TALLOC_CTX *mem_ctx)
2600 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2603 /*******************************************************************
2604 * fill a notify_info_data with the device mode
2605 * jfm:xxxx don't to it for know but that's a real problem !!!
2606 ********************************************************************/
2608 static void spoolss_notify_devmode(int snum,
2609 struct spoolss_Notify *data,
2610 print_queue_struct *queue,
2611 NT_PRINTER_INFO_LEVEL *printer,
2612 TALLOC_CTX *mem_ctx)
2614 /* for a dummy implementation we have to zero the fields */
2615 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2618 /*******************************************************************
2619 * fill a notify_info_data with the separator file name
2620 ********************************************************************/
2622 static void spoolss_notify_sepfile(int snum,
2623 struct spoolss_Notify *data,
2624 print_queue_struct *queue,
2625 NT_PRINTER_INFO_LEVEL *printer,
2626 TALLOC_CTX *mem_ctx)
2628 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2631 /*******************************************************************
2632 * fill a notify_info_data with the print processor
2633 * jfm:xxxx return always winprint to indicate we don't do anything to it
2634 ********************************************************************/
2636 static void spoolss_notify_print_processor(int snum,
2637 struct spoolss_Notify *data,
2638 print_queue_struct *queue,
2639 NT_PRINTER_INFO_LEVEL *printer,
2640 TALLOC_CTX *mem_ctx)
2642 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2645 /*******************************************************************
2646 * fill a notify_info_data with the print processor options
2647 * jfm:xxxx send an empty string
2648 ********************************************************************/
2650 static void spoolss_notify_parameters(int snum,
2651 struct spoolss_Notify *data,
2652 print_queue_struct *queue,
2653 NT_PRINTER_INFO_LEVEL *printer,
2654 TALLOC_CTX *mem_ctx)
2656 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2659 /*******************************************************************
2660 * fill a notify_info_data with the data type
2661 * jfm:xxxx always send RAW as data type
2662 ********************************************************************/
2664 static void spoolss_notify_datatype(int snum,
2665 struct spoolss_Notify *data,
2666 print_queue_struct *queue,
2667 NT_PRINTER_INFO_LEVEL *printer,
2668 TALLOC_CTX *mem_ctx)
2670 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2673 /*******************************************************************
2674 * fill a notify_info_data with the security descriptor
2675 * jfm:xxxx send an null pointer to say no security desc
2676 * have to implement security before !
2677 ********************************************************************/
2679 static void spoolss_notify_security_desc(int snum,
2680 struct spoolss_Notify *data,
2681 print_queue_struct *queue,
2682 NT_PRINTER_INFO_LEVEL *printer,
2683 TALLOC_CTX *mem_ctx)
2685 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2686 printer->info_2->secdesc_buf->sd_size,
2687 printer->info_2->secdesc_buf->sd);
2690 /*******************************************************************
2691 * fill a notify_info_data with the attributes
2692 * jfm:xxxx a samba printer is always shared
2693 ********************************************************************/
2695 static void spoolss_notify_attributes(int snum,
2696 struct spoolss_Notify *data,
2697 print_queue_struct *queue,
2698 NT_PRINTER_INFO_LEVEL *printer,
2699 TALLOC_CTX *mem_ctx)
2701 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2704 /*******************************************************************
2705 * fill a notify_info_data with the priority
2706 ********************************************************************/
2708 static void spoolss_notify_priority(int snum,
2709 struct spoolss_Notify *data,
2710 print_queue_struct *queue,
2711 NT_PRINTER_INFO_LEVEL *printer,
2712 TALLOC_CTX *mem_ctx)
2714 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2717 /*******************************************************************
2718 * fill a notify_info_data with the default priority
2719 ********************************************************************/
2721 static void spoolss_notify_default_priority(int snum,
2722 struct spoolss_Notify *data,
2723 print_queue_struct *queue,
2724 NT_PRINTER_INFO_LEVEL *printer,
2725 TALLOC_CTX *mem_ctx)
2727 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2730 /*******************************************************************
2731 * fill a notify_info_data with the start time
2732 ********************************************************************/
2734 static void spoolss_notify_start_time(int snum,
2735 struct spoolss_Notify *data,
2736 print_queue_struct *queue,
2737 NT_PRINTER_INFO_LEVEL *printer,
2738 TALLOC_CTX *mem_ctx)
2740 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2743 /*******************************************************************
2744 * fill a notify_info_data with the until time
2745 ********************************************************************/
2747 static void spoolss_notify_until_time(int snum,
2748 struct spoolss_Notify *data,
2749 print_queue_struct *queue,
2750 NT_PRINTER_INFO_LEVEL *printer,
2751 TALLOC_CTX *mem_ctx)
2753 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2756 /*******************************************************************
2757 * fill a notify_info_data with the status
2758 ********************************************************************/
2760 static void spoolss_notify_status(int snum,
2761 struct spoolss_Notify *data,
2762 print_queue_struct *queue,
2763 NT_PRINTER_INFO_LEVEL *printer,
2764 TALLOC_CTX *mem_ctx)
2766 print_status_struct status;
2768 print_queue_length(snum, &status);
2769 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2772 /*******************************************************************
2773 * fill a notify_info_data with the number of jobs queued
2774 ********************************************************************/
2776 static void spoolss_notify_cjobs(int snum,
2777 struct spoolss_Notify *data,
2778 print_queue_struct *queue,
2779 NT_PRINTER_INFO_LEVEL *printer,
2780 TALLOC_CTX *mem_ctx)
2782 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2785 /*******************************************************************
2786 * fill a notify_info_data with the average ppm
2787 ********************************************************************/
2789 static void spoolss_notify_average_ppm(int snum,
2790 struct spoolss_Notify *data,
2791 print_queue_struct *queue,
2792 NT_PRINTER_INFO_LEVEL *printer,
2793 TALLOC_CTX *mem_ctx)
2795 /* always respond 8 pages per minutes */
2796 /* a little hard ! */
2797 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2800 /*******************************************************************
2801 * fill a notify_info_data with username
2802 ********************************************************************/
2804 static void spoolss_notify_username(int snum,
2805 struct spoolss_Notify *data,
2806 print_queue_struct *queue,
2807 NT_PRINTER_INFO_LEVEL *printer,
2808 TALLOC_CTX *mem_ctx)
2810 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2813 /*******************************************************************
2814 * fill a notify_info_data with job status
2815 ********************************************************************/
2817 static void spoolss_notify_job_status(int snum,
2818 struct spoolss_Notify *data,
2819 print_queue_struct *queue,
2820 NT_PRINTER_INFO_LEVEL *printer,
2821 TALLOC_CTX *mem_ctx)
2823 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2826 /*******************************************************************
2827 * fill a notify_info_data with job name
2828 ********************************************************************/
2830 static void spoolss_notify_job_name(int snum,
2831 struct spoolss_Notify *data,
2832 print_queue_struct *queue,
2833 NT_PRINTER_INFO_LEVEL *printer,
2834 TALLOC_CTX *mem_ctx)
2836 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2839 /*******************************************************************
2840 * fill a notify_info_data with job status
2841 ********************************************************************/
2843 static void spoolss_notify_job_status_string(int snum,
2844 struct spoolss_Notify *data,
2845 print_queue_struct *queue,
2846 NT_PRINTER_INFO_LEVEL *printer,
2847 TALLOC_CTX *mem_ctx)
2850 * Now we're returning job status codes we just return a "" here. JRA.
2853 const char *p = "";
2855 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2856 p = "unknown";
2858 switch (queue->status) {
2859 case LPQ_QUEUED:
2860 p = "Queued";
2861 break;
2862 case LPQ_PAUSED:
2863 p = ""; /* NT provides the paused string */
2864 break;
2865 case LPQ_SPOOLING:
2866 p = "Spooling";
2867 break;
2868 case LPQ_PRINTING:
2869 p = "Printing";
2870 break;
2872 #endif /* NO LONGER NEEDED. */
2874 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2877 /*******************************************************************
2878 * fill a notify_info_data with job time
2879 ********************************************************************/
2881 static void spoolss_notify_job_time(int snum,
2882 struct spoolss_Notify *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2887 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2890 /*******************************************************************
2891 * fill a notify_info_data with job size
2892 ********************************************************************/
2894 static void spoolss_notify_job_size(int snum,
2895 struct spoolss_Notify *data,
2896 print_queue_struct *queue,
2897 NT_PRINTER_INFO_LEVEL *printer,
2898 TALLOC_CTX *mem_ctx)
2900 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2903 /*******************************************************************
2904 * fill a notify_info_data with page info
2905 ********************************************************************/
2906 static void spoolss_notify_total_pages(int snum,
2907 struct spoolss_Notify *data,
2908 print_queue_struct *queue,
2909 NT_PRINTER_INFO_LEVEL *printer,
2910 TALLOC_CTX *mem_ctx)
2912 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2915 /*******************************************************************
2916 * fill a notify_info_data with pages printed info.
2917 ********************************************************************/
2918 static void spoolss_notify_pages_printed(int snum,
2919 struct spoolss_Notify *data,
2920 print_queue_struct *queue,
2921 NT_PRINTER_INFO_LEVEL *printer,
2922 TALLOC_CTX *mem_ctx)
2924 /* Add code when back-end tracks this */
2925 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2928 /*******************************************************************
2929 Fill a notify_info_data with job position.
2930 ********************************************************************/
2932 static void spoolss_notify_job_position(int snum,
2933 struct spoolss_Notify *data,
2934 print_queue_struct *queue,
2935 NT_PRINTER_INFO_LEVEL *printer,
2936 TALLOC_CTX *mem_ctx)
2938 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2941 /*******************************************************************
2942 Fill a notify_info_data with submitted time.
2943 ********************************************************************/
2945 static void spoolss_notify_submitted_time(int snum,
2946 struct spoolss_Notify *data,
2947 print_queue_struct *queue,
2948 NT_PRINTER_INFO_LEVEL *printer,
2949 TALLOC_CTX *mem_ctx)
2951 data->data.string.string = NULL;
2952 data->data.string.size = 0;
2954 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2955 &data->data.string.string,
2956 &data->data.string.size);
2960 struct s_notify_info_data_table
2962 enum spoolss_NotifyType type;
2963 uint16_t field;
2964 const char *name;
2965 enum spoolss_NotifyTable variable_type;
2966 void (*fn) (int snum, struct spoolss_Notify *data,
2967 print_queue_struct *queue,
2968 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2971 /* A table describing the various print notification constants and
2972 whether the notification data is a pointer to a variable sized
2973 buffer, a one value uint32_t or a two value uint32_t. */
2975 static const struct s_notify_info_data_table notify_info_data_table[] =
2977 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2978 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2979 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2980 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2981 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2982 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2983 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2984 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2985 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2986 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2987 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2988 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
2998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
2999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3003 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3004 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3005 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3006 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3007 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3008 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3009 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3010 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3011 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3012 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3013 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3014 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3015 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3016 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3017 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3018 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3019 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3020 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3021 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3022 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3023 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3024 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3025 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3028 /*******************************************************************
3029 Return the variable_type of info_data structure.
3030 ********************************************************************/
3032 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3033 uint16_t field)
3035 int i=0;
3037 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3038 if ( (notify_info_data_table[i].type == type) &&
3039 (notify_info_data_table[i].field == field) ) {
3040 return notify_info_data_table[i].variable_type;
3044 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3046 return 0;
3049 /****************************************************************************
3050 ****************************************************************************/
3052 static bool search_notify(enum spoolss_NotifyType type,
3053 uint16_t field,
3054 int *value)
3056 int i;
3058 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3059 if (notify_info_data_table[i].type == type &&
3060 notify_info_data_table[i].field == field &&
3061 notify_info_data_table[i].fn != NULL) {
3062 *value = i;
3063 return true;
3067 return false;
3070 /****************************************************************************
3071 ****************************************************************************/
3073 void construct_info_data(struct spoolss_Notify *info_data,
3074 enum spoolss_NotifyType type,
3075 uint16_t field,
3076 int id)
3078 info_data->type = type;
3079 info_data->field.field = field;
3080 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3081 info_data->job_id = id;
3084 /*******************************************************************
3086 * fill a notify_info struct with info asked
3088 ********************************************************************/
3090 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3091 struct spoolss_NotifyInfo *info,
3092 int snum,
3093 const struct spoolss_NotifyOptionType *option_type,
3094 uint32_t id,
3095 TALLOC_CTX *mem_ctx)
3097 int field_num,j;
3098 enum spoolss_NotifyType type;
3099 uint16_t field;
3101 struct spoolss_Notify *current_data;
3102 NT_PRINTER_INFO_LEVEL *printer = NULL;
3103 print_queue_struct *queue=NULL;
3105 type = option_type->type;
3107 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3108 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3109 option_type->count, lp_servicename(snum)));
3111 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3112 return false;
3114 for(field_num=0; field_num < option_type->count; field_num++) {
3115 field = option_type->fields[field_num].field;
3117 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3119 if (!search_notify(type, field, &j) )
3120 continue;
3122 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3123 struct spoolss_Notify,
3124 info->count + 1);
3125 if (info->notifies == NULL) {
3126 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3127 free_a_printer(&printer, 2);
3128 return false;
3131 current_data = &info->notifies[info->count];
3133 construct_info_data(current_data, type, field, id);
3135 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3136 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3138 notify_info_data_table[j].fn(snum, current_data, queue,
3139 printer, mem_ctx);
3141 info->count++;
3144 free_a_printer(&printer, 2);
3145 return true;
3148 /*******************************************************************
3150 * fill a notify_info struct with info asked
3152 ********************************************************************/
3154 static bool construct_notify_jobs_info(print_queue_struct *queue,
3155 struct spoolss_NotifyInfo *info,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 int snum,
3158 const struct spoolss_NotifyOptionType *option_type,
3159 uint32_t id,
3160 TALLOC_CTX *mem_ctx)
3162 int field_num,j;
3163 enum spoolss_NotifyType type;
3164 uint16_t field;
3165 struct spoolss_Notify *current_data;
3167 DEBUG(4,("construct_notify_jobs_info\n"));
3169 type = option_type->type;
3171 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3172 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3173 option_type->count));
3175 for(field_num=0; field_num<option_type->count; field_num++) {
3176 field = option_type->fields[field_num].field;
3178 if (!search_notify(type, field, &j) )
3179 continue;
3181 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3182 struct spoolss_Notify,
3183 info->count + 1);
3184 if (info->notifies == NULL) {
3185 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3186 return false;
3189 current_data=&(info->notifies[info->count]);
3191 construct_info_data(current_data, type, field, id);
3192 notify_info_data_table[j].fn(snum, current_data, queue,
3193 printer, mem_ctx);
3194 info->count++;
3197 return true;
3201 * JFM: The enumeration is not that simple, it's even non obvious.
3203 * let's take an example: I want to monitor the PRINTER SERVER for
3204 * the printer's name and the number of jobs currently queued.
3205 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3206 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3208 * I have 3 printers on the back of my server.
3210 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3211 * structures.
3212 * Number Data Id
3213 * 1 printer 1 name 1
3214 * 2 printer 1 cjob 1
3215 * 3 printer 2 name 2
3216 * 4 printer 2 cjob 2
3217 * 5 printer 3 name 3
3218 * 6 printer 3 name 3
3220 * that's the print server case, the printer case is even worse.
3223 /*******************************************************************
3225 * enumerate all printers on the printserver
3226 * fill a notify_info struct with info asked
3228 ********************************************************************/
3230 static WERROR printserver_notify_info(pipes_struct *p,
3231 struct policy_handle *hnd,
3232 struct spoolss_NotifyInfo *info,
3233 TALLOC_CTX *mem_ctx)
3235 int snum;
3236 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3237 int n_services=lp_numservices();
3238 int i;
3239 struct spoolss_NotifyOption *option;
3240 struct spoolss_NotifyOptionType option_type;
3242 DEBUG(4,("printserver_notify_info\n"));
3244 if (!Printer)
3245 return WERR_BADFID;
3247 option = Printer->notify.option;
3249 info->version = 2;
3250 info->notifies = NULL;
3251 info->count = 0;
3253 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3254 sending a ffpcn() request first */
3256 if ( !option )
3257 return WERR_BADFID;
3259 for (i=0; i<option->count; i++) {
3260 option_type = option->types[i];
3262 if (option_type.type != PRINTER_NOTIFY_TYPE)
3263 continue;
3265 for (snum=0; snum<n_services; snum++)
3267 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3268 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3272 #if 0
3274 * Debugging information, don't delete.
3277 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3278 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3279 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3281 for (i=0; i<info->count; i++) {
3282 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3283 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3284 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3286 #endif
3288 return WERR_OK;
3291 /*******************************************************************
3293 * fill a notify_info struct with info asked
3295 ********************************************************************/
3297 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3298 struct spoolss_NotifyInfo *info,
3299 TALLOC_CTX *mem_ctx)
3301 int snum;
3302 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3303 int i;
3304 uint32_t id;
3305 struct spoolss_NotifyOption *option;
3306 struct spoolss_NotifyOptionType option_type;
3307 int count,j;
3308 print_queue_struct *queue=NULL;
3309 print_status_struct status;
3311 DEBUG(4,("printer_notify_info\n"));
3313 if (!Printer)
3314 return WERR_BADFID;
3316 option = Printer->notify.option;
3317 id = 0x0;
3319 info->version = 2;
3320 info->notifies = NULL;
3321 info->count = 0;
3323 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3324 sending a ffpcn() request first */
3326 if ( !option )
3327 return WERR_BADFID;
3329 get_printer_snum(p, hnd, &snum, NULL);
3331 for (i=0; i<option->count; i++) {
3332 option_type = option->types[i];
3334 switch (option_type.type) {
3335 case PRINTER_NOTIFY_TYPE:
3336 if(construct_notify_printer_info(Printer, info, snum,
3337 &option_type, id,
3338 mem_ctx))
3339 id--;
3340 break;
3342 case JOB_NOTIFY_TYPE: {
3343 NT_PRINTER_INFO_LEVEL *printer = NULL;
3345 count = print_queue_status(snum, &queue, &status);
3347 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3348 goto done;
3350 for (j=0; j<count; j++) {
3351 construct_notify_jobs_info(&queue[j], info,
3352 printer, snum,
3353 &option_type,
3354 queue[j].job,
3355 mem_ctx);
3358 free_a_printer(&printer, 2);
3360 done:
3361 SAFE_FREE(queue);
3362 break;
3368 * Debugging information, don't delete.
3371 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3372 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3373 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3375 for (i=0; i<info->count; i++) {
3376 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3377 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3378 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3381 return WERR_OK;
3384 /****************************************************************
3385 _spoolss_RouterRefreshPrinterChangeNotify
3386 ****************************************************************/
3388 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3389 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3391 struct spoolss_NotifyInfo *info;
3393 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3394 WERROR result = WERR_BADFID;
3396 /* we always have a spoolss_NotifyInfo struct */
3397 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3398 if (!info) {
3399 result = WERR_NOMEM;
3400 goto done;
3403 *r->out.info = info;
3405 if (!Printer) {
3406 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3407 "Invalid handle (%s:%u:%u).\n",
3408 OUR_HANDLE(r->in.handle)));
3409 goto done;
3412 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3415 * We are now using the change value, and
3416 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3417 * I don't have a global notification system, I'm sending back all the
3418 * informations even when _NOTHING_ has changed.
3421 /* We need to keep track of the change value to send back in
3422 RRPCN replies otherwise our updates are ignored. */
3424 Printer->notify.fnpcn = true;
3426 if (Printer->notify.client_connected) {
3427 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3428 "Saving change value in request [%x]\n",
3429 r->in.change_low));
3430 Printer->notify.change = r->in.change_low;
3433 /* just ignore the spoolss_NotifyOption */
3435 switch (Printer->printer_type) {
3436 case SPLHND_SERVER:
3437 result = printserver_notify_info(p, r->in.handle,
3438 info, p->mem_ctx);
3439 break;
3441 case SPLHND_PRINTER:
3442 result = printer_notify_info(p, r->in.handle,
3443 info, p->mem_ctx);
3444 break;
3447 Printer->notify.fnpcn = false;
3449 done:
3450 return result;
3453 /********************************************************************
3454 * construct_printer_info_0
3455 * fill a printer_info_0 struct
3456 ********************************************************************/
3458 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3459 const NT_PRINTER_INFO_LEVEL *ntprinter,
3460 struct spoolss_PrinterInfo0 *r,
3461 int snum)
3463 int count;
3464 counter_printer_0 *session_counter;
3465 time_t setuptime;
3466 print_status_struct status;
3468 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3469 W_ERROR_HAVE_NO_MEMORY(r->printername);
3471 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3472 W_ERROR_HAVE_NO_MEMORY(r->servername);
3474 count = print_queue_length(snum, &status);
3476 /* check if we already have a counter for this printer */
3477 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3478 if (session_counter->snum == snum)
3479 break;
3482 /* it's the first time, add it to the list */
3483 if (session_counter == NULL) {
3484 session_counter = SMB_MALLOC_P(counter_printer_0);
3485 W_ERROR_HAVE_NO_MEMORY(session_counter);
3486 ZERO_STRUCTP(session_counter);
3487 session_counter->snum = snum;
3488 session_counter->counter = 0;
3489 DLIST_ADD(counter_list, session_counter);
3492 /* increment it */
3493 session_counter->counter++;
3495 r->cjobs = count;
3496 r->total_jobs = 0;
3497 r->total_bytes = 0;
3499 setuptime = (time_t)ntprinter->info_2->setuptime;
3501 init_systemtime(&r->time, gmtime(&setuptime));
3503 /* JFM:
3504 * the global_counter should be stored in a TDB as it's common to all the clients
3505 * and should be zeroed on samba startup
3507 r->global_counter = session_counter->counter;
3508 r->total_pages = 0;
3509 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3510 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3511 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3512 r->free_build = SPOOLSS_RELEASE_BUILD;
3513 r->spooling = 0;
3514 r->max_spooling = 0;
3515 r->session_counter = session_counter->counter;
3516 r->num_error_out_of_paper = 0x0;
3517 r->num_error_not_ready = 0x0; /* number of print failure */
3518 r->job_error = 0x0;
3519 r->number_of_processors = 0x1;
3520 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3521 r->high_part_total_bytes = 0x0;
3522 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3523 r->last_error = WERR_OK;
3524 r->status = nt_printq_status(status.status);
3525 r->enumerate_network_printers = 0x0;
3526 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3527 r->processor_architecture = 0x0;
3528 r->processor_level = 0x6; /* 6 ???*/
3529 r->ref_ic = 0;
3530 r->reserved2 = 0;
3531 r->reserved3 = 0;
3533 return WERR_OK;
3536 /****************************************************************************
3537 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3538 should be valid upon entry
3539 ****************************************************************************/
3541 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3542 struct spoolss_DeviceMode *r,
3543 const NT_DEVICEMODE *ntdevmode)
3545 if (!r || !ntdevmode) {
3546 return WERR_INVALID_PARAM;
3549 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3550 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3552 r->specversion = ntdevmode->specversion;
3553 r->driverversion = ntdevmode->driverversion;
3554 r->size = ntdevmode->size;
3555 r->__driverextra_length = ntdevmode->driverextra;
3556 r->fields = ntdevmode->fields;
3558 r->orientation = ntdevmode->orientation;
3559 r->papersize = ntdevmode->papersize;
3560 r->paperlength = ntdevmode->paperlength;
3561 r->paperwidth = ntdevmode->paperwidth;
3562 r->scale = ntdevmode->scale;
3563 r->copies = ntdevmode->copies;
3564 r->defaultsource = ntdevmode->defaultsource;
3565 r->printquality = ntdevmode->printquality;
3566 r->color = ntdevmode->color;
3567 r->duplex = ntdevmode->duplex;
3568 r->yresolution = ntdevmode->yresolution;
3569 r->ttoption = ntdevmode->ttoption;
3570 r->collate = ntdevmode->collate;
3572 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3573 W_ERROR_HAVE_NO_MEMORY(r->formname);
3575 r->logpixels = ntdevmode->logpixels;
3576 r->bitsperpel = ntdevmode->bitsperpel;
3577 r->pelswidth = ntdevmode->pelswidth;
3578 r->pelsheight = ntdevmode->pelsheight;
3579 r->displayflags = ntdevmode->displayflags;
3580 r->displayfrequency = ntdevmode->displayfrequency;
3581 r->icmmethod = ntdevmode->icmmethod;
3582 r->icmintent = ntdevmode->icmintent;
3583 r->mediatype = ntdevmode->mediatype;
3584 r->dithertype = ntdevmode->dithertype;
3585 r->reserved1 = ntdevmode->reserved1;
3586 r->reserved2 = ntdevmode->reserved2;
3587 r->panningwidth = ntdevmode->panningwidth;
3588 r->panningheight = ntdevmode->panningheight;
3590 if (ntdevmode->nt_dev_private != NULL) {
3591 r->driverextra_data = data_blob_talloc(mem_ctx,
3592 ntdevmode->nt_dev_private,
3593 ntdevmode->driverextra);
3594 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3597 return WERR_OK;
3601 /****************************************************************************
3602 Create a spoolss_DeviceMode struct. Returns talloced memory.
3603 ****************************************************************************/
3605 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3606 const char *servicename)
3608 WERROR result;
3609 NT_PRINTER_INFO_LEVEL *printer = NULL;
3610 struct spoolss_DeviceMode *devmode = NULL;
3612 DEBUG(7,("construct_dev_mode\n"));
3614 DEBUGADD(8,("getting printer characteristics\n"));
3616 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3617 return NULL;
3619 if (!printer->info_2->devmode) {
3620 DEBUG(5, ("BONG! There was no device mode!\n"));
3621 goto done;
3624 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3625 if (!devmode) {
3626 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3627 goto done;
3630 DEBUGADD(8,("loading DEVICEMODE\n"));
3632 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3633 if (!W_ERROR_IS_OK(result)) {
3634 TALLOC_FREE(devmode);
3637 done:
3638 free_a_printer(&printer,2);
3640 return devmode;
3643 /********************************************************************
3644 * construct_printer_info1
3645 * fill a spoolss_PrinterInfo1 struct
3646 ********************************************************************/
3648 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3649 const NT_PRINTER_INFO_LEVEL *ntprinter,
3650 uint32_t flags,
3651 struct spoolss_PrinterInfo1 *r,
3652 int snum)
3654 r->flags = flags;
3656 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3657 ntprinter->info_2->printername,
3658 ntprinter->info_2->drivername,
3659 ntprinter->info_2->location);
3660 W_ERROR_HAVE_NO_MEMORY(r->description);
3662 if (*ntprinter->info_2->comment == '\0') {
3663 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3664 } else {
3665 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3667 W_ERROR_HAVE_NO_MEMORY(r->comment);
3669 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3670 W_ERROR_HAVE_NO_MEMORY(r->name);
3672 return WERR_OK;
3675 /********************************************************************
3676 * construct_printer_info2
3677 * fill a spoolss_PrinterInfo2 struct
3678 ********************************************************************/
3680 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3681 const NT_PRINTER_INFO_LEVEL *ntprinter,
3682 struct spoolss_PrinterInfo2 *r,
3683 int snum)
3685 int count;
3687 print_status_struct status;
3689 count = print_queue_length(snum, &status);
3691 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3692 W_ERROR_HAVE_NO_MEMORY(r->servername);
3693 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3694 W_ERROR_HAVE_NO_MEMORY(r->printername);
3695 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3696 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3697 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3698 W_ERROR_HAVE_NO_MEMORY(r->portname);
3699 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3700 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3702 if (*ntprinter->info_2->comment == '\0') {
3703 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3704 } else {
3705 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3707 W_ERROR_HAVE_NO_MEMORY(r->comment);
3709 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3710 W_ERROR_HAVE_NO_MEMORY(r->location);
3711 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3712 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3713 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3714 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3715 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3716 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3717 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3718 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3720 r->attributes = ntprinter->info_2->attributes;
3722 r->priority = ntprinter->info_2->priority;
3723 r->defaultpriority = ntprinter->info_2->default_priority;
3724 r->starttime = ntprinter->info_2->starttime;
3725 r->untiltime = ntprinter->info_2->untiltime;
3726 r->status = nt_printq_status(status.status);
3727 r->cjobs = count;
3728 r->averageppm = ntprinter->info_2->averageppm;
3730 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3731 if (!r->devmode) {
3732 DEBUG(8,("Returning NULL Devicemode!\n"));
3735 r->secdesc = NULL;
3737 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3738 /* don't use talloc_steal() here unless you do a deep steal of all
3739 the SEC_DESC members */
3741 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3744 return WERR_OK;
3747 /********************************************************************
3748 * construct_printer_info3
3749 * fill a spoolss_PrinterInfo3 struct
3750 ********************************************************************/
3752 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3753 const NT_PRINTER_INFO_LEVEL *ntprinter,
3754 struct spoolss_PrinterInfo3 *r,
3755 int snum)
3757 /* These are the components of the SD we are returning. */
3759 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3760 /* don't use talloc_steal() here unless you do a deep steal of all
3761 the SEC_DESC members */
3763 r->secdesc = dup_sec_desc(mem_ctx,
3764 ntprinter->info_2->secdesc_buf->sd);
3765 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3768 return WERR_OK;
3771 /********************************************************************
3772 * construct_printer_info4
3773 * fill a spoolss_PrinterInfo4 struct
3774 ********************************************************************/
3776 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3777 const NT_PRINTER_INFO_LEVEL *ntprinter,
3778 struct spoolss_PrinterInfo4 *r,
3779 int snum)
3781 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3782 W_ERROR_HAVE_NO_MEMORY(r->printername);
3783 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3784 W_ERROR_HAVE_NO_MEMORY(r->servername);
3786 r->attributes = ntprinter->info_2->attributes;
3788 return WERR_OK;
3791 /********************************************************************
3792 * construct_printer_info5
3793 * fill a spoolss_PrinterInfo5 struct
3794 ********************************************************************/
3796 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3797 const NT_PRINTER_INFO_LEVEL *ntprinter,
3798 struct spoolss_PrinterInfo5 *r,
3799 int snum)
3801 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3802 W_ERROR_HAVE_NO_MEMORY(r->printername);
3803 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3804 W_ERROR_HAVE_NO_MEMORY(r->portname);
3806 r->attributes = ntprinter->info_2->attributes;
3808 /* these two are not used by NT+ according to MSDN */
3810 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3811 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3813 return WERR_OK;
3816 /********************************************************************
3817 * construct_printer_info_6
3818 * fill a spoolss_PrinterInfo6 struct
3819 ********************************************************************/
3821 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3822 const NT_PRINTER_INFO_LEVEL *ntprinter,
3823 struct spoolss_PrinterInfo6 *r,
3824 int snum)
3826 int count;
3827 print_status_struct status;
3829 count = print_queue_length(snum, &status);
3831 r->status = nt_printq_status(status.status);
3833 return WERR_OK;
3836 /********************************************************************
3837 * construct_printer_info7
3838 * fill a spoolss_PrinterInfo7 struct
3839 ********************************************************************/
3841 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3842 Printer_entry *print_hnd,
3843 struct spoolss_PrinterInfo7 *r,
3844 int snum)
3846 struct GUID guid;
3848 if (is_printer_published(print_hnd, snum, &guid)) {
3849 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3850 r->action = DSPRINT_PUBLISH;
3851 } else {
3852 r->guid = talloc_strdup(mem_ctx, "");
3853 r->action = DSPRINT_UNPUBLISH;
3855 W_ERROR_HAVE_NO_MEMORY(r->guid);
3857 return WERR_OK;
3860 /********************************************************************
3861 * construct_printer_info8
3862 * fill a spoolss_PrinterInfo8 struct
3863 ********************************************************************/
3865 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3866 const NT_PRINTER_INFO_LEVEL *ntprinter,
3867 struct spoolss_DeviceModeInfo *r,
3868 int snum)
3870 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3871 if (!r->devmode) {
3872 DEBUG(8,("Returning NULL Devicemode!\n"));
3875 return WERR_OK;
3879 /********************************************************************
3880 ********************************************************************/
3882 static bool snum_is_shared_printer(int snum)
3884 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3887 /********************************************************************
3888 Spoolss_enumprinters.
3889 ********************************************************************/
3891 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3892 uint32_t level,
3893 uint32_t flags,
3894 union spoolss_PrinterInfo **info_p,
3895 uint32_t *count_p)
3897 int snum;
3898 int n_services = lp_numservices();
3899 union spoolss_PrinterInfo *info = NULL;
3900 uint32_t count = 0;
3901 WERROR result = WERR_OK;
3903 *count_p = 0;
3904 *info_p = NULL;
3906 for (snum = 0; snum < n_services; snum++) {
3908 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3910 if (!snum_is_shared_printer(snum)) {
3911 continue;
3914 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3915 lp_servicename(snum), snum));
3917 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3918 union spoolss_PrinterInfo,
3919 count + 1);
3920 if (!info) {
3921 result = WERR_NOMEM;
3922 goto out;
3925 result = get_a_printer(NULL, &ntprinter, 2,
3926 lp_const_servicename(snum));
3927 if (!W_ERROR_IS_OK(result)) {
3928 goto out;
3931 switch (level) {
3932 case 0:
3933 result = construct_printer_info0(info, ntprinter,
3934 &info[count].info0, snum);
3935 break;
3936 case 1:
3937 result = construct_printer_info1(info, ntprinter, flags,
3938 &info[count].info1, snum);
3939 break;
3940 case 2:
3941 result = construct_printer_info2(info, ntprinter,
3942 &info[count].info2, snum);
3943 break;
3944 case 4:
3945 result = construct_printer_info4(info, ntprinter,
3946 &info[count].info4, snum);
3947 break;
3948 case 5:
3949 result = construct_printer_info5(info, ntprinter,
3950 &info[count].info5, snum);
3951 break;
3953 default:
3954 result = WERR_UNKNOWN_LEVEL;
3955 free_a_printer(&ntprinter, 2);
3956 goto out;
3959 free_a_printer(&ntprinter, 2);
3960 if (!W_ERROR_IS_OK(result)) {
3961 goto out;
3964 count++;
3967 *count_p = count;
3968 *info_p = info;
3970 out:
3971 if (!W_ERROR_IS_OK(result)) {
3972 TALLOC_FREE(info);
3973 return result;
3976 *info_p = info;
3978 return WERR_OK;
3981 /********************************************************************
3982 * handle enumeration of printers at level 0
3983 ********************************************************************/
3985 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3986 uint32_t flags,
3987 const char *servername,
3988 union spoolss_PrinterInfo **info,
3989 uint32_t *count)
3991 DEBUG(4,("enum_all_printers_info_0\n"));
3993 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
3997 /********************************************************************
3998 ********************************************************************/
4000 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4001 uint32_t flags,
4002 union spoolss_PrinterInfo **info,
4003 uint32_t *count)
4005 DEBUG(4,("enum_all_printers_info_1\n"));
4007 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4010 /********************************************************************
4011 enum_all_printers_info_1_local.
4012 *********************************************************************/
4014 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4015 union spoolss_PrinterInfo **info,
4016 uint32_t *count)
4018 DEBUG(4,("enum_all_printers_info_1_local\n"));
4020 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4023 /********************************************************************
4024 enum_all_printers_info_1_name.
4025 *********************************************************************/
4027 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4028 const char *name,
4029 union spoolss_PrinterInfo **info,
4030 uint32_t *count)
4032 const char *s = name;
4034 DEBUG(4,("enum_all_printers_info_1_name\n"));
4036 if ((name[0] == '\\') && (name[1] == '\\')) {
4037 s = name + 2;
4040 if (!is_myname_or_ipaddr(s)) {
4041 return WERR_INVALID_NAME;
4044 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4047 /********************************************************************
4048 enum_all_printers_info_1_network.
4049 *********************************************************************/
4051 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4052 const char *name,
4053 union spoolss_PrinterInfo **info,
4054 uint32_t *count)
4056 const char *s = name;
4058 DEBUG(4,("enum_all_printers_info_1_network\n"));
4060 /* If we respond to a enum_printers level 1 on our name with flags
4061 set to PRINTER_ENUM_REMOTE with a list of printers then these
4062 printers incorrectly appear in the APW browse list.
4063 Specifically the printers for the server appear at the workgroup
4064 level where all the other servers in the domain are
4065 listed. Windows responds to this call with a
4066 WERR_CAN_NOT_COMPLETE so we should do the same. */
4068 if (name[0] == '\\' && name[1] == '\\') {
4069 s = name + 2;
4072 if (is_myname_or_ipaddr(s)) {
4073 return WERR_CAN_NOT_COMPLETE;
4076 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4079 /********************************************************************
4080 * api_spoolss_enumprinters
4082 * called from api_spoolss_enumprinters (see this to understand)
4083 ********************************************************************/
4085 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4086 union spoolss_PrinterInfo **info,
4087 uint32_t *count)
4089 DEBUG(4,("enum_all_printers_info_2\n"));
4091 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4094 /********************************************************************
4095 * handle enumeration of printers at level 1
4096 ********************************************************************/
4098 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4099 uint32_t flags,
4100 const char *name,
4101 union spoolss_PrinterInfo **info,
4102 uint32_t *count)
4104 /* Not all the flags are equals */
4106 if (flags & PRINTER_ENUM_LOCAL) {
4107 return enum_all_printers_info_1_local(mem_ctx, info, count);
4110 if (flags & PRINTER_ENUM_NAME) {
4111 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4114 if (flags & PRINTER_ENUM_NETWORK) {
4115 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4118 return WERR_OK; /* NT4sp5 does that */
4121 /********************************************************************
4122 * handle enumeration of printers at level 2
4123 ********************************************************************/
4125 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4126 uint32_t flags,
4127 const char *servername,
4128 union spoolss_PrinterInfo **info,
4129 uint32_t *count)
4131 if (flags & PRINTER_ENUM_LOCAL) {
4132 return enum_all_printers_info_2(mem_ctx, info, count);
4135 if (flags & PRINTER_ENUM_NAME) {
4136 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4137 return WERR_INVALID_NAME;
4140 return enum_all_printers_info_2(mem_ctx, info, count);
4143 if (flags & PRINTER_ENUM_REMOTE) {
4144 return WERR_UNKNOWN_LEVEL;
4147 return WERR_OK;
4150 /********************************************************************
4151 * handle enumeration of printers at level 4
4152 ********************************************************************/
4154 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4155 uint32_t flags,
4156 const char *servername,
4157 union spoolss_PrinterInfo **info,
4158 uint32_t *count)
4160 DEBUG(4,("enum_all_printers_info_4\n"));
4162 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4166 /********************************************************************
4167 * handle enumeration of printers at level 5
4168 ********************************************************************/
4170 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4171 uint32_t flags,
4172 const char *servername,
4173 union spoolss_PrinterInfo **info,
4174 uint32_t *count)
4176 DEBUG(4,("enum_all_printers_info_5\n"));
4178 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4181 /****************************************************************
4182 _spoolss_EnumPrinters
4183 ****************************************************************/
4185 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4186 struct spoolss_EnumPrinters *r)
4188 const char *name = NULL;
4189 WERROR result;
4191 /* that's an [in out] buffer */
4193 if (!r->in.buffer && (r->in.offered != 0)) {
4194 return WERR_INVALID_PARAM;
4197 DEBUG(4,("_spoolss_EnumPrinters\n"));
4199 *r->out.needed = 0;
4200 *r->out.count = 0;
4201 *r->out.info = NULL;
4204 * Level 1:
4205 * flags==PRINTER_ENUM_NAME
4206 * if name=="" then enumerates all printers
4207 * if name!="" then enumerate the printer
4208 * flags==PRINTER_ENUM_REMOTE
4209 * name is NULL, enumerate printers
4210 * Level 2: name!="" enumerates printers, name can't be NULL
4211 * Level 3: doesn't exist
4212 * Level 4: does a local registry lookup
4213 * Level 5: same as Level 2
4216 if (r->in.server) {
4217 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4218 W_ERROR_HAVE_NO_MEMORY(name);
4221 switch (r->in.level) {
4222 case 0:
4223 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4224 r->out.info, r->out.count);
4225 break;
4226 case 1:
4227 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4228 r->out.info, r->out.count);
4229 break;
4230 case 2:
4231 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4232 r->out.info, r->out.count);
4233 break;
4234 case 4:
4235 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4236 r->out.info, r->out.count);
4237 break;
4238 case 5:
4239 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4240 r->out.info, r->out.count);
4241 break;
4242 default:
4243 return WERR_UNKNOWN_LEVEL;
4246 if (!W_ERROR_IS_OK(result)) {
4247 return result;
4250 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4251 spoolss_EnumPrinters,
4252 *r->out.info, r->in.level,
4253 *r->out.count);
4254 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4255 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4257 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4260 /****************************************************************
4261 _spoolss_GetPrinter
4262 ****************************************************************/
4264 WERROR _spoolss_GetPrinter(pipes_struct *p,
4265 struct spoolss_GetPrinter *r)
4267 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4268 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4269 WERROR result = WERR_OK;
4271 int snum;
4273 /* that's an [in out] buffer */
4275 if (!r->in.buffer && (r->in.offered != 0)) {
4276 return WERR_INVALID_PARAM;
4279 *r->out.needed = 0;
4281 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4282 return WERR_BADFID;
4285 result = get_a_printer(Printer, &ntprinter, 2,
4286 lp_const_servicename(snum));
4287 if (!W_ERROR_IS_OK(result)) {
4288 return result;
4291 switch (r->in.level) {
4292 case 0:
4293 result = construct_printer_info0(p->mem_ctx, ntprinter,
4294 &r->out.info->info0, snum);
4295 break;
4296 case 1:
4297 result = construct_printer_info1(p->mem_ctx, ntprinter,
4298 PRINTER_ENUM_ICON8,
4299 &r->out.info->info1, snum);
4300 break;
4301 case 2:
4302 result = construct_printer_info2(p->mem_ctx, ntprinter,
4303 &r->out.info->info2, snum);
4304 break;
4305 case 3:
4306 result = construct_printer_info3(p->mem_ctx, ntprinter,
4307 &r->out.info->info3, snum);
4308 break;
4309 case 4:
4310 result = construct_printer_info4(p->mem_ctx, ntprinter,
4311 &r->out.info->info4, snum);
4312 break;
4313 case 5:
4314 result = construct_printer_info5(p->mem_ctx, ntprinter,
4315 &r->out.info->info5, snum);
4316 break;
4317 case 6:
4318 result = construct_printer_info6(p->mem_ctx, ntprinter,
4319 &r->out.info->info6, snum);
4320 break;
4321 case 7:
4322 result = construct_printer_info7(p->mem_ctx, Printer,
4323 &r->out.info->info7, snum);
4324 break;
4325 case 8:
4326 result = construct_printer_info8(p->mem_ctx, ntprinter,
4327 &r->out.info->info8, snum);
4328 break;
4329 default:
4330 result = WERR_UNKNOWN_LEVEL;
4331 break;
4334 free_a_printer(&ntprinter, 2);
4336 if (!W_ERROR_IS_OK(result)) {
4337 TALLOC_FREE(r->out.info);
4338 return result;
4341 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4342 r->out.info, r->in.level);
4343 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4345 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4348 /********************************************************************
4349 ********************************************************************/
4351 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4352 const char **string_array,
4353 const char *cservername)
4355 int i, num_strings = 0;
4356 const char **array = NULL;
4358 if (!string_array) {
4359 return NULL;
4362 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4364 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4365 cservername, string_array[i]);
4366 if (!str) {
4367 TALLOC_FREE(array);
4368 return NULL;
4372 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4373 TALLOC_FREE(array);
4374 return NULL;
4378 if (i > 0) {
4379 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4380 &array, &num_strings);
4383 return array;
4386 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4387 do { \
4388 if (in && strlen(in)) { \
4389 out = talloc_strdup(mem_ctx, in); \
4390 W_ERROR_HAVE_NO_MEMORY(out); \
4391 } else { \
4392 out = NULL; \
4394 } while (0);
4396 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4397 do { \
4398 if (in && strlen(in)) { \
4399 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4400 } else { \
4401 out = talloc_strdup(mem_ctx, ""); \
4403 W_ERROR_HAVE_NO_MEMORY(out); \
4404 } while (0);
4406 /********************************************************************
4407 * fill a spoolss_DriverInfo1 struct
4408 ********************************************************************/
4410 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4411 struct spoolss_DriverInfo1 *r,
4412 const struct spoolss_DriverInfo8 *driver,
4413 const char *servername)
4415 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4416 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4418 return WERR_OK;
4421 /********************************************************************
4422 * fill a spoolss_DriverInfo2 struct
4423 ********************************************************************/
4425 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4426 struct spoolss_DriverInfo2 *r,
4427 const struct spoolss_DriverInfo8 *driver,
4428 const char *servername)
4431 const char *cservername = canon_servername(servername);
4433 r->version = driver->version;
4435 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4436 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4437 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4438 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4440 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4441 driver->driver_path,
4442 r->driver_path);
4444 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4445 driver->data_file,
4446 r->data_file);
4448 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4449 driver->config_file,
4450 r->config_file);
4452 return WERR_OK;
4455 /********************************************************************
4456 * fill a spoolss_DriverInfo3 struct
4457 ********************************************************************/
4459 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4460 struct spoolss_DriverInfo3 *r,
4461 const struct spoolss_DriverInfo8 *driver,
4462 const char *servername)
4464 const char *cservername = canon_servername(servername);
4466 r->version = driver->version;
4468 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4469 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4470 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4471 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4473 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4474 driver->driver_path,
4475 r->driver_path);
4477 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4478 driver->data_file,
4479 r->data_file);
4481 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4482 driver->config_file,
4483 r->config_file);
4485 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4486 driver->help_file,
4487 r->help_file);
4489 FILL_DRIVER_STRING(mem_ctx,
4490 driver->monitor_name,
4491 r->monitor_name);
4493 FILL_DRIVER_STRING(mem_ctx,
4494 driver->default_datatype,
4495 r->default_datatype);
4497 r->dependent_files = string_array_from_driver_info(mem_ctx,
4498 driver->dependent_files,
4499 cservername);
4500 return WERR_OK;
4503 /********************************************************************
4504 * fill a spoolss_DriverInfo4 struct
4505 ********************************************************************/
4507 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4508 struct spoolss_DriverInfo4 *r,
4509 const struct spoolss_DriverInfo8 *driver,
4510 const char *servername)
4512 const char *cservername = canon_servername(servername);
4514 r->version = driver->version;
4516 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4517 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4518 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4519 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4521 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4522 driver->driver_path,
4523 r->driver_path);
4525 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4526 driver->data_file,
4527 r->data_file);
4529 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4530 driver->config_file,
4531 r->config_file);
4533 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4534 driver->help_file,
4535 r->help_file);
4537 r->dependent_files = string_array_from_driver_info(mem_ctx,
4538 driver->dependent_files,
4539 cservername);
4541 FILL_DRIVER_STRING(mem_ctx,
4542 driver->monitor_name,
4543 r->monitor_name);
4545 FILL_DRIVER_STRING(mem_ctx,
4546 driver->default_datatype,
4547 r->default_datatype);
4549 r->previous_names = string_array_from_driver_info(mem_ctx,
4550 driver->previous_names,
4551 cservername);
4553 return WERR_OK;
4556 /********************************************************************
4557 * fill a spoolss_DriverInfo5 struct
4558 ********************************************************************/
4560 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4561 struct spoolss_DriverInfo5 *r,
4562 const struct spoolss_DriverInfo8 *driver,
4563 const char *servername)
4565 const char *cservername = canon_servername(servername);
4567 r->version = driver->version;
4569 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4570 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4571 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4572 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4574 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4575 driver->driver_path,
4576 r->driver_path);
4578 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4579 driver->data_file,
4580 r->data_file);
4582 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4583 driver->config_file,
4584 r->config_file);
4586 r->driver_attributes = 0;
4587 r->config_version = 0;
4588 r->driver_version = 0;
4590 return WERR_OK;
4592 /********************************************************************
4593 * fill a spoolss_DriverInfo6 struct
4594 ********************************************************************/
4596 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4597 struct spoolss_DriverInfo6 *r,
4598 const struct spoolss_DriverInfo8 *driver,
4599 const char *servername)
4601 const char *cservername = canon_servername(servername);
4603 r->version = driver->version;
4605 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4606 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4607 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4608 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4610 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4611 driver->driver_path,
4612 r->driver_path);
4614 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4615 driver->data_file,
4616 r->data_file);
4618 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4619 driver->config_file,
4620 r->config_file);
4622 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4623 driver->help_file,
4624 r->help_file);
4626 FILL_DRIVER_STRING(mem_ctx,
4627 driver->monitor_name,
4628 r->monitor_name);
4630 FILL_DRIVER_STRING(mem_ctx,
4631 driver->default_datatype,
4632 r->default_datatype);
4634 r->dependent_files = string_array_from_driver_info(mem_ctx,
4635 driver->dependent_files,
4636 cservername);
4637 r->previous_names = string_array_from_driver_info(mem_ctx,
4638 driver->previous_names,
4639 cservername);
4641 r->driver_date = driver->driver_date;
4642 r->driver_version = driver->driver_version;
4644 FILL_DRIVER_STRING(mem_ctx,
4645 driver->manufacturer_name,
4646 r->manufacturer_name);
4647 FILL_DRIVER_STRING(mem_ctx,
4648 driver->manufacturer_url,
4649 r->manufacturer_url);
4650 FILL_DRIVER_STRING(mem_ctx,
4651 driver->hardware_id,
4652 r->hardware_id);
4653 FILL_DRIVER_STRING(mem_ctx,
4654 driver->provider,
4655 r->provider);
4657 return WERR_OK;
4660 /********************************************************************
4661 * fill a spoolss_DriverInfo8 struct
4662 ********************************************************************/
4664 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4665 struct spoolss_DriverInfo8 *r,
4666 const struct spoolss_DriverInfo8 *driver,
4667 const char *servername)
4669 const char *cservername = canon_servername(servername);
4671 r->version = driver->version;
4673 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4674 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4675 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4676 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4678 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4679 driver->driver_path,
4680 r->driver_path);
4682 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4683 driver->data_file,
4684 r->data_file);
4686 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4687 driver->config_file,
4688 r->config_file);
4690 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4691 driver->help_file,
4692 r->help_file);
4694 FILL_DRIVER_STRING(mem_ctx,
4695 driver->monitor_name,
4696 r->monitor_name);
4698 FILL_DRIVER_STRING(mem_ctx,
4699 driver->default_datatype,
4700 r->default_datatype);
4702 r->dependent_files = string_array_from_driver_info(mem_ctx,
4703 driver->dependent_files,
4704 cservername);
4705 r->previous_names = string_array_from_driver_info(mem_ctx,
4706 driver->previous_names,
4707 cservername);
4709 r->driver_date = driver->driver_date;
4710 r->driver_version = driver->driver_version;
4712 FILL_DRIVER_STRING(mem_ctx,
4713 driver->manufacturer_name,
4714 r->manufacturer_name);
4715 FILL_DRIVER_STRING(mem_ctx,
4716 driver->manufacturer_url,
4717 r->manufacturer_url);
4718 FILL_DRIVER_STRING(mem_ctx,
4719 driver->hardware_id,
4720 r->hardware_id);
4721 FILL_DRIVER_STRING(mem_ctx,
4722 driver->provider,
4723 r->provider);
4725 FILL_DRIVER_STRING(mem_ctx,
4726 driver->print_processor,
4727 r->print_processor);
4728 FILL_DRIVER_STRING(mem_ctx,
4729 driver->vendor_setup,
4730 r->vendor_setup);
4732 r->color_profiles = string_array_from_driver_info(mem_ctx,
4733 driver->color_profiles,
4734 cservername);
4736 FILL_DRIVER_STRING(mem_ctx,
4737 driver->inf_path,
4738 r->inf_path);
4740 r->printer_driver_attributes = driver->printer_driver_attributes;
4742 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4743 driver->core_driver_dependencies,
4744 cservername);
4746 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4747 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4749 return WERR_OK;
4752 #if 0 /* disabled until marshalling issues are resolved - gd */
4753 /********************************************************************
4754 ********************************************************************/
4756 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4757 struct spoolss_DriverFileInfo *r,
4758 const char *cservername,
4759 const char *file_name,
4760 enum spoolss_DriverFileType file_type,
4761 uint32_t file_version)
4763 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4764 cservername, file_name);
4765 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4766 r->file_type = file_type;
4767 r->file_version = file_version;
4769 return WERR_OK;
4772 /********************************************************************
4773 ********************************************************************/
4775 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4776 const struct spoolss_DriverInfo8 *driver,
4777 const char *cservername,
4778 struct spoolss_DriverFileInfo **info_p,
4779 uint32_t *count_p)
4781 struct spoolss_DriverFileInfo *info = NULL;
4782 uint32_t count = 0;
4783 WERROR result;
4784 uint32_t i;
4786 *info_p = NULL;
4787 *count_p = 0;
4789 if (strlen(driver->driver_path)) {
4790 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4791 struct spoolss_DriverFileInfo,
4792 count + 1);
4793 W_ERROR_HAVE_NO_MEMORY(info);
4794 result = fill_spoolss_DriverFileInfo(info,
4795 &info[count],
4796 cservername,
4797 driver->driver_path,
4798 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4800 W_ERROR_NOT_OK_RETURN(result);
4801 count++;
4804 if (strlen(driver->config_file)) {
4805 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4806 struct spoolss_DriverFileInfo,
4807 count + 1);
4808 W_ERROR_HAVE_NO_MEMORY(info);
4809 result = fill_spoolss_DriverFileInfo(info,
4810 &info[count],
4811 cservername,
4812 driver->config_file,
4813 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4815 W_ERROR_NOT_OK_RETURN(result);
4816 count++;
4819 if (strlen(driver->data_file)) {
4820 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4821 struct spoolss_DriverFileInfo,
4822 count + 1);
4823 W_ERROR_HAVE_NO_MEMORY(info);
4824 result = fill_spoolss_DriverFileInfo(info,
4825 &info[count],
4826 cservername,
4827 driver->data_file,
4828 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4830 W_ERROR_NOT_OK_RETURN(result);
4831 count++;
4834 if (strlen(driver->help_file)) {
4835 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4836 struct spoolss_DriverFileInfo,
4837 count + 1);
4838 W_ERROR_HAVE_NO_MEMORY(info);
4839 result = fill_spoolss_DriverFileInfo(info,
4840 &info[count],
4841 cservername,
4842 driver->help_file,
4843 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4845 W_ERROR_NOT_OK_RETURN(result);
4846 count++;
4849 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4850 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4851 struct spoolss_DriverFileInfo,
4852 count + 1);
4853 W_ERROR_HAVE_NO_MEMORY(info);
4854 result = fill_spoolss_DriverFileInfo(info,
4855 &info[count],
4856 cservername,
4857 driver->dependent_files[i],
4858 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4860 W_ERROR_NOT_OK_RETURN(result);
4861 count++;
4864 *info_p = info;
4865 *count_p = count;
4867 return WERR_OK;
4870 /********************************************************************
4871 * fill a spoolss_DriverInfo101 struct
4872 ********************************************************************/
4874 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4875 struct spoolss_DriverInfo101 *r,
4876 const struct spoolss_DriverInfo8 *driver,
4877 const char *servername)
4879 const char *cservername = canon_servername(servername);
4880 WERROR result;
4882 r->version = driver->version;
4884 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4885 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4886 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4887 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4889 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4890 cservername,
4891 &r->file_info,
4892 &r->file_count);
4893 if (!W_ERROR_IS_OK(result)) {
4894 return result;
4897 FILL_DRIVER_STRING(mem_ctx,
4898 driver->monitor_name,
4899 r->monitor_name);
4901 FILL_DRIVER_STRING(mem_ctx,
4902 driver->default_datatype,
4903 r->default_datatype);
4905 r->previous_names = string_array_from_driver_info(mem_ctx,
4906 driver->previous_names,
4907 cservername);
4908 r->driver_date = driver->driver_date;
4909 r->driver_version = driver->driver_version;
4911 FILL_DRIVER_STRING(mem_ctx,
4912 driver->manufacturer_name,
4913 r->manufacturer_name);
4914 FILL_DRIVER_STRING(mem_ctx,
4915 driver->manufacturer_url,
4916 r->manufacturer_url);
4917 FILL_DRIVER_STRING(mem_ctx,
4918 driver->hardware_id,
4919 r->hardware_id);
4920 FILL_DRIVER_STRING(mem_ctx,
4921 driver->provider,
4922 r->provider);
4924 return WERR_OK;
4926 #endif
4927 /********************************************************************
4928 ********************************************************************/
4930 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4931 uint32_t level,
4932 union spoolss_DriverInfo *r,
4933 int snum,
4934 const char *servername,
4935 const char *architecture,
4936 uint32_t version)
4938 NT_PRINTER_INFO_LEVEL *printer = NULL;
4939 struct spoolss_DriverInfo8 *driver;
4940 WERROR result;
4942 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4944 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4945 win_errstr(result)));
4947 if (!W_ERROR_IS_OK(result)) {
4948 return WERR_INVALID_PRINTER_NAME;
4951 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4952 architecture, version);
4954 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4955 win_errstr(result)));
4957 if (!W_ERROR_IS_OK(result)) {
4959 * Is this a W2k client ?
4962 if (version < 3) {
4963 free_a_printer(&printer, 2);
4964 return WERR_UNKNOWN_PRINTER_DRIVER;
4967 /* Yes - try again with a WinNT driver. */
4968 version = 2;
4969 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4970 architecture, version);
4971 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4972 win_errstr(result)));
4973 if (!W_ERROR_IS_OK(result)) {
4974 free_a_printer(&printer, 2);
4975 return WERR_UNKNOWN_PRINTER_DRIVER;
4979 switch (level) {
4980 case 1:
4981 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4982 break;
4983 case 2:
4984 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4985 break;
4986 case 3:
4987 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4988 break;
4989 case 4:
4990 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4991 break;
4992 case 5:
4993 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4994 break;
4995 case 6:
4996 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4997 break;
4998 case 8:
4999 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5000 break;
5001 #if 0 /* disabled until marshalling issues are resolved - gd */
5002 case 101:
5003 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5004 break;
5005 #endif
5006 default:
5007 result = WERR_UNKNOWN_LEVEL;
5008 break;
5011 free_a_printer(&printer, 2);
5012 free_a_printer_driver(driver);
5014 return result;
5017 /****************************************************************
5018 _spoolss_GetPrinterDriver2
5019 ****************************************************************/
5021 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5022 struct spoolss_GetPrinterDriver2 *r)
5024 Printer_entry *printer;
5025 WERROR result;
5027 const char *servername;
5028 int snum;
5030 /* that's an [in out] buffer */
5032 if (!r->in.buffer && (r->in.offered != 0)) {
5033 return WERR_INVALID_PARAM;
5036 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5038 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5039 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5040 return WERR_INVALID_PRINTER_NAME;
5043 *r->out.needed = 0;
5044 *r->out.server_major_version = 0;
5045 *r->out.server_minor_version = 0;
5047 servername = get_server_name(printer);
5049 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5050 return WERR_BADFID;
5053 result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5054 r->out.info, snum,
5055 servername,
5056 r->in.architecture,
5057 r->in.client_major_version);
5058 if (!W_ERROR_IS_OK(result)) {
5059 TALLOC_FREE(r->out.info);
5060 return result;
5063 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5064 r->out.info, r->in.level);
5065 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5067 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5071 /****************************************************************
5072 _spoolss_StartPagePrinter
5073 ****************************************************************/
5075 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5076 struct spoolss_StartPagePrinter *r)
5078 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5080 if (!Printer) {
5081 DEBUG(3,("_spoolss_StartPagePrinter: "
5082 "Error in startpageprinter printer handle\n"));
5083 return WERR_BADFID;
5086 Printer->page_started = true;
5087 return WERR_OK;
5090 /****************************************************************
5091 _spoolss_EndPagePrinter
5092 ****************************************************************/
5094 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5095 struct spoolss_EndPagePrinter *r)
5097 int snum;
5099 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5101 if (!Printer) {
5102 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5103 OUR_HANDLE(r->in.handle)));
5104 return WERR_BADFID;
5107 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5108 return WERR_BADFID;
5110 Printer->page_started = false;
5111 print_job_endpage(snum, Printer->jobid);
5113 return WERR_OK;
5116 /****************************************************************
5117 _spoolss_StartDocPrinter
5118 ****************************************************************/
5120 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5121 struct spoolss_StartDocPrinter *r)
5123 struct spoolss_DocumentInfo1 *info_1;
5124 int snum;
5125 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5127 if (!Printer) {
5128 DEBUG(2,("_spoolss_StartDocPrinter: "
5129 "Invalid handle (%s:%u:%u)\n",
5130 OUR_HANDLE(r->in.handle)));
5131 return WERR_BADFID;
5134 if (r->in.level != 1) {
5135 return WERR_UNKNOWN_LEVEL;
5138 info_1 = r->in.info.info1;
5141 * a nice thing with NT is it doesn't listen to what you tell it.
5142 * when asked to send _only_ RAW datas, it tries to send datas
5143 * in EMF format.
5145 * So I add checks like in NT Server ...
5148 if (info_1->datatype) {
5149 if (strcmp(info_1->datatype, "RAW") != 0) {
5150 *r->out.job_id = 0;
5151 return WERR_INVALID_DATATYPE;
5155 /* get the share number of the printer */
5156 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5157 return WERR_BADFID;
5160 Printer->jobid = print_job_start(p->server_info, snum,
5161 info_1->document_name,
5162 Printer->nt_devmode);
5164 /* An error occured in print_job_start() so return an appropriate
5165 NT error code. */
5167 if (Printer->jobid == -1) {
5168 return map_werror_from_unix(errno);
5171 Printer->document_started = true;
5172 *r->out.job_id = Printer->jobid;
5174 return WERR_OK;
5177 /****************************************************************
5178 _spoolss_EndDocPrinter
5179 ****************************************************************/
5181 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5182 struct spoolss_EndDocPrinter *r)
5184 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5185 int snum;
5187 if (!Printer) {
5188 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5189 OUR_HANDLE(r->in.handle)));
5190 return WERR_BADFID;
5193 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5194 return WERR_BADFID;
5197 Printer->document_started = false;
5198 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5199 /* error codes unhandled so far ... */
5201 return WERR_OK;
5204 /****************************************************************
5205 _spoolss_WritePrinter
5206 ****************************************************************/
5208 WERROR _spoolss_WritePrinter(pipes_struct *p,
5209 struct spoolss_WritePrinter *r)
5211 ssize_t buffer_written;
5212 int snum;
5213 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5215 if (!Printer) {
5216 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5217 OUR_HANDLE(r->in.handle)));
5218 *r->out.num_written = r->in._data_size;
5219 return WERR_BADFID;
5222 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5223 return WERR_BADFID;
5225 buffer_written = print_job_write(snum, Printer->jobid,
5226 (const char *)r->in.data.data,
5227 (SMB_OFF_T)-1,
5228 (size_t)r->in._data_size);
5229 if (buffer_written == (ssize_t)-1) {
5230 *r->out.num_written = 0;
5231 if (errno == ENOSPC)
5232 return WERR_NO_SPOOL_SPACE;
5233 else
5234 return WERR_ACCESS_DENIED;
5237 *r->out.num_written = r->in._data_size;
5239 return WERR_OK;
5242 /********************************************************************
5243 * api_spoolss_getprinter
5244 * called from the spoolss dispatcher
5246 ********************************************************************/
5248 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5249 pipes_struct *p)
5251 int snum;
5252 WERROR errcode = WERR_BADFUNC;
5253 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5255 if (!Printer) {
5256 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5257 OUR_HANDLE(handle)));
5258 return WERR_BADFID;
5261 if (!get_printer_snum(p, handle, &snum, NULL))
5262 return WERR_BADFID;
5264 switch (command) {
5265 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5266 errcode = print_queue_pause(p->server_info, snum);
5267 break;
5268 case SPOOLSS_PRINTER_CONTROL_RESUME:
5269 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5270 errcode = print_queue_resume(p->server_info, snum);
5271 break;
5272 case SPOOLSS_PRINTER_CONTROL_PURGE:
5273 errcode = print_queue_purge(p->server_info, snum);
5274 break;
5275 default:
5276 return WERR_UNKNOWN_LEVEL;
5279 return errcode;
5283 /****************************************************************
5284 _spoolss_AbortPrinter
5285 * From MSDN: "Deletes printer's spool file if printer is configured
5286 * for spooling"
5287 ****************************************************************/
5289 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5290 struct spoolss_AbortPrinter *r)
5292 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5293 int snum;
5294 WERROR errcode = WERR_OK;
5296 if (!Printer) {
5297 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5298 OUR_HANDLE(r->in.handle)));
5299 return WERR_BADFID;
5302 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5303 return WERR_BADFID;
5305 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5307 return errcode;
5310 /********************************************************************
5311 * called by spoolss_api_setprinter
5312 * when updating a printer description
5313 ********************************************************************/
5315 static WERROR update_printer_sec(struct policy_handle *handle,
5316 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5318 struct sec_desc_buf *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5319 WERROR result;
5320 int snum;
5322 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5324 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5325 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5326 OUR_HANDLE(handle)));
5328 result = WERR_BADFID;
5329 goto done;
5332 if (!secdesc_ctr) {
5333 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5334 result = WERR_INVALID_PARAM;
5335 goto done;
5338 /* Check the user has permissions to change the security
5339 descriptor. By experimentation with two NT machines, the user
5340 requires Full Access to the printer to change security
5341 information. */
5343 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5344 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5345 result = WERR_ACCESS_DENIED;
5346 goto done;
5349 /* NT seems to like setting the security descriptor even though
5350 nothing may have actually changed. */
5352 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5353 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5354 result = WERR_BADFID;
5355 goto done;
5358 if (DEBUGLEVEL >= 10) {
5359 struct security_acl *the_acl;
5360 int i;
5362 the_acl = old_secdesc_ctr->sd->dacl;
5363 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5364 PRINTERNAME(snum), the_acl->num_aces));
5366 for (i = 0; i < the_acl->num_aces; i++) {
5367 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5368 &the_acl->aces[i].trustee),
5369 the_acl->aces[i].access_mask));
5372 the_acl = secdesc_ctr->sd->dacl;
5374 if (the_acl) {
5375 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5376 PRINTERNAME(snum), the_acl->num_aces));
5378 for (i = 0; i < the_acl->num_aces; i++) {
5379 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5380 &the_acl->aces[i].trustee),
5381 the_acl->aces[i].access_mask));
5383 } else {
5384 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5388 new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5389 if (!new_secdesc_ctr) {
5390 result = WERR_NOMEM;
5391 goto done;
5394 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5395 result = WERR_OK;
5396 goto done;
5399 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5401 done:
5403 return result;
5406 /********************************************************************
5407 Canonicalize printer info from a client
5409 ATTN: It does not matter what we set the servername to hear
5410 since we do the necessary work in get_a_printer() to set it to
5411 the correct value based on what the client sent in the
5412 _spoolss_open_printer_ex().
5413 ********************************************************************/
5415 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5417 fstring printername;
5418 const char *p;
5420 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5421 "portname=%s drivername=%s comment=%s location=%s\n",
5422 info->servername, info->printername, info->sharename,
5423 info->portname, info->drivername, info->comment, info->location));
5425 /* we force some elements to "correct" values */
5426 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5427 fstrcpy(info->sharename, lp_servicename(snum));
5429 /* check to see if we allow printername != sharename */
5431 if ( lp_force_printername(snum) ) {
5432 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5433 global_myname(), info->sharename );
5434 } else {
5436 /* make sure printername is in \\server\printername format */
5438 fstrcpy( printername, info->printername );
5439 p = printername;
5440 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5441 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5442 p++;
5445 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5446 global_myname(), p );
5449 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5450 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5454 return true;
5457 /****************************************************************************
5458 ****************************************************************************/
5460 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5462 char *cmd = lp_addport_cmd();
5463 char *command = NULL;
5464 int ret;
5465 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5466 bool is_print_op = false;
5468 if ( !*cmd ) {
5469 return WERR_ACCESS_DENIED;
5472 command = talloc_asprintf(ctx,
5473 "%s \"%s\" \"%s\"", cmd, portname, uri );
5474 if (!command) {
5475 return WERR_NOMEM;
5478 if ( token )
5479 is_print_op = user_has_privileges( token, &se_printop );
5481 DEBUG(10,("Running [%s]\n", command));
5483 /********* BEGIN SePrintOperatorPrivilege **********/
5485 if ( is_print_op )
5486 become_root();
5488 ret = smbrun(command, NULL);
5490 if ( is_print_op )
5491 unbecome_root();
5493 /********* END SePrintOperatorPrivilege **********/
5495 DEBUGADD(10,("returned [%d]\n", ret));
5497 TALLOC_FREE(command);
5499 if ( ret != 0 ) {
5500 return WERR_ACCESS_DENIED;
5503 return WERR_OK;
5506 /****************************************************************************
5507 ****************************************************************************/
5509 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5511 char *cmd = lp_addprinter_cmd();
5512 char **qlines;
5513 char *command = NULL;
5514 int numlines;
5515 int ret;
5516 int fd;
5517 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5518 bool is_print_op = false;
5519 char *remote_machine = talloc_strdup(ctx, "%m");
5521 if (!remote_machine) {
5522 return false;
5524 remote_machine = talloc_sub_basic(ctx,
5525 current_user_info.smb_name,
5526 current_user_info.domain,
5527 remote_machine);
5528 if (!remote_machine) {
5529 return false;
5532 command = talloc_asprintf(ctx,
5533 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5534 cmd, printer->info_2->printername, printer->info_2->sharename,
5535 printer->info_2->portname, printer->info_2->drivername,
5536 printer->info_2->location, printer->info_2->comment, remote_machine);
5537 if (!command) {
5538 return false;
5541 if ( token )
5542 is_print_op = user_has_privileges( token, &se_printop );
5544 DEBUG(10,("Running [%s]\n", command));
5546 /********* BEGIN SePrintOperatorPrivilege **********/
5548 if ( is_print_op )
5549 become_root();
5551 if ( (ret = smbrun(command, &fd)) == 0 ) {
5552 /* Tell everyone we updated smb.conf. */
5553 message_send_all(smbd_messaging_context(),
5554 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5557 if ( is_print_op )
5558 unbecome_root();
5560 /********* END SePrintOperatorPrivilege **********/
5562 DEBUGADD(10,("returned [%d]\n", ret));
5564 TALLOC_FREE(command);
5565 TALLOC_FREE(remote_machine);
5567 if ( ret != 0 ) {
5568 if (fd != -1)
5569 close(fd);
5570 return false;
5573 /* reload our services immediately */
5574 become_root();
5575 reload_services(false);
5576 unbecome_root();
5578 numlines = 0;
5579 /* Get lines and convert them back to dos-codepage */
5580 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5581 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5582 close(fd);
5584 /* Set the portname to what the script says the portname should be. */
5585 /* but don't require anything to be return from the script exit a good error code */
5587 if (numlines) {
5588 /* Set the portname to what the script says the portname should be. */
5589 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5590 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5593 TALLOC_FREE(qlines);
5594 return true;
5598 /********************************************************************
5599 * Called by spoolss_api_setprinter
5600 * when updating a printer description.
5601 ********************************************************************/
5603 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5604 struct spoolss_SetPrinterInfoCtr *info_ctr,
5605 struct spoolss_DeviceMode *devmode)
5607 int snum;
5608 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5609 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5610 WERROR result;
5611 DATA_BLOB buffer;
5612 fstring asc_buffer;
5614 DEBUG(8,("update_printer\n"));
5616 result = WERR_OK;
5618 if (!Printer) {
5619 result = WERR_BADFID;
5620 goto done;
5623 if (!get_printer_snum(p, handle, &snum, NULL)) {
5624 result = WERR_BADFID;
5625 goto done;
5628 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5629 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5630 result = WERR_BADFID;
5631 goto done;
5634 DEBUGADD(8,("Converting info_2 struct\n"));
5637 * convert_printer_info converts the incoming
5638 * info from the client and overwrites the info
5639 * just read from the tdb in the pointer 'printer'.
5642 if (!convert_printer_info(info_ctr, printer)) {
5643 result = WERR_NOMEM;
5644 goto done;
5647 if (devmode) {
5648 /* we have a valid devmode
5649 convert it and link it*/
5651 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5652 if (!convert_devicemode(printer->info_2->printername, devmode,
5653 &printer->info_2->devmode)) {
5654 result = WERR_NOMEM;
5655 goto done;
5659 /* Do sanity check on the requested changes for Samba */
5661 if (!check_printer_ok(printer->info_2, snum)) {
5662 result = WERR_INVALID_PARAM;
5663 goto done;
5666 /* FIXME!!! If the driver has changed we really should verify that
5667 it is installed before doing much else --jerry */
5669 /* Check calling user has permission to update printer description */
5671 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5672 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5673 result = WERR_ACCESS_DENIED;
5674 goto done;
5677 /* Call addprinter hook */
5678 /* Check changes to see if this is really needed */
5680 if ( *lp_addprinter_cmd()
5681 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5682 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5683 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5684 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5686 /* add_printer_hook() will call reload_services() */
5688 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5689 printer) ) {
5690 result = WERR_ACCESS_DENIED;
5691 goto done;
5696 * When a *new* driver is bound to a printer, the drivername is used to
5697 * lookup previously saved driver initialization info, which is then
5698 * bound to the printer, simulating what happens in the Windows arch.
5700 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5702 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5703 printer->info_2->drivername));
5705 notify_printer_driver(snum, printer->info_2->drivername);
5709 * flag which changes actually occured. This is a small subset of
5710 * all the possible changes. We also have to update things in the
5711 * DsSpooler key.
5714 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5715 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5716 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5717 REG_SZ, buffer.data, buffer.length);
5719 notify_printer_comment(snum, printer->info_2->comment);
5722 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5723 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5724 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5725 REG_SZ, buffer.data, buffer.length);
5727 notify_printer_sharename(snum, printer->info_2->sharename);
5730 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5731 char *pname;
5733 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5734 pname++;
5735 else
5736 pname = printer->info_2->printername;
5739 push_reg_sz(talloc_tos(), &buffer, pname);
5740 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5741 REG_SZ, buffer.data, buffer.length);
5743 notify_printer_printername( snum, pname );
5746 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5747 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5748 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5749 REG_SZ, buffer.data, buffer.length);
5751 notify_printer_port(snum, printer->info_2->portname);
5754 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5755 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5756 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5757 REG_SZ, buffer.data, buffer.length);
5759 notify_printer_location(snum, printer->info_2->location);
5762 /* here we need to update some more DsSpooler keys */
5763 /* uNCName, serverName, shortServerName */
5765 push_reg_sz(talloc_tos(), &buffer, global_myname());
5766 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5767 REG_SZ, buffer.data, buffer.length);
5768 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5769 REG_SZ, buffer.data, buffer.length);
5771 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5772 global_myname(), printer->info_2->sharename );
5773 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5774 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5775 REG_SZ, buffer.data, buffer.length);
5777 /* Update printer info */
5778 result = mod_a_printer(printer, 2);
5780 done:
5781 free_a_printer(&printer, 2);
5782 free_a_printer(&old_printer, 2);
5785 return result;
5788 /****************************************************************************
5789 ****************************************************************************/
5790 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5791 struct policy_handle *handle,
5792 struct spoolss_SetPrinterInfo7 *info7)
5794 #ifdef HAVE_ADS
5795 int snum;
5796 Printer_entry *Printer;
5798 if ( lp_security() != SEC_ADS ) {
5799 return WERR_UNKNOWN_LEVEL;
5802 Printer = find_printer_index_by_hnd(p, handle);
5804 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5806 if (!Printer)
5807 return WERR_BADFID;
5809 if (!get_printer_snum(p, handle, &snum, NULL))
5810 return WERR_BADFID;
5812 nt_printer_publish(Printer, snum, info7->action);
5814 return WERR_OK;
5815 #else
5816 return WERR_UNKNOWN_LEVEL;
5817 #endif
5820 /********************************************************************
5821 ********************************************************************/
5823 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5824 struct spoolss_DeviceMode *devmode)
5826 int snum;
5827 NT_PRINTER_INFO_LEVEL *printer = NULL;
5828 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5829 WERROR result;
5831 DEBUG(8,("update_printer_devmode\n"));
5833 result = WERR_OK;
5835 if (!Printer) {
5836 result = WERR_BADFID;
5837 goto done;
5840 if (!get_printer_snum(p, handle, &snum, NULL)) {
5841 result = WERR_BADFID;
5842 goto done;
5845 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5846 result = WERR_BADFID;
5847 goto done;
5850 if (devmode) {
5851 /* we have a valid devmode
5852 convert it and link it*/
5854 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5855 if (!convert_devicemode(printer->info_2->printername, devmode,
5856 &printer->info_2->devmode)) {
5857 result = WERR_NOMEM;
5858 goto done;
5862 /* Check calling user has permission to update printer description */
5864 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5865 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5866 result = WERR_ACCESS_DENIED;
5867 goto done;
5871 /* Update printer info */
5872 result = mod_a_printer(printer, 2);
5874 done:
5875 free_a_printer(&printer, 2);
5877 return result;
5881 /****************************************************************
5882 _spoolss_SetPrinter
5883 ****************************************************************/
5885 WERROR _spoolss_SetPrinter(pipes_struct *p,
5886 struct spoolss_SetPrinter *r)
5888 WERROR result;
5890 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5892 if (!Printer) {
5893 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5894 OUR_HANDLE(r->in.handle)));
5895 return WERR_BADFID;
5898 /* check the level */
5899 switch (r->in.info_ctr->level) {
5900 case 0:
5901 return control_printer(r->in.handle, r->in.command, p);
5902 case 2:
5903 result = update_printer(p, r->in.handle,
5904 r->in.info_ctr,
5905 r->in.devmode_ctr->devmode);
5906 if (!W_ERROR_IS_OK(result))
5907 return result;
5908 if (r->in.secdesc_ctr->sd)
5909 result = update_printer_sec(r->in.handle, p,
5910 r->in.secdesc_ctr);
5911 return result;
5912 case 3:
5913 return update_printer_sec(r->in.handle, p,
5914 r->in.secdesc_ctr);
5915 case 7:
5916 return publish_or_unpublish_printer(p, r->in.handle,
5917 r->in.info_ctr->info.info7);
5918 case 8:
5919 return update_printer_devmode(p, r->in.handle,
5920 r->in.devmode_ctr->devmode);
5921 default:
5922 return WERR_UNKNOWN_LEVEL;
5926 /****************************************************************
5927 _spoolss_FindClosePrinterNotify
5928 ****************************************************************/
5930 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5931 struct spoolss_FindClosePrinterNotify *r)
5933 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5935 if (!Printer) {
5936 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5937 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5938 return WERR_BADFID;
5941 if (Printer->notify.client_connected == true) {
5942 int snum = -1;
5944 if ( Printer->printer_type == SPLHND_SERVER)
5945 snum = -1;
5946 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5947 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5948 return WERR_BADFID;
5950 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5953 Printer->notify.flags=0;
5954 Printer->notify.options=0;
5955 Printer->notify.localmachine[0]='\0';
5956 Printer->notify.printerlocal=0;
5957 TALLOC_FREE(Printer->notify.option);
5958 Printer->notify.client_connected = false;
5960 return WERR_OK;
5963 /****************************************************************
5964 _spoolss_AddJob
5965 ****************************************************************/
5967 WERROR _spoolss_AddJob(pipes_struct *p,
5968 struct spoolss_AddJob *r)
5970 if (!r->in.buffer && (r->in.offered != 0)) {
5971 return WERR_INVALID_PARAM;
5974 /* this is what a NT server returns for AddJob. AddJob must fail on
5975 * non-local printers */
5977 if (r->in.level != 1) {
5978 return WERR_UNKNOWN_LEVEL;
5981 return WERR_INVALID_PARAM;
5984 /****************************************************************************
5985 fill_job_info1
5986 ****************************************************************************/
5988 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5989 struct spoolss_JobInfo1 *r,
5990 const print_queue_struct *queue,
5991 int position, int snum,
5992 const NT_PRINTER_INFO_LEVEL *ntprinter)
5994 struct tm *t;
5996 t = gmtime(&queue->time);
5998 r->job_id = queue->job;
6000 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6001 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6002 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6003 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6004 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6005 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6006 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6007 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6008 r->data_type = talloc_strdup(mem_ctx, "RAW");
6009 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6010 r->text_status = talloc_strdup(mem_ctx, "");
6011 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6013 r->status = nt_printj_status(queue->status);
6014 r->priority = queue->priority;
6015 r->position = position;
6016 r->total_pages = queue->page_count;
6017 r->pages_printed = 0; /* ??? */
6019 init_systemtime(&r->submitted, t);
6021 return WERR_OK;
6024 /****************************************************************************
6025 fill_job_info2
6026 ****************************************************************************/
6028 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6029 struct spoolss_JobInfo2 *r,
6030 const print_queue_struct *queue,
6031 int position, int snum,
6032 const NT_PRINTER_INFO_LEVEL *ntprinter,
6033 struct spoolss_DeviceMode *devmode)
6035 struct tm *t;
6037 t = gmtime(&queue->time);
6039 r->job_id = queue->job;
6041 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6042 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6043 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6044 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6045 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6046 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6047 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6048 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6049 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6050 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6051 r->data_type = talloc_strdup(mem_ctx, "RAW");
6052 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6053 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6054 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6055 r->parameters = talloc_strdup(mem_ctx, "");
6056 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6057 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6058 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6060 r->devmode = devmode;
6062 r->text_status = talloc_strdup(mem_ctx, "");
6063 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6065 r->secdesc = NULL;
6067 r->status = nt_printj_status(queue->status);
6068 r->priority = queue->priority;
6069 r->position = position;
6070 r->start_time = 0;
6071 r->until_time = 0;
6072 r->total_pages = queue->page_count;
6073 r->size = queue->size;
6074 init_systemtime(&r->submitted, t);
6075 r->time = 0;
6076 r->pages_printed = 0; /* ??? */
6078 return WERR_OK;
6081 /****************************************************************************
6082 fill_job_info3
6083 ****************************************************************************/
6085 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6086 struct spoolss_JobInfo3 *r,
6087 const print_queue_struct *queue,
6088 const print_queue_struct *next_queue,
6089 int position, int snum,
6090 const NT_PRINTER_INFO_LEVEL *ntprinter)
6092 r->job_id = queue->job;
6093 r->next_job_id = 0;
6094 if (next_queue) {
6095 r->next_job_id = next_queue->job;
6097 r->reserved = 0;
6099 return WERR_OK;
6102 /****************************************************************************
6103 Enumjobs at level 1.
6104 ****************************************************************************/
6106 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6107 const print_queue_struct *queue,
6108 uint32_t num_queues, int snum,
6109 const NT_PRINTER_INFO_LEVEL *ntprinter,
6110 union spoolss_JobInfo **info_p,
6111 uint32_t *count)
6113 union spoolss_JobInfo *info;
6114 int i;
6115 WERROR result = WERR_OK;
6117 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6118 W_ERROR_HAVE_NO_MEMORY(info);
6120 *count = num_queues;
6122 for (i=0; i<*count; i++) {
6123 result = fill_job_info1(info,
6124 &info[i].info1,
6125 &queue[i],
6127 snum,
6128 ntprinter);
6129 if (!W_ERROR_IS_OK(result)) {
6130 goto out;
6134 out:
6135 if (!W_ERROR_IS_OK(result)) {
6136 TALLOC_FREE(info);
6137 *count = 0;
6138 return result;
6141 *info_p = info;
6143 return WERR_OK;
6146 /****************************************************************************
6147 Enumjobs at level 2.
6148 ****************************************************************************/
6150 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6151 const print_queue_struct *queue,
6152 uint32_t num_queues, int snum,
6153 const NT_PRINTER_INFO_LEVEL *ntprinter,
6154 union spoolss_JobInfo **info_p,
6155 uint32_t *count)
6157 union spoolss_JobInfo *info;
6158 int i;
6159 WERROR result = WERR_OK;
6161 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6162 W_ERROR_HAVE_NO_MEMORY(info);
6164 *count = num_queues;
6166 for (i=0; i<*count; i++) {
6168 struct spoolss_DeviceMode *devmode;
6170 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6171 if (!devmode) {
6172 result = WERR_NOMEM;
6173 goto out;
6176 result = fill_job_info2(info,
6177 &info[i].info2,
6178 &queue[i],
6180 snum,
6181 ntprinter,
6182 devmode);
6183 if (!W_ERROR_IS_OK(result)) {
6184 goto out;
6188 out:
6189 if (!W_ERROR_IS_OK(result)) {
6190 TALLOC_FREE(info);
6191 *count = 0;
6192 return result;
6195 *info_p = info;
6197 return WERR_OK;
6200 /****************************************************************************
6201 Enumjobs at level 3.
6202 ****************************************************************************/
6204 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6205 const print_queue_struct *queue,
6206 uint32_t num_queues, int snum,
6207 const NT_PRINTER_INFO_LEVEL *ntprinter,
6208 union spoolss_JobInfo **info_p,
6209 uint32_t *count)
6211 union spoolss_JobInfo *info;
6212 int i;
6213 WERROR result = WERR_OK;
6215 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6216 W_ERROR_HAVE_NO_MEMORY(info);
6218 *count = num_queues;
6220 for (i=0; i<*count; i++) {
6221 const print_queue_struct *next_queue = NULL;
6223 if (i+1 < *count) {
6224 next_queue = &queue[i+1];
6227 result = fill_job_info3(info,
6228 &info[i].info3,
6229 &queue[i],
6230 next_queue,
6232 snum,
6233 ntprinter);
6234 if (!W_ERROR_IS_OK(result)) {
6235 goto out;
6239 out:
6240 if (!W_ERROR_IS_OK(result)) {
6241 TALLOC_FREE(info);
6242 *count = 0;
6243 return result;
6246 *info_p = info;
6248 return WERR_OK;
6251 /****************************************************************
6252 _spoolss_EnumJobs
6253 ****************************************************************/
6255 WERROR _spoolss_EnumJobs(pipes_struct *p,
6256 struct spoolss_EnumJobs *r)
6258 WERROR result;
6259 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6260 int snum;
6261 print_status_struct prt_status;
6262 print_queue_struct *queue = NULL;
6263 uint32_t count;
6265 /* that's an [in out] buffer */
6267 if (!r->in.buffer && (r->in.offered != 0)) {
6268 return WERR_INVALID_PARAM;
6271 DEBUG(4,("_spoolss_EnumJobs\n"));
6273 *r->out.needed = 0;
6274 *r->out.count = 0;
6275 *r->out.info = NULL;
6277 /* lookup the printer snum and tdb entry */
6279 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6280 return WERR_BADFID;
6283 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6284 if (!W_ERROR_IS_OK(result)) {
6285 return result;
6288 count = print_queue_status(snum, &queue, &prt_status);
6289 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6290 count, prt_status.status, prt_status.message));
6292 if (count == 0) {
6293 SAFE_FREE(queue);
6294 free_a_printer(&ntprinter, 2);
6295 return WERR_OK;
6298 switch (r->in.level) {
6299 case 1:
6300 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6301 ntprinter, r->out.info, r->out.count);
6302 break;
6303 case 2:
6304 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6305 ntprinter, r->out.info, r->out.count);
6306 break;
6307 case 3:
6308 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6309 ntprinter, r->out.info, r->out.count);
6310 break;
6311 default:
6312 result = WERR_UNKNOWN_LEVEL;
6313 break;
6316 SAFE_FREE(queue);
6317 free_a_printer(&ntprinter, 2);
6319 if (!W_ERROR_IS_OK(result)) {
6320 return result;
6323 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6324 spoolss_EnumJobs,
6325 *r->out.info, r->in.level,
6326 *r->out.count);
6327 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6328 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6330 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6333 /****************************************************************
6334 _spoolss_ScheduleJob
6335 ****************************************************************/
6337 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6338 struct spoolss_ScheduleJob *r)
6340 return WERR_OK;
6343 /****************************************************************
6344 ****************************************************************/
6346 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6347 const char *printer_name,
6348 uint32_t job_id,
6349 struct spoolss_SetJobInfo1 *r)
6351 char *old_doc_name;
6353 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6354 return WERR_BADFID;
6357 if (strequal(old_doc_name, r->document_name)) {
6358 return WERR_OK;
6361 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6362 return WERR_BADFID;
6365 return WERR_OK;
6368 /****************************************************************
6369 _spoolss_SetJob
6370 ****************************************************************/
6372 WERROR _spoolss_SetJob(pipes_struct *p,
6373 struct spoolss_SetJob *r)
6375 int snum;
6376 WERROR errcode = WERR_BADFUNC;
6378 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6379 return WERR_BADFID;
6382 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6383 return WERR_INVALID_PRINTER_NAME;
6386 switch (r->in.command) {
6387 case SPOOLSS_JOB_CONTROL_CANCEL:
6388 case SPOOLSS_JOB_CONTROL_DELETE:
6389 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6390 errcode = WERR_OK;
6392 break;
6393 case SPOOLSS_JOB_CONTROL_PAUSE:
6394 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6395 errcode = WERR_OK;
6397 break;
6398 case SPOOLSS_JOB_CONTROL_RESTART:
6399 case SPOOLSS_JOB_CONTROL_RESUME:
6400 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6401 errcode = WERR_OK;
6403 break;
6404 case 0:
6405 errcode = WERR_OK;
6406 break;
6407 default:
6408 return WERR_UNKNOWN_LEVEL;
6411 if (!W_ERROR_IS_OK(errcode)) {
6412 return errcode;
6415 if (r->in.ctr == NULL) {
6416 return errcode;
6419 switch (r->in.ctr->level) {
6420 case 1:
6421 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6422 r->in.job_id,
6423 r->in.ctr->info.info1);
6424 break;
6425 case 2:
6426 case 3:
6427 case 4:
6428 default:
6429 return WERR_UNKNOWN_LEVEL;
6432 return errcode;
6435 /****************************************************************************
6436 Enumerates all printer drivers by level and architecture.
6437 ****************************************************************************/
6439 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6440 const char *servername,
6441 const char *architecture,
6442 uint32_t level,
6443 union spoolss_DriverInfo **info_p,
6444 uint32_t *count_p)
6446 int i;
6447 int ndrivers;
6448 uint32_t version;
6449 fstring *list = NULL;
6450 struct spoolss_DriverInfo8 *driver;
6451 union spoolss_DriverInfo *info = NULL;
6452 uint32_t count = 0;
6453 WERROR result = WERR_OK;
6455 *count_p = 0;
6456 *info_p = NULL;
6458 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6459 list = NULL;
6460 ndrivers = get_ntdrivers(&list, architecture, version);
6461 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6462 ndrivers, architecture, version));
6464 if (ndrivers == -1) {
6465 result = WERR_NOMEM;
6466 goto out;
6469 if (ndrivers != 0) {
6470 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6471 union spoolss_DriverInfo,
6472 count + ndrivers);
6473 if (!info) {
6474 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6475 "failed to enlarge driver info buffer!\n"));
6476 result = WERR_NOMEM;
6477 goto out;
6481 for (i=0; i<ndrivers; i++) {
6482 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6483 ZERO_STRUCT(driver);
6484 result = get_a_printer_driver(mem_ctx, &driver, list[i],
6485 architecture, version);
6486 if (!W_ERROR_IS_OK(result)) {
6487 goto out;
6490 switch (level) {
6491 case 1:
6492 result = fill_printer_driver_info1(info, &info[count+i].info1,
6493 driver, servername);
6494 break;
6495 case 2:
6496 result = fill_printer_driver_info2(info, &info[count+i].info2,
6497 driver, servername);
6498 break;
6499 case 3:
6500 result = fill_printer_driver_info3(info, &info[count+i].info3,
6501 driver, servername);
6502 break;
6503 case 4:
6504 result = fill_printer_driver_info4(info, &info[count+i].info4,
6505 driver, servername);
6506 break;
6507 case 5:
6508 result = fill_printer_driver_info5(info, &info[count+i].info5,
6509 driver, servername);
6510 break;
6511 case 6:
6512 result = fill_printer_driver_info6(info, &info[count+i].info6,
6513 driver, servername);
6514 break;
6515 case 8:
6516 result = fill_printer_driver_info8(info, &info[count+i].info8,
6517 driver, servername);
6518 break;
6519 default:
6520 result = WERR_UNKNOWN_LEVEL;
6521 break;
6524 free_a_printer_driver(driver);
6526 if (!W_ERROR_IS_OK(result)) {
6527 goto out;
6531 count += ndrivers;
6532 SAFE_FREE(list);
6535 out:
6536 SAFE_FREE(list);
6538 if (!W_ERROR_IS_OK(result)) {
6539 TALLOC_FREE(info);
6540 return result;
6543 *info_p = info;
6544 *count_p = count;
6546 return WERR_OK;
6549 /****************************************************************************
6550 Enumerates all printer drivers by level.
6551 ****************************************************************************/
6553 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6554 const char *servername,
6555 const char *architecture,
6556 uint32_t level,
6557 union spoolss_DriverInfo **info_p,
6558 uint32_t *count_p)
6560 uint32_t a,i;
6561 WERROR result = WERR_OK;
6563 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6565 for (a=0; archi_table[a].long_archi != NULL; a++) {
6567 union spoolss_DriverInfo *info = NULL;
6568 uint32_t count = 0;
6570 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6571 servername,
6572 archi_table[a].long_archi,
6573 level,
6574 &info,
6575 &count);
6576 if (!W_ERROR_IS_OK(result)) {
6577 continue;
6580 for (i=0; i < count; i++) {
6581 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6582 info[i], info_p, count_p);
6586 return result;
6589 return enumprinterdrivers_level_by_architecture(mem_ctx,
6590 servername,
6591 architecture,
6592 level,
6593 info_p,
6594 count_p);
6597 /****************************************************************
6598 _spoolss_EnumPrinterDrivers
6599 ****************************************************************/
6601 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6602 struct spoolss_EnumPrinterDrivers *r)
6604 const char *cservername;
6605 WERROR result;
6607 /* that's an [in out] buffer */
6609 if (!r->in.buffer && (r->in.offered != 0)) {
6610 return WERR_INVALID_PARAM;
6613 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6615 *r->out.needed = 0;
6616 *r->out.count = 0;
6617 *r->out.info = NULL;
6619 cservername = canon_servername(r->in.server);
6621 if (!is_myname_or_ipaddr(cservername)) {
6622 return WERR_UNKNOWN_PRINTER_DRIVER;
6625 result = enumprinterdrivers_level(p->mem_ctx, cservername,
6626 r->in.environment,
6627 r->in.level,
6628 r->out.info,
6629 r->out.count);
6630 if (!W_ERROR_IS_OK(result)) {
6631 return result;
6634 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6635 spoolss_EnumPrinterDrivers,
6636 *r->out.info, r->in.level,
6637 *r->out.count);
6638 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6639 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6641 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6644 /****************************************************************************
6645 ****************************************************************************/
6647 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6648 struct spoolss_FormInfo1 *r,
6649 const nt_forms_struct *form)
6651 r->form_name = talloc_strdup(mem_ctx, form->name);
6652 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6654 r->flags = form->flag;
6655 r->size.width = form->width;
6656 r->size.height = form->length;
6657 r->area.left = form->left;
6658 r->area.top = form->top;
6659 r->area.right = form->right;
6660 r->area.bottom = form->bottom;
6662 return WERR_OK;
6665 /****************************************************************
6666 spoolss_enumforms_level1
6667 ****************************************************************/
6669 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6670 const nt_forms_struct *builtin_forms,
6671 uint32_t num_builtin_forms,
6672 const nt_forms_struct *user_forms,
6673 uint32_t num_user_forms,
6674 union spoolss_FormInfo **info_p,
6675 uint32_t *count)
6677 union spoolss_FormInfo *info;
6678 WERROR result = WERR_OK;
6679 int i;
6681 *count = num_builtin_forms + num_user_forms;
6683 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6684 W_ERROR_HAVE_NO_MEMORY(info);
6686 /* construct the list of form structures */
6687 for (i=0; i<num_builtin_forms; i++) {
6688 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6689 result = fill_form_info_1(info, &info[i].info1,
6690 &builtin_forms[i]);
6691 if (!W_ERROR_IS_OK(result)) {
6692 goto out;
6696 for (i=0; i<num_user_forms; i++) {
6697 DEBUGADD(6,("Filling user form number [%d]\n",i));
6698 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6699 &user_forms[i]);
6700 if (!W_ERROR_IS_OK(result)) {
6701 goto out;
6705 out:
6706 if (!W_ERROR_IS_OK(result)) {
6707 TALLOC_FREE(info);
6708 *count = 0;
6709 return result;
6712 *info_p = info;
6714 return WERR_OK;
6717 /****************************************************************
6718 _spoolss_EnumForms
6719 ****************************************************************/
6721 WERROR _spoolss_EnumForms(pipes_struct *p,
6722 struct spoolss_EnumForms *r)
6724 WERROR result;
6725 nt_forms_struct *user_forms = NULL;
6726 nt_forms_struct *builtin_forms = NULL;
6727 uint32_t num_user_forms;
6728 uint32_t num_builtin_forms;
6730 *r->out.count = 0;
6731 *r->out.needed = 0;
6732 *r->out.info = NULL;
6734 /* that's an [in out] buffer */
6736 if (!r->in.buffer && (r->in.offered != 0) ) {
6737 return WERR_INVALID_PARAM;
6740 DEBUG(4,("_spoolss_EnumForms\n"));
6741 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6742 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6744 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6745 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6746 num_user_forms = get_ntforms(&user_forms);
6747 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6749 if (num_user_forms + num_builtin_forms == 0) {
6750 SAFE_FREE(builtin_forms);
6751 SAFE_FREE(user_forms);
6752 return WERR_NO_MORE_ITEMS;
6755 switch (r->in.level) {
6756 case 1:
6757 result = spoolss_enumforms_level1(p->mem_ctx,
6758 builtin_forms,
6759 num_builtin_forms,
6760 user_forms,
6761 num_user_forms,
6762 r->out.info,
6763 r->out.count);
6764 break;
6765 default:
6766 result = WERR_UNKNOWN_LEVEL;
6767 break;
6770 SAFE_FREE(user_forms);
6771 SAFE_FREE(builtin_forms);
6773 if (!W_ERROR_IS_OK(result)) {
6774 return result;
6777 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6778 spoolss_EnumForms,
6779 *r->out.info, r->in.level,
6780 *r->out.count);
6781 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6782 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6784 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6787 /****************************************************************
6788 ****************************************************************/
6790 static WERROR find_form_byname(const char *name,
6791 nt_forms_struct *form)
6793 nt_forms_struct *list = NULL;
6794 int num_forms = 0, i = 0;
6796 if (get_a_builtin_ntform_by_string(name, form)) {
6797 return WERR_OK;
6800 num_forms = get_ntforms(&list);
6801 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6803 if (num_forms == 0) {
6804 return WERR_BADFID;
6807 /* Check if the requested name is in the list of form structures */
6808 for (i = 0; i < num_forms; i++) {
6810 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6812 if (strequal(name, list[i].name)) {
6813 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6814 *form = list[i];
6815 SAFE_FREE(list);
6816 return WERR_OK;
6820 SAFE_FREE(list);
6822 return WERR_BADFID;
6825 /****************************************************************
6826 _spoolss_GetForm
6827 ****************************************************************/
6829 WERROR _spoolss_GetForm(pipes_struct *p,
6830 struct spoolss_GetForm *r)
6832 WERROR result;
6833 nt_forms_struct form;
6835 /* that's an [in out] buffer */
6837 if (!r->in.buffer && (r->in.offered != 0)) {
6838 return WERR_INVALID_PARAM;
6841 DEBUG(4,("_spoolss_GetForm\n"));
6842 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6843 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6845 result = find_form_byname(r->in.form_name, &form);
6846 if (!W_ERROR_IS_OK(result)) {
6847 TALLOC_FREE(r->out.info);
6848 return result;
6851 switch (r->in.level) {
6852 case 1:
6853 result = fill_form_info_1(p->mem_ctx,
6854 &r->out.info->info1,
6855 &form);
6856 break;
6858 default:
6859 result = WERR_UNKNOWN_LEVEL;
6860 break;
6863 if (!W_ERROR_IS_OK(result)) {
6864 TALLOC_FREE(r->out.info);
6865 return result;
6868 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6869 r->out.info, r->in.level);
6870 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6872 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6875 /****************************************************************************
6876 ****************************************************************************/
6878 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6879 struct spoolss_PortInfo1 *r,
6880 const char *name)
6882 r->port_name = talloc_strdup(mem_ctx, name);
6883 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6885 return WERR_OK;
6888 /****************************************************************************
6889 TODO: This probably needs distinguish between TCP/IP and Local ports
6890 somehow.
6891 ****************************************************************************/
6893 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6894 struct spoolss_PortInfo2 *r,
6895 const char *name)
6897 r->port_name = talloc_strdup(mem_ctx, name);
6898 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6900 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6901 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6903 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6904 W_ERROR_HAVE_NO_MEMORY(r->description);
6906 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6907 r->reserved = 0;
6909 return WERR_OK;
6913 /****************************************************************************
6914 wrapper around the enumer ports command
6915 ****************************************************************************/
6917 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6919 char *cmd = lp_enumports_cmd();
6920 char **qlines = NULL;
6921 char *command = NULL;
6922 int numlines;
6923 int ret;
6924 int fd;
6926 *count = 0;
6927 *lines = NULL;
6929 /* if no hook then just fill in the default port */
6931 if ( !*cmd ) {
6932 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6933 return WERR_NOMEM;
6935 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6936 TALLOC_FREE(qlines);
6937 return WERR_NOMEM;
6939 qlines[1] = NULL;
6940 numlines = 1;
6942 else {
6943 /* we have a valid enumport command */
6945 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6946 if (!command) {
6947 return WERR_NOMEM;
6950 DEBUG(10,("Running [%s]\n", command));
6951 ret = smbrun(command, &fd);
6952 DEBUG(10,("Returned [%d]\n", ret));
6953 TALLOC_FREE(command);
6954 if (ret != 0) {
6955 if (fd != -1) {
6956 close(fd);
6958 return WERR_ACCESS_DENIED;
6961 numlines = 0;
6962 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6963 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6964 close(fd);
6967 *count = numlines;
6968 *lines = qlines;
6970 return WERR_OK;
6973 /****************************************************************************
6974 enumports level 1.
6975 ****************************************************************************/
6977 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6978 union spoolss_PortInfo **info_p,
6979 uint32_t *count)
6981 union spoolss_PortInfo *info = NULL;
6982 int i=0;
6983 WERROR result = WERR_OK;
6984 char **qlines = NULL;
6985 int numlines = 0;
6987 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6988 if (!W_ERROR_IS_OK(result)) {
6989 goto out;
6992 if (numlines) {
6993 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6994 if (!info) {
6995 DEBUG(10,("Returning WERR_NOMEM\n"));
6996 result = WERR_NOMEM;
6997 goto out;
7000 for (i=0; i<numlines; i++) {
7001 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7002 result = fill_port_1(info, &info[i].info1, qlines[i]);
7003 if (!W_ERROR_IS_OK(result)) {
7004 goto out;
7008 TALLOC_FREE(qlines);
7010 out:
7011 if (!W_ERROR_IS_OK(result)) {
7012 TALLOC_FREE(info);
7013 TALLOC_FREE(qlines);
7014 *count = 0;
7015 *info_p = NULL;
7016 return result;
7019 *info_p = info;
7020 *count = numlines;
7022 return WERR_OK;
7025 /****************************************************************************
7026 enumports level 2.
7027 ****************************************************************************/
7029 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7030 union spoolss_PortInfo **info_p,
7031 uint32_t *count)
7033 union spoolss_PortInfo *info = NULL;
7034 int i=0;
7035 WERROR result = WERR_OK;
7036 char **qlines = NULL;
7037 int numlines = 0;
7039 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7040 if (!W_ERROR_IS_OK(result)) {
7041 goto out;
7044 if (numlines) {
7045 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7046 if (!info) {
7047 DEBUG(10,("Returning WERR_NOMEM\n"));
7048 result = WERR_NOMEM;
7049 goto out;
7052 for (i=0; i<numlines; i++) {
7053 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7054 result = fill_port_2(info, &info[i].info2, qlines[i]);
7055 if (!W_ERROR_IS_OK(result)) {
7056 goto out;
7060 TALLOC_FREE(qlines);
7062 out:
7063 if (!W_ERROR_IS_OK(result)) {
7064 TALLOC_FREE(info);
7065 TALLOC_FREE(qlines);
7066 *count = 0;
7067 *info_p = NULL;
7068 return result;
7071 *info_p = info;
7072 *count = numlines;
7074 return WERR_OK;
7077 /****************************************************************
7078 _spoolss_EnumPorts
7079 ****************************************************************/
7081 WERROR _spoolss_EnumPorts(pipes_struct *p,
7082 struct spoolss_EnumPorts *r)
7084 WERROR result;
7086 /* that's an [in out] buffer */
7088 if (!r->in.buffer && (r->in.offered != 0)) {
7089 return WERR_INVALID_PARAM;
7092 DEBUG(4,("_spoolss_EnumPorts\n"));
7094 *r->out.count = 0;
7095 *r->out.needed = 0;
7096 *r->out.info = NULL;
7098 switch (r->in.level) {
7099 case 1:
7100 result = enumports_level_1(p->mem_ctx, r->out.info,
7101 r->out.count);
7102 break;
7103 case 2:
7104 result = enumports_level_2(p->mem_ctx, r->out.info,
7105 r->out.count);
7106 break;
7107 default:
7108 return WERR_UNKNOWN_LEVEL;
7111 if (!W_ERROR_IS_OK(result)) {
7112 return result;
7115 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7116 spoolss_EnumPorts,
7117 *r->out.info, r->in.level,
7118 *r->out.count);
7119 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7120 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7122 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7125 /****************************************************************************
7126 ****************************************************************************/
7128 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7129 const char *server,
7130 struct spoolss_SetPrinterInfoCtr *info_ctr,
7131 struct spoolss_DeviceMode *devmode,
7132 struct security_descriptor *sec_desc,
7133 struct spoolss_UserLevelCtr *user_ctr,
7134 struct policy_handle *handle)
7136 NT_PRINTER_INFO_LEVEL *printer = NULL;
7137 fstring name;
7138 int snum;
7139 WERROR err = WERR_OK;
7141 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7142 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7143 return WERR_NOMEM;
7146 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7147 if (!convert_printer_info(info_ctr, printer)) {
7148 free_a_printer(&printer, 2);
7149 return WERR_NOMEM;
7152 /* samba does not have a concept of local, non-shared printers yet, so
7153 * make sure we always setup sharename - gd */
7154 if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7155 DEBUG(5, ("spoolss_addprinterex_level_2: "
7156 "no sharename has been set, setting printername %s as sharename\n",
7157 printer->info_2->printername));
7158 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7161 /* check to see if the printer already exists */
7163 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7164 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7165 printer->info_2->sharename));
7166 free_a_printer(&printer, 2);
7167 return WERR_PRINTER_ALREADY_EXISTS;
7170 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7171 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7172 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7173 printer->info_2->printername));
7174 free_a_printer(&printer, 2);
7175 return WERR_PRINTER_ALREADY_EXISTS;
7179 /* validate printer info struct */
7180 if (!info_ctr->info.info2->printername ||
7181 strlen(info_ctr->info.info2->printername) == 0) {
7182 free_a_printer(&printer,2);
7183 return WERR_INVALID_PRINTER_NAME;
7185 if (!info_ctr->info.info2->portname ||
7186 strlen(info_ctr->info.info2->portname) == 0) {
7187 free_a_printer(&printer,2);
7188 return WERR_UNKNOWN_PORT;
7190 if (!info_ctr->info.info2->drivername ||
7191 strlen(info_ctr->info.info2->drivername) == 0) {
7192 free_a_printer(&printer,2);
7193 return WERR_UNKNOWN_PRINTER_DRIVER;
7195 if (!info_ctr->info.info2->printprocessor ||
7196 strlen(info_ctr->info.info2->printprocessor) == 0) {
7197 free_a_printer(&printer,2);
7198 return WERR_UNKNOWN_PRINTPROCESSOR;
7201 /* FIXME!!! smbd should check to see if the driver is installed before
7202 trying to add a printer like this --jerry */
7204 if (*lp_addprinter_cmd() ) {
7205 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7206 printer) ) {
7207 free_a_printer(&printer,2);
7208 return WERR_ACCESS_DENIED;
7210 } else {
7211 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7212 "smb.conf parameter \"addprinter command\" is defined. This"
7213 "parameter must exist for this call to succeed\n",
7214 printer->info_2->sharename ));
7217 /* use our primary netbios name since get_a_printer() will convert
7218 it to what the client expects on a case by case basis */
7220 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7221 printer->info_2->sharename);
7224 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7225 free_a_printer(&printer,2);
7226 return WERR_ACCESS_DENIED;
7229 /* you must be a printer admin to add a new printer */
7230 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7231 free_a_printer(&printer,2);
7232 return WERR_ACCESS_DENIED;
7236 * Do sanity check on the requested changes for Samba.
7239 if (!check_printer_ok(printer->info_2, snum)) {
7240 free_a_printer(&printer,2);
7241 return WERR_INVALID_PARAM;
7245 * When a printer is created, the drivername bound to the printer is used
7246 * to lookup previously saved driver initialization info, which is then
7247 * bound to the new printer, simulating what happens in the Windows arch.
7250 if (devmode)
7252 /* A valid devmode was included, convert and link it
7254 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7256 if (!convert_devicemode(printer->info_2->printername, devmode,
7257 &printer->info_2->devmode)) {
7258 return WERR_NOMEM;
7262 /* write the ASCII on disk */
7263 err = mod_a_printer(printer, 2);
7264 if (!W_ERROR_IS_OK(err)) {
7265 free_a_printer(&printer,2);
7266 return err;
7269 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7270 /* Handle open failed - remove addition. */
7271 del_a_printer(printer->info_2->sharename);
7272 free_a_printer(&printer,2);
7273 ZERO_STRUCTP(handle);
7274 return WERR_ACCESS_DENIED;
7277 update_c_setprinter(false);
7278 free_a_printer(&printer,2);
7280 return WERR_OK;
7283 /****************************************************************
7284 _spoolss_AddPrinterEx
7285 ****************************************************************/
7287 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7288 struct spoolss_AddPrinterEx *r)
7290 switch (r->in.info_ctr->level) {
7291 case 1:
7292 /* we don't handle yet */
7293 /* but I know what to do ... */
7294 return WERR_UNKNOWN_LEVEL;
7295 case 2:
7296 return spoolss_addprinterex_level_2(p, r->in.server,
7297 r->in.info_ctr,
7298 r->in.devmode_ctr->devmode,
7299 r->in.secdesc_ctr->sd,
7300 r->in.userlevel_ctr,
7301 r->out.handle);
7302 default:
7303 return WERR_UNKNOWN_LEVEL;
7307 /****************************************************************
7308 _spoolss_AddPrinter
7309 ****************************************************************/
7311 WERROR _spoolss_AddPrinter(pipes_struct *p,
7312 struct spoolss_AddPrinter *r)
7314 struct spoolss_AddPrinterEx a;
7315 struct spoolss_UserLevelCtr userlevel_ctr;
7317 ZERO_STRUCT(userlevel_ctr);
7319 userlevel_ctr.level = 1;
7321 a.in.server = r->in.server;
7322 a.in.info_ctr = r->in.info_ctr;
7323 a.in.devmode_ctr = r->in.devmode_ctr;
7324 a.in.secdesc_ctr = r->in.secdesc_ctr;
7325 a.in.userlevel_ctr = &userlevel_ctr;
7326 a.out.handle = r->out.handle;
7328 return _spoolss_AddPrinterEx(p, &a);
7331 /****************************************************************
7332 _spoolss_AddPrinterDriverEx
7333 ****************************************************************/
7335 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7336 struct spoolss_AddPrinterDriverEx *r)
7338 WERROR err = WERR_OK;
7339 char *driver_name = NULL;
7340 uint32_t version;
7341 const char *fn;
7343 switch (p->hdr_req.opnum) {
7344 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7345 fn = "_spoolss_AddPrinterDriver";
7346 break;
7347 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7348 fn = "_spoolss_AddPrinterDriverEx";
7349 break;
7350 default:
7351 return WERR_INVALID_PARAM;
7355 * we only support the semantics of AddPrinterDriver()
7356 * i.e. only copy files that are newer than existing ones
7359 if (r->in.flags == 0) {
7360 return WERR_INVALID_PARAM;
7363 if (r->in.flags != APD_COPY_NEW_FILES) {
7364 return WERR_ACCESS_DENIED;
7367 /* FIXME */
7368 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7369 /* Clever hack from Martin Zielinski <mz@seh.de>
7370 * to allow downgrade from level 8 (Vista).
7372 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7373 r->in.info_ctr->level));
7374 return WERR_UNKNOWN_LEVEL;
7377 DEBUG(5,("Cleaning driver's information\n"));
7378 err = clean_up_driver_struct(p, r->in.info_ctr);
7379 if (!W_ERROR_IS_OK(err))
7380 goto done;
7382 DEBUG(5,("Moving driver to final destination\n"));
7383 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7384 &err)) ) {
7385 goto done;
7388 if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7389 err = WERR_ACCESS_DENIED;
7390 goto done;
7394 * I think this is where he DrvUpgradePrinter() hook would be
7395 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7396 * server. Right now, we just need to send ourselves a message
7397 * to update each printer bound to this driver. --jerry
7400 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7401 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7402 fn, driver_name));
7405 done:
7406 return err;
7409 /****************************************************************
7410 _spoolss_AddPrinterDriver
7411 ****************************************************************/
7413 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7414 struct spoolss_AddPrinterDriver *r)
7416 struct spoolss_AddPrinterDriverEx a;
7418 switch (r->in.info_ctr->level) {
7419 case 2:
7420 case 3:
7421 case 4:
7422 case 5:
7423 break;
7424 default:
7425 return WERR_UNKNOWN_LEVEL;
7428 a.in.servername = r->in.servername;
7429 a.in.info_ctr = r->in.info_ctr;
7430 a.in.flags = APD_COPY_NEW_FILES;
7432 return _spoolss_AddPrinterDriverEx(p, &a);
7435 /****************************************************************************
7436 ****************************************************************************/
7438 struct _spoolss_paths {
7439 int type;
7440 const char *share;
7441 const char *dir;
7444 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7446 static const struct _spoolss_paths spoolss_paths[]= {
7447 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7448 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7451 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7452 const char *servername,
7453 const char *environment,
7454 int component,
7455 char **path)
7457 const char *pservername = NULL;
7458 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7459 const char *short_archi;
7461 *path = NULL;
7463 /* environment may be empty */
7464 if (environment && strlen(environment)) {
7465 long_archi = environment;
7468 /* servername may be empty */
7469 if (servername && strlen(servername)) {
7470 pservername = canon_servername(servername);
7472 if (!is_myname_or_ipaddr(pservername)) {
7473 return WERR_INVALID_PARAM;
7477 if (!(short_archi = get_short_archi(long_archi))) {
7478 return WERR_INVALID_ENVIRONMENT;
7481 switch (component) {
7482 case SPOOLSS_PRTPROCS_PATH:
7483 case SPOOLSS_DRIVER_PATH:
7484 if (pservername) {
7485 *path = talloc_asprintf(mem_ctx,
7486 "\\\\%s\\%s\\%s",
7487 pservername,
7488 spoolss_paths[component].share,
7489 short_archi);
7490 } else {
7491 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7492 SPOOLSS_DEFAULT_SERVER_PATH,
7493 spoolss_paths[component].dir,
7494 short_archi);
7496 break;
7497 default:
7498 return WERR_INVALID_PARAM;
7501 if (!*path) {
7502 return WERR_NOMEM;
7505 return WERR_OK;
7508 /****************************************************************************
7509 ****************************************************************************/
7511 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7512 const char *servername,
7513 const char *environment,
7514 struct spoolss_DriverDirectoryInfo1 *r)
7516 WERROR werr;
7517 char *path = NULL;
7519 werr = compose_spoolss_server_path(mem_ctx,
7520 servername,
7521 environment,
7522 SPOOLSS_DRIVER_PATH,
7523 &path);
7524 if (!W_ERROR_IS_OK(werr)) {
7525 return werr;
7528 DEBUG(4,("printer driver directory: [%s]\n", path));
7530 r->directory_name = path;
7532 return WERR_OK;
7535 /****************************************************************
7536 _spoolss_GetPrinterDriverDirectory
7537 ****************************************************************/
7539 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7540 struct spoolss_GetPrinterDriverDirectory *r)
7542 WERROR werror;
7544 /* that's an [in out] buffer */
7546 if (!r->in.buffer && (r->in.offered != 0)) {
7547 return WERR_INVALID_PARAM;
7550 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7551 r->in.level));
7553 *r->out.needed = 0;
7555 /* r->in.level is ignored */
7557 werror = getprinterdriverdir_level_1(p->mem_ctx,
7558 r->in.server,
7559 r->in.environment,
7560 &r->out.info->info1);
7561 if (!W_ERROR_IS_OK(werror)) {
7562 TALLOC_FREE(r->out.info);
7563 return werror;
7566 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7567 r->out.info, r->in.level);
7568 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7570 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7573 /****************************************************************
7574 _spoolss_EnumPrinterData
7575 ****************************************************************/
7577 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7578 struct spoolss_EnumPrinterData *r)
7580 WERROR result;
7581 struct spoolss_EnumPrinterDataEx r2;
7582 uint32_t count;
7583 struct spoolss_PrinterEnumValues *info, *val = NULL;
7584 uint32_t needed;
7586 r2.in.handle = r->in.handle;
7587 r2.in.key_name = "PrinterDriverData";
7588 r2.in.offered = 0;
7589 r2.out.count = &count;
7590 r2.out.info = &info;
7591 r2.out.needed = &needed;
7593 result = _spoolss_EnumPrinterDataEx(p, &r2);
7594 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7595 r2.in.offered = needed;
7596 result = _spoolss_EnumPrinterDataEx(p, &r2);
7598 if (!W_ERROR_IS_OK(result)) {
7599 return result;
7603 * The NT machine wants to know the biggest size of value and data
7605 * cf: MSDN EnumPrinterData remark section
7608 if (!r->in.value_offered && !r->in.data_offered) {
7609 uint32_t biggest_valuesize = 0;
7610 uint32_t biggest_datasize = 0;
7611 int i, name_length;
7613 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7615 for (i=0; i<count; i++) {
7617 name_length = strlen(info[i].value_name);
7618 if (strlen(info[i].value_name) > biggest_valuesize) {
7619 biggest_valuesize = name_length;
7622 if (info[i].data_length > biggest_datasize) {
7623 biggest_datasize = info[i].data_length;
7626 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7627 biggest_datasize));
7630 /* the value is an UNICODE string but real_value_size is the length
7631 in bytes including the trailing 0 */
7633 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7634 *r->out.data_needed = biggest_datasize;
7636 DEBUG(6,("final values: [%d], [%d]\n",
7637 *r->out.value_needed, *r->out.data_needed));
7639 return WERR_OK;
7642 if (r->in.enum_index < count) {
7643 val = &info[r->in.enum_index];
7646 if (val == NULL) {
7647 /* out_value should default to "" or else NT4 has
7648 problems unmarshalling the response */
7650 if (r->in.value_offered) {
7651 *r->out.value_needed = 1;
7652 r->out.value_name = talloc_strdup(r, "");
7653 if (!r->out.value_name) {
7654 return WERR_NOMEM;
7656 } else {
7657 r->out.value_name = NULL;
7658 *r->out.value_needed = 0;
7661 /* the data is counted in bytes */
7663 *r->out.data_needed = r->in.data_offered;
7665 result = WERR_NO_MORE_ITEMS;
7666 } else {
7668 * the value is:
7669 * - counted in bytes in the request
7670 * - counted in UNICODE chars in the max reply
7671 * - counted in bytes in the real size
7673 * take a pause *before* coding not *during* coding
7676 /* name */
7677 if (r->in.value_offered) {
7678 r->out.value_name = talloc_strdup(r, val->value_name);
7679 if (!r->out.value_name) {
7680 return WERR_NOMEM;
7682 *r->out.value_needed = val->value_name_len;
7683 } else {
7684 r->out.value_name = NULL;
7685 *r->out.value_needed = 0;
7688 /* type */
7690 *r->out.type = val->type;
7692 /* data - counted in bytes */
7695 * See the section "Dynamically Typed Query Parameters"
7696 * in MS-RPRN.
7699 if (r->out.data && val->data && val->data->data &&
7700 val->data_length && r->in.data_offered) {
7701 memcpy(r->out.data, val->data->data,
7702 MIN(val->data_length,r->in.data_offered));
7705 *r->out.data_needed = val->data_length;
7707 result = WERR_OK;
7710 return result;
7713 /****************************************************************
7714 _spoolss_SetPrinterData
7715 ****************************************************************/
7717 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7718 struct spoolss_SetPrinterData *r)
7720 struct spoolss_SetPrinterDataEx r2;
7722 r2.in.handle = r->in.handle;
7723 r2.in.key_name = "PrinterDriverData";
7724 r2.in.value_name = r->in.value_name;
7725 r2.in.type = r->in.type;
7726 r2.in.data = r->in.data;
7727 r2.in.offered = r->in.offered;
7729 return _spoolss_SetPrinterDataEx(p, &r2);
7732 /****************************************************************
7733 _spoolss_ResetPrinter
7734 ****************************************************************/
7736 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7737 struct spoolss_ResetPrinter *r)
7739 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7740 int snum;
7742 DEBUG(5,("_spoolss_ResetPrinter\n"));
7745 * All we do is to check to see if the handle and queue is valid.
7746 * This call really doesn't mean anything to us because we only
7747 * support RAW printing. --jerry
7750 if (!Printer) {
7751 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7752 OUR_HANDLE(r->in.handle)));
7753 return WERR_BADFID;
7756 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7757 return WERR_BADFID;
7760 /* blindly return success */
7761 return WERR_OK;
7764 /****************************************************************
7765 _spoolss_DeletePrinterData
7766 ****************************************************************/
7768 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7769 struct spoolss_DeletePrinterData *r)
7771 struct spoolss_DeletePrinterDataEx r2;
7773 r2.in.handle = r->in.handle;
7774 r2.in.key_name = "PrinterDriverData";
7775 r2.in.value_name = r->in.value_name;
7777 return _spoolss_DeletePrinterDataEx(p, &r2);
7780 /****************************************************************
7781 _spoolss_AddForm
7782 ****************************************************************/
7784 WERROR _spoolss_AddForm(pipes_struct *p,
7785 struct spoolss_AddForm *r)
7787 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7788 nt_forms_struct tmpForm;
7789 int snum = -1;
7790 WERROR status = WERR_OK;
7791 NT_PRINTER_INFO_LEVEL *printer = NULL;
7792 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7794 int count=0;
7795 nt_forms_struct *list=NULL;
7796 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7797 int i;
7799 DEBUG(5,("_spoolss_AddForm\n"));
7801 if (!Printer) {
7802 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7803 OUR_HANDLE(r->in.handle)));
7804 return WERR_BADFID;
7808 /* forms can be added on printer or on the print server handle */
7810 if ( Printer->printer_type == SPLHND_PRINTER )
7812 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7813 return WERR_BADFID;
7815 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7816 if (!W_ERROR_IS_OK(status))
7817 goto done;
7820 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7821 and not a printer admin, then fail */
7823 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7824 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7825 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7826 NULL, NULL,
7827 p->server_info->ptok,
7828 lp_printer_admin(snum))) {
7829 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7830 status = WERR_ACCESS_DENIED;
7831 goto done;
7834 switch (form->flags) {
7835 case SPOOLSS_FORM_USER:
7836 case SPOOLSS_FORM_BUILTIN:
7837 case SPOOLSS_FORM_PRINTER:
7838 break;
7839 default:
7840 status = WERR_INVALID_PARAM;
7841 goto done;
7844 /* can't add if builtin */
7846 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7847 status = WERR_FILE_EXISTS;
7848 goto done;
7851 count = get_ntforms(&list);
7853 for (i=0; i < count; i++) {
7854 if (strequal(form->form_name, list[i].name)) {
7855 status = WERR_FILE_EXISTS;
7856 goto done;
7860 if(!add_a_form(&list, form, &count)) {
7861 status = WERR_NOMEM;
7862 goto done;
7865 become_root();
7866 write_ntforms(&list, count);
7867 unbecome_root();
7870 * ChangeID must always be set if this is a printer
7873 if ( Printer->printer_type == SPLHND_PRINTER )
7874 status = mod_a_printer(printer, 2);
7876 done:
7877 if ( printer )
7878 free_a_printer(&printer, 2);
7879 SAFE_FREE(list);
7881 return status;
7884 /****************************************************************
7885 _spoolss_DeleteForm
7886 ****************************************************************/
7888 WERROR _spoolss_DeleteForm(pipes_struct *p,
7889 struct spoolss_DeleteForm *r)
7891 const char *form_name = r->in.form_name;
7892 nt_forms_struct tmpForm;
7893 int count=0;
7894 nt_forms_struct *list=NULL;
7895 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7896 int snum = -1;
7897 WERROR status = WERR_OK;
7898 NT_PRINTER_INFO_LEVEL *printer = NULL;
7899 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7900 bool ret = false;
7902 DEBUG(5,("_spoolss_DeleteForm\n"));
7904 if (!Printer) {
7905 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7906 OUR_HANDLE(r->in.handle)));
7907 return WERR_BADFID;
7910 /* forms can be deleted on printer of on the print server handle */
7912 if ( Printer->printer_type == SPLHND_PRINTER )
7914 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7915 return WERR_BADFID;
7917 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7918 if (!W_ERROR_IS_OK(status))
7919 goto done;
7922 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7923 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7924 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7925 NULL, NULL,
7926 p->server_info->ptok,
7927 lp_printer_admin(snum))) {
7928 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7929 return WERR_ACCESS_DENIED;
7933 /* can't delete if builtin */
7935 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7936 status = WERR_INVALID_PARAM;
7937 goto done;
7940 count = get_ntforms(&list);
7942 become_root();
7943 ret = delete_a_form(&list, form_name, &count, &status);
7944 unbecome_root();
7945 if (ret == false) {
7946 goto done;
7950 * ChangeID must always be set if this is a printer
7953 if ( Printer->printer_type == SPLHND_PRINTER )
7954 status = mod_a_printer(printer, 2);
7956 done:
7957 if ( printer )
7958 free_a_printer(&printer, 2);
7959 SAFE_FREE(list);
7961 return status;
7964 /****************************************************************
7965 _spoolss_SetForm
7966 ****************************************************************/
7968 WERROR _spoolss_SetForm(pipes_struct *p,
7969 struct spoolss_SetForm *r)
7971 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7972 nt_forms_struct tmpForm;
7973 int snum = -1;
7974 WERROR status = WERR_OK;
7975 NT_PRINTER_INFO_LEVEL *printer = NULL;
7976 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7978 int count=0;
7979 nt_forms_struct *list=NULL;
7980 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7982 DEBUG(5,("_spoolss_SetForm\n"));
7984 if (!Printer) {
7985 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7986 OUR_HANDLE(r->in.handle)));
7987 return WERR_BADFID;
7990 /* forms can be modified on printer of on the print server handle */
7992 if ( Printer->printer_type == SPLHND_PRINTER )
7994 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7995 return WERR_BADFID;
7997 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7998 if (!W_ERROR_IS_OK(status))
7999 goto done;
8002 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8003 and not a printer admin, then fail */
8005 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8006 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8007 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8008 NULL, NULL,
8009 p->server_info->ptok,
8010 lp_printer_admin(snum))) {
8011 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8012 status = WERR_ACCESS_DENIED;
8013 goto done;
8016 /* can't set if builtin */
8017 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8018 status = WERR_INVALID_PARAM;
8019 goto done;
8022 count = get_ntforms(&list);
8023 update_a_form(&list, form, count);
8024 become_root();
8025 write_ntforms(&list, count);
8026 unbecome_root();
8029 * ChangeID must always be set if this is a printer
8032 if ( Printer->printer_type == SPLHND_PRINTER )
8033 status = mod_a_printer(printer, 2);
8036 done:
8037 if ( printer )
8038 free_a_printer(&printer, 2);
8039 SAFE_FREE(list);
8041 return status;
8044 /****************************************************************************
8045 fill_print_processor1
8046 ****************************************************************************/
8048 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8049 struct spoolss_PrintProcessorInfo1 *r,
8050 const char *print_processor_name)
8052 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8053 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8055 return WERR_OK;
8058 /****************************************************************************
8059 enumprintprocessors level 1.
8060 ****************************************************************************/
8062 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8063 union spoolss_PrintProcessorInfo **info_p,
8064 uint32_t *count)
8066 union spoolss_PrintProcessorInfo *info;
8067 WERROR result;
8069 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8070 W_ERROR_HAVE_NO_MEMORY(info);
8072 *count = 1;
8074 result = fill_print_processor1(info, &info[0].info1, "winprint");
8075 if (!W_ERROR_IS_OK(result)) {
8076 goto out;
8079 out:
8080 if (!W_ERROR_IS_OK(result)) {
8081 TALLOC_FREE(info);
8082 *count = 0;
8083 return result;
8086 *info_p = info;
8088 return WERR_OK;
8091 /****************************************************************
8092 _spoolss_EnumPrintProcessors
8093 ****************************************************************/
8095 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8096 struct spoolss_EnumPrintProcessors *r)
8098 WERROR result;
8100 /* that's an [in out] buffer */
8102 if (!r->in.buffer && (r->in.offered != 0)) {
8103 return WERR_INVALID_PARAM;
8106 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8109 * Enumerate the print processors ...
8111 * Just reply with "winprint", to keep NT happy
8112 * and I can use my nice printer checker.
8115 *r->out.count = 0;
8116 *r->out.needed = 0;
8117 *r->out.info = NULL;
8119 switch (r->in.level) {
8120 case 1:
8121 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8122 r->out.count);
8123 break;
8124 default:
8125 return WERR_UNKNOWN_LEVEL;
8128 if (!W_ERROR_IS_OK(result)) {
8129 return result;
8132 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8133 spoolss_EnumPrintProcessors,
8134 *r->out.info, r->in.level,
8135 *r->out.count);
8136 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8137 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8139 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8142 /****************************************************************************
8143 fill_printprocdatatype1
8144 ****************************************************************************/
8146 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8147 struct spoolss_PrintProcDataTypesInfo1 *r,
8148 const char *name_array)
8150 r->name_array = talloc_strdup(mem_ctx, name_array);
8151 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8153 return WERR_OK;
8156 /****************************************************************************
8157 enumprintprocdatatypes level 1.
8158 ****************************************************************************/
8160 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8161 union spoolss_PrintProcDataTypesInfo **info_p,
8162 uint32_t *count)
8164 WERROR result;
8165 union spoolss_PrintProcDataTypesInfo *info;
8167 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8168 W_ERROR_HAVE_NO_MEMORY(info);
8170 *count = 1;
8172 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8173 if (!W_ERROR_IS_OK(result)) {
8174 goto out;
8177 out:
8178 if (!W_ERROR_IS_OK(result)) {
8179 TALLOC_FREE(info);
8180 *count = 0;
8181 return result;
8184 *info_p = info;
8186 return WERR_OK;
8189 /****************************************************************
8190 _spoolss_EnumPrintProcDataTypes
8191 ****************************************************************/
8193 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8194 struct spoolss_EnumPrintProcDataTypes *r)
8196 WERROR result;
8198 /* that's an [in out] buffer */
8200 if (!r->in.buffer && (r->in.offered != 0)) {
8201 return WERR_INVALID_PARAM;
8204 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8206 *r->out.count = 0;
8207 *r->out.needed = 0;
8208 *r->out.info = NULL;
8210 switch (r->in.level) {
8211 case 1:
8212 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8213 r->out.count);
8214 break;
8215 default:
8216 return WERR_UNKNOWN_LEVEL;
8219 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8220 spoolss_EnumPrintProcDataTypes,
8221 *r->out.info, r->in.level,
8222 *r->out.count);
8223 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8224 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8226 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8229 /****************************************************************************
8230 fill_monitor_1
8231 ****************************************************************************/
8233 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8234 struct spoolss_MonitorInfo1 *r,
8235 const char *monitor_name)
8237 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8238 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8240 return WERR_OK;
8243 /****************************************************************************
8244 fill_monitor_2
8245 ****************************************************************************/
8247 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8248 struct spoolss_MonitorInfo2 *r,
8249 const char *monitor_name,
8250 const char *environment,
8251 const char *dll_name)
8253 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8254 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8255 r->environment = talloc_strdup(mem_ctx, environment);
8256 W_ERROR_HAVE_NO_MEMORY(r->environment);
8257 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8258 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8260 return WERR_OK;
8263 /****************************************************************************
8264 enumprintmonitors level 1.
8265 ****************************************************************************/
8267 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8268 union spoolss_MonitorInfo **info_p,
8269 uint32_t *count)
8271 union spoolss_MonitorInfo *info;
8272 WERROR result = WERR_OK;
8274 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8275 W_ERROR_HAVE_NO_MEMORY(info);
8277 *count = 2;
8279 result = fill_monitor_1(info, &info[0].info1,
8280 SPL_LOCAL_PORT);
8281 if (!W_ERROR_IS_OK(result)) {
8282 goto out;
8285 result = fill_monitor_1(info, &info[1].info1,
8286 SPL_TCPIP_PORT);
8287 if (!W_ERROR_IS_OK(result)) {
8288 goto out;
8291 out:
8292 if (!W_ERROR_IS_OK(result)) {
8293 TALLOC_FREE(info);
8294 *count = 0;
8295 return result;
8298 *info_p = info;
8300 return WERR_OK;
8303 /****************************************************************************
8304 enumprintmonitors level 2.
8305 ****************************************************************************/
8307 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8308 union spoolss_MonitorInfo **info_p,
8309 uint32_t *count)
8311 union spoolss_MonitorInfo *info;
8312 WERROR result = WERR_OK;
8314 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8315 W_ERROR_HAVE_NO_MEMORY(info);
8317 *count = 2;
8319 result = fill_monitor_2(info, &info[0].info2,
8320 SPL_LOCAL_PORT,
8321 "Windows NT X86", /* FIXME */
8322 "localmon.dll");
8323 if (!W_ERROR_IS_OK(result)) {
8324 goto out;
8327 result = fill_monitor_2(info, &info[1].info2,
8328 SPL_TCPIP_PORT,
8329 "Windows NT X86", /* FIXME */
8330 "tcpmon.dll");
8331 if (!W_ERROR_IS_OK(result)) {
8332 goto out;
8335 out:
8336 if (!W_ERROR_IS_OK(result)) {
8337 TALLOC_FREE(info);
8338 *count = 0;
8339 return result;
8342 *info_p = info;
8344 return WERR_OK;
8347 /****************************************************************
8348 _spoolss_EnumMonitors
8349 ****************************************************************/
8351 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8352 struct spoolss_EnumMonitors *r)
8354 WERROR result;
8356 /* that's an [in out] buffer */
8358 if (!r->in.buffer && (r->in.offered != 0)) {
8359 return WERR_INVALID_PARAM;
8362 DEBUG(5,("_spoolss_EnumMonitors\n"));
8365 * Enumerate the print monitors ...
8367 * Just reply with "Local Port", to keep NT happy
8368 * and I can use my nice printer checker.
8371 *r->out.count = 0;
8372 *r->out.needed = 0;
8373 *r->out.info = NULL;
8375 switch (r->in.level) {
8376 case 1:
8377 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8378 r->out.count);
8379 break;
8380 case 2:
8381 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8382 r->out.count);
8383 break;
8384 default:
8385 return WERR_UNKNOWN_LEVEL;
8388 if (!W_ERROR_IS_OK(result)) {
8389 return result;
8392 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8393 spoolss_EnumMonitors,
8394 *r->out.info, r->in.level,
8395 *r->out.count);
8396 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8397 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8399 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8402 /****************************************************************************
8403 ****************************************************************************/
8405 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8406 const print_queue_struct *queue,
8407 int count, int snum,
8408 const NT_PRINTER_INFO_LEVEL *ntprinter,
8409 uint32_t jobid,
8410 struct spoolss_JobInfo1 *r)
8412 int i = 0;
8413 bool found = false;
8415 for (i=0; i<count; i++) {
8416 if (queue[i].job == (int)jobid) {
8417 found = true;
8418 break;
8422 if (found == false) {
8423 /* NT treats not found as bad param... yet another bad choice */
8424 return WERR_INVALID_PARAM;
8427 return fill_job_info1(mem_ctx,
8429 &queue[i],
8431 snum,
8432 ntprinter);
8435 /****************************************************************************
8436 ****************************************************************************/
8438 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8439 const print_queue_struct *queue,
8440 int count, int snum,
8441 const NT_PRINTER_INFO_LEVEL *ntprinter,
8442 uint32_t jobid,
8443 struct spoolss_JobInfo2 *r)
8445 int i = 0;
8446 bool found = false;
8447 struct spoolss_DeviceMode *devmode;
8448 NT_DEVICEMODE *nt_devmode;
8449 WERROR result;
8451 for (i=0; i<count; i++) {
8452 if (queue[i].job == (int)jobid) {
8453 found = true;
8454 break;
8458 if (found == false) {
8459 /* NT treats not found as bad param... yet another bad
8460 choice */
8461 return WERR_INVALID_PARAM;
8465 * if the print job does not have a DEVMODE associated with it,
8466 * just use the one for the printer. A NULL devicemode is not
8467 * a failure condition
8470 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8471 if (nt_devmode) {
8472 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8473 W_ERROR_HAVE_NO_MEMORY(devmode);
8474 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8475 if (!W_ERROR_IS_OK(result)) {
8476 return result;
8478 } else {
8479 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8480 W_ERROR_HAVE_NO_MEMORY(devmode);
8483 return fill_job_info2(mem_ctx,
8485 &queue[i],
8487 snum,
8488 ntprinter,
8489 devmode);
8492 /****************************************************************
8493 _spoolss_GetJob
8494 ****************************************************************/
8496 WERROR _spoolss_GetJob(pipes_struct *p,
8497 struct spoolss_GetJob *r)
8499 WERROR result = WERR_OK;
8500 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8501 int snum;
8502 int count;
8503 print_queue_struct *queue = NULL;
8504 print_status_struct prt_status;
8506 /* that's an [in out] buffer */
8508 if (!r->in.buffer && (r->in.offered != 0)) {
8509 return WERR_INVALID_PARAM;
8512 DEBUG(5,("_spoolss_GetJob\n"));
8514 *r->out.needed = 0;
8516 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8517 return WERR_BADFID;
8520 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8521 if (!W_ERROR_IS_OK(result)) {
8522 return result;
8525 count = print_queue_status(snum, &queue, &prt_status);
8527 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8528 count, prt_status.status, prt_status.message));
8530 switch (r->in.level) {
8531 case 1:
8532 result = getjob_level_1(p->mem_ctx,
8533 queue, count, snum, ntprinter,
8534 r->in.job_id, &r->out.info->info1);
8535 break;
8536 case 2:
8537 result = getjob_level_2(p->mem_ctx,
8538 queue, count, snum, ntprinter,
8539 r->in.job_id, &r->out.info->info2);
8540 break;
8541 default:
8542 result = WERR_UNKNOWN_LEVEL;
8543 break;
8546 SAFE_FREE(queue);
8547 free_a_printer(&ntprinter, 2);
8549 if (!W_ERROR_IS_OK(result)) {
8550 TALLOC_FREE(r->out.info);
8551 return result;
8554 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8555 r->in.level);
8556 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8558 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8561 /****************************************************************
8562 _spoolss_GetPrinterDataEx
8563 ****************************************************************/
8565 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8566 struct spoolss_GetPrinterDataEx *r)
8569 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8570 struct regval_blob *val = NULL;
8571 NT_PRINTER_INFO_LEVEL *printer = NULL;
8572 int snum = 0;
8573 WERROR result = WERR_OK;
8574 DATA_BLOB blob;
8576 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8578 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8579 r->in.key_name, r->in.value_name));
8581 /* in case of problem, return some default values */
8583 *r->out.needed = 0;
8584 *r->out.type = REG_NONE;
8586 if (!Printer) {
8587 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8588 OUR_HANDLE(r->in.handle)));
8589 result = WERR_BADFID;
8590 goto done;
8593 /* Is the handle to a printer or to the server? */
8595 if (Printer->printer_type == SPLHND_SERVER) {
8597 union spoolss_PrinterData data;
8599 result = getprinterdata_printer_server(p->mem_ctx,
8600 r->in.value_name,
8601 r->out.type,
8602 &data);
8603 if (!W_ERROR_IS_OK(result)) {
8604 goto done;
8607 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8608 *r->out.type, &data);
8609 if (!W_ERROR_IS_OK(result)) {
8610 goto done;
8613 *r->out.needed = blob.length;
8615 if (r->in.offered >= *r->out.needed) {
8616 memcpy(r->out.data, blob.data, blob.length);
8619 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8622 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8623 result = WERR_BADFID;
8624 goto done;
8627 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8628 if (!W_ERROR_IS_OK(result)) {
8629 goto done;
8632 /* check to see if the keyname is valid */
8633 if (!strlen(r->in.key_name)) {
8634 result = WERR_INVALID_PARAM;
8635 goto done;
8638 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8640 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8641 strequal(r->in.value_name, "ChangeId")) {
8642 *r->out.type = REG_DWORD;
8643 *r->out.needed = 4;
8644 if (r->in.offered >= *r->out.needed) {
8645 SIVAL(r->out.data, 0, printer->info_2->changeid);
8646 result = WERR_OK;
8648 goto done;
8651 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8652 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8653 "Invalid keyname [%s]\n", r->in.key_name ));
8654 result = WERR_BADFILE;
8655 goto done;
8658 val = get_printer_data(printer->info_2,
8659 r->in.key_name, r->in.value_name);
8660 if (!val) {
8661 result = WERR_BADFILE;
8662 goto done;
8665 *r->out.needed = regval_size(val);
8666 *r->out.type = regval_type(val);
8668 if (r->in.offered >= *r->out.needed) {
8669 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8671 done:
8672 if (printer) {
8673 free_a_printer(&printer, 2);
8676 if (!W_ERROR_IS_OK(result)) {
8677 return result;
8680 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8681 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8683 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8686 /****************************************************************
8687 _spoolss_SetPrinterDataEx
8688 ****************************************************************/
8690 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8691 struct spoolss_SetPrinterDataEx *r)
8693 NT_PRINTER_INFO_LEVEL *printer = NULL;
8694 int snum = 0;
8695 WERROR result = WERR_OK;
8696 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8697 char *oid_string;
8699 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8701 /* From MSDN documentation of SetPrinterDataEx: pass request to
8702 SetPrinterData if key is "PrinterDriverData" */
8704 if (!Printer) {
8705 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8706 OUR_HANDLE(r->in.handle)));
8707 return WERR_BADFID;
8710 if (Printer->printer_type == SPLHND_SERVER) {
8711 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8712 "Not implemented for server handles yet\n"));
8713 return WERR_INVALID_PARAM;
8716 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8717 return WERR_BADFID;
8721 * Access check : NT returns "access denied" if you make a
8722 * SetPrinterData call without the necessary privildge.
8723 * we were originally returning OK if nothing changed
8724 * which made Win2k issue **a lot** of SetPrinterData
8725 * when connecting to a printer --jerry
8728 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8729 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8730 "change denied by handle access permissions\n"));
8731 return WERR_ACCESS_DENIED;
8734 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8735 if (!W_ERROR_IS_OK(result)) {
8736 return result;
8739 /* check for OID in valuename */
8741 oid_string = strchr(r->in.value_name, ',');
8742 if (oid_string) {
8743 *oid_string = '\0';
8744 oid_string++;
8747 /* save the registry data */
8749 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8750 r->in.type, r->in.data, r->in.offered);
8752 if (W_ERROR_IS_OK(result)) {
8753 /* save the OID if one was specified */
8754 if (oid_string) {
8755 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8756 r->in.key_name, SPOOL_OID_KEY);
8757 if (!str) {
8758 result = WERR_NOMEM;
8759 goto done;
8763 * I'm not checking the status here on purpose. Don't know
8764 * if this is right, but I'm returning the status from the
8765 * previous set_printer_dataex() call. I have no idea if
8766 * this is right. --jerry
8769 set_printer_dataex(printer, str, r->in.value_name,
8770 REG_SZ, (uint8_t *)oid_string,
8771 strlen(oid_string)+1);
8774 result = mod_a_printer(printer, 2);
8777 done:
8778 free_a_printer(&printer, 2);
8780 return result;
8783 /****************************************************************
8784 _spoolss_DeletePrinterDataEx
8785 ****************************************************************/
8787 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8788 struct spoolss_DeletePrinterDataEx *r)
8790 NT_PRINTER_INFO_LEVEL *printer = NULL;
8791 int snum=0;
8792 WERROR status = WERR_OK;
8793 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8795 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8797 if (!Printer) {
8798 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8799 "Invalid handle (%s:%u:%u).\n",
8800 OUR_HANDLE(r->in.handle)));
8801 return WERR_BADFID;
8804 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8805 return WERR_BADFID;
8807 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8808 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8809 "printer properties change denied by handle\n"));
8810 return WERR_ACCESS_DENIED;
8813 if (!r->in.value_name || !r->in.key_name) {
8814 return WERR_NOMEM;
8817 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8818 if (!W_ERROR_IS_OK(status))
8819 return status;
8821 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8823 if ( W_ERROR_IS_OK(status) )
8824 mod_a_printer( printer, 2 );
8826 free_a_printer(&printer, 2);
8828 return status;
8831 /****************************************************************
8832 _spoolss_EnumPrinterKey
8833 ****************************************************************/
8835 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8836 struct spoolss_EnumPrinterKey *r)
8838 fstring *keynames = NULL;
8839 int num_keys;
8840 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8841 NT_PRINTER_DATA *data;
8842 NT_PRINTER_INFO_LEVEL *printer = NULL;
8843 int snum = 0;
8844 WERROR result = WERR_BADFILE;
8845 int i;
8846 const char **array = NULL;
8847 DATA_BLOB blob;
8849 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8851 if (!Printer) {
8852 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8853 OUR_HANDLE(r->in.handle)));
8854 return WERR_BADFID;
8857 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8858 return WERR_BADFID;
8861 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8862 if (!W_ERROR_IS_OK(result)) {
8863 return result;
8866 /* get the list of subkey names */
8868 data = printer->info_2->data;
8870 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8871 if (num_keys == -1) {
8872 result = WERR_BADFILE;
8873 goto done;
8876 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8877 if (!array) {
8878 result = WERR_NOMEM;
8879 goto done;
8882 if (!num_keys) {
8883 array[0] = talloc_strdup(array, "");
8884 if (!array[0]) {
8885 result = WERR_NOMEM;
8886 goto done;
8890 for (i=0; i < num_keys; i++) {
8892 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8893 keynames[i]));
8895 array[i] = talloc_strdup(array, keynames[i]);
8896 if (!array[i]) {
8897 result = WERR_NOMEM;
8898 goto done;
8902 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8903 result = WERR_NOMEM;
8904 goto done;
8907 *r->out._ndr_size = r->in.offered / 2;
8908 *r->out.needed = blob.length;
8910 if (r->in.offered < *r->out.needed) {
8911 result = WERR_MORE_DATA;
8912 } else {
8913 result = WERR_OK;
8914 r->out.key_buffer->string_array = array;
8917 done:
8918 if (!W_ERROR_IS_OK(result)) {
8919 TALLOC_FREE(array);
8920 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8921 *r->out.needed = 0;
8925 free_a_printer(&printer, 2);
8926 SAFE_FREE(keynames);
8928 return result;
8931 /****************************************************************
8932 _spoolss_DeletePrinterKey
8933 ****************************************************************/
8935 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8936 struct spoolss_DeletePrinterKey *r)
8938 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8939 NT_PRINTER_INFO_LEVEL *printer = NULL;
8940 int snum=0;
8941 WERROR status;
8943 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8945 if (!Printer) {
8946 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8947 OUR_HANDLE(r->in.handle)));
8948 return WERR_BADFID;
8951 /* if keyname == NULL, return error */
8953 if ( !r->in.key_name )
8954 return WERR_INVALID_PARAM;
8956 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8957 return WERR_BADFID;
8959 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8960 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8961 "printer properties change denied by handle\n"));
8962 return WERR_ACCESS_DENIED;
8965 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8966 if (!W_ERROR_IS_OK(status))
8967 return status;
8969 /* delete the key and all subneys */
8971 status = delete_all_printer_data( printer->info_2, r->in.key_name );
8973 if ( W_ERROR_IS_OK(status) )
8974 status = mod_a_printer(printer, 2);
8976 free_a_printer( &printer, 2 );
8978 return status;
8981 /****************************************************************
8982 ****************************************************************/
8984 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8985 struct regval_blob *v,
8986 struct spoolss_PrinterEnumValues *r)
8988 r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
8989 W_ERROR_HAVE_NO_MEMORY(r->data);
8991 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
8992 W_ERROR_HAVE_NO_MEMORY(r->value_name);
8994 r->value_name_len = strlen_m_term(regval_name(v)) * 2;
8996 r->type = regval_type(v);
8997 r->data_length = regval_size(v);
8999 if (r->data_length) {
9000 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9003 return WERR_OK;
9006 /****************************************************************
9007 _spoolss_EnumPrinterDataEx
9008 ****************************************************************/
9010 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9011 struct spoolss_EnumPrinterDataEx *r)
9013 uint32_t count = 0;
9014 NT_PRINTER_INFO_LEVEL *printer = NULL;
9015 struct spoolss_PrinterEnumValues *info = NULL;
9016 NT_PRINTER_DATA *p_data;
9017 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9018 int snum;
9019 WERROR result;
9020 int key_index;
9021 int i;
9023 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9025 *r->out.count = 0;
9026 *r->out.needed = 0;
9027 *r->out.info = NULL;
9029 if (!Printer) {
9030 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9031 OUR_HANDLE(r->in.handle)));
9032 return WERR_BADFID;
9036 * first check for a keyname of NULL or "". Win2k seems to send
9037 * this a lot and we should send back WERR_INVALID_PARAM
9038 * no need to spend time looking up the printer in this case.
9039 * --jerry
9042 if (!strlen(r->in.key_name)) {
9043 result = WERR_INVALID_PARAM;
9044 goto done;
9047 /* get the printer off of disk */
9049 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9050 return WERR_BADFID;
9053 ZERO_STRUCT(printer);
9054 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9055 if (!W_ERROR_IS_OK(result)) {
9056 return result;
9059 /* now look for a match on the key name */
9061 p_data = printer->info_2->data;
9063 key_index = lookup_printerkey(p_data, r->in.key_name);
9064 if (key_index == -1) {
9065 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9066 r->in.key_name));
9067 result = WERR_INVALID_PARAM;
9068 goto done;
9071 /* allocate the memory for the array of pointers -- if necessary */
9073 count = regval_ctr_numvals(p_data->keys[key_index].values);
9074 if (!count) {
9075 result = WERR_OK; /* ??? */
9076 goto done;
9079 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9080 struct spoolss_PrinterEnumValues,
9081 count);
9082 if (!info) {
9083 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9084 result = WERR_NOMEM;
9085 goto done;
9089 * loop through all params and build the array to pass
9090 * back to the client
9093 for (i=0; i < count; i++) {
9095 struct regval_blob *val;
9097 /* lookup the registry value */
9099 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9101 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9103 /* copy the data */
9105 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9106 if (!W_ERROR_IS_OK(result)) {
9107 goto done;
9111 #if 0 /* FIXME - gd */
9112 /* housekeeping information in the reply */
9114 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9115 * the hand marshalled container size is a multiple
9116 * of 4 bytes for RPC alignment.
9119 if (needed % 4) {
9120 needed += 4-(needed % 4);
9122 #endif
9123 *r->out.count = count;
9124 *r->out.info = info;
9126 done:
9128 if (printer) {
9129 free_a_printer(&printer, 2);
9132 if (!W_ERROR_IS_OK(result)) {
9133 return result;
9136 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9137 spoolss_EnumPrinterDataEx,
9138 *r->out.info,
9139 *r->out.count);
9140 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9141 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9143 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9146 /****************************************************************************
9147 ****************************************************************************/
9149 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9150 const char *servername,
9151 const char *environment,
9152 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9154 WERROR werr;
9155 char *path = NULL;
9157 werr = compose_spoolss_server_path(mem_ctx,
9158 servername,
9159 environment,
9160 SPOOLSS_PRTPROCS_PATH,
9161 &path);
9162 if (!W_ERROR_IS_OK(werr)) {
9163 return werr;
9166 DEBUG(4,("print processor directory: [%s]\n", path));
9168 r->directory_name = path;
9170 return WERR_OK;
9173 /****************************************************************
9174 _spoolss_GetPrintProcessorDirectory
9175 ****************************************************************/
9177 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9178 struct spoolss_GetPrintProcessorDirectory *r)
9180 WERROR result;
9182 /* that's an [in out] buffer */
9184 if (!r->in.buffer && (r->in.offered != 0)) {
9185 return WERR_INVALID_PARAM;
9188 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9189 r->in.level));
9191 *r->out.needed = 0;
9193 /* r->in.level is ignored */
9195 /* We always should reply with a local print processor directory so that
9196 * users are not forced to have a [prnproc$] share on the Samba spoolss
9197 * server - Guenther */
9199 result = getprintprocessordirectory_level_1(p->mem_ctx,
9200 NULL, /* r->in.server */
9201 r->in.environment,
9202 &r->out.info->info1);
9203 if (!W_ERROR_IS_OK(result)) {
9204 TALLOC_FREE(r->out.info);
9205 return result;
9208 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9209 r->out.info, r->in.level);
9210 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9212 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9215 /*******************************************************************
9216 ********************************************************************/
9218 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9219 const char *dllname)
9221 enum ndr_err_code ndr_err;
9222 struct spoolss_MonitorUi ui;
9224 ui.dll_name = dllname;
9226 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9227 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9228 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9229 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9231 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9234 /*******************************************************************
9235 Streams the monitor UI DLL name in UNICODE
9236 *******************************************************************/
9238 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9239 NT_USER_TOKEN *token, DATA_BLOB *in,
9240 DATA_BLOB *out, uint32_t *needed)
9242 const char *dllname = "tcpmonui.dll";
9244 *needed = (strlen(dllname)+1) * 2;
9246 if (out->length < *needed) {
9247 return WERR_INSUFFICIENT_BUFFER;
9250 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9251 return WERR_NOMEM;
9254 return WERR_OK;
9257 /*******************************************************************
9258 ********************************************************************/
9260 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9261 struct spoolss_PortData1 *port1,
9262 const DATA_BLOB *buf)
9264 enum ndr_err_code ndr_err;
9265 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9266 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9267 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9268 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9270 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9273 /*******************************************************************
9274 ********************************************************************/
9276 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9277 struct spoolss_PortData2 *port2,
9278 const DATA_BLOB *buf)
9280 enum ndr_err_code ndr_err;
9281 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9282 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9283 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9284 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9286 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9289 /*******************************************************************
9290 Create a new TCP/IP port
9291 *******************************************************************/
9293 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9294 NT_USER_TOKEN *token, DATA_BLOB *in,
9295 DATA_BLOB *out, uint32_t *needed)
9297 struct spoolss_PortData1 port1;
9298 struct spoolss_PortData2 port2;
9299 char *device_uri = NULL;
9300 uint32_t version;
9302 const char *portname;
9303 const char *hostaddress;
9304 const char *queue;
9305 uint32_t port_number;
9306 uint32_t protocol;
9308 /* peek for spoolss_PortData version */
9310 if (!in || (in->length < (128 + 4))) {
9311 return WERR_GENERAL_FAILURE;
9314 version = IVAL(in->data, 128);
9316 switch (version) {
9317 case 1:
9318 ZERO_STRUCT(port1);
9320 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9321 return WERR_NOMEM;
9324 portname = port1.portname;
9325 hostaddress = port1.hostaddress;
9326 queue = port1.queue;
9327 protocol = port1.protocol;
9328 port_number = port1.port_number;
9330 break;
9331 case 2:
9332 ZERO_STRUCT(port2);
9334 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9335 return WERR_NOMEM;
9338 portname = port2.portname;
9339 hostaddress = port2.hostaddress;
9340 queue = port2.queue;
9341 protocol = port2.protocol;
9342 port_number = port2.port_number;
9344 break;
9345 default:
9346 DEBUG(1,("xcvtcp_addport: "
9347 "unknown version of port_data: %d\n", version));
9348 return WERR_UNKNOWN_PORT;
9351 /* create the device URI and call the add_port_hook() */
9353 switch (protocol) {
9354 case PROTOCOL_RAWTCP_TYPE:
9355 device_uri = talloc_asprintf(mem_ctx,
9356 "socket://%s:%d/", hostaddress,
9357 port_number);
9358 break;
9360 case PROTOCOL_LPR_TYPE:
9361 device_uri = talloc_asprintf(mem_ctx,
9362 "lpr://%s/%s", hostaddress, queue );
9363 break;
9365 default:
9366 return WERR_UNKNOWN_PORT;
9369 if (!device_uri) {
9370 return WERR_NOMEM;
9373 return add_port_hook(mem_ctx, token, portname, device_uri);
9376 /*******************************************************************
9377 *******************************************************************/
9379 struct xcv_api_table xcvtcp_cmds[] = {
9380 { "MonitorUI", xcvtcp_monitorui },
9381 { "AddPort", xcvtcp_addport},
9382 { NULL, NULL }
9385 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9386 NT_USER_TOKEN *token, const char *command,
9387 DATA_BLOB *inbuf,
9388 DATA_BLOB *outbuf,
9389 uint32_t *needed )
9391 int i;
9393 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9395 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9396 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9397 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9400 return WERR_BADFUNC;
9403 /*******************************************************************
9404 *******************************************************************/
9405 #if 0 /* don't support management using the "Local Port" monitor */
9407 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9408 NT_USER_TOKEN *token, DATA_BLOB *in,
9409 DATA_BLOB *out, uint32_t *needed)
9411 const char *dllname = "localui.dll";
9413 *needed = (strlen(dllname)+1) * 2;
9415 if (out->length < *needed) {
9416 return WERR_INSUFFICIENT_BUFFER;
9419 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9420 return WERR_NOMEM;
9423 return WERR_OK;
9426 /*******************************************************************
9427 *******************************************************************/
9429 struct xcv_api_table xcvlocal_cmds[] = {
9430 { "MonitorUI", xcvlocal_monitorui },
9431 { NULL, NULL }
9433 #else
9434 struct xcv_api_table xcvlocal_cmds[] = {
9435 { NULL, NULL }
9437 #endif
9441 /*******************************************************************
9442 *******************************************************************/
9444 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9445 NT_USER_TOKEN *token, const char *command,
9446 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9447 uint32_t *needed)
9449 int i;
9451 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9453 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9454 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9455 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9457 return WERR_BADFUNC;
9460 /****************************************************************
9461 _spoolss_XcvData
9462 ****************************************************************/
9464 WERROR _spoolss_XcvData(pipes_struct *p,
9465 struct spoolss_XcvData *r)
9467 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9468 DATA_BLOB out_data = data_blob_null;
9469 WERROR werror;
9471 if (!Printer) {
9472 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9473 OUR_HANDLE(r->in.handle)));
9474 return WERR_BADFID;
9477 /* Has to be a handle to the TCP/IP port monitor */
9479 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9480 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9481 return WERR_BADFID;
9484 /* requires administrative access to the server */
9486 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9487 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9488 return WERR_ACCESS_DENIED;
9491 /* Allocate the outgoing buffer */
9493 if (r->in.out_data_size) {
9494 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9495 if (out_data.data == NULL) {
9496 return WERR_NOMEM;
9500 switch ( Printer->printer_type ) {
9501 case SPLHND_PORTMON_TCP:
9502 werror = process_xcvtcp_command(p->mem_ctx,
9503 p->server_info->ptok,
9504 r->in.function_name,
9505 &r->in.in_data, &out_data,
9506 r->out.needed);
9507 break;
9508 case SPLHND_PORTMON_LOCAL:
9509 werror = process_xcvlocal_command(p->mem_ctx,
9510 p->server_info->ptok,
9511 r->in.function_name,
9512 &r->in.in_data, &out_data,
9513 r->out.needed);
9514 break;
9515 default:
9516 werror = WERR_INVALID_PRINT_MONITOR;
9519 if (!W_ERROR_IS_OK(werror)) {
9520 return werror;
9523 *r->out.status_code = 0;
9525 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9526 memcpy(r->out.out_data, out_data.data,
9527 MIN(r->in.out_data_size, out_data.length));
9530 return WERR_OK;
9533 /****************************************************************
9534 _spoolss_AddPrintProcessor
9535 ****************************************************************/
9537 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9538 struct spoolss_AddPrintProcessor *r)
9540 /* for now, just indicate success and ignore the add. We'll
9541 automatically set the winprint processor for printer
9542 entries later. Used to debug the LexMark Optra S 1855 PCL
9543 driver --jerry */
9545 return WERR_OK;
9548 /****************************************************************
9549 _spoolss_AddPort
9550 ****************************************************************/
9552 WERROR _spoolss_AddPort(pipes_struct *p,
9553 struct spoolss_AddPort *r)
9555 /* do what w2k3 does */
9557 return WERR_NOT_SUPPORTED;
9560 /****************************************************************
9561 _spoolss_GetPrinterDriver
9562 ****************************************************************/
9564 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9565 struct spoolss_GetPrinterDriver *r)
9567 p->rng_fault_state = true;
9568 return WERR_NOT_SUPPORTED;
9571 /****************************************************************
9572 _spoolss_ReadPrinter
9573 ****************************************************************/
9575 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9576 struct spoolss_ReadPrinter *r)
9578 p->rng_fault_state = true;
9579 return WERR_NOT_SUPPORTED;
9582 /****************************************************************
9583 _spoolss_WaitForPrinterChange
9584 ****************************************************************/
9586 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9587 struct spoolss_WaitForPrinterChange *r)
9589 p->rng_fault_state = true;
9590 return WERR_NOT_SUPPORTED;
9593 /****************************************************************
9594 _spoolss_ConfigurePort
9595 ****************************************************************/
9597 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9598 struct spoolss_ConfigurePort *r)
9600 p->rng_fault_state = true;
9601 return WERR_NOT_SUPPORTED;
9604 /****************************************************************
9605 _spoolss_DeletePort
9606 ****************************************************************/
9608 WERROR _spoolss_DeletePort(pipes_struct *p,
9609 struct spoolss_DeletePort *r)
9611 p->rng_fault_state = true;
9612 return WERR_NOT_SUPPORTED;
9615 /****************************************************************
9616 _spoolss_CreatePrinterIC
9617 ****************************************************************/
9619 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9620 struct spoolss_CreatePrinterIC *r)
9622 p->rng_fault_state = true;
9623 return WERR_NOT_SUPPORTED;
9626 /****************************************************************
9627 _spoolss_PlayGDIScriptOnPrinterIC
9628 ****************************************************************/
9630 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9631 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9633 p->rng_fault_state = true;
9634 return WERR_NOT_SUPPORTED;
9637 /****************************************************************
9638 _spoolss_DeletePrinterIC
9639 ****************************************************************/
9641 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9642 struct spoolss_DeletePrinterIC *r)
9644 p->rng_fault_state = true;
9645 return WERR_NOT_SUPPORTED;
9648 /****************************************************************
9649 _spoolss_AddPrinterConnection
9650 ****************************************************************/
9652 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9653 struct spoolss_AddPrinterConnection *r)
9655 p->rng_fault_state = true;
9656 return WERR_NOT_SUPPORTED;
9659 /****************************************************************
9660 _spoolss_DeletePrinterConnection
9661 ****************************************************************/
9663 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9664 struct spoolss_DeletePrinterConnection *r)
9666 p->rng_fault_state = true;
9667 return WERR_NOT_SUPPORTED;
9670 /****************************************************************
9671 _spoolss_PrinterMessageBox
9672 ****************************************************************/
9674 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9675 struct spoolss_PrinterMessageBox *r)
9677 p->rng_fault_state = true;
9678 return WERR_NOT_SUPPORTED;
9681 /****************************************************************
9682 _spoolss_AddMonitor
9683 ****************************************************************/
9685 WERROR _spoolss_AddMonitor(pipes_struct *p,
9686 struct spoolss_AddMonitor *r)
9688 p->rng_fault_state = true;
9689 return WERR_NOT_SUPPORTED;
9692 /****************************************************************
9693 _spoolss_DeleteMonitor
9694 ****************************************************************/
9696 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9697 struct spoolss_DeleteMonitor *r)
9699 p->rng_fault_state = true;
9700 return WERR_NOT_SUPPORTED;
9703 /****************************************************************
9704 _spoolss_DeletePrintProcessor
9705 ****************************************************************/
9707 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9708 struct spoolss_DeletePrintProcessor *r)
9710 p->rng_fault_state = true;
9711 return WERR_NOT_SUPPORTED;
9714 /****************************************************************
9715 _spoolss_AddPrintProvidor
9716 ****************************************************************/
9718 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9719 struct spoolss_AddPrintProvidor *r)
9721 p->rng_fault_state = true;
9722 return WERR_NOT_SUPPORTED;
9725 /****************************************************************
9726 _spoolss_DeletePrintProvidor
9727 ****************************************************************/
9729 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9730 struct spoolss_DeletePrintProvidor *r)
9732 p->rng_fault_state = true;
9733 return WERR_NOT_SUPPORTED;
9736 /****************************************************************
9737 _spoolss_FindFirstPrinterChangeNotification
9738 ****************************************************************/
9740 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9741 struct spoolss_FindFirstPrinterChangeNotification *r)
9743 p->rng_fault_state = true;
9744 return WERR_NOT_SUPPORTED;
9747 /****************************************************************
9748 _spoolss_FindNextPrinterChangeNotification
9749 ****************************************************************/
9751 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9752 struct spoolss_FindNextPrinterChangeNotification *r)
9754 p->rng_fault_state = true;
9755 return WERR_NOT_SUPPORTED;
9758 /****************************************************************
9759 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9760 ****************************************************************/
9762 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9763 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9765 p->rng_fault_state = true;
9766 return WERR_NOT_SUPPORTED;
9769 /****************************************************************
9770 _spoolss_ReplyOpenPrinter
9771 ****************************************************************/
9773 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9774 struct spoolss_ReplyOpenPrinter *r)
9776 p->rng_fault_state = true;
9777 return WERR_NOT_SUPPORTED;
9780 /****************************************************************
9781 _spoolss_RouterReplyPrinter
9782 ****************************************************************/
9784 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9785 struct spoolss_RouterReplyPrinter *r)
9787 p->rng_fault_state = true;
9788 return WERR_NOT_SUPPORTED;
9791 /****************************************************************
9792 _spoolss_ReplyClosePrinter
9793 ****************************************************************/
9795 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9796 struct spoolss_ReplyClosePrinter *r)
9798 p->rng_fault_state = true;
9799 return WERR_NOT_SUPPORTED;
9802 /****************************************************************
9803 _spoolss_AddPortEx
9804 ****************************************************************/
9806 WERROR _spoolss_AddPortEx(pipes_struct *p,
9807 struct spoolss_AddPortEx *r)
9809 p->rng_fault_state = true;
9810 return WERR_NOT_SUPPORTED;
9813 /****************************************************************
9814 _spoolss_RouterFindFirstPrinterChangeNotification
9815 ****************************************************************/
9817 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9818 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9820 p->rng_fault_state = true;
9821 return WERR_NOT_SUPPORTED;
9824 /****************************************************************
9825 _spoolss_SpoolerInit
9826 ****************************************************************/
9828 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9829 struct spoolss_SpoolerInit *r)
9831 p->rng_fault_state = true;
9832 return WERR_NOT_SUPPORTED;
9835 /****************************************************************
9836 _spoolss_ResetPrinterEx
9837 ****************************************************************/
9839 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9840 struct spoolss_ResetPrinterEx *r)
9842 p->rng_fault_state = true;
9843 return WERR_NOT_SUPPORTED;
9846 /****************************************************************
9847 _spoolss_RouterReplyPrinterEx
9848 ****************************************************************/
9850 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9851 struct spoolss_RouterReplyPrinterEx *r)
9853 p->rng_fault_state = true;
9854 return WERR_NOT_SUPPORTED;
9857 /****************************************************************
9858 _spoolss_44
9859 ****************************************************************/
9861 WERROR _spoolss_44(pipes_struct *p,
9862 struct spoolss_44 *r)
9864 p->rng_fault_state = true;
9865 return WERR_NOT_SUPPORTED;
9868 /****************************************************************
9869 _spoolss_47
9870 ****************************************************************/
9872 WERROR _spoolss_47(pipes_struct *p,
9873 struct spoolss_47 *r)
9875 p->rng_fault_state = true;
9876 return WERR_NOT_SUPPORTED;
9879 /****************************************************************
9880 _spoolss_4a
9881 ****************************************************************/
9883 WERROR _spoolss_4a(pipes_struct *p,
9884 struct spoolss_4a *r)
9886 p->rng_fault_state = true;
9887 return WERR_NOT_SUPPORTED;
9890 /****************************************************************
9891 _spoolss_4b
9892 ****************************************************************/
9894 WERROR _spoolss_4b(pipes_struct *p,
9895 struct spoolss_4b *r)
9897 p->rng_fault_state = true;
9898 return WERR_NOT_SUPPORTED;
9901 /****************************************************************
9902 _spoolss_4c
9903 ****************************************************************/
9905 WERROR _spoolss_4c(pipes_struct *p,
9906 struct spoolss_4c *r)
9908 p->rng_fault_state = true;
9909 return WERR_NOT_SUPPORTED;
9912 /****************************************************************
9913 _spoolss_53
9914 ****************************************************************/
9916 WERROR _spoolss_53(pipes_struct *p,
9917 struct spoolss_53 *r)
9919 p->rng_fault_state = true;
9920 return WERR_NOT_SUPPORTED;
9923 /****************************************************************
9924 _spoolss_55
9925 ****************************************************************/
9927 WERROR _spoolss_55(pipes_struct *p,
9928 struct spoolss_55 *r)
9930 p->rng_fault_state = true;
9931 return WERR_NOT_SUPPORTED;
9934 /****************************************************************
9935 _spoolss_56
9936 ****************************************************************/
9938 WERROR _spoolss_56(pipes_struct *p,
9939 struct spoolss_56 *r)
9941 p->rng_fault_state = true;
9942 return WERR_NOT_SUPPORTED;
9945 /****************************************************************
9946 _spoolss_57
9947 ****************************************************************/
9949 WERROR _spoolss_57(pipes_struct *p,
9950 struct spoolss_57 *r)
9952 p->rng_fault_state = true;
9953 return WERR_NOT_SUPPORTED;
9956 /****************************************************************
9957 _spoolss_5a
9958 ****************************************************************/
9960 WERROR _spoolss_5a(pipes_struct *p,
9961 struct spoolss_5a *r)
9963 p->rng_fault_state = true;
9964 return WERR_NOT_SUPPORTED;
9967 /****************************************************************
9968 _spoolss_5b
9969 ****************************************************************/
9971 WERROR _spoolss_5b(pipes_struct *p,
9972 struct spoolss_5b *r)
9974 p->rng_fault_state = true;
9975 return WERR_NOT_SUPPORTED;
9978 /****************************************************************
9979 _spoolss_5c
9980 ****************************************************************/
9982 WERROR _spoolss_5c(pipes_struct *p,
9983 struct spoolss_5c *r)
9985 p->rng_fault_state = true;
9986 return WERR_NOT_SUPPORTED;
9989 /****************************************************************
9990 _spoolss_5d
9991 ****************************************************************/
9993 WERROR _spoolss_5d(pipes_struct *p,
9994 struct spoolss_5d *r)
9996 p->rng_fault_state = true;
9997 return WERR_NOT_SUPPORTED;
10000 /****************************************************************
10001 _spoolss_5e
10002 ****************************************************************/
10004 WERROR _spoolss_5e(pipes_struct *p,
10005 struct spoolss_5e *r)
10007 p->rng_fault_state = true;
10008 return WERR_NOT_SUPPORTED;
10011 /****************************************************************
10012 _spoolss_5f
10013 ****************************************************************/
10015 WERROR _spoolss_5f(pipes_struct *p,
10016 struct spoolss_5f *r)
10018 p->rng_fault_state = true;
10019 return WERR_NOT_SUPPORTED;
10022 /****************************************************************
10023 _spoolss_60
10024 ****************************************************************/
10026 WERROR _spoolss_60(pipes_struct *p,
10027 struct spoolss_60 *r)
10029 p->rng_fault_state = true;
10030 return WERR_NOT_SUPPORTED;
10033 /****************************************************************
10034 _spoolss_61
10035 ****************************************************************/
10037 WERROR _spoolss_61(pipes_struct *p,
10038 struct spoolss_61 *r)
10040 p->rng_fault_state = true;
10041 return WERR_NOT_SUPPORTED;
10044 /****************************************************************
10045 _spoolss_62
10046 ****************************************************************/
10048 WERROR _spoolss_62(pipes_struct *p,
10049 struct spoolss_62 *r)
10051 p->rng_fault_state = true;
10052 return WERR_NOT_SUPPORTED;
10055 /****************************************************************
10056 _spoolss_63
10057 ****************************************************************/
10059 WERROR _spoolss_63(pipes_struct *p,
10060 struct spoolss_63 *r)
10062 p->rng_fault_state = true;
10063 return WERR_NOT_SUPPORTED;
10066 /****************************************************************
10067 _spoolss_64
10068 ****************************************************************/
10070 WERROR _spoolss_64(pipes_struct *p,
10071 struct spoolss_64 *r)
10073 p->rng_fault_state = true;
10074 return WERR_NOT_SUPPORTED;
10077 /****************************************************************
10078 _spoolss_65
10079 ****************************************************************/
10081 WERROR _spoolss_65(pipes_struct *p,
10082 struct spoolss_65 *r)
10084 p->rng_fault_state = true;
10085 return WERR_NOT_SUPPORTED;
10088 /****************************************************************
10089 _spoolss_GetCorePrinterDrivers
10090 ****************************************************************/
10092 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10093 struct spoolss_GetCorePrinterDrivers *r)
10095 p->rng_fault_state = true;
10096 return WERR_NOT_SUPPORTED;
10099 /****************************************************************
10100 _spoolss_67
10101 ****************************************************************/
10103 WERROR _spoolss_67(pipes_struct *p,
10104 struct spoolss_67 *r)
10106 p->rng_fault_state = true;
10107 return WERR_NOT_SUPPORTED;
10110 /****************************************************************
10111 _spoolss_GetPrinterDriverPackagePath
10112 ****************************************************************/
10114 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10115 struct spoolss_GetPrinterDriverPackagePath *r)
10117 p->rng_fault_state = true;
10118 return WERR_NOT_SUPPORTED;
10121 /****************************************************************
10122 _spoolss_69
10123 ****************************************************************/
10125 WERROR _spoolss_69(pipes_struct *p,
10126 struct spoolss_69 *r)
10128 p->rng_fault_state = true;
10129 return WERR_NOT_SUPPORTED;
10132 /****************************************************************
10133 _spoolss_6a
10134 ****************************************************************/
10136 WERROR _spoolss_6a(pipes_struct *p,
10137 struct spoolss_6a *r)
10139 p->rng_fault_state = true;
10140 return WERR_NOT_SUPPORTED;
10143 /****************************************************************
10144 _spoolss_6b
10145 ****************************************************************/
10147 WERROR _spoolss_6b(pipes_struct *p,
10148 struct spoolss_6b *r)
10150 p->rng_fault_state = true;
10151 return WERR_NOT_SUPPORTED;
10154 /****************************************************************
10155 _spoolss_6c
10156 ****************************************************************/
10158 WERROR _spoolss_6c(pipes_struct *p,
10159 struct spoolss_6c *r)
10161 p->rng_fault_state = true;
10162 return WERR_NOT_SUPPORTED;
10165 /****************************************************************
10166 _spoolss_6d
10167 ****************************************************************/
10169 WERROR _spoolss_6d(pipes_struct *p,
10170 struct spoolss_6d *r)
10172 p->rng_fault_state = true;
10173 return WERR_NOT_SUPPORTED;