s3-rpc_server: Created a per connection spoolss pipe.
[Samba/ekacnet.git] / source3 / rpc_server / srv_spoolss_nt.c
blob81c72c20ae0d956949f5bb4debb94ef1e5530ddd
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 "rpc_client/init_spoolss.h"
33 #include "librpc/gen_ndr/messaging.h"
34 #include "registry.h"
35 #include "registry/reg_objects.h"
37 /* macros stolen from s4 spoolss server */
38 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
39 ((info)?ndr_size_##fn(info, level, 0):0)
41 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
42 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
44 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
45 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
47 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
50 extern userdom_struct current_user_info;
52 #undef DBGC_CLASS
53 #define DBGC_CLASS DBGC_RPC_SRV
55 #ifndef MAX_OPEN_PRINTER_EXS
56 #define MAX_OPEN_PRINTER_EXS 50
57 #endif
59 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
61 static Printer_entry *printers_list;
63 typedef struct _counter_printer_0 {
64 struct _counter_printer_0 *next;
65 struct _counter_printer_0 *prev;
67 int snum;
68 uint32_t counter;
69 } counter_printer_0;
71 static counter_printer_0 *counter_list;
73 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
74 static uint32_t smb_connections = 0;
77 /* in printing/nt_printing.c */
79 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
81 /* API table for Xcv Monitor functions */
83 struct xcv_api_table {
84 const char *name;
85 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
88 /********************************************************************
89 * Canonicalize servername.
90 ********************************************************************/
92 static const char *canon_servername(const char *servername)
94 const char *pservername = servername;
95 while (*pservername == '\\') {
96 pservername++;
98 return pservername;
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v)
104 switch (v) {
105 case LPQ_QUEUED:
106 return 0;
107 case LPQ_PAUSED:
108 return JOB_STATUS_PAUSED;
109 case LPQ_SPOOLING:
110 return JOB_STATUS_SPOOLING;
111 case LPQ_PRINTING:
112 return JOB_STATUS_PRINTING;
113 case LPQ_ERROR:
114 return JOB_STATUS_ERROR;
115 case LPQ_DELETING:
116 return JOB_STATUS_DELETING;
117 case LPQ_OFFLINE:
118 return JOB_STATUS_OFFLINE;
119 case LPQ_PAPEROUT:
120 return JOB_STATUS_PAPEROUT;
121 case LPQ_PRINTED:
122 return JOB_STATUS_PRINTED;
123 case LPQ_DELETED:
124 return JOB_STATUS_DELETED;
125 case LPQ_BLOCKED:
126 return JOB_STATUS_BLOCKED_DEVQ;
127 case LPQ_USER_INTERVENTION:
128 return JOB_STATUS_USER_INTERVENTION;
130 return 0;
133 static int nt_printq_status(int v)
135 switch (v) {
136 case LPQ_PAUSED:
137 return PRINTER_STATUS_PAUSED;
138 case LPQ_QUEUED:
139 case LPQ_SPOOLING:
140 case LPQ_PRINTING:
141 return 0;
143 return 0;
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
152 WERROR result;
153 NTSTATUS status;
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 return;
169 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
170 handle,
171 &result);
172 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 win_errstr(result)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2, NULL);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
191 smb_connections--;
194 /****************************************************************************
195 Functions to free a printer entry datastruct.
196 ****************************************************************************/
198 static int printer_entry_destructor(Printer_entry *Printer)
200 if (Printer->notify.client_connected == true) {
201 int snum = -1;
203 if ( Printer->printer_type == SPLHND_SERVER) {
204 snum = -1;
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == SPLHND_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
208 if (snum != -1)
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 TALLOC_FREE(Printer->notify.option);
219 Printer->notify.client_connected = false;
221 free_nt_devicemode( &Printer->nt_devmode );
222 free_a_printer( &Printer->printer_info, 2 );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
226 return 0;
229 /****************************************************************************
230 find printer index by handle
231 ****************************************************************************/
233 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
234 struct policy_handle *hnd)
236 Printer_entry *find_printer = NULL;
238 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
239 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
240 return NULL;
243 return find_printer;
246 /****************************************************************************
247 Close printer index by handle.
248 ****************************************************************************/
250 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
252 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
254 if (!Printer) {
255 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
256 OUR_HANDLE(hnd)));
257 return false;
260 close_policy_hnd(p, hnd);
262 return true;
265 /****************************************************************************
266 Delete a printer given a handle.
267 ****************************************************************************/
269 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
271 char *cmd = lp_deleteprinter_cmd();
272 char *command = NULL;
273 int ret;
274 SE_PRIV se_printop = SE_PRINT_OPERATOR;
275 bool is_print_op = false;
277 /* can't fail if we don't try */
279 if ( !*cmd )
280 return WERR_OK;
282 command = talloc_asprintf(ctx,
283 "%s \"%s\"",
284 cmd, sharename);
285 if (!command) {
286 return WERR_NOMEM;
288 if ( token )
289 is_print_op = user_has_privileges( token, &se_printop );
291 DEBUG(10,("Running [%s]\n", command));
293 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
295 if ( is_print_op )
296 become_root();
298 if ( (ret = smbrun(command, NULL)) == 0 ) {
299 /* Tell everyone we updated smb.conf. */
300 message_send_all(smbd_messaging_context(),
301 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
304 if ( is_print_op )
305 unbecome_root();
307 /********** END SePrintOperatorPrivlege BLOCK **********/
309 DEBUGADD(10,("returned [%d]\n", ret));
311 TALLOC_FREE(command);
313 if (ret != 0)
314 return WERR_BADFID; /* What to return here? */
316 /* go ahead and re-read the services immediately */
317 become_root();
318 reload_services(false);
319 unbecome_root();
321 if ( lp_servicenumber( sharename ) > 0 )
322 return WERR_ACCESS_DENIED;
324 return WERR_OK;
327 /****************************************************************************
328 Delete a printer given a handle.
329 ****************************************************************************/
331 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
333 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
335 if (!Printer) {
336 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
337 OUR_HANDLE(hnd)));
338 return WERR_BADFID;
342 * It turns out that Windows allows delete printer on a handle
343 * opened by an admin user, then used on a pipe handle created
344 * by an anonymous user..... but they're working on security.... riiight !
345 * JRA.
348 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
349 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
350 return WERR_ACCESS_DENIED;
353 /* this does not need a become root since the access check has been
354 done on the handle already */
356 if (del_a_printer( Printer->sharename ) != 0) {
357 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
358 return WERR_BADFID;
361 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
362 Printer->sharename );
365 /****************************************************************************
366 Return the snum of a printer corresponding to an handle.
367 ****************************************************************************/
369 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
370 int *number, struct share_params **params)
372 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
374 if (!Printer) {
375 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
376 OUR_HANDLE(hnd)));
377 return false;
380 switch (Printer->printer_type) {
381 case SPLHND_PRINTER:
382 DEBUG(4,("short name:%s\n", Printer->sharename));
383 *number = print_queue_snum(Printer->sharename);
384 return (*number != -1);
385 case SPLHND_SERVER:
386 return false;
387 default:
388 return false;
392 /****************************************************************************
393 Set printer handle type.
394 Check if it's \\server or \\server\printer
395 ****************************************************************************/
397 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
399 DEBUG(3,("Setting printer type=%s\n", handlename));
401 if ( strlen(handlename) < 3 ) {
402 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
403 return false;
406 /* it's a print server */
407 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
408 DEBUGADD(4,("Printer is a print server\n"));
409 Printer->printer_type = SPLHND_SERVER;
411 /* it's a printer (set_printer_hnd_name() will handle port monitors */
412 else {
413 DEBUGADD(4,("Printer is a printer\n"));
414 Printer->printer_type = SPLHND_PRINTER;
417 return true;
420 /****************************************************************************
421 Set printer handle name.. Accept names like \\server, \\server\printer,
422 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
423 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
424 XcvDataPort() interface.
425 ****************************************************************************/
427 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
429 int snum;
430 int n_services=lp_numservices();
431 char *aprinter, *printername;
432 const char *servername;
433 fstring sname;
434 bool found = false;
435 NT_PRINTER_INFO_LEVEL *printer = NULL;
436 WERROR result;
438 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
439 (unsigned long)strlen(handlename)));
441 aprinter = CONST_DISCARD(char *, handlename);
442 if ( *handlename == '\\' ) {
443 servername = canon_servername(handlename);
444 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
445 *aprinter = '\0';
446 aprinter++;
448 } else {
449 servername = global_myname();
452 /* save the servername to fill in replies on this handle */
454 if ( !is_myname_or_ipaddr( servername ) )
455 return false;
457 fstrcpy( Printer->servername, servername );
459 if ( Printer->printer_type == SPLHND_SERVER )
460 return true;
462 if ( Printer->printer_type != SPLHND_PRINTER )
463 return false;
465 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
467 /* check for the Port Monitor Interface */
469 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
470 Printer->printer_type = SPLHND_PORTMON_TCP;
471 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
472 found = true;
474 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
475 Printer->printer_type = SPLHND_PORTMON_LOCAL;
476 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
477 found = true;
480 /* Search all sharenames first as this is easier than pulling
481 the printer_info_2 off of disk. Don't use find_service() since
482 that calls out to map_username() */
484 /* do another loop to look for printernames */
486 for (snum=0; !found && snum<n_services; snum++) {
488 /* no point going on if this is not a printer */
490 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
491 continue;
493 fstrcpy(sname, lp_servicename(snum));
494 if ( strequal( aprinter, sname ) ) {
495 found = true;
496 break;
499 /* no point looking up the printer object if
500 we aren't allowing printername != sharename */
502 if ( lp_force_printername(snum) )
503 continue;
505 fstrcpy(sname, lp_servicename(snum));
507 printer = NULL;
509 /* This call doesn't fill in the location or comment from
510 * a CUPS server for efficiency with large numbers of printers.
511 * JRA.
514 result = get_a_printer_search( NULL, &printer, 2, sname );
515 if ( !W_ERROR_IS_OK(result) ) {
516 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
517 sname, win_errstr(result)));
518 continue;
521 /* printername is always returned as \\server\printername */
522 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
523 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
524 printer->info_2->printername));
525 free_a_printer( &printer, 2);
526 continue;
529 printername++;
531 if ( strequal(printername, aprinter) ) {
532 free_a_printer( &printer, 2);
533 found = true;
534 break;
537 DEBUGADD(10, ("printername: %s\n", printername));
539 free_a_printer( &printer, 2);
542 free_a_printer( &printer, 2);
544 if ( !found ) {
545 DEBUGADD(4,("Printer not found\n"));
546 return false;
549 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
551 fstrcpy(Printer->sharename, sname);
553 return true;
556 /****************************************************************************
557 Find first available printer slot. creates a printer handle for you.
558 ****************************************************************************/
560 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
561 const char *name, uint32_t access_granted)
563 Printer_entry *new_printer;
565 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
567 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
568 if (new_printer == NULL) {
569 return false;
571 talloc_set_destructor(new_printer, printer_entry_destructor);
573 if (!create_policy_hnd(p, hnd, new_printer)) {
574 TALLOC_FREE(new_printer);
575 return false;
578 /* Add to the internal list. */
579 DLIST_ADD(printers_list, new_printer);
581 new_printer->notify.option=NULL;
583 if (!set_printer_hnd_printertype(new_printer, name)) {
584 close_printer_handle(p, hnd);
585 return false;
588 if (!set_printer_hnd_name(new_printer, name)) {
589 close_printer_handle(p, hnd);
590 return false;
593 new_printer->access_granted = access_granted;
595 DEBUG(5, ("%d printer handles active\n",
596 (int)num_pipe_handles(p->pipe_handles)));
598 return true;
601 /***************************************************************************
602 check to see if the client motify handle is monitoring the notification
603 given by (notify_type, notify_field).
604 **************************************************************************/
606 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
607 uint16_t notify_field)
609 return true;
612 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
613 uint16_t notify_field)
615 struct spoolss_NotifyOption *option = p->notify.option;
616 uint32_t i, j;
619 * Flags should always be zero when the change notify
620 * is registered by the client's spooler. A user Win32 app
621 * might use the flags though instead of the NOTIFY_OPTION_INFO
622 * --jerry
625 if (!option) {
626 return false;
629 if (p->notify.flags)
630 return is_monitoring_event_flags(
631 p->notify.flags, notify_type, notify_field);
633 for (i = 0; i < option->count; i++) {
635 /* Check match for notify_type */
637 if (option->types[i].type != notify_type)
638 continue;
640 /* Check match for field */
642 for (j = 0; j < option->types[i].count; j++) {
643 if (option->types[i].fields[j].field == notify_field) {
644 return true;
649 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
650 p->servername, p->sharename, notify_type, notify_field));
652 return false;
655 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
656 _data->data.integer[0] = _integer; \
657 _data->data.integer[1] = 0;
660 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
661 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
662 if (!_data->data.string.string) {\
663 _data->data.string.size = 0; \
665 _data->data.string.size = strlen_m_term(_p) * 2;
667 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
668 _data->data.devmode.devmode = _devmode;
670 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
671 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
672 if (!_data->data.sd.sd) { \
673 _data->data.sd.sd_size = 0; \
675 _data->data.sd.sd_size = _size;
677 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
678 struct tm *t,
679 const char **pp,
680 uint32_t *plen)
682 struct spoolss_Time st;
683 uint32_t len = 16;
684 char *p;
686 if (!init_systemtime(&st, t)) {
687 return;
690 p = talloc_array(mem_ctx, char, len);
691 if (!p) {
692 return;
696 * Systemtime must be linearized as a set of UINT16's.
697 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
700 SSVAL(p, 0, st.year);
701 SSVAL(p, 2, st.month);
702 SSVAL(p, 4, st.day_of_week);
703 SSVAL(p, 6, st.day);
704 SSVAL(p, 8, st.hour);
705 SSVAL(p, 10, st.minute);
706 SSVAL(p, 12, st.second);
707 SSVAL(p, 14, st.millisecond);
709 *pp = p;
710 *plen = len;
713 /* Convert a notification message to a struct spoolss_Notify */
715 static void notify_one_value(struct spoolss_notify_msg *msg,
716 struct spoolss_Notify *data,
717 TALLOC_CTX *mem_ctx)
719 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
722 static void notify_string(struct spoolss_notify_msg *msg,
723 struct spoolss_Notify *data,
724 TALLOC_CTX *mem_ctx)
726 /* The length of the message includes the trailing \0 */
728 data->data.string.size = msg->len * 2;
729 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
730 if (!data->data.string.string) {
731 data->data.string.size = 0;
732 return;
736 static void notify_system_time(struct spoolss_notify_msg *msg,
737 struct spoolss_Notify *data,
738 TALLOC_CTX *mem_ctx)
740 data->data.string.string = NULL;
741 data->data.string.size = 0;
743 if (msg->len != sizeof(time_t)) {
744 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
745 msg->len));
746 return;
749 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
750 &data->data.string.string,
751 &data->data.string.size);
754 struct notify2_message_table {
755 const char *name;
756 void (*fn)(struct spoolss_notify_msg *msg,
757 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
760 static struct notify2_message_table printer_notify_table[] = {
761 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
762 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
763 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
764 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
765 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
766 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
767 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
768 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
769 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
770 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
771 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
772 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
773 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
774 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
775 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
776 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
777 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
778 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
779 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
782 static struct notify2_message_table job_notify_table[] = {
783 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
784 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
785 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
786 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
787 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
788 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
789 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
790 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
791 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
792 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
793 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
794 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
795 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
796 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
797 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
798 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
799 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
800 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
801 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
802 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
803 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
804 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
805 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
806 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
810 /***********************************************************************
811 Allocate talloc context for container object
812 **********************************************************************/
814 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
816 if ( !ctr )
817 return;
819 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
821 return;
824 /***********************************************************************
825 release all allocated memory and zero out structure
826 **********************************************************************/
828 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
830 if ( !ctr )
831 return;
833 if ( ctr->ctx )
834 talloc_destroy(ctr->ctx);
836 ZERO_STRUCTP(ctr);
838 return;
841 /***********************************************************************
842 **********************************************************************/
844 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
846 if ( !ctr )
847 return NULL;
849 return ctr->ctx;
852 /***********************************************************************
853 **********************************************************************/
855 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
857 if ( !ctr || !ctr->msg_groups )
858 return NULL;
860 if ( idx >= ctr->num_groups )
861 return NULL;
863 return &ctr->msg_groups[idx];
867 /***********************************************************************
868 How many groups of change messages do we have ?
869 **********************************************************************/
871 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
873 if ( !ctr )
874 return 0;
876 return ctr->num_groups;
879 /***********************************************************************
880 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
881 **********************************************************************/
883 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
885 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
886 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
887 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
888 int i, new_slot;
890 if ( !ctr || !msg )
891 return 0;
893 /* loop over all groups looking for a matching printer name */
895 for ( i=0; i<ctr->num_groups; i++ ) {
896 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
897 break;
900 /* add a new group? */
902 if ( i == ctr->num_groups ) {
903 ctr->num_groups++;
905 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
906 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
907 return 0;
909 ctr->msg_groups = groups;
911 /* clear the new entry and set the printer name */
913 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
914 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
917 /* add the change messages; 'i' is the correct index now regardless */
919 msg_grp = &ctr->msg_groups[i];
921 msg_grp->num_msgs++;
923 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
924 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
925 return 0;
927 msg_grp->msgs = msg_list;
929 new_slot = msg_grp->num_msgs-1;
930 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
932 /* need to allocate own copy of data */
934 if ( msg->len != 0 )
935 msg_grp->msgs[new_slot].notify.data = (char *)
936 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
938 return ctr->num_groups;
941 void construct_info_data(struct spoolss_Notify *info_data,
942 enum spoolss_NotifyType type,
943 uint16_t field,
944 int id);
946 /***********************************************************************
947 Send a change notication message on all handles which have a call
948 back registered
949 **********************************************************************/
951 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
953 Printer_entry *p;
954 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
955 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
956 SPOOLSS_NOTIFY_MSG *messages;
957 int sending_msg_count;
959 if ( !msg_group ) {
960 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
961 return;
964 messages = msg_group->msgs;
966 if ( !messages ) {
967 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
968 return;
971 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
973 /* loop over all printers */
975 for (p = printers_list; p; p = p->next) {
976 struct spoolss_Notify *notifies;
977 uint32_t count = 0;
978 uint32_t id;
979 int i;
981 /* Is there notification on this handle? */
983 if ( !p->notify.client_connected )
984 continue;
986 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
988 /* For this printer? Print servers always receive
989 notifications. */
991 if ( ( p->printer_type == SPLHND_PRINTER ) &&
992 ( !strequal(msg_group->printername, p->sharename) ) )
993 continue;
995 DEBUG(10,("Our printer\n"));
997 /* allocate the max entries possible */
999 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1000 if (!notifies) {
1001 return;
1004 /* build the array of change notifications */
1006 sending_msg_count = 0;
1008 for ( i=0; i<msg_group->num_msgs; i++ ) {
1009 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1011 /* Are we monitoring this event? */
1013 if (!is_monitoring_event(p, msg->type, msg->field))
1014 continue;
1016 sending_msg_count++;
1019 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1020 msg->type, msg->field, p->sharename));
1023 * if the is a printer notification handle and not a job notification
1024 * type, then set the id to 0. Other wise just use what was specified
1025 * in the message.
1027 * When registering change notification on a print server handle
1028 * we always need to send back the id (snum) matching the printer
1029 * for which the change took place. For change notify registered
1030 * on a printer handle, this does not matter and the id should be 0.
1032 * --jerry
1035 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1036 id = 0;
1037 else
1038 id = msg->id;
1041 /* Convert unix jobid to smb jobid */
1043 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1044 id = sysjob_to_jobid(msg->id);
1046 if (id == -1) {
1047 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1048 goto done;
1052 construct_info_data( &notifies[count], msg->type, msg->field, id );
1054 switch(msg->type) {
1055 case PRINTER_NOTIFY_TYPE:
1056 if ( printer_notify_table[msg->field].fn )
1057 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1058 break;
1060 case JOB_NOTIFY_TYPE:
1061 if ( job_notify_table[msg->field].fn )
1062 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1063 break;
1065 default:
1066 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1067 goto done;
1070 count++;
1073 if ( sending_msg_count ) {
1074 NTSTATUS status;
1075 WERROR werr;
1076 union spoolss_ReplyPrinterInfo info;
1077 struct spoolss_NotifyInfo info0;
1078 uint32_t reply_result;
1080 info0.version = 0x2;
1081 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1082 info0.count = count;
1083 info0.notifies = notifies;
1085 info.info0 = &info0;
1087 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1088 &p->notify.client_hnd,
1089 p->notify.change, /* color */
1090 p->notify.flags,
1091 &reply_result,
1092 0, /* reply_type, must be 0 */
1093 info,
1094 &werr);
1095 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1096 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1097 notify_cli_pipe->srv_name_slash,
1098 win_errstr(werr)));
1100 switch (reply_result) {
1101 case 0:
1102 break;
1103 case PRINTER_NOTIFY_INFO_DISCARDED:
1104 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1105 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1106 break;
1107 default:
1108 break;
1113 done:
1114 DEBUG(8,("send_notify2_changes: Exit...\n"));
1115 return;
1118 /***********************************************************************
1119 **********************************************************************/
1121 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1124 uint32_t tv_sec, tv_usec;
1125 size_t offset = 0;
1127 /* Unpack message */
1129 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1130 msg->printer);
1132 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1133 &tv_sec, &tv_usec,
1134 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1136 if (msg->len == 0)
1137 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1138 &msg->notify.value[0], &msg->notify.value[1]);
1139 else
1140 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1141 &msg->len, &msg->notify.data);
1143 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1144 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1146 tv->tv_sec = tv_sec;
1147 tv->tv_usec = tv_usec;
1149 if (msg->len == 0)
1150 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1151 msg->notify.value[1]));
1152 else
1153 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1155 return true;
1158 /********************************************************************
1159 Receive a notify2 message list
1160 ********************************************************************/
1162 static void receive_notify2_message_list(struct messaging_context *msg,
1163 void *private_data,
1164 uint32_t msg_type,
1165 struct server_id server_id,
1166 DATA_BLOB *data)
1168 size_t msg_count, i;
1169 char *buf = (char *)data->data;
1170 char *msg_ptr;
1171 size_t msg_len;
1172 SPOOLSS_NOTIFY_MSG notify;
1173 SPOOLSS_NOTIFY_MSG_CTR messages;
1174 int num_groups;
1176 if (data->length < 4) {
1177 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1178 return;
1181 msg_count = IVAL(buf, 0);
1182 msg_ptr = buf + 4;
1184 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1186 if (msg_count == 0) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1188 return;
1191 /* initialize the container */
1193 ZERO_STRUCT( messages );
1194 notify_msg_ctr_init( &messages );
1197 * build message groups for each printer identified
1198 * in a change_notify msg. Remember that a PCN message
1199 * includes the handle returned for the srv_spoolss_replyopenprinter()
1200 * call. Therefore messages are grouped according to printer handle.
1203 for ( i=0; i<msg_count; i++ ) {
1204 struct timeval msg_tv;
1206 if (msg_ptr + 4 - buf > data->length) {
1207 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1208 return;
1211 msg_len = IVAL(msg_ptr,0);
1212 msg_ptr += 4;
1214 if (msg_ptr + msg_len - buf > data->length) {
1215 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1216 return;
1219 /* unpack messages */
1221 ZERO_STRUCT( notify );
1222 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1223 msg_ptr += msg_len;
1225 /* add to correct list in container */
1227 notify_msg_ctr_addmsg( &messages, &notify );
1229 /* free memory that might have been allocated by notify2_unpack_msg() */
1231 if ( notify.len != 0 )
1232 SAFE_FREE( notify.notify.data );
1235 /* process each group of messages */
1237 num_groups = notify_msg_ctr_numgroups( &messages );
1238 for ( i=0; i<num_groups; i++ )
1239 send_notify2_changes( &messages, i );
1242 /* cleanup */
1244 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1245 (uint32_t)msg_count ));
1247 notify_msg_ctr_destroy( &messages );
1249 return;
1252 /********************************************************************
1253 Send a message to ourself about new driver being installed
1254 so we can upgrade the information for each printer bound to this
1255 driver
1256 ********************************************************************/
1258 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1260 int len = strlen(drivername);
1262 if (!len)
1263 return false;
1265 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1266 drivername));
1268 messaging_send_buf(smbd_messaging_context(), procid_self(),
1269 MSG_PRINTER_DRVUPGRADE,
1270 (uint8_t *)drivername, len+1);
1272 return true;
1275 /**********************************************************************
1276 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1277 over all printers, upgrading ones as necessary
1278 **********************************************************************/
1280 void do_drv_upgrade_printer(struct messaging_context *msg,
1281 void *private_data,
1282 uint32_t msg_type,
1283 struct server_id server_id,
1284 DATA_BLOB *data)
1286 fstring drivername;
1287 int snum;
1288 int n_services = lp_numservices();
1289 size_t len;
1291 len = MIN(data->length,sizeof(drivername)-1);
1292 strncpy(drivername, (const char *)data->data, len);
1294 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1296 /* Iterate the printer list */
1298 for (snum=0; snum<n_services; snum++)
1300 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1302 WERROR result;
1303 NT_PRINTER_INFO_LEVEL *printer = NULL;
1305 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1306 if (!W_ERROR_IS_OK(result))
1307 continue;
1309 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1311 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1313 /* all we care about currently is the change_id */
1315 result = mod_a_printer(printer, 2);
1316 if (!W_ERROR_IS_OK(result)) {
1317 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1318 win_errstr(result)));
1322 free_a_printer(&printer, 2);
1326 /* all done */
1329 /********************************************************************
1330 Update the cache for all printq's with a registered client
1331 connection
1332 ********************************************************************/
1334 void update_monitored_printq_cache( void )
1336 Printer_entry *printer = printers_list;
1337 int snum;
1339 /* loop through all printers and update the cache where
1340 client_connected == true */
1341 while ( printer )
1343 if ( (printer->printer_type == SPLHND_PRINTER)
1344 && printer->notify.client_connected )
1346 snum = print_queue_snum(printer->sharename);
1347 print_queue_status( snum, NULL, NULL );
1350 printer = printer->next;
1353 return;
1356 /****************************************************************
1357 _spoolss_OpenPrinter
1358 ****************************************************************/
1360 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1361 struct spoolss_OpenPrinter *r)
1363 struct spoolss_OpenPrinterEx e;
1364 WERROR werr;
1366 ZERO_STRUCT(e.in.userlevel);
1368 e.in.printername = r->in.printername;
1369 e.in.datatype = r->in.datatype;
1370 e.in.devmode_ctr = r->in.devmode_ctr;
1371 e.in.access_mask = r->in.access_mask;
1372 e.in.level = 0;
1374 e.out.handle = r->out.handle;
1376 werr = _spoolss_OpenPrinterEx(p, &e);
1378 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1379 /* OpenPrinterEx returns this for a bad
1380 * printer name. We must return WERR_INVALID_PRINTER_NAME
1381 * instead.
1383 werr = WERR_INVALID_PRINTER_NAME;
1386 return werr;
1389 /********************************************************************
1390 ********************************************************************/
1392 bool convert_devicemode(const char *printername,
1393 const struct spoolss_DeviceMode *devmode,
1394 NT_DEVICEMODE **pp_nt_devmode)
1396 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1399 * Ensure nt_devmode is a valid pointer
1400 * as we will be overwriting it.
1403 if (nt_devmode == NULL) {
1404 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1405 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1406 return false;
1409 fstrcpy(nt_devmode->devicename, devmode->devicename);
1410 fstrcpy(nt_devmode->formname, devmode->formname);
1412 nt_devmode->devicename[31] = '\0';
1413 nt_devmode->formname[31] = '\0';
1415 nt_devmode->specversion = devmode->specversion;
1416 nt_devmode->driverversion = devmode->driverversion;
1417 nt_devmode->size = devmode->size;
1418 nt_devmode->fields = devmode->fields;
1419 nt_devmode->orientation = devmode->orientation;
1420 nt_devmode->papersize = devmode->papersize;
1421 nt_devmode->paperlength = devmode->paperlength;
1422 nt_devmode->paperwidth = devmode->paperwidth;
1423 nt_devmode->scale = devmode->scale;
1424 nt_devmode->copies = devmode->copies;
1425 nt_devmode->defaultsource = devmode->defaultsource;
1426 nt_devmode->printquality = devmode->printquality;
1427 nt_devmode->color = devmode->color;
1428 nt_devmode->duplex = devmode->duplex;
1429 nt_devmode->yresolution = devmode->yresolution;
1430 nt_devmode->ttoption = devmode->ttoption;
1431 nt_devmode->collate = devmode->collate;
1433 nt_devmode->logpixels = devmode->logpixels;
1434 nt_devmode->bitsperpel = devmode->bitsperpel;
1435 nt_devmode->pelswidth = devmode->pelswidth;
1436 nt_devmode->pelsheight = devmode->pelsheight;
1437 nt_devmode->displayflags = devmode->displayflags;
1438 nt_devmode->displayfrequency = devmode->displayfrequency;
1439 nt_devmode->icmmethod = devmode->icmmethod;
1440 nt_devmode->icmintent = devmode->icmintent;
1441 nt_devmode->mediatype = devmode->mediatype;
1442 nt_devmode->dithertype = devmode->dithertype;
1443 nt_devmode->reserved1 = devmode->reserved1;
1444 nt_devmode->reserved2 = devmode->reserved2;
1445 nt_devmode->panningwidth = devmode->panningwidth;
1446 nt_devmode->panningheight = devmode->panningheight;
1449 * Only change private and driverextra if the incoming devmode
1450 * has a new one. JRA.
1453 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1454 SAFE_FREE(nt_devmode->nt_dev_private);
1455 nt_devmode->driverextra = devmode->__driverextra_length;
1456 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1457 return false;
1458 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1461 *pp_nt_devmode = nt_devmode;
1463 return true;
1466 /****************************************************************
1467 _spoolss_OpenPrinterEx
1468 ****************************************************************/
1470 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1471 struct spoolss_OpenPrinterEx *r)
1473 int snum;
1474 Printer_entry *Printer=NULL;
1476 if (!r->in.printername) {
1477 return WERR_INVALID_PARAM;
1480 /* some sanity check because you can open a printer or a print server */
1481 /* aka: \\server\printer or \\server */
1483 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1485 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1486 ZERO_STRUCTP(r->out.handle);
1487 return WERR_INVALID_PARAM;
1490 Printer = find_printer_index_by_hnd(p, r->out.handle);
1491 if ( !Printer ) {
1492 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1493 "handle we created for printer %s\n", r->in.printername));
1494 close_printer_handle(p, r->out.handle);
1495 ZERO_STRUCTP(r->out.handle);
1496 return WERR_INVALID_PARAM;
1500 * First case: the user is opening the print server:
1502 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1503 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1505 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1506 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1507 * or if the user is listed in the smb.conf printer admin parameter.
1509 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1510 * client view printer folder, but does not show the MSAPW.
1512 * Note: this test needs code to check access rights here too. Jeremy
1513 * could you look at this?
1515 * Second case: the user is opening a printer:
1516 * NT doesn't let us connect to a printer if the connecting user
1517 * doesn't have print permission.
1519 * Third case: user is opening a Port Monitor
1520 * access checks same as opening a handle to the print server.
1523 switch (Printer->printer_type )
1525 case SPLHND_SERVER:
1526 case SPLHND_PORTMON_TCP:
1527 case SPLHND_PORTMON_LOCAL:
1528 /* Printserver handles use global struct... */
1530 snum = -1;
1532 /* Map standard access rights to object specific access rights */
1534 se_map_standard(&r->in.access_mask,
1535 &printserver_std_mapping);
1537 /* Deny any object specific bits that don't apply to print
1538 servers (i.e printer and job specific bits) */
1540 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1542 if (r->in.access_mask &
1543 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1544 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1545 close_printer_handle(p, r->out.handle);
1546 ZERO_STRUCTP(r->out.handle);
1547 return WERR_ACCESS_DENIED;
1550 /* Allow admin access */
1552 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1554 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1556 if (!lp_ms_add_printer_wizard()) {
1557 close_printer_handle(p, r->out.handle);
1558 ZERO_STRUCTP(r->out.handle);
1559 return WERR_ACCESS_DENIED;
1562 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1563 and not a printer admin, then fail */
1565 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1566 !user_has_privileges(p->server_info->ptok,
1567 &se_printop ) &&
1568 !token_contains_name_in_list(
1569 uidtoname(p->server_info->utok.uid),
1570 NULL, NULL,
1571 p->server_info->ptok,
1572 lp_printer_admin(snum))) {
1573 close_printer_handle(p, r->out.handle);
1574 ZERO_STRUCTP(r->out.handle);
1575 return WERR_ACCESS_DENIED;
1578 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1580 else
1582 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1585 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1586 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1588 /* We fall through to return WERR_OK */
1589 break;
1591 case SPLHND_PRINTER:
1592 /* NT doesn't let us connect to a printer if the connecting user
1593 doesn't have print permission. */
1595 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1596 close_printer_handle(p, r->out.handle);
1597 ZERO_STRUCTP(r->out.handle);
1598 return WERR_BADFID;
1601 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1602 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1605 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1607 /* map an empty access mask to the minimum access mask */
1608 if (r->in.access_mask == 0x0)
1609 r->in.access_mask = PRINTER_ACCESS_USE;
1612 * If we are not serving the printer driver for this printer,
1613 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1614 * will keep NT clients happy --jerry
1617 if (lp_use_client_driver(snum)
1618 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1620 r->in.access_mask = PRINTER_ACCESS_USE;
1623 /* check smb.conf parameters and the the sec_desc */
1625 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1626 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1627 ZERO_STRUCTP(r->out.handle);
1628 return WERR_ACCESS_DENIED;
1631 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1632 p->server_info->ptok, snum) ||
1633 !print_access_check(p->server_info, snum,
1634 r->in.access_mask)) {
1635 DEBUG(3, ("access DENIED for printer open\n"));
1636 close_printer_handle(p, r->out.handle);
1637 ZERO_STRUCTP(r->out.handle);
1638 return WERR_ACCESS_DENIED;
1641 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1642 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1643 close_printer_handle(p, r->out.handle);
1644 ZERO_STRUCTP(r->out.handle);
1645 return WERR_ACCESS_DENIED;
1648 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1649 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1650 else
1651 r->in.access_mask = PRINTER_ACCESS_USE;
1653 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1654 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1656 break;
1658 default:
1659 /* sanity check to prevent programmer error */
1660 ZERO_STRUCTP(r->out.handle);
1661 return WERR_BADFID;
1664 Printer->access_granted = r->in.access_mask;
1667 * If the client sent a devmode in the OpenPrinter() call, then
1668 * save it here in case we get a job submission on this handle
1671 if ((Printer->printer_type != SPLHND_SERVER) &&
1672 r->in.devmode_ctr.devmode) {
1673 convert_devicemode(Printer->sharename,
1674 r->in.devmode_ctr.devmode,
1675 &Printer->nt_devmode);
1678 #if 0 /* JERRY -- I'm doubtful this is really effective */
1679 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1680 optimization in Windows 2000 clients --jerry */
1682 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1683 && (RA_WIN2K == get_remote_arch()) )
1685 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1686 sys_usleep( 500000 );
1688 #endif
1690 return WERR_OK;
1693 /****************************************************************************
1694 ****************************************************************************/
1696 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1697 NT_PRINTER_INFO_LEVEL_2 *d)
1699 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1701 if (!r || !d) {
1702 return false;
1705 d->attributes = r->attributes;
1706 d->priority = r->priority;
1707 d->default_priority = r->defaultpriority;
1708 d->starttime = r->starttime;
1709 d->untiltime = r->untiltime;
1710 d->status = r->status;
1711 d->cjobs = r->cjobs;
1713 fstrcpy(d->servername, r->servername);
1714 fstrcpy(d->printername, r->printername);
1715 fstrcpy(d->sharename, r->sharename);
1716 fstrcpy(d->portname, r->portname);
1717 fstrcpy(d->drivername, r->drivername);
1718 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1719 fstrcpy(d->location, r->location);
1720 fstrcpy(d->sepfile, r->sepfile);
1721 fstrcpy(d->printprocessor, r->printprocessor);
1722 fstrcpy(d->datatype, r->datatype);
1723 fstrcpy(d->parameters, r->parameters);
1725 return true;
1728 /****************************************************************************
1729 ****************************************************************************/
1731 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1732 NT_PRINTER_INFO_LEVEL *printer)
1734 bool ret;
1736 switch (info_ctr->level) {
1737 case 2:
1738 /* allocate memory if needed. Messy because
1739 convert_printer_info is used to update an existing
1740 printer or build a new one */
1742 if (!printer->info_2) {
1743 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1744 if (!printer->info_2) {
1745 DEBUG(0,("convert_printer_info: "
1746 "talloc() failed!\n"));
1747 return false;
1751 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1752 printer->info_2);
1753 printer->info_2->setuptime = time(NULL);
1754 return ret;
1757 return false;
1760 /****************************************************************
1761 _spoolss_ClosePrinter
1762 ****************************************************************/
1764 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1765 struct spoolss_ClosePrinter *r)
1767 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1769 if (Printer && Printer->document_started) {
1770 struct spoolss_EndDocPrinter e;
1772 e.in.handle = r->in.handle;
1774 _spoolss_EndDocPrinter(p, &e);
1777 if (!close_printer_handle(p, r->in.handle))
1778 return WERR_BADFID;
1780 /* clear the returned printer handle. Observed behavior
1781 from Win2k server. Don't think this really matters.
1782 Previous code just copied the value of the closed
1783 handle. --jerry */
1785 ZERO_STRUCTP(r->out.handle);
1787 return WERR_OK;
1790 /****************************************************************
1791 _spoolss_DeletePrinter
1792 ****************************************************************/
1794 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1795 struct spoolss_DeletePrinter *r)
1797 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1798 WERROR result;
1800 if (Printer && Printer->document_started) {
1801 struct spoolss_EndDocPrinter e;
1803 e.in.handle = r->in.handle;
1805 _spoolss_EndDocPrinter(p, &e);
1808 result = delete_printer_handle(p, r->in.handle);
1810 update_c_setprinter(false);
1812 return result;
1815 /*******************************************************************
1816 * static function to lookup the version id corresponding to an
1817 * long architecture string
1818 ******************************************************************/
1820 static const struct print_architecture_table_node archi_table[]= {
1822 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1823 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1824 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1825 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1826 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1827 {"Windows IA64", SPL_ARCH_IA64, 3 },
1828 {"Windows x64", SPL_ARCH_X64, 3 },
1829 {NULL, "", -1 }
1832 static int get_version_id(const char *arch)
1834 int i;
1836 for (i=0; archi_table[i].long_archi != NULL; i++)
1838 if (strcmp(arch, archi_table[i].long_archi) == 0)
1839 return (archi_table[i].version);
1842 return -1;
1845 /****************************************************************
1846 _spoolss_DeletePrinterDriver
1847 ****************************************************************/
1849 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1850 struct spoolss_DeletePrinterDriver *r)
1853 struct spoolss_DriverInfo8 *info = NULL;
1854 struct spoolss_DriverInfo8 *info_win2k = NULL;
1855 int version;
1856 WERROR status;
1857 WERROR status_win2k = WERR_ACCESS_DENIED;
1858 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1860 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1861 and not a printer admin, then fail */
1863 if ( (p->server_info->utok.uid != sec_initial_uid())
1864 && !user_has_privileges(p->server_info->ptok, &se_printop )
1865 && !token_contains_name_in_list(
1866 uidtoname(p->server_info->utok.uid), NULL,
1867 NULL, p->server_info->ptok,
1868 lp_printer_admin(-1)) )
1870 return WERR_ACCESS_DENIED;
1873 /* check that we have a valid driver name first */
1875 if ((version = get_version_id(r->in.architecture)) == -1)
1876 return WERR_INVALID_ENVIRONMENT;
1878 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1879 r->in.architecture,
1880 version)))
1882 /* try for Win2k driver if "Windows NT x86" */
1884 if ( version == 2 ) {
1885 version = 3;
1886 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1887 &info,
1888 r->in.driver,
1889 r->in.architecture,
1890 version))) {
1891 status = WERR_UNKNOWN_PRINTER_DRIVER;
1892 goto done;
1895 /* otherwise it was a failure */
1896 else {
1897 status = WERR_UNKNOWN_PRINTER_DRIVER;
1898 goto done;
1903 if (printer_driver_in_use(info)) {
1904 status = WERR_PRINTER_DRIVER_IN_USE;
1905 goto done;
1908 if ( version == 2 )
1910 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1911 &info_win2k,
1912 r->in.driver,
1913 r->in.architecture, 3)))
1915 /* if we get to here, we now have 2 driver info structures to remove */
1916 /* remove the Win2k driver first*/
1918 status_win2k = delete_printer_driver(
1919 p, info_win2k, 3, false);
1920 free_a_printer_driver(info_win2k);
1922 /* this should not have failed---if it did, report to client */
1923 if ( !W_ERROR_IS_OK(status_win2k) )
1925 status = status_win2k;
1926 goto done;
1931 status = delete_printer_driver(p, info, version, false);
1933 /* if at least one of the deletes succeeded return OK */
1935 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1936 status = WERR_OK;
1938 done:
1939 free_a_printer_driver(info);
1941 return status;
1944 /****************************************************************
1945 _spoolss_DeletePrinterDriverEx
1946 ****************************************************************/
1948 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1949 struct spoolss_DeletePrinterDriverEx *r)
1951 struct spoolss_DriverInfo8 *info = NULL;
1952 struct spoolss_DriverInfo8 *info_win2k = NULL;
1953 int version;
1954 bool delete_files;
1955 WERROR status;
1956 WERROR status_win2k = WERR_ACCESS_DENIED;
1957 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1959 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1960 and not a printer admin, then fail */
1962 if ( (p->server_info->utok.uid != sec_initial_uid())
1963 && !user_has_privileges(p->server_info->ptok, &se_printop )
1964 && !token_contains_name_in_list(
1965 uidtoname(p->server_info->utok.uid), NULL, NULL,
1966 p->server_info->ptok, lp_printer_admin(-1)) )
1968 return WERR_ACCESS_DENIED;
1971 /* check that we have a valid driver name first */
1972 if ((version = get_version_id(r->in.architecture)) == -1) {
1973 /* this is what NT returns */
1974 return WERR_INVALID_ENVIRONMENT;
1977 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1978 version = r->in.version;
1980 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1981 r->in.architecture, version);
1983 if ( !W_ERROR_IS_OK(status) )
1986 * if the client asked for a specific version,
1987 * or this is something other than Windows NT x86,
1988 * then we've failed
1991 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1992 goto done;
1994 /* try for Win2k driver if "Windows NT x86" */
1996 version = 3;
1997 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1998 r->in.architecture,
1999 version))) {
2000 status = WERR_UNKNOWN_PRINTER_DRIVER;
2001 goto done;
2005 if (printer_driver_in_use(info)) {
2006 status = WERR_PRINTER_DRIVER_IN_USE;
2007 goto done;
2011 * we have a couple of cases to consider.
2012 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2013 * then the delete should fail if **any** files overlap with
2014 * other drivers
2015 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2016 * non-overlapping files
2017 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2018 * is set, the do not delete any files
2019 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2022 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2024 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2026 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2027 /* no idea of the correct error here */
2028 status = WERR_ACCESS_DENIED;
2029 goto done;
2033 /* also check for W32X86/3 if necessary; maybe we already have? */
2035 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2036 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2037 r->in.driver,
2038 r->in.architecture, 3)))
2041 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2042 /* no idea of the correct error here */
2043 free_a_printer_driver(info_win2k);
2044 status = WERR_ACCESS_DENIED;
2045 goto done;
2048 /* if we get to here, we now have 2 driver info structures to remove */
2049 /* remove the Win2k driver first*/
2051 status_win2k = delete_printer_driver(
2052 p, info_win2k, 3, delete_files);
2053 free_a_printer_driver(info_win2k);
2055 /* this should not have failed---if it did, report to client */
2057 if ( !W_ERROR_IS_OK(status_win2k) )
2058 goto done;
2062 status = delete_printer_driver(p, info, version, delete_files);
2064 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2065 status = WERR_OK;
2066 done:
2067 free_a_printer_driver(info);
2069 return status;
2073 /****************************************************************************
2074 Internal routine for removing printerdata
2075 ***************************************************************************/
2077 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2079 return delete_printer_data( printer->info_2, key, value );
2082 /****************************************************************************
2083 Internal routine for storing printerdata
2084 ***************************************************************************/
2086 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2087 const char *key, const char *value,
2088 uint32_t type, uint8_t *data, int real_len)
2090 /* the registry objects enforce uniqueness based on value name */
2092 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2095 /********************************************************************
2096 GetPrinterData on a printer server Handle.
2097 ********************************************************************/
2099 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2100 const char *value,
2101 enum winreg_Type *type,
2102 union spoolss_PrinterData *data)
2104 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2106 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2107 *type = REG_DWORD;
2108 data->value = 0x00;
2109 return WERR_OK;
2112 if (!StrCaseCmp(value, "BeepEnabled")) {
2113 *type = REG_DWORD;
2114 data->value = 0x00;
2115 return WERR_OK;
2118 if (!StrCaseCmp(value, "EventLog")) {
2119 *type = REG_DWORD;
2120 /* formally was 0x1b */
2121 data->value = 0x00;
2122 return WERR_OK;
2125 if (!StrCaseCmp(value, "NetPopup")) {
2126 *type = REG_DWORD;
2127 data->value = 0x00;
2128 return WERR_OK;
2131 if (!StrCaseCmp(value, "MajorVersion")) {
2132 *type = REG_DWORD;
2134 /* Windows NT 4.0 seems to not allow uploading of drivers
2135 to a server that reports 0x3 as the MajorVersion.
2136 need to investigate more how Win2k gets around this .
2137 -- jerry */
2139 if (RA_WINNT == get_remote_arch()) {
2140 data->value = 0x02;
2141 } else {
2142 data->value = 0x03;
2145 return WERR_OK;
2148 if (!StrCaseCmp(value, "MinorVersion")) {
2149 *type = REG_DWORD;
2150 data->value = 0x00;
2151 return WERR_OK;
2154 /* REG_BINARY
2155 * uint32_t size = 0x114
2156 * uint32_t major = 5
2157 * uint32_t minor = [0|1]
2158 * uint32_t build = [2195|2600]
2159 * extra unicode string = e.g. "Service Pack 3"
2161 if (!StrCaseCmp(value, "OSVersion")) {
2162 DATA_BLOB blob;
2163 enum ndr_err_code ndr_err;
2164 struct spoolss_OSVersion os;
2166 os.major = 5; /* Windows 2000 == 5.0 */
2167 os.minor = 0;
2168 os.build = 2195; /* build */
2169 os.extra_string = ""; /* leave extra string empty */
2171 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2172 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2173 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2174 return WERR_GENERAL_FAILURE;
2177 *type = REG_BINARY;
2178 data->binary = blob;
2180 return WERR_OK;
2184 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2185 *type = REG_SZ;
2187 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2188 W_ERROR_HAVE_NO_MEMORY(data->string);
2190 return WERR_OK;
2193 if (!StrCaseCmp(value, "Architecture")) {
2194 *type = REG_SZ;
2195 data->string = talloc_strdup(mem_ctx,
2196 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2197 W_ERROR_HAVE_NO_MEMORY(data->string);
2199 return WERR_OK;
2202 if (!StrCaseCmp(value, "DsPresent")) {
2203 *type = REG_DWORD;
2205 /* only show the publish check box if we are a
2206 member of a AD domain */
2208 if (lp_security() == SEC_ADS) {
2209 data->value = 0x01;
2210 } else {
2211 data->value = 0x00;
2213 return WERR_OK;
2216 if (!StrCaseCmp(value, "DNSMachineName")) {
2217 const char *hostname = get_mydnsfullname();
2219 if (!hostname) {
2220 return WERR_BADFILE;
2223 *type = REG_SZ;
2224 data->string = talloc_strdup(mem_ctx, hostname);
2225 W_ERROR_HAVE_NO_MEMORY(data->string);
2227 return WERR_OK;
2230 *type = REG_NONE;
2232 return WERR_INVALID_PARAM;
2235 /****************************************************************
2236 _spoolss_GetPrinterData
2237 ****************************************************************/
2239 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2240 struct spoolss_GetPrinterData *r)
2242 struct spoolss_GetPrinterDataEx r2;
2244 r2.in.handle = r->in.handle;
2245 r2.in.key_name = "PrinterDriverData";
2246 r2.in.value_name = r->in.value_name;
2247 r2.in.offered = r->in.offered;
2248 r2.out.type = r->out.type;
2249 r2.out.data = r->out.data;
2250 r2.out.needed = r->out.needed;
2252 return _spoolss_GetPrinterDataEx(p, &r2);
2255 /*********************************************************
2256 Connect to the client machine.
2257 **********************************************************/
2259 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2260 struct sockaddr_storage *client_ss, const char *remote_machine)
2262 NTSTATUS ret;
2263 struct cli_state *the_cli;
2264 struct sockaddr_storage rm_addr;
2265 char addr[INET6_ADDRSTRLEN];
2267 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2268 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2269 remote_machine));
2270 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2271 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2272 return false;
2274 print_sockaddr(addr, sizeof(addr), &rm_addr);
2275 } else {
2276 rm_addr = *client_ss;
2277 print_sockaddr(addr, sizeof(addr), &rm_addr);
2278 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2279 addr));
2282 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2283 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2284 addr));
2285 return false;
2288 /* setup the connection */
2289 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2290 &rm_addr, 0, "IPC$", "IPC",
2291 "", /* username */
2292 "", /* domain */
2293 "", /* password */
2294 0, lp_client_signing(), NULL );
2296 if ( !NT_STATUS_IS_OK( ret ) ) {
2297 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2298 remote_machine ));
2299 return false;
2302 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2303 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2304 cli_shutdown(the_cli);
2305 return false;
2309 * Ok - we have an anonymous connection to the IPC$ share.
2310 * Now start the NT Domain stuff :-).
2313 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2314 if (!NT_STATUS_IS_OK(ret)) {
2315 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2316 remote_machine, nt_errstr(ret)));
2317 cli_shutdown(the_cli);
2318 return false;
2321 return true;
2324 /***************************************************************************
2325 Connect to the client.
2326 ****************************************************************************/
2328 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2329 uint32_t localprinter, uint32_t type,
2330 struct policy_handle *handle,
2331 struct sockaddr_storage *client_ss)
2333 WERROR result;
2334 NTSTATUS status;
2337 * If it's the first connection, contact the client
2338 * and connect to the IPC$ share anonymously
2340 if (smb_connections==0) {
2341 fstring unix_printer;
2343 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2345 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2346 return false;
2348 messaging_register(smbd_messaging_context(), NULL,
2349 MSG_PRINTER_NOTIFY2,
2350 receive_notify2_message_list);
2351 /* Tell the connections db we're now interested in printer
2352 * notify messages. */
2353 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2357 * Tell the specific printing tdb we want messages for this printer
2358 * by registering our PID.
2361 if (!print_notify_register_pid(snum))
2362 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2364 smb_connections++;
2366 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2367 printer,
2368 localprinter,
2369 type,
2371 NULL,
2372 handle,
2373 &result);
2374 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2375 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2376 win_errstr(result)));
2378 return (W_ERROR_IS_OK(result));
2381 /****************************************************************
2382 ****************************************************************/
2384 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2385 const struct spoolss_NotifyOption *r)
2387 struct spoolss_NotifyOption *option;
2388 uint32_t i,k;
2390 if (!r) {
2391 return NULL;
2394 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2395 if (!option) {
2396 return NULL;
2399 *option = *r;
2401 if (!option->count) {
2402 return option;
2405 option->types = talloc_zero_array(option,
2406 struct spoolss_NotifyOptionType, option->count);
2407 if (!option->types) {
2408 talloc_free(option);
2409 return NULL;
2412 for (i=0; i < option->count; i++) {
2413 option->types[i] = r->types[i];
2415 if (option->types[i].count) {
2416 option->types[i].fields = talloc_zero_array(option,
2417 union spoolss_Field, option->types[i].count);
2418 if (!option->types[i].fields) {
2419 talloc_free(option);
2420 return NULL;
2422 for (k=0; k<option->types[i].count; k++) {
2423 option->types[i].fields[k] =
2424 r->types[i].fields[k];
2429 return option;
2432 /****************************************************************
2433 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2435 * before replying OK: status=0 a rpc call is made to the workstation
2436 * asking ReplyOpenPrinter
2438 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2439 * called from api_spoolss_rffpcnex
2440 ****************************************************************/
2442 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2443 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2445 int snum = -1;
2446 struct spoolss_NotifyOption *option = r->in.notify_options;
2447 struct sockaddr_storage client_ss;
2449 /* store the notify value in the printer struct */
2451 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2453 if (!Printer) {
2454 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2455 "Invalid handle (%s:%u:%u).\n",
2456 OUR_HANDLE(r->in.handle)));
2457 return WERR_BADFID;
2460 Printer->notify.flags = r->in.flags;
2461 Printer->notify.options = r->in.options;
2462 Printer->notify.printerlocal = r->in.printer_local;
2464 TALLOC_FREE(Printer->notify.option);
2465 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2467 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2469 /* Connect to the client machine and send a ReplyOpenPrinter */
2471 if ( Printer->printer_type == SPLHND_SERVER)
2472 snum = -1;
2473 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2474 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2475 return WERR_BADFID;
2477 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2478 "client_address is %s\n", p->client_address));
2480 if (!interpret_string_addr(&client_ss, p->client_address,
2481 AI_NUMERICHOST)) {
2482 return WERR_SERVER_UNAVAILABLE;
2485 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2486 Printer->notify.printerlocal, 1,
2487 &Printer->notify.client_hnd, &client_ss))
2488 return WERR_SERVER_UNAVAILABLE;
2490 Printer->notify.client_connected = true;
2492 return WERR_OK;
2495 /*******************************************************************
2496 * fill a notify_info_data with the servername
2497 ********************************************************************/
2499 static void spoolss_notify_server_name(int snum,
2500 struct spoolss_Notify *data,
2501 print_queue_struct *queue,
2502 NT_PRINTER_INFO_LEVEL *printer,
2503 TALLOC_CTX *mem_ctx)
2505 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2508 /*******************************************************************
2509 * fill a notify_info_data with the printername (not including the servername).
2510 ********************************************************************/
2512 static void spoolss_notify_printer_name(int snum,
2513 struct spoolss_Notify *data,
2514 print_queue_struct *queue,
2515 NT_PRINTER_INFO_LEVEL *printer,
2516 TALLOC_CTX *mem_ctx)
2518 /* the notify name should not contain the \\server\ part */
2519 char *p = strrchr(printer->info_2->printername, '\\');
2521 if (!p) {
2522 p = printer->info_2->printername;
2523 } else {
2524 p++;
2527 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2530 /*******************************************************************
2531 * fill a notify_info_data with the servicename
2532 ********************************************************************/
2534 static void spoolss_notify_share_name(int snum,
2535 struct spoolss_Notify *data,
2536 print_queue_struct *queue,
2537 NT_PRINTER_INFO_LEVEL *printer,
2538 TALLOC_CTX *mem_ctx)
2540 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2543 /*******************************************************************
2544 * fill a notify_info_data with the port name
2545 ********************************************************************/
2547 static void spoolss_notify_port_name(int snum,
2548 struct spoolss_Notify *data,
2549 print_queue_struct *queue,
2550 NT_PRINTER_INFO_LEVEL *printer,
2551 TALLOC_CTX *mem_ctx)
2553 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2556 /*******************************************************************
2557 * fill a notify_info_data with the printername
2558 * but it doesn't exist, have to see what to do
2559 ********************************************************************/
2561 static void spoolss_notify_driver_name(int snum,
2562 struct spoolss_Notify *data,
2563 print_queue_struct *queue,
2564 NT_PRINTER_INFO_LEVEL *printer,
2565 TALLOC_CTX *mem_ctx)
2567 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2570 /*******************************************************************
2571 * fill a notify_info_data with the comment
2572 ********************************************************************/
2574 static void spoolss_notify_comment(int snum,
2575 struct spoolss_Notify *data,
2576 print_queue_struct *queue,
2577 NT_PRINTER_INFO_LEVEL *printer,
2578 TALLOC_CTX *mem_ctx)
2580 char *p;
2582 if (*printer->info_2->comment == '\0') {
2583 p = lp_comment(snum);
2584 } else {
2585 p = printer->info_2->comment;
2588 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2591 /*******************************************************************
2592 * fill a notify_info_data with the comment
2593 * location = "Room 1, floor 2, building 3"
2594 ********************************************************************/
2596 static void spoolss_notify_location(int snum,
2597 struct spoolss_Notify *data,
2598 print_queue_struct *queue,
2599 NT_PRINTER_INFO_LEVEL *printer,
2600 TALLOC_CTX *mem_ctx)
2602 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2605 /*******************************************************************
2606 * fill a notify_info_data with the device mode
2607 * jfm:xxxx don't to it for know but that's a real problem !!!
2608 ********************************************************************/
2610 static void spoolss_notify_devmode(int snum,
2611 struct spoolss_Notify *data,
2612 print_queue_struct *queue,
2613 NT_PRINTER_INFO_LEVEL *printer,
2614 TALLOC_CTX *mem_ctx)
2616 /* for a dummy implementation we have to zero the fields */
2617 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2620 /*******************************************************************
2621 * fill a notify_info_data with the separator file name
2622 ********************************************************************/
2624 static void spoolss_notify_sepfile(int snum,
2625 struct spoolss_Notify *data,
2626 print_queue_struct *queue,
2627 NT_PRINTER_INFO_LEVEL *printer,
2628 TALLOC_CTX *mem_ctx)
2630 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2633 /*******************************************************************
2634 * fill a notify_info_data with the print processor
2635 * jfm:xxxx return always winprint to indicate we don't do anything to it
2636 ********************************************************************/
2638 static void spoolss_notify_print_processor(int snum,
2639 struct spoolss_Notify *data,
2640 print_queue_struct *queue,
2641 NT_PRINTER_INFO_LEVEL *printer,
2642 TALLOC_CTX *mem_ctx)
2644 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2647 /*******************************************************************
2648 * fill a notify_info_data with the print processor options
2649 * jfm:xxxx send an empty string
2650 ********************************************************************/
2652 static void spoolss_notify_parameters(int snum,
2653 struct spoolss_Notify *data,
2654 print_queue_struct *queue,
2655 NT_PRINTER_INFO_LEVEL *printer,
2656 TALLOC_CTX *mem_ctx)
2658 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2661 /*******************************************************************
2662 * fill a notify_info_data with the data type
2663 * jfm:xxxx always send RAW as data type
2664 ********************************************************************/
2666 static void spoolss_notify_datatype(int snum,
2667 struct spoolss_Notify *data,
2668 print_queue_struct *queue,
2669 NT_PRINTER_INFO_LEVEL *printer,
2670 TALLOC_CTX *mem_ctx)
2672 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2675 /*******************************************************************
2676 * fill a notify_info_data with the security descriptor
2677 * jfm:xxxx send an null pointer to say no security desc
2678 * have to implement security before !
2679 ********************************************************************/
2681 static void spoolss_notify_security_desc(int snum,
2682 struct spoolss_Notify *data,
2683 print_queue_struct *queue,
2684 NT_PRINTER_INFO_LEVEL *printer,
2685 TALLOC_CTX *mem_ctx)
2687 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2688 printer->info_2->secdesc_buf->sd_size,
2689 printer->info_2->secdesc_buf->sd);
2692 /*******************************************************************
2693 * fill a notify_info_data with the attributes
2694 * jfm:xxxx a samba printer is always shared
2695 ********************************************************************/
2697 static void spoolss_notify_attributes(int snum,
2698 struct spoolss_Notify *data,
2699 print_queue_struct *queue,
2700 NT_PRINTER_INFO_LEVEL *printer,
2701 TALLOC_CTX *mem_ctx)
2703 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2706 /*******************************************************************
2707 * fill a notify_info_data with the priority
2708 ********************************************************************/
2710 static void spoolss_notify_priority(int snum,
2711 struct spoolss_Notify *data,
2712 print_queue_struct *queue,
2713 NT_PRINTER_INFO_LEVEL *printer,
2714 TALLOC_CTX *mem_ctx)
2716 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2719 /*******************************************************************
2720 * fill a notify_info_data with the default priority
2721 ********************************************************************/
2723 static void spoolss_notify_default_priority(int snum,
2724 struct spoolss_Notify *data,
2725 print_queue_struct *queue,
2726 NT_PRINTER_INFO_LEVEL *printer,
2727 TALLOC_CTX *mem_ctx)
2729 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2732 /*******************************************************************
2733 * fill a notify_info_data with the start time
2734 ********************************************************************/
2736 static void spoolss_notify_start_time(int snum,
2737 struct spoolss_Notify *data,
2738 print_queue_struct *queue,
2739 NT_PRINTER_INFO_LEVEL *printer,
2740 TALLOC_CTX *mem_ctx)
2742 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2745 /*******************************************************************
2746 * fill a notify_info_data with the until time
2747 ********************************************************************/
2749 static void spoolss_notify_until_time(int snum,
2750 struct spoolss_Notify *data,
2751 print_queue_struct *queue,
2752 NT_PRINTER_INFO_LEVEL *printer,
2753 TALLOC_CTX *mem_ctx)
2755 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2758 /*******************************************************************
2759 * fill a notify_info_data with the status
2760 ********************************************************************/
2762 static void spoolss_notify_status(int snum,
2763 struct spoolss_Notify *data,
2764 print_queue_struct *queue,
2765 NT_PRINTER_INFO_LEVEL *printer,
2766 TALLOC_CTX *mem_ctx)
2768 print_status_struct status;
2770 print_queue_length(snum, &status);
2771 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2774 /*******************************************************************
2775 * fill a notify_info_data with the number of jobs queued
2776 ********************************************************************/
2778 static void spoolss_notify_cjobs(int snum,
2779 struct spoolss_Notify *data,
2780 print_queue_struct *queue,
2781 NT_PRINTER_INFO_LEVEL *printer,
2782 TALLOC_CTX *mem_ctx)
2784 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2787 /*******************************************************************
2788 * fill a notify_info_data with the average ppm
2789 ********************************************************************/
2791 static void spoolss_notify_average_ppm(int snum,
2792 struct spoolss_Notify *data,
2793 print_queue_struct *queue,
2794 NT_PRINTER_INFO_LEVEL *printer,
2795 TALLOC_CTX *mem_ctx)
2797 /* always respond 8 pages per minutes */
2798 /* a little hard ! */
2799 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2802 /*******************************************************************
2803 * fill a notify_info_data with username
2804 ********************************************************************/
2806 static void spoolss_notify_username(int snum,
2807 struct spoolss_Notify *data,
2808 print_queue_struct *queue,
2809 NT_PRINTER_INFO_LEVEL *printer,
2810 TALLOC_CTX *mem_ctx)
2812 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2815 /*******************************************************************
2816 * fill a notify_info_data with job status
2817 ********************************************************************/
2819 static void spoolss_notify_job_status(int snum,
2820 struct spoolss_Notify *data,
2821 print_queue_struct *queue,
2822 NT_PRINTER_INFO_LEVEL *printer,
2823 TALLOC_CTX *mem_ctx)
2825 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2828 /*******************************************************************
2829 * fill a notify_info_data with job name
2830 ********************************************************************/
2832 static void spoolss_notify_job_name(int snum,
2833 struct spoolss_Notify *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2838 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2841 /*******************************************************************
2842 * fill a notify_info_data with job status
2843 ********************************************************************/
2845 static void spoolss_notify_job_status_string(int snum,
2846 struct spoolss_Notify *data,
2847 print_queue_struct *queue,
2848 NT_PRINTER_INFO_LEVEL *printer,
2849 TALLOC_CTX *mem_ctx)
2852 * Now we're returning job status codes we just return a "" here. JRA.
2855 const char *p = "";
2857 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2858 p = "unknown";
2860 switch (queue->status) {
2861 case LPQ_QUEUED:
2862 p = "Queued";
2863 break;
2864 case LPQ_PAUSED:
2865 p = ""; /* NT provides the paused string */
2866 break;
2867 case LPQ_SPOOLING:
2868 p = "Spooling";
2869 break;
2870 case LPQ_PRINTING:
2871 p = "Printing";
2872 break;
2874 #endif /* NO LONGER NEEDED. */
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2879 /*******************************************************************
2880 * fill a notify_info_data with job time
2881 ********************************************************************/
2883 static void spoolss_notify_job_time(int snum,
2884 struct spoolss_Notify *data,
2885 print_queue_struct *queue,
2886 NT_PRINTER_INFO_LEVEL *printer,
2887 TALLOC_CTX *mem_ctx)
2889 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2892 /*******************************************************************
2893 * fill a notify_info_data with job size
2894 ********************************************************************/
2896 static void spoolss_notify_job_size(int snum,
2897 struct spoolss_Notify *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2902 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2905 /*******************************************************************
2906 * fill a notify_info_data with page info
2907 ********************************************************************/
2908 static void spoolss_notify_total_pages(int snum,
2909 struct spoolss_Notify *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2914 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2917 /*******************************************************************
2918 * fill a notify_info_data with pages printed info.
2919 ********************************************************************/
2920 static void spoolss_notify_pages_printed(int snum,
2921 struct spoolss_Notify *data,
2922 print_queue_struct *queue,
2923 NT_PRINTER_INFO_LEVEL *printer,
2924 TALLOC_CTX *mem_ctx)
2926 /* Add code when back-end tracks this */
2927 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2930 /*******************************************************************
2931 Fill a notify_info_data with job position.
2932 ********************************************************************/
2934 static void spoolss_notify_job_position(int snum,
2935 struct spoolss_Notify *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer,
2938 TALLOC_CTX *mem_ctx)
2940 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2943 /*******************************************************************
2944 Fill a notify_info_data with submitted time.
2945 ********************************************************************/
2947 static void spoolss_notify_submitted_time(int snum,
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 NT_PRINTER_INFO_LEVEL *printer,
2951 TALLOC_CTX *mem_ctx)
2953 data->data.string.string = NULL;
2954 data->data.string.size = 0;
2956 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2957 &data->data.string.string,
2958 &data->data.string.size);
2962 struct s_notify_info_data_table
2964 enum spoolss_NotifyType type;
2965 uint16_t field;
2966 const char *name;
2967 enum spoolss_NotifyTable variable_type;
2968 void (*fn) (int snum, struct spoolss_Notify *data,
2969 print_queue_struct *queue,
2970 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2973 /* A table describing the various print notification constants and
2974 whether the notification data is a pointer to a variable sized
2975 buffer, a one value uint32_t or a two value uint32_t. */
2977 static const struct s_notify_info_data_table notify_info_data_table[] =
2979 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2980 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2981 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2982 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2983 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2984 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2985 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2986 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2987 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2988 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3003 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3004 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3005 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3006 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3007 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3008 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3009 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3010 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3011 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3012 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3013 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3014 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3015 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3016 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3017 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3018 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3019 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3020 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3021 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3022 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3023 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3024 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3025 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3026 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3027 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3030 /*******************************************************************
3031 Return the variable_type of info_data structure.
3032 ********************************************************************/
3034 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3035 uint16_t field)
3037 int i=0;
3039 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3040 if ( (notify_info_data_table[i].type == type) &&
3041 (notify_info_data_table[i].field == field) ) {
3042 return notify_info_data_table[i].variable_type;
3046 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3048 return 0;
3051 /****************************************************************************
3052 ****************************************************************************/
3054 static bool search_notify(enum spoolss_NotifyType type,
3055 uint16_t field,
3056 int *value)
3058 int i;
3060 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3061 if (notify_info_data_table[i].type == type &&
3062 notify_info_data_table[i].field == field &&
3063 notify_info_data_table[i].fn != NULL) {
3064 *value = i;
3065 return true;
3069 return false;
3072 /****************************************************************************
3073 ****************************************************************************/
3075 void construct_info_data(struct spoolss_Notify *info_data,
3076 enum spoolss_NotifyType type,
3077 uint16_t field,
3078 int id)
3080 info_data->type = type;
3081 info_data->field.field = field;
3082 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3083 info_data->job_id = id;
3086 /*******************************************************************
3088 * fill a notify_info struct with info asked
3090 ********************************************************************/
3092 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3093 struct spoolss_NotifyInfo *info,
3094 int snum,
3095 const struct spoolss_NotifyOptionType *option_type,
3096 uint32_t id,
3097 TALLOC_CTX *mem_ctx)
3099 int field_num,j;
3100 enum spoolss_NotifyType type;
3101 uint16_t field;
3103 struct spoolss_Notify *current_data;
3104 NT_PRINTER_INFO_LEVEL *printer = NULL;
3105 print_queue_struct *queue=NULL;
3107 type = option_type->type;
3109 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3110 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3111 option_type->count, lp_servicename(snum)));
3113 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3114 return false;
3116 for(field_num=0; field_num < option_type->count; field_num++) {
3117 field = option_type->fields[field_num].field;
3119 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3121 if (!search_notify(type, field, &j) )
3122 continue;
3124 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3125 struct spoolss_Notify,
3126 info->count + 1);
3127 if (info->notifies == NULL) {
3128 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3129 free_a_printer(&printer, 2);
3130 return false;
3133 current_data = &info->notifies[info->count];
3135 construct_info_data(current_data, type, field, id);
3137 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3138 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3140 notify_info_data_table[j].fn(snum, current_data, queue,
3141 printer, mem_ctx);
3143 info->count++;
3146 free_a_printer(&printer, 2);
3147 return true;
3150 /*******************************************************************
3152 * fill a notify_info struct with info asked
3154 ********************************************************************/
3156 static bool construct_notify_jobs_info(print_queue_struct *queue,
3157 struct spoolss_NotifyInfo *info,
3158 NT_PRINTER_INFO_LEVEL *printer,
3159 int snum,
3160 const struct spoolss_NotifyOptionType *option_type,
3161 uint32_t id,
3162 TALLOC_CTX *mem_ctx)
3164 int field_num,j;
3165 enum spoolss_NotifyType type;
3166 uint16_t field;
3167 struct spoolss_Notify *current_data;
3169 DEBUG(4,("construct_notify_jobs_info\n"));
3171 type = option_type->type;
3173 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3174 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3175 option_type->count));
3177 for(field_num=0; field_num<option_type->count; field_num++) {
3178 field = option_type->fields[field_num].field;
3180 if (!search_notify(type, field, &j) )
3181 continue;
3183 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3184 struct spoolss_Notify,
3185 info->count + 1);
3186 if (info->notifies == NULL) {
3187 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3188 return false;
3191 current_data=&(info->notifies[info->count]);
3193 construct_info_data(current_data, type, field, id);
3194 notify_info_data_table[j].fn(snum, current_data, queue,
3195 printer, mem_ctx);
3196 info->count++;
3199 return true;
3203 * JFM: The enumeration is not that simple, it's even non obvious.
3205 * let's take an example: I want to monitor the PRINTER SERVER for
3206 * the printer's name and the number of jobs currently queued.
3207 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3208 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3210 * I have 3 printers on the back of my server.
3212 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3213 * structures.
3214 * Number Data Id
3215 * 1 printer 1 name 1
3216 * 2 printer 1 cjob 1
3217 * 3 printer 2 name 2
3218 * 4 printer 2 cjob 2
3219 * 5 printer 3 name 3
3220 * 6 printer 3 name 3
3222 * that's the print server case, the printer case is even worse.
3225 /*******************************************************************
3227 * enumerate all printers on the printserver
3228 * fill a notify_info struct with info asked
3230 ********************************************************************/
3232 static WERROR printserver_notify_info(pipes_struct *p,
3233 struct policy_handle *hnd,
3234 struct spoolss_NotifyInfo *info,
3235 TALLOC_CTX *mem_ctx)
3237 int snum;
3238 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3239 int n_services=lp_numservices();
3240 int i;
3241 struct spoolss_NotifyOption *option;
3242 struct spoolss_NotifyOptionType option_type;
3244 DEBUG(4,("printserver_notify_info\n"));
3246 if (!Printer)
3247 return WERR_BADFID;
3249 option = Printer->notify.option;
3251 info->version = 2;
3252 info->notifies = NULL;
3253 info->count = 0;
3255 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3256 sending a ffpcn() request first */
3258 if ( !option )
3259 return WERR_BADFID;
3261 for (i=0; i<option->count; i++) {
3262 option_type = option->types[i];
3264 if (option_type.type != PRINTER_NOTIFY_TYPE)
3265 continue;
3267 for (snum=0; snum<n_services; snum++)
3269 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3270 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3274 #if 0
3276 * Debugging information, don't delete.
3279 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3280 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3281 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3283 for (i=0; i<info->count; i++) {
3284 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3285 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3286 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3288 #endif
3290 return WERR_OK;
3293 /*******************************************************************
3295 * fill a notify_info struct with info asked
3297 ********************************************************************/
3299 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3300 struct spoolss_NotifyInfo *info,
3301 TALLOC_CTX *mem_ctx)
3303 int snum;
3304 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3305 int i;
3306 uint32_t id;
3307 struct spoolss_NotifyOption *option;
3308 struct spoolss_NotifyOptionType option_type;
3309 int count,j;
3310 print_queue_struct *queue=NULL;
3311 print_status_struct status;
3313 DEBUG(4,("printer_notify_info\n"));
3315 if (!Printer)
3316 return WERR_BADFID;
3318 option = Printer->notify.option;
3319 id = 0x0;
3321 info->version = 2;
3322 info->notifies = NULL;
3323 info->count = 0;
3325 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3326 sending a ffpcn() request first */
3328 if ( !option )
3329 return WERR_BADFID;
3331 get_printer_snum(p, hnd, &snum, NULL);
3333 for (i=0; i<option->count; i++) {
3334 option_type = option->types[i];
3336 switch (option_type.type) {
3337 case PRINTER_NOTIFY_TYPE:
3338 if(construct_notify_printer_info(Printer, info, snum,
3339 &option_type, id,
3340 mem_ctx))
3341 id--;
3342 break;
3344 case JOB_NOTIFY_TYPE: {
3345 NT_PRINTER_INFO_LEVEL *printer = NULL;
3347 count = print_queue_status(snum, &queue, &status);
3349 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3350 goto done;
3352 for (j=0; j<count; j++) {
3353 construct_notify_jobs_info(&queue[j], info,
3354 printer, snum,
3355 &option_type,
3356 queue[j].job,
3357 mem_ctx);
3360 free_a_printer(&printer, 2);
3362 done:
3363 SAFE_FREE(queue);
3364 break;
3370 * Debugging information, don't delete.
3373 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3374 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3375 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3377 for (i=0; i<info->count; i++) {
3378 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3379 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3380 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3383 return WERR_OK;
3386 /****************************************************************
3387 _spoolss_RouterRefreshPrinterChangeNotify
3388 ****************************************************************/
3390 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3391 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3393 struct spoolss_NotifyInfo *info;
3395 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3396 WERROR result = WERR_BADFID;
3398 /* we always have a spoolss_NotifyInfo struct */
3399 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3400 if (!info) {
3401 result = WERR_NOMEM;
3402 goto done;
3405 *r->out.info = info;
3407 if (!Printer) {
3408 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3409 "Invalid handle (%s:%u:%u).\n",
3410 OUR_HANDLE(r->in.handle)));
3411 goto done;
3414 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3417 * We are now using the change value, and
3418 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3419 * I don't have a global notification system, I'm sending back all the
3420 * informations even when _NOTHING_ has changed.
3423 /* We need to keep track of the change value to send back in
3424 RRPCN replies otherwise our updates are ignored. */
3426 Printer->notify.fnpcn = true;
3428 if (Printer->notify.client_connected) {
3429 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3430 "Saving change value in request [%x]\n",
3431 r->in.change_low));
3432 Printer->notify.change = r->in.change_low;
3435 /* just ignore the spoolss_NotifyOption */
3437 switch (Printer->printer_type) {
3438 case SPLHND_SERVER:
3439 result = printserver_notify_info(p, r->in.handle,
3440 info, p->mem_ctx);
3441 break;
3443 case SPLHND_PRINTER:
3444 result = printer_notify_info(p, r->in.handle,
3445 info, p->mem_ctx);
3446 break;
3449 Printer->notify.fnpcn = false;
3451 done:
3452 return result;
3455 /********************************************************************
3456 * construct_printer_info_0
3457 * fill a printer_info_0 struct
3458 ********************************************************************/
3460 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3461 const NT_PRINTER_INFO_LEVEL *ntprinter,
3462 struct spoolss_PrinterInfo0 *r,
3463 int snum)
3465 int count;
3466 counter_printer_0 *session_counter;
3467 time_t setuptime;
3468 print_status_struct status;
3470 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3471 W_ERROR_HAVE_NO_MEMORY(r->printername);
3473 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3474 W_ERROR_HAVE_NO_MEMORY(r->servername);
3476 count = print_queue_length(snum, &status);
3478 /* check if we already have a counter for this printer */
3479 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3480 if (session_counter->snum == snum)
3481 break;
3484 /* it's the first time, add it to the list */
3485 if (session_counter == NULL) {
3486 session_counter = SMB_MALLOC_P(counter_printer_0);
3487 W_ERROR_HAVE_NO_MEMORY(session_counter);
3488 ZERO_STRUCTP(session_counter);
3489 session_counter->snum = snum;
3490 session_counter->counter = 0;
3491 DLIST_ADD(counter_list, session_counter);
3494 /* increment it */
3495 session_counter->counter++;
3497 r->cjobs = count;
3498 r->total_jobs = 0;
3499 r->total_bytes = 0;
3501 setuptime = (time_t)ntprinter->info_2->setuptime;
3503 init_systemtime(&r->time, gmtime(&setuptime));
3505 /* JFM:
3506 * the global_counter should be stored in a TDB as it's common to all the clients
3507 * and should be zeroed on samba startup
3509 r->global_counter = session_counter->counter;
3510 r->total_pages = 0;
3511 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3512 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3513 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3514 r->free_build = SPOOLSS_RELEASE_BUILD;
3515 r->spooling = 0;
3516 r->max_spooling = 0;
3517 r->session_counter = session_counter->counter;
3518 r->num_error_out_of_paper = 0x0;
3519 r->num_error_not_ready = 0x0; /* number of print failure */
3520 r->job_error = 0x0;
3521 r->number_of_processors = 0x1;
3522 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3523 r->high_part_total_bytes = 0x0;
3524 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3525 r->last_error = WERR_OK;
3526 r->status = nt_printq_status(status.status);
3527 r->enumerate_network_printers = 0x0;
3528 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3529 r->processor_architecture = 0x0;
3530 r->processor_level = 0x6; /* 6 ???*/
3531 r->ref_ic = 0;
3532 r->reserved2 = 0;
3533 r->reserved3 = 0;
3535 return WERR_OK;
3538 /****************************************************************************
3539 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3540 should be valid upon entry
3541 ****************************************************************************/
3543 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3544 struct spoolss_DeviceMode *r,
3545 const NT_DEVICEMODE *ntdevmode)
3547 if (!r || !ntdevmode) {
3548 return WERR_INVALID_PARAM;
3551 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3552 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3554 r->specversion = ntdevmode->specversion;
3555 r->driverversion = ntdevmode->driverversion;
3556 r->size = ntdevmode->size;
3557 r->__driverextra_length = ntdevmode->driverextra;
3558 r->fields = ntdevmode->fields;
3560 r->orientation = ntdevmode->orientation;
3561 r->papersize = ntdevmode->papersize;
3562 r->paperlength = ntdevmode->paperlength;
3563 r->paperwidth = ntdevmode->paperwidth;
3564 r->scale = ntdevmode->scale;
3565 r->copies = ntdevmode->copies;
3566 r->defaultsource = ntdevmode->defaultsource;
3567 r->printquality = ntdevmode->printquality;
3568 r->color = ntdevmode->color;
3569 r->duplex = ntdevmode->duplex;
3570 r->yresolution = ntdevmode->yresolution;
3571 r->ttoption = ntdevmode->ttoption;
3572 r->collate = ntdevmode->collate;
3574 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3575 W_ERROR_HAVE_NO_MEMORY(r->formname);
3577 r->logpixels = ntdevmode->logpixels;
3578 r->bitsperpel = ntdevmode->bitsperpel;
3579 r->pelswidth = ntdevmode->pelswidth;
3580 r->pelsheight = ntdevmode->pelsheight;
3581 r->displayflags = ntdevmode->displayflags;
3582 r->displayfrequency = ntdevmode->displayfrequency;
3583 r->icmmethod = ntdevmode->icmmethod;
3584 r->icmintent = ntdevmode->icmintent;
3585 r->mediatype = ntdevmode->mediatype;
3586 r->dithertype = ntdevmode->dithertype;
3587 r->reserved1 = ntdevmode->reserved1;
3588 r->reserved2 = ntdevmode->reserved2;
3589 r->panningwidth = ntdevmode->panningwidth;
3590 r->panningheight = ntdevmode->panningheight;
3592 if (ntdevmode->nt_dev_private != NULL) {
3593 r->driverextra_data = data_blob_talloc(mem_ctx,
3594 ntdevmode->nt_dev_private,
3595 ntdevmode->driverextra);
3596 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3599 return WERR_OK;
3603 /****************************************************************************
3604 Create a spoolss_DeviceMode struct. Returns talloced memory.
3605 ****************************************************************************/
3607 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3608 const char *servicename)
3610 WERROR result;
3611 NT_PRINTER_INFO_LEVEL *printer = NULL;
3612 struct spoolss_DeviceMode *devmode = NULL;
3614 DEBUG(7,("construct_dev_mode\n"));
3616 DEBUGADD(8,("getting printer characteristics\n"));
3618 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3619 return NULL;
3621 if (!printer->info_2->devmode) {
3622 DEBUG(5, ("BONG! There was no device mode!\n"));
3623 goto done;
3626 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3627 if (!devmode) {
3628 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3629 goto done;
3632 DEBUGADD(8,("loading DEVICEMODE\n"));
3634 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3635 if (!W_ERROR_IS_OK(result)) {
3636 TALLOC_FREE(devmode);
3639 done:
3640 free_a_printer(&printer,2);
3642 return devmode;
3645 /********************************************************************
3646 * construct_printer_info1
3647 * fill a spoolss_PrinterInfo1 struct
3648 ********************************************************************/
3650 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3651 const NT_PRINTER_INFO_LEVEL *ntprinter,
3652 uint32_t flags,
3653 struct spoolss_PrinterInfo1 *r,
3654 int snum)
3656 r->flags = flags;
3658 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3659 ntprinter->info_2->printername,
3660 ntprinter->info_2->drivername,
3661 ntprinter->info_2->location);
3662 W_ERROR_HAVE_NO_MEMORY(r->description);
3664 if (*ntprinter->info_2->comment == '\0') {
3665 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3666 } else {
3667 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3669 W_ERROR_HAVE_NO_MEMORY(r->comment);
3671 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3672 W_ERROR_HAVE_NO_MEMORY(r->name);
3674 return WERR_OK;
3677 /********************************************************************
3678 * construct_printer_info2
3679 * fill a spoolss_PrinterInfo2 struct
3680 ********************************************************************/
3682 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3683 const NT_PRINTER_INFO_LEVEL *ntprinter,
3684 struct spoolss_PrinterInfo2 *r,
3685 int snum)
3687 int count;
3689 print_status_struct status;
3691 count = print_queue_length(snum, &status);
3693 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3694 W_ERROR_HAVE_NO_MEMORY(r->servername);
3695 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3696 W_ERROR_HAVE_NO_MEMORY(r->printername);
3697 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3698 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3699 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3700 W_ERROR_HAVE_NO_MEMORY(r->portname);
3701 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3702 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3704 if (*ntprinter->info_2->comment == '\0') {
3705 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3706 } else {
3707 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3709 W_ERROR_HAVE_NO_MEMORY(r->comment);
3711 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3712 W_ERROR_HAVE_NO_MEMORY(r->location);
3713 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3714 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3715 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3716 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3717 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3718 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3719 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3720 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3722 r->attributes = ntprinter->info_2->attributes;
3724 r->priority = ntprinter->info_2->priority;
3725 r->defaultpriority = ntprinter->info_2->default_priority;
3726 r->starttime = ntprinter->info_2->starttime;
3727 r->untiltime = ntprinter->info_2->untiltime;
3728 r->status = nt_printq_status(status.status);
3729 r->cjobs = count;
3730 r->averageppm = ntprinter->info_2->averageppm;
3732 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3733 if (!r->devmode) {
3734 DEBUG(8,("Returning NULL Devicemode!\n"));
3737 r->secdesc = NULL;
3739 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3740 /* don't use talloc_steal() here unless you do a deep steal of all
3741 the SEC_DESC members */
3743 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3746 return WERR_OK;
3749 /********************************************************************
3750 * construct_printer_info3
3751 * fill a spoolss_PrinterInfo3 struct
3752 ********************************************************************/
3754 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3755 const NT_PRINTER_INFO_LEVEL *ntprinter,
3756 struct spoolss_PrinterInfo3 *r,
3757 int snum)
3759 /* These are the components of the SD we are returning. */
3761 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3762 /* don't use talloc_steal() here unless you do a deep steal of all
3763 the SEC_DESC members */
3765 r->secdesc = dup_sec_desc(mem_ctx,
3766 ntprinter->info_2->secdesc_buf->sd);
3767 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3770 return WERR_OK;
3773 /********************************************************************
3774 * construct_printer_info4
3775 * fill a spoolss_PrinterInfo4 struct
3776 ********************************************************************/
3778 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3779 const NT_PRINTER_INFO_LEVEL *ntprinter,
3780 struct spoolss_PrinterInfo4 *r,
3781 int snum)
3783 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3784 W_ERROR_HAVE_NO_MEMORY(r->printername);
3785 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3786 W_ERROR_HAVE_NO_MEMORY(r->servername);
3788 r->attributes = ntprinter->info_2->attributes;
3790 return WERR_OK;
3793 /********************************************************************
3794 * construct_printer_info5
3795 * fill a spoolss_PrinterInfo5 struct
3796 ********************************************************************/
3798 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3799 const NT_PRINTER_INFO_LEVEL *ntprinter,
3800 struct spoolss_PrinterInfo5 *r,
3801 int snum)
3803 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3804 W_ERROR_HAVE_NO_MEMORY(r->printername);
3805 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3806 W_ERROR_HAVE_NO_MEMORY(r->portname);
3808 r->attributes = ntprinter->info_2->attributes;
3810 /* these two are not used by NT+ according to MSDN */
3812 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3813 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3815 return WERR_OK;
3818 /********************************************************************
3819 * construct_printer_info_6
3820 * fill a spoolss_PrinterInfo6 struct
3821 ********************************************************************/
3823 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3824 const NT_PRINTER_INFO_LEVEL *ntprinter,
3825 struct spoolss_PrinterInfo6 *r,
3826 int snum)
3828 int count;
3829 print_status_struct status;
3831 count = print_queue_length(snum, &status);
3833 r->status = nt_printq_status(status.status);
3835 return WERR_OK;
3838 /********************************************************************
3839 * construct_printer_info7
3840 * fill a spoolss_PrinterInfo7 struct
3841 ********************************************************************/
3843 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3844 Printer_entry *print_hnd,
3845 struct spoolss_PrinterInfo7 *r,
3846 int snum)
3848 struct GUID guid;
3850 if (is_printer_published(print_hnd, snum, &guid)) {
3851 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3852 r->action = DSPRINT_PUBLISH;
3853 } else {
3854 r->guid = talloc_strdup(mem_ctx, "");
3855 r->action = DSPRINT_UNPUBLISH;
3857 W_ERROR_HAVE_NO_MEMORY(r->guid);
3859 return WERR_OK;
3862 /********************************************************************
3863 * construct_printer_info8
3864 * fill a spoolss_PrinterInfo8 struct
3865 ********************************************************************/
3867 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3868 const NT_PRINTER_INFO_LEVEL *ntprinter,
3869 struct spoolss_DeviceModeInfo *r,
3870 int snum)
3872 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3873 if (!r->devmode) {
3874 DEBUG(8,("Returning NULL Devicemode!\n"));
3877 return WERR_OK;
3881 /********************************************************************
3882 ********************************************************************/
3884 static bool snum_is_shared_printer(int snum)
3886 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3889 /********************************************************************
3890 Spoolss_enumprinters.
3891 ********************************************************************/
3893 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3894 uint32_t level,
3895 uint32_t flags,
3896 union spoolss_PrinterInfo **info_p,
3897 uint32_t *count_p)
3899 int snum;
3900 int n_services = lp_numservices();
3901 union spoolss_PrinterInfo *info = NULL;
3902 uint32_t count = 0;
3903 WERROR result = WERR_OK;
3905 *count_p = 0;
3906 *info_p = NULL;
3908 for (snum = 0; snum < n_services; snum++) {
3910 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3912 if (!snum_is_shared_printer(snum)) {
3913 continue;
3916 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3917 lp_servicename(snum), snum));
3919 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3920 union spoolss_PrinterInfo,
3921 count + 1);
3922 if (!info) {
3923 result = WERR_NOMEM;
3924 goto out;
3927 result = get_a_printer(NULL, &ntprinter, 2,
3928 lp_const_servicename(snum));
3929 if (!W_ERROR_IS_OK(result)) {
3930 goto out;
3933 switch (level) {
3934 case 0:
3935 result = construct_printer_info0(info, ntprinter,
3936 &info[count].info0, snum);
3937 break;
3938 case 1:
3939 result = construct_printer_info1(info, ntprinter, flags,
3940 &info[count].info1, snum);
3941 break;
3942 case 2:
3943 result = construct_printer_info2(info, ntprinter,
3944 &info[count].info2, snum);
3945 break;
3946 case 4:
3947 result = construct_printer_info4(info, ntprinter,
3948 &info[count].info4, snum);
3949 break;
3950 case 5:
3951 result = construct_printer_info5(info, ntprinter,
3952 &info[count].info5, snum);
3953 break;
3955 default:
3956 result = WERR_UNKNOWN_LEVEL;
3957 free_a_printer(&ntprinter, 2);
3958 goto out;
3961 free_a_printer(&ntprinter, 2);
3962 if (!W_ERROR_IS_OK(result)) {
3963 goto out;
3966 count++;
3969 *count_p = count;
3970 *info_p = info;
3972 out:
3973 if (!W_ERROR_IS_OK(result)) {
3974 TALLOC_FREE(info);
3975 return result;
3978 *info_p = info;
3980 return WERR_OK;
3983 /********************************************************************
3984 * handle enumeration of printers at level 0
3985 ********************************************************************/
3987 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3988 uint32_t flags,
3989 const char *servername,
3990 union spoolss_PrinterInfo **info,
3991 uint32_t *count)
3993 DEBUG(4,("enum_all_printers_info_0\n"));
3995 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
3999 /********************************************************************
4000 ********************************************************************/
4002 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4003 uint32_t flags,
4004 union spoolss_PrinterInfo **info,
4005 uint32_t *count)
4007 DEBUG(4,("enum_all_printers_info_1\n"));
4009 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4012 /********************************************************************
4013 enum_all_printers_info_1_local.
4014 *********************************************************************/
4016 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4017 union spoolss_PrinterInfo **info,
4018 uint32_t *count)
4020 DEBUG(4,("enum_all_printers_info_1_local\n"));
4022 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4025 /********************************************************************
4026 enum_all_printers_info_1_name.
4027 *********************************************************************/
4029 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4030 const char *name,
4031 union spoolss_PrinterInfo **info,
4032 uint32_t *count)
4034 const char *s = name;
4036 DEBUG(4,("enum_all_printers_info_1_name\n"));
4038 if ((name[0] == '\\') && (name[1] == '\\')) {
4039 s = name + 2;
4042 if (!is_myname_or_ipaddr(s)) {
4043 return WERR_INVALID_NAME;
4046 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4049 /********************************************************************
4050 enum_all_printers_info_1_network.
4051 *********************************************************************/
4053 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4054 const char *name,
4055 union spoolss_PrinterInfo **info,
4056 uint32_t *count)
4058 const char *s = name;
4060 DEBUG(4,("enum_all_printers_info_1_network\n"));
4062 /* If we respond to a enum_printers level 1 on our name with flags
4063 set to PRINTER_ENUM_REMOTE with a list of printers then these
4064 printers incorrectly appear in the APW browse list.
4065 Specifically the printers for the server appear at the workgroup
4066 level where all the other servers in the domain are
4067 listed. Windows responds to this call with a
4068 WERR_CAN_NOT_COMPLETE so we should do the same. */
4070 if (name[0] == '\\' && name[1] == '\\') {
4071 s = name + 2;
4074 if (is_myname_or_ipaddr(s)) {
4075 return WERR_CAN_NOT_COMPLETE;
4078 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4081 /********************************************************************
4082 * api_spoolss_enumprinters
4084 * called from api_spoolss_enumprinters (see this to understand)
4085 ********************************************************************/
4087 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4088 union spoolss_PrinterInfo **info,
4089 uint32_t *count)
4091 DEBUG(4,("enum_all_printers_info_2\n"));
4093 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4096 /********************************************************************
4097 * handle enumeration of printers at level 1
4098 ********************************************************************/
4100 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4101 uint32_t flags,
4102 const char *name,
4103 union spoolss_PrinterInfo **info,
4104 uint32_t *count)
4106 /* Not all the flags are equals */
4108 if (flags & PRINTER_ENUM_LOCAL) {
4109 return enum_all_printers_info_1_local(mem_ctx, info, count);
4112 if (flags & PRINTER_ENUM_NAME) {
4113 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4116 if (flags & PRINTER_ENUM_NETWORK) {
4117 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4120 return WERR_OK; /* NT4sp5 does that */
4123 /********************************************************************
4124 * handle enumeration of printers at level 2
4125 ********************************************************************/
4127 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4128 uint32_t flags,
4129 const char *servername,
4130 union spoolss_PrinterInfo **info,
4131 uint32_t *count)
4133 if (flags & PRINTER_ENUM_LOCAL) {
4134 return enum_all_printers_info_2(mem_ctx, info, count);
4137 if (flags & PRINTER_ENUM_NAME) {
4138 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4139 return WERR_INVALID_NAME;
4142 return enum_all_printers_info_2(mem_ctx, info, count);
4145 if (flags & PRINTER_ENUM_REMOTE) {
4146 return WERR_UNKNOWN_LEVEL;
4149 return WERR_OK;
4152 /********************************************************************
4153 * handle enumeration of printers at level 4
4154 ********************************************************************/
4156 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4157 uint32_t flags,
4158 const char *servername,
4159 union spoolss_PrinterInfo **info,
4160 uint32_t *count)
4162 DEBUG(4,("enum_all_printers_info_4\n"));
4164 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4168 /********************************************************************
4169 * handle enumeration of printers at level 5
4170 ********************************************************************/
4172 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4173 uint32_t flags,
4174 const char *servername,
4175 union spoolss_PrinterInfo **info,
4176 uint32_t *count)
4178 DEBUG(4,("enum_all_printers_info_5\n"));
4180 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4183 /****************************************************************
4184 _spoolss_EnumPrinters
4185 ****************************************************************/
4187 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4188 struct spoolss_EnumPrinters *r)
4190 const char *name = NULL;
4191 WERROR result;
4193 /* that's an [in out] buffer */
4195 if (!r->in.buffer && (r->in.offered != 0)) {
4196 return WERR_INVALID_PARAM;
4199 DEBUG(4,("_spoolss_EnumPrinters\n"));
4201 *r->out.needed = 0;
4202 *r->out.count = 0;
4203 *r->out.info = NULL;
4206 * Level 1:
4207 * flags==PRINTER_ENUM_NAME
4208 * if name=="" then enumerates all printers
4209 * if name!="" then enumerate the printer
4210 * flags==PRINTER_ENUM_REMOTE
4211 * name is NULL, enumerate printers
4212 * Level 2: name!="" enumerates printers, name can't be NULL
4213 * Level 3: doesn't exist
4214 * Level 4: does a local registry lookup
4215 * Level 5: same as Level 2
4218 if (r->in.server) {
4219 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4220 W_ERROR_HAVE_NO_MEMORY(name);
4223 switch (r->in.level) {
4224 case 0:
4225 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4226 r->out.info, r->out.count);
4227 break;
4228 case 1:
4229 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4230 r->out.info, r->out.count);
4231 break;
4232 case 2:
4233 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4234 r->out.info, r->out.count);
4235 break;
4236 case 4:
4237 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4238 r->out.info, r->out.count);
4239 break;
4240 case 5:
4241 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4242 r->out.info, r->out.count);
4243 break;
4244 default:
4245 return WERR_UNKNOWN_LEVEL;
4248 if (!W_ERROR_IS_OK(result)) {
4249 return result;
4252 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4253 spoolss_EnumPrinters,
4254 *r->out.info, r->in.level,
4255 *r->out.count);
4256 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4257 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4259 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4262 /****************************************************************
4263 _spoolss_GetPrinter
4264 ****************************************************************/
4266 WERROR _spoolss_GetPrinter(pipes_struct *p,
4267 struct spoolss_GetPrinter *r)
4269 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4270 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4271 WERROR result = WERR_OK;
4273 int snum;
4275 /* that's an [in out] buffer */
4277 if (!r->in.buffer && (r->in.offered != 0)) {
4278 return WERR_INVALID_PARAM;
4281 *r->out.needed = 0;
4283 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4284 return WERR_BADFID;
4287 result = get_a_printer(Printer, &ntprinter, 2,
4288 lp_const_servicename(snum));
4289 if (!W_ERROR_IS_OK(result)) {
4290 return result;
4293 switch (r->in.level) {
4294 case 0:
4295 result = construct_printer_info0(p->mem_ctx, ntprinter,
4296 &r->out.info->info0, snum);
4297 break;
4298 case 1:
4299 result = construct_printer_info1(p->mem_ctx, ntprinter,
4300 PRINTER_ENUM_ICON8,
4301 &r->out.info->info1, snum);
4302 break;
4303 case 2:
4304 result = construct_printer_info2(p->mem_ctx, ntprinter,
4305 &r->out.info->info2, snum);
4306 break;
4307 case 3:
4308 result = construct_printer_info3(p->mem_ctx, ntprinter,
4309 &r->out.info->info3, snum);
4310 break;
4311 case 4:
4312 result = construct_printer_info4(p->mem_ctx, ntprinter,
4313 &r->out.info->info4, snum);
4314 break;
4315 case 5:
4316 result = construct_printer_info5(p->mem_ctx, ntprinter,
4317 &r->out.info->info5, snum);
4318 break;
4319 case 6:
4320 result = construct_printer_info6(p->mem_ctx, ntprinter,
4321 &r->out.info->info6, snum);
4322 break;
4323 case 7:
4324 result = construct_printer_info7(p->mem_ctx, Printer,
4325 &r->out.info->info7, snum);
4326 break;
4327 case 8:
4328 result = construct_printer_info8(p->mem_ctx, ntprinter,
4329 &r->out.info->info8, snum);
4330 break;
4331 default:
4332 result = WERR_UNKNOWN_LEVEL;
4333 break;
4336 free_a_printer(&ntprinter, 2);
4338 if (!W_ERROR_IS_OK(result)) {
4339 TALLOC_FREE(r->out.info);
4340 return result;
4343 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4344 r->out.info, r->in.level);
4345 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4347 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4350 /********************************************************************
4351 ********************************************************************/
4353 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4354 const char **string_array,
4355 const char *cservername)
4357 int i, num_strings = 0;
4358 const char **array = NULL;
4360 if (!string_array) {
4361 return NULL;
4364 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4366 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4367 cservername, string_array[i]);
4368 if (!str) {
4369 TALLOC_FREE(array);
4370 return NULL;
4374 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4375 TALLOC_FREE(array);
4376 return NULL;
4380 if (i > 0) {
4381 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4382 &array, &num_strings);
4385 return array;
4388 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4389 do { \
4390 if (in && strlen(in)) { \
4391 out = talloc_strdup(mem_ctx, in); \
4392 W_ERROR_HAVE_NO_MEMORY(out); \
4393 } else { \
4394 out = NULL; \
4396 } while (0);
4398 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4399 do { \
4400 if (in && strlen(in)) { \
4401 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4402 } else { \
4403 out = talloc_strdup(mem_ctx, ""); \
4405 W_ERROR_HAVE_NO_MEMORY(out); \
4406 } while (0);
4408 /********************************************************************
4409 * fill a spoolss_DriverInfo1 struct
4410 ********************************************************************/
4412 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4413 struct spoolss_DriverInfo1 *r,
4414 const struct spoolss_DriverInfo8 *driver,
4415 const char *servername)
4417 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4418 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4420 return WERR_OK;
4423 /********************************************************************
4424 * fill a spoolss_DriverInfo2 struct
4425 ********************************************************************/
4427 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4428 struct spoolss_DriverInfo2 *r,
4429 const struct spoolss_DriverInfo8 *driver,
4430 const char *servername)
4433 const char *cservername = canon_servername(servername);
4435 r->version = driver->version;
4437 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4438 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4439 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4440 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4442 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4443 driver->driver_path,
4444 r->driver_path);
4446 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4447 driver->data_file,
4448 r->data_file);
4450 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4451 driver->config_file,
4452 r->config_file);
4454 return WERR_OK;
4457 /********************************************************************
4458 * fill a spoolss_DriverInfo3 struct
4459 ********************************************************************/
4461 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4462 struct spoolss_DriverInfo3 *r,
4463 const struct spoolss_DriverInfo8 *driver,
4464 const char *servername)
4466 const char *cservername = canon_servername(servername);
4468 r->version = driver->version;
4470 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4471 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4472 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4473 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4475 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4476 driver->driver_path,
4477 r->driver_path);
4479 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4480 driver->data_file,
4481 r->data_file);
4483 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4484 driver->config_file,
4485 r->config_file);
4487 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4488 driver->help_file,
4489 r->help_file);
4491 FILL_DRIVER_STRING(mem_ctx,
4492 driver->monitor_name,
4493 r->monitor_name);
4495 FILL_DRIVER_STRING(mem_ctx,
4496 driver->default_datatype,
4497 r->default_datatype);
4499 r->dependent_files = string_array_from_driver_info(mem_ctx,
4500 driver->dependent_files,
4501 cservername);
4502 return WERR_OK;
4505 /********************************************************************
4506 * fill a spoolss_DriverInfo4 struct
4507 ********************************************************************/
4509 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4510 struct spoolss_DriverInfo4 *r,
4511 const struct spoolss_DriverInfo8 *driver,
4512 const char *servername)
4514 const char *cservername = canon_servername(servername);
4516 r->version = driver->version;
4518 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4519 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4520 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4521 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4523 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4524 driver->driver_path,
4525 r->driver_path);
4527 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4528 driver->data_file,
4529 r->data_file);
4531 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4532 driver->config_file,
4533 r->config_file);
4535 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4536 driver->help_file,
4537 r->help_file);
4539 r->dependent_files = string_array_from_driver_info(mem_ctx,
4540 driver->dependent_files,
4541 cservername);
4543 FILL_DRIVER_STRING(mem_ctx,
4544 driver->monitor_name,
4545 r->monitor_name);
4547 FILL_DRIVER_STRING(mem_ctx,
4548 driver->default_datatype,
4549 r->default_datatype);
4551 r->previous_names = string_array_from_driver_info(mem_ctx,
4552 driver->previous_names,
4553 cservername);
4555 return WERR_OK;
4558 /********************************************************************
4559 * fill a spoolss_DriverInfo5 struct
4560 ********************************************************************/
4562 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4563 struct spoolss_DriverInfo5 *r,
4564 const struct spoolss_DriverInfo8 *driver,
4565 const char *servername)
4567 const char *cservername = canon_servername(servername);
4569 r->version = driver->version;
4571 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4572 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4573 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4574 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4576 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4577 driver->driver_path,
4578 r->driver_path);
4580 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4581 driver->data_file,
4582 r->data_file);
4584 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4585 driver->config_file,
4586 r->config_file);
4588 r->driver_attributes = 0;
4589 r->config_version = 0;
4590 r->driver_version = 0;
4592 return WERR_OK;
4594 /********************************************************************
4595 * fill a spoolss_DriverInfo6 struct
4596 ********************************************************************/
4598 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4599 struct spoolss_DriverInfo6 *r,
4600 const struct spoolss_DriverInfo8 *driver,
4601 const char *servername)
4603 const char *cservername = canon_servername(servername);
4605 r->version = driver->version;
4607 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4608 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4609 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4610 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4612 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4613 driver->driver_path,
4614 r->driver_path);
4616 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4617 driver->data_file,
4618 r->data_file);
4620 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4621 driver->config_file,
4622 r->config_file);
4624 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4625 driver->help_file,
4626 r->help_file);
4628 FILL_DRIVER_STRING(mem_ctx,
4629 driver->monitor_name,
4630 r->monitor_name);
4632 FILL_DRIVER_STRING(mem_ctx,
4633 driver->default_datatype,
4634 r->default_datatype);
4636 r->dependent_files = string_array_from_driver_info(mem_ctx,
4637 driver->dependent_files,
4638 cservername);
4639 r->previous_names = string_array_from_driver_info(mem_ctx,
4640 driver->previous_names,
4641 cservername);
4643 r->driver_date = driver->driver_date;
4644 r->driver_version = driver->driver_version;
4646 FILL_DRIVER_STRING(mem_ctx,
4647 driver->manufacturer_name,
4648 r->manufacturer_name);
4649 FILL_DRIVER_STRING(mem_ctx,
4650 driver->manufacturer_url,
4651 r->manufacturer_url);
4652 FILL_DRIVER_STRING(mem_ctx,
4653 driver->hardware_id,
4654 r->hardware_id);
4655 FILL_DRIVER_STRING(mem_ctx,
4656 driver->provider,
4657 r->provider);
4659 return WERR_OK;
4662 /********************************************************************
4663 * fill a spoolss_DriverInfo8 struct
4664 ********************************************************************/
4666 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4667 struct spoolss_DriverInfo8 *r,
4668 const struct spoolss_DriverInfo8 *driver,
4669 const char *servername)
4671 const char *cservername = canon_servername(servername);
4673 r->version = driver->version;
4675 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4676 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4677 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4678 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4680 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4681 driver->driver_path,
4682 r->driver_path);
4684 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4685 driver->data_file,
4686 r->data_file);
4688 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4689 driver->config_file,
4690 r->config_file);
4692 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4693 driver->help_file,
4694 r->help_file);
4696 FILL_DRIVER_STRING(mem_ctx,
4697 driver->monitor_name,
4698 r->monitor_name);
4700 FILL_DRIVER_STRING(mem_ctx,
4701 driver->default_datatype,
4702 r->default_datatype);
4704 r->dependent_files = string_array_from_driver_info(mem_ctx,
4705 driver->dependent_files,
4706 cservername);
4707 r->previous_names = string_array_from_driver_info(mem_ctx,
4708 driver->previous_names,
4709 cservername);
4711 r->driver_date = driver->driver_date;
4712 r->driver_version = driver->driver_version;
4714 FILL_DRIVER_STRING(mem_ctx,
4715 driver->manufacturer_name,
4716 r->manufacturer_name);
4717 FILL_DRIVER_STRING(mem_ctx,
4718 driver->manufacturer_url,
4719 r->manufacturer_url);
4720 FILL_DRIVER_STRING(mem_ctx,
4721 driver->hardware_id,
4722 r->hardware_id);
4723 FILL_DRIVER_STRING(mem_ctx,
4724 driver->provider,
4725 r->provider);
4727 FILL_DRIVER_STRING(mem_ctx,
4728 driver->print_processor,
4729 r->print_processor);
4730 FILL_DRIVER_STRING(mem_ctx,
4731 driver->vendor_setup,
4732 r->vendor_setup);
4734 r->color_profiles = string_array_from_driver_info(mem_ctx,
4735 driver->color_profiles,
4736 cservername);
4738 FILL_DRIVER_STRING(mem_ctx,
4739 driver->inf_path,
4740 r->inf_path);
4742 r->printer_driver_attributes = driver->printer_driver_attributes;
4744 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4745 driver->core_driver_dependencies,
4746 cservername);
4748 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4749 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4751 return WERR_OK;
4754 #if 0 /* disabled until marshalling issues are resolved - gd */
4755 /********************************************************************
4756 ********************************************************************/
4758 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4759 struct spoolss_DriverFileInfo *r,
4760 const char *cservername,
4761 const char *file_name,
4762 enum spoolss_DriverFileType file_type,
4763 uint32_t file_version)
4765 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4766 cservername, file_name);
4767 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4768 r->file_type = file_type;
4769 r->file_version = file_version;
4771 return WERR_OK;
4774 /********************************************************************
4775 ********************************************************************/
4777 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4778 const struct spoolss_DriverInfo8 *driver,
4779 const char *cservername,
4780 struct spoolss_DriverFileInfo **info_p,
4781 uint32_t *count_p)
4783 struct spoolss_DriverFileInfo *info = NULL;
4784 uint32_t count = 0;
4785 WERROR result;
4786 uint32_t i;
4788 *info_p = NULL;
4789 *count_p = 0;
4791 if (strlen(driver->driver_path)) {
4792 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4793 struct spoolss_DriverFileInfo,
4794 count + 1);
4795 W_ERROR_HAVE_NO_MEMORY(info);
4796 result = fill_spoolss_DriverFileInfo(info,
4797 &info[count],
4798 cservername,
4799 driver->driver_path,
4800 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4802 W_ERROR_NOT_OK_RETURN(result);
4803 count++;
4806 if (strlen(driver->config_file)) {
4807 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4808 struct spoolss_DriverFileInfo,
4809 count + 1);
4810 W_ERROR_HAVE_NO_MEMORY(info);
4811 result = fill_spoolss_DriverFileInfo(info,
4812 &info[count],
4813 cservername,
4814 driver->config_file,
4815 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4817 W_ERROR_NOT_OK_RETURN(result);
4818 count++;
4821 if (strlen(driver->data_file)) {
4822 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4823 struct spoolss_DriverFileInfo,
4824 count + 1);
4825 W_ERROR_HAVE_NO_MEMORY(info);
4826 result = fill_spoolss_DriverFileInfo(info,
4827 &info[count],
4828 cservername,
4829 driver->data_file,
4830 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4832 W_ERROR_NOT_OK_RETURN(result);
4833 count++;
4836 if (strlen(driver->help_file)) {
4837 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4838 struct spoolss_DriverFileInfo,
4839 count + 1);
4840 W_ERROR_HAVE_NO_MEMORY(info);
4841 result = fill_spoolss_DriverFileInfo(info,
4842 &info[count],
4843 cservername,
4844 driver->help_file,
4845 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4847 W_ERROR_NOT_OK_RETURN(result);
4848 count++;
4851 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4852 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4853 struct spoolss_DriverFileInfo,
4854 count + 1);
4855 W_ERROR_HAVE_NO_MEMORY(info);
4856 result = fill_spoolss_DriverFileInfo(info,
4857 &info[count],
4858 cservername,
4859 driver->dependent_files[i],
4860 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4862 W_ERROR_NOT_OK_RETURN(result);
4863 count++;
4866 *info_p = info;
4867 *count_p = count;
4869 return WERR_OK;
4872 /********************************************************************
4873 * fill a spoolss_DriverInfo101 struct
4874 ********************************************************************/
4876 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4877 struct spoolss_DriverInfo101 *r,
4878 const struct spoolss_DriverInfo8 *driver,
4879 const char *servername)
4881 const char *cservername = canon_servername(servername);
4882 WERROR result;
4884 r->version = driver->version;
4886 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4887 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4888 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4889 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4891 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4892 cservername,
4893 &r->file_info,
4894 &r->file_count);
4895 if (!W_ERROR_IS_OK(result)) {
4896 return result;
4899 FILL_DRIVER_STRING(mem_ctx,
4900 driver->monitor_name,
4901 r->monitor_name);
4903 FILL_DRIVER_STRING(mem_ctx,
4904 driver->default_datatype,
4905 r->default_datatype);
4907 r->previous_names = string_array_from_driver_info(mem_ctx,
4908 driver->previous_names,
4909 cservername);
4910 r->driver_date = driver->driver_date;
4911 r->driver_version = driver->driver_version;
4913 FILL_DRIVER_STRING(mem_ctx,
4914 driver->manufacturer_name,
4915 r->manufacturer_name);
4916 FILL_DRIVER_STRING(mem_ctx,
4917 driver->manufacturer_url,
4918 r->manufacturer_url);
4919 FILL_DRIVER_STRING(mem_ctx,
4920 driver->hardware_id,
4921 r->hardware_id);
4922 FILL_DRIVER_STRING(mem_ctx,
4923 driver->provider,
4924 r->provider);
4926 return WERR_OK;
4928 #endif
4929 /********************************************************************
4930 ********************************************************************/
4932 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4933 uint32_t level,
4934 union spoolss_DriverInfo *r,
4935 int snum,
4936 const char *servername,
4937 const char *architecture,
4938 uint32_t version)
4940 NT_PRINTER_INFO_LEVEL *printer = NULL;
4941 struct spoolss_DriverInfo8 *driver;
4942 WERROR result;
4944 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4946 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4947 win_errstr(result)));
4949 if (!W_ERROR_IS_OK(result)) {
4950 return WERR_INVALID_PRINTER_NAME;
4953 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4954 architecture, version);
4956 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4957 win_errstr(result)));
4959 if (!W_ERROR_IS_OK(result)) {
4961 * Is this a W2k client ?
4964 if (version < 3) {
4965 free_a_printer(&printer, 2);
4966 return WERR_UNKNOWN_PRINTER_DRIVER;
4969 /* Yes - try again with a WinNT driver. */
4970 version = 2;
4971 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4972 architecture, version);
4973 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4974 win_errstr(result)));
4975 if (!W_ERROR_IS_OK(result)) {
4976 free_a_printer(&printer, 2);
4977 return WERR_UNKNOWN_PRINTER_DRIVER;
4981 switch (level) {
4982 case 1:
4983 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4984 break;
4985 case 2:
4986 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4987 break;
4988 case 3:
4989 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4990 break;
4991 case 4:
4992 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4993 break;
4994 case 5:
4995 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4996 break;
4997 case 6:
4998 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4999 break;
5000 case 8:
5001 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5002 break;
5003 #if 0 /* disabled until marshalling issues are resolved - gd */
5004 case 101:
5005 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5006 break;
5007 #endif
5008 default:
5009 result = WERR_UNKNOWN_LEVEL;
5010 break;
5013 free_a_printer(&printer, 2);
5014 free_a_printer_driver(driver);
5016 return result;
5019 /****************************************************************
5020 _spoolss_GetPrinterDriver2
5021 ****************************************************************/
5023 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5024 struct spoolss_GetPrinterDriver2 *r)
5026 Printer_entry *printer;
5027 WERROR result;
5029 const char *servername;
5030 int snum;
5032 /* that's an [in out] buffer */
5034 if (!r->in.buffer && (r->in.offered != 0)) {
5035 return WERR_INVALID_PARAM;
5038 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5040 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5041 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5042 return WERR_INVALID_PRINTER_NAME;
5045 *r->out.needed = 0;
5046 *r->out.server_major_version = 0;
5047 *r->out.server_minor_version = 0;
5049 servername = get_server_name(printer);
5051 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5052 return WERR_BADFID;
5055 result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5056 r->out.info, snum,
5057 servername,
5058 r->in.architecture,
5059 r->in.client_major_version);
5060 if (!W_ERROR_IS_OK(result)) {
5061 TALLOC_FREE(r->out.info);
5062 return result;
5065 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5066 r->out.info, r->in.level);
5067 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5069 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5073 /****************************************************************
5074 _spoolss_StartPagePrinter
5075 ****************************************************************/
5077 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5078 struct spoolss_StartPagePrinter *r)
5080 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5082 if (!Printer) {
5083 DEBUG(3,("_spoolss_StartPagePrinter: "
5084 "Error in startpageprinter printer handle\n"));
5085 return WERR_BADFID;
5088 Printer->page_started = true;
5089 return WERR_OK;
5092 /****************************************************************
5093 _spoolss_EndPagePrinter
5094 ****************************************************************/
5096 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5097 struct spoolss_EndPagePrinter *r)
5099 int snum;
5101 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5103 if (!Printer) {
5104 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5105 OUR_HANDLE(r->in.handle)));
5106 return WERR_BADFID;
5109 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5110 return WERR_BADFID;
5112 Printer->page_started = false;
5113 print_job_endpage(snum, Printer->jobid);
5115 return WERR_OK;
5118 /****************************************************************
5119 _spoolss_StartDocPrinter
5120 ****************************************************************/
5122 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5123 struct spoolss_StartDocPrinter *r)
5125 struct spoolss_DocumentInfo1 *info_1;
5126 int snum;
5127 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5129 if (!Printer) {
5130 DEBUG(2,("_spoolss_StartDocPrinter: "
5131 "Invalid handle (%s:%u:%u)\n",
5132 OUR_HANDLE(r->in.handle)));
5133 return WERR_BADFID;
5136 if (r->in.level != 1) {
5137 return WERR_UNKNOWN_LEVEL;
5140 info_1 = r->in.info.info1;
5143 * a nice thing with NT is it doesn't listen to what you tell it.
5144 * when asked to send _only_ RAW datas, it tries to send datas
5145 * in EMF format.
5147 * So I add checks like in NT Server ...
5150 if (info_1->datatype) {
5151 if (strcmp(info_1->datatype, "RAW") != 0) {
5152 *r->out.job_id = 0;
5153 return WERR_INVALID_DATATYPE;
5157 /* get the share number of the printer */
5158 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5159 return WERR_BADFID;
5162 Printer->jobid = print_job_start(p->server_info, snum,
5163 info_1->document_name,
5164 Printer->nt_devmode);
5166 /* An error occured in print_job_start() so return an appropriate
5167 NT error code. */
5169 if (Printer->jobid == -1) {
5170 return map_werror_from_unix(errno);
5173 Printer->document_started = true;
5174 *r->out.job_id = Printer->jobid;
5176 return WERR_OK;
5179 /****************************************************************
5180 _spoolss_EndDocPrinter
5181 ****************************************************************/
5183 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5184 struct spoolss_EndDocPrinter *r)
5186 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5187 int snum;
5189 if (!Printer) {
5190 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5191 OUR_HANDLE(r->in.handle)));
5192 return WERR_BADFID;
5195 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5196 return WERR_BADFID;
5199 Printer->document_started = false;
5200 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5201 /* error codes unhandled so far ... */
5203 return WERR_OK;
5206 /****************************************************************
5207 _spoolss_WritePrinter
5208 ****************************************************************/
5210 WERROR _spoolss_WritePrinter(pipes_struct *p,
5211 struct spoolss_WritePrinter *r)
5213 ssize_t buffer_written;
5214 int snum;
5215 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5217 if (!Printer) {
5218 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5219 OUR_HANDLE(r->in.handle)));
5220 *r->out.num_written = r->in._data_size;
5221 return WERR_BADFID;
5224 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5225 return WERR_BADFID;
5227 buffer_written = print_job_write(snum, Printer->jobid,
5228 (const char *)r->in.data.data,
5229 (SMB_OFF_T)-1,
5230 (size_t)r->in._data_size);
5231 if (buffer_written == (ssize_t)-1) {
5232 *r->out.num_written = 0;
5233 if (errno == ENOSPC)
5234 return WERR_NO_SPOOL_SPACE;
5235 else
5236 return WERR_ACCESS_DENIED;
5239 *r->out.num_written = r->in._data_size;
5241 return WERR_OK;
5244 /********************************************************************
5245 * api_spoolss_getprinter
5246 * called from the spoolss dispatcher
5248 ********************************************************************/
5250 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5251 pipes_struct *p)
5253 int snum;
5254 WERROR errcode = WERR_BADFUNC;
5255 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5257 if (!Printer) {
5258 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5259 OUR_HANDLE(handle)));
5260 return WERR_BADFID;
5263 if (!get_printer_snum(p, handle, &snum, NULL))
5264 return WERR_BADFID;
5266 switch (command) {
5267 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5268 errcode = print_queue_pause(p->server_info, snum);
5269 break;
5270 case SPOOLSS_PRINTER_CONTROL_RESUME:
5271 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5272 errcode = print_queue_resume(p->server_info, snum);
5273 break;
5274 case SPOOLSS_PRINTER_CONTROL_PURGE:
5275 errcode = print_queue_purge(p->server_info, snum);
5276 break;
5277 default:
5278 return WERR_UNKNOWN_LEVEL;
5281 return errcode;
5285 /****************************************************************
5286 _spoolss_AbortPrinter
5287 * From MSDN: "Deletes printer's spool file if printer is configured
5288 * for spooling"
5289 ****************************************************************/
5291 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5292 struct spoolss_AbortPrinter *r)
5294 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5295 int snum;
5296 WERROR errcode = WERR_OK;
5298 if (!Printer) {
5299 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5300 OUR_HANDLE(r->in.handle)));
5301 return WERR_BADFID;
5304 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5305 return WERR_BADFID;
5307 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5309 return errcode;
5312 /********************************************************************
5313 * called by spoolss_api_setprinter
5314 * when updating a printer description
5315 ********************************************************************/
5317 static WERROR update_printer_sec(struct policy_handle *handle,
5318 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5320 struct sec_desc_buf *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5321 WERROR result;
5322 int snum;
5324 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5326 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5327 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5328 OUR_HANDLE(handle)));
5330 result = WERR_BADFID;
5331 goto done;
5334 if (!secdesc_ctr) {
5335 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5336 result = WERR_INVALID_PARAM;
5337 goto done;
5340 /* Check the user has permissions to change the security
5341 descriptor. By experimentation with two NT machines, the user
5342 requires Full Access to the printer to change security
5343 information. */
5345 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5346 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5347 result = WERR_ACCESS_DENIED;
5348 goto done;
5351 /* NT seems to like setting the security descriptor even though
5352 nothing may have actually changed. */
5354 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5355 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5356 result = WERR_BADFID;
5357 goto done;
5360 if (DEBUGLEVEL >= 10) {
5361 struct security_acl *the_acl;
5362 int i;
5364 the_acl = old_secdesc_ctr->sd->dacl;
5365 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5366 PRINTERNAME(snum), the_acl->num_aces));
5368 for (i = 0; i < the_acl->num_aces; i++) {
5369 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5370 &the_acl->aces[i].trustee),
5371 the_acl->aces[i].access_mask));
5374 the_acl = secdesc_ctr->sd->dacl;
5376 if (the_acl) {
5377 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5378 PRINTERNAME(snum), the_acl->num_aces));
5380 for (i = 0; i < the_acl->num_aces; i++) {
5381 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5382 &the_acl->aces[i].trustee),
5383 the_acl->aces[i].access_mask));
5385 } else {
5386 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5390 new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5391 if (!new_secdesc_ctr) {
5392 result = WERR_NOMEM;
5393 goto done;
5396 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5397 result = WERR_OK;
5398 goto done;
5401 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5403 done:
5405 return result;
5408 /********************************************************************
5409 Canonicalize printer info from a client
5411 ATTN: It does not matter what we set the servername to hear
5412 since we do the necessary work in get_a_printer() to set it to
5413 the correct value based on what the client sent in the
5414 _spoolss_open_printer_ex().
5415 ********************************************************************/
5417 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5419 fstring printername;
5420 const char *p;
5422 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5423 "portname=%s drivername=%s comment=%s location=%s\n",
5424 info->servername, info->printername, info->sharename,
5425 info->portname, info->drivername, info->comment, info->location));
5427 /* we force some elements to "correct" values */
5428 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5429 fstrcpy(info->sharename, lp_servicename(snum));
5431 /* check to see if we allow printername != sharename */
5433 if ( lp_force_printername(snum) ) {
5434 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5435 global_myname(), info->sharename );
5436 } else {
5438 /* make sure printername is in \\server\printername format */
5440 fstrcpy( printername, info->printername );
5441 p = printername;
5442 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5443 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5444 p++;
5447 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5448 global_myname(), p );
5451 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5452 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5456 return true;
5459 /****************************************************************************
5460 ****************************************************************************/
5462 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5464 char *cmd = lp_addport_cmd();
5465 char *command = NULL;
5466 int ret;
5467 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5468 bool is_print_op = false;
5470 if ( !*cmd ) {
5471 return WERR_ACCESS_DENIED;
5474 command = talloc_asprintf(ctx,
5475 "%s \"%s\" \"%s\"", cmd, portname, uri );
5476 if (!command) {
5477 return WERR_NOMEM;
5480 if ( token )
5481 is_print_op = user_has_privileges( token, &se_printop );
5483 DEBUG(10,("Running [%s]\n", command));
5485 /********* BEGIN SePrintOperatorPrivilege **********/
5487 if ( is_print_op )
5488 become_root();
5490 ret = smbrun(command, NULL);
5492 if ( is_print_op )
5493 unbecome_root();
5495 /********* END SePrintOperatorPrivilege **********/
5497 DEBUGADD(10,("returned [%d]\n", ret));
5499 TALLOC_FREE(command);
5501 if ( ret != 0 ) {
5502 return WERR_ACCESS_DENIED;
5505 return WERR_OK;
5508 /****************************************************************************
5509 ****************************************************************************/
5511 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5513 char *cmd = lp_addprinter_cmd();
5514 char **qlines;
5515 char *command = NULL;
5516 int numlines;
5517 int ret;
5518 int fd;
5519 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5520 bool is_print_op = false;
5521 char *remote_machine = talloc_strdup(ctx, "%m");
5523 if (!remote_machine) {
5524 return false;
5526 remote_machine = talloc_sub_basic(ctx,
5527 current_user_info.smb_name,
5528 current_user_info.domain,
5529 remote_machine);
5530 if (!remote_machine) {
5531 return false;
5534 command = talloc_asprintf(ctx,
5535 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5536 cmd, printer->info_2->printername, printer->info_2->sharename,
5537 printer->info_2->portname, printer->info_2->drivername,
5538 printer->info_2->location, printer->info_2->comment, remote_machine);
5539 if (!command) {
5540 return false;
5543 if ( token )
5544 is_print_op = user_has_privileges( token, &se_printop );
5546 DEBUG(10,("Running [%s]\n", command));
5548 /********* BEGIN SePrintOperatorPrivilege **********/
5550 if ( is_print_op )
5551 become_root();
5553 if ( (ret = smbrun(command, &fd)) == 0 ) {
5554 /* Tell everyone we updated smb.conf. */
5555 message_send_all(smbd_messaging_context(),
5556 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5559 if ( is_print_op )
5560 unbecome_root();
5562 /********* END SePrintOperatorPrivilege **********/
5564 DEBUGADD(10,("returned [%d]\n", ret));
5566 TALLOC_FREE(command);
5567 TALLOC_FREE(remote_machine);
5569 if ( ret != 0 ) {
5570 if (fd != -1)
5571 close(fd);
5572 return false;
5575 /* reload our services immediately */
5576 become_root();
5577 reload_services(false);
5578 unbecome_root();
5580 numlines = 0;
5581 /* Get lines and convert them back to dos-codepage */
5582 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5583 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5584 close(fd);
5586 /* Set the portname to what the script says the portname should be. */
5587 /* but don't require anything to be return from the script exit a good error code */
5589 if (numlines) {
5590 /* Set the portname to what the script says the portname should be. */
5591 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5592 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5595 TALLOC_FREE(qlines);
5596 return true;
5600 /********************************************************************
5601 * Called by spoolss_api_setprinter
5602 * when updating a printer description.
5603 ********************************************************************/
5605 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5606 struct spoolss_SetPrinterInfoCtr *info_ctr,
5607 struct spoolss_DeviceMode *devmode)
5609 int snum;
5610 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5611 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5612 WERROR result;
5613 DATA_BLOB buffer;
5614 fstring asc_buffer;
5616 DEBUG(8,("update_printer\n"));
5618 result = WERR_OK;
5620 if (!Printer) {
5621 result = WERR_BADFID;
5622 goto done;
5625 if (!get_printer_snum(p, handle, &snum, NULL)) {
5626 result = WERR_BADFID;
5627 goto done;
5630 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5631 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5632 result = WERR_BADFID;
5633 goto done;
5636 DEBUGADD(8,("Converting info_2 struct\n"));
5639 * convert_printer_info converts the incoming
5640 * info from the client and overwrites the info
5641 * just read from the tdb in the pointer 'printer'.
5644 if (!convert_printer_info(info_ctr, printer)) {
5645 result = WERR_NOMEM;
5646 goto done;
5649 if (devmode) {
5650 /* we have a valid devmode
5651 convert it and link it*/
5653 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5654 if (!convert_devicemode(printer->info_2->printername, devmode,
5655 &printer->info_2->devmode)) {
5656 result = WERR_NOMEM;
5657 goto done;
5661 /* Do sanity check on the requested changes for Samba */
5663 if (!check_printer_ok(printer->info_2, snum)) {
5664 result = WERR_INVALID_PARAM;
5665 goto done;
5668 /* FIXME!!! If the driver has changed we really should verify that
5669 it is installed before doing much else --jerry */
5671 /* Check calling user has permission to update printer description */
5673 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5674 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5675 result = WERR_ACCESS_DENIED;
5676 goto done;
5679 /* Call addprinter hook */
5680 /* Check changes to see if this is really needed */
5682 if ( *lp_addprinter_cmd()
5683 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5684 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5685 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5686 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5688 /* add_printer_hook() will call reload_services() */
5690 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5691 printer) ) {
5692 result = WERR_ACCESS_DENIED;
5693 goto done;
5698 * When a *new* driver is bound to a printer, the drivername is used to
5699 * lookup previously saved driver initialization info, which is then
5700 * bound to the printer, simulating what happens in the Windows arch.
5702 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5704 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5705 printer->info_2->drivername));
5707 notify_printer_driver(snum, printer->info_2->drivername);
5711 * flag which changes actually occured. This is a small subset of
5712 * all the possible changes. We also have to update things in the
5713 * DsSpooler key.
5716 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5717 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5718 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5719 REG_SZ, buffer.data, buffer.length);
5721 notify_printer_comment(snum, printer->info_2->comment);
5724 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5725 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5726 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5727 REG_SZ, buffer.data, buffer.length);
5729 notify_printer_sharename(snum, printer->info_2->sharename);
5732 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5733 char *pname;
5735 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5736 pname++;
5737 else
5738 pname = printer->info_2->printername;
5741 push_reg_sz(talloc_tos(), &buffer, pname);
5742 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5743 REG_SZ, buffer.data, buffer.length);
5745 notify_printer_printername( snum, pname );
5748 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5749 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5750 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5751 REG_SZ, buffer.data, buffer.length);
5753 notify_printer_port(snum, printer->info_2->portname);
5756 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5757 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5758 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5759 REG_SZ, buffer.data, buffer.length);
5761 notify_printer_location(snum, printer->info_2->location);
5764 /* here we need to update some more DsSpooler keys */
5765 /* uNCName, serverName, shortServerName */
5767 push_reg_sz(talloc_tos(), &buffer, global_myname());
5768 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5769 REG_SZ, buffer.data, buffer.length);
5770 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5771 REG_SZ, buffer.data, buffer.length);
5773 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5774 global_myname(), printer->info_2->sharename );
5775 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5776 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5777 REG_SZ, buffer.data, buffer.length);
5779 /* Update printer info */
5780 result = mod_a_printer(printer, 2);
5782 done:
5783 free_a_printer(&printer, 2);
5784 free_a_printer(&old_printer, 2);
5787 return result;
5790 /****************************************************************************
5791 ****************************************************************************/
5792 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5793 struct policy_handle *handle,
5794 struct spoolss_SetPrinterInfo7 *info7)
5796 #ifdef HAVE_ADS
5797 int snum;
5798 Printer_entry *Printer;
5800 if ( lp_security() != SEC_ADS ) {
5801 return WERR_UNKNOWN_LEVEL;
5804 Printer = find_printer_index_by_hnd(p, handle);
5806 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5808 if (!Printer)
5809 return WERR_BADFID;
5811 if (!get_printer_snum(p, handle, &snum, NULL))
5812 return WERR_BADFID;
5814 nt_printer_publish(Printer, snum, info7->action);
5816 return WERR_OK;
5817 #else
5818 return WERR_UNKNOWN_LEVEL;
5819 #endif
5822 /********************************************************************
5823 ********************************************************************/
5825 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5826 struct spoolss_DeviceMode *devmode)
5828 int snum;
5829 NT_PRINTER_INFO_LEVEL *printer = NULL;
5830 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5831 WERROR result;
5833 DEBUG(8,("update_printer_devmode\n"));
5835 result = WERR_OK;
5837 if (!Printer) {
5838 result = WERR_BADFID;
5839 goto done;
5842 if (!get_printer_snum(p, handle, &snum, NULL)) {
5843 result = WERR_BADFID;
5844 goto done;
5847 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5848 result = WERR_BADFID;
5849 goto done;
5852 if (devmode) {
5853 /* we have a valid devmode
5854 convert it and link it*/
5856 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5857 if (!convert_devicemode(printer->info_2->printername, devmode,
5858 &printer->info_2->devmode)) {
5859 result = WERR_NOMEM;
5860 goto done;
5864 /* Check calling user has permission to update printer description */
5866 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5867 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5868 result = WERR_ACCESS_DENIED;
5869 goto done;
5873 /* Update printer info */
5874 result = mod_a_printer(printer, 2);
5876 done:
5877 free_a_printer(&printer, 2);
5879 return result;
5883 /****************************************************************
5884 _spoolss_SetPrinter
5885 ****************************************************************/
5887 WERROR _spoolss_SetPrinter(pipes_struct *p,
5888 struct spoolss_SetPrinter *r)
5890 WERROR result;
5892 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5894 if (!Printer) {
5895 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5896 OUR_HANDLE(r->in.handle)));
5897 return WERR_BADFID;
5900 /* check the level */
5901 switch (r->in.info_ctr->level) {
5902 case 0:
5903 return control_printer(r->in.handle, r->in.command, p);
5904 case 2:
5905 result = update_printer(p, r->in.handle,
5906 r->in.info_ctr,
5907 r->in.devmode_ctr->devmode);
5908 if (!W_ERROR_IS_OK(result))
5909 return result;
5910 if (r->in.secdesc_ctr->sd)
5911 result = update_printer_sec(r->in.handle, p,
5912 r->in.secdesc_ctr);
5913 return result;
5914 case 3:
5915 return update_printer_sec(r->in.handle, p,
5916 r->in.secdesc_ctr);
5917 case 7:
5918 return publish_or_unpublish_printer(p, r->in.handle,
5919 r->in.info_ctr->info.info7);
5920 case 8:
5921 return update_printer_devmode(p, r->in.handle,
5922 r->in.devmode_ctr->devmode);
5923 default:
5924 return WERR_UNKNOWN_LEVEL;
5928 /****************************************************************
5929 _spoolss_FindClosePrinterNotify
5930 ****************************************************************/
5932 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5933 struct spoolss_FindClosePrinterNotify *r)
5935 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5937 if (!Printer) {
5938 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5939 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5940 return WERR_BADFID;
5943 if (Printer->notify.client_connected == true) {
5944 int snum = -1;
5946 if ( Printer->printer_type == SPLHND_SERVER)
5947 snum = -1;
5948 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5949 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5950 return WERR_BADFID;
5952 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5955 Printer->notify.flags=0;
5956 Printer->notify.options=0;
5957 Printer->notify.localmachine[0]='\0';
5958 Printer->notify.printerlocal=0;
5959 TALLOC_FREE(Printer->notify.option);
5960 Printer->notify.client_connected = false;
5962 return WERR_OK;
5965 /****************************************************************
5966 _spoolss_AddJob
5967 ****************************************************************/
5969 WERROR _spoolss_AddJob(pipes_struct *p,
5970 struct spoolss_AddJob *r)
5972 if (!r->in.buffer && (r->in.offered != 0)) {
5973 return WERR_INVALID_PARAM;
5976 /* this is what a NT server returns for AddJob. AddJob must fail on
5977 * non-local printers */
5979 if (r->in.level != 1) {
5980 return WERR_UNKNOWN_LEVEL;
5983 return WERR_INVALID_PARAM;
5986 /****************************************************************************
5987 fill_job_info1
5988 ****************************************************************************/
5990 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5991 struct spoolss_JobInfo1 *r,
5992 const print_queue_struct *queue,
5993 int position, int snum,
5994 const NT_PRINTER_INFO_LEVEL *ntprinter)
5996 struct tm *t;
5998 t = gmtime(&queue->time);
6000 r->job_id = queue->job;
6002 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6003 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6004 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6005 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6006 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6007 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6008 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6009 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6010 r->data_type = talloc_strdup(mem_ctx, "RAW");
6011 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6012 r->text_status = talloc_strdup(mem_ctx, "");
6013 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6015 r->status = nt_printj_status(queue->status);
6016 r->priority = queue->priority;
6017 r->position = position;
6018 r->total_pages = queue->page_count;
6019 r->pages_printed = 0; /* ??? */
6021 init_systemtime(&r->submitted, t);
6023 return WERR_OK;
6026 /****************************************************************************
6027 fill_job_info2
6028 ****************************************************************************/
6030 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6031 struct spoolss_JobInfo2 *r,
6032 const print_queue_struct *queue,
6033 int position, int snum,
6034 const NT_PRINTER_INFO_LEVEL *ntprinter,
6035 struct spoolss_DeviceMode *devmode)
6037 struct tm *t;
6039 t = gmtime(&queue->time);
6041 r->job_id = queue->job;
6043 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6044 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6045 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6046 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6047 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6048 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6049 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6050 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6051 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6052 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6053 r->data_type = talloc_strdup(mem_ctx, "RAW");
6054 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6055 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6056 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6057 r->parameters = talloc_strdup(mem_ctx, "");
6058 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6059 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6060 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6062 r->devmode = devmode;
6064 r->text_status = talloc_strdup(mem_ctx, "");
6065 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6067 r->secdesc = NULL;
6069 r->status = nt_printj_status(queue->status);
6070 r->priority = queue->priority;
6071 r->position = position;
6072 r->start_time = 0;
6073 r->until_time = 0;
6074 r->total_pages = queue->page_count;
6075 r->size = queue->size;
6076 init_systemtime(&r->submitted, t);
6077 r->time = 0;
6078 r->pages_printed = 0; /* ??? */
6080 return WERR_OK;
6083 /****************************************************************************
6084 fill_job_info3
6085 ****************************************************************************/
6087 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6088 struct spoolss_JobInfo3 *r,
6089 const print_queue_struct *queue,
6090 const print_queue_struct *next_queue,
6091 int position, int snum,
6092 const NT_PRINTER_INFO_LEVEL *ntprinter)
6094 r->job_id = queue->job;
6095 r->next_job_id = 0;
6096 if (next_queue) {
6097 r->next_job_id = next_queue->job;
6099 r->reserved = 0;
6101 return WERR_OK;
6104 /****************************************************************************
6105 Enumjobs at level 1.
6106 ****************************************************************************/
6108 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6109 const print_queue_struct *queue,
6110 uint32_t num_queues, int snum,
6111 const NT_PRINTER_INFO_LEVEL *ntprinter,
6112 union spoolss_JobInfo **info_p,
6113 uint32_t *count)
6115 union spoolss_JobInfo *info;
6116 int i;
6117 WERROR result = WERR_OK;
6119 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6120 W_ERROR_HAVE_NO_MEMORY(info);
6122 *count = num_queues;
6124 for (i=0; i<*count; i++) {
6125 result = fill_job_info1(info,
6126 &info[i].info1,
6127 &queue[i],
6129 snum,
6130 ntprinter);
6131 if (!W_ERROR_IS_OK(result)) {
6132 goto out;
6136 out:
6137 if (!W_ERROR_IS_OK(result)) {
6138 TALLOC_FREE(info);
6139 *count = 0;
6140 return result;
6143 *info_p = info;
6145 return WERR_OK;
6148 /****************************************************************************
6149 Enumjobs at level 2.
6150 ****************************************************************************/
6152 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6153 const print_queue_struct *queue,
6154 uint32_t num_queues, int snum,
6155 const NT_PRINTER_INFO_LEVEL *ntprinter,
6156 union spoolss_JobInfo **info_p,
6157 uint32_t *count)
6159 union spoolss_JobInfo *info;
6160 int i;
6161 WERROR result = WERR_OK;
6163 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6164 W_ERROR_HAVE_NO_MEMORY(info);
6166 *count = num_queues;
6168 for (i=0; i<*count; i++) {
6170 struct spoolss_DeviceMode *devmode;
6172 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6173 if (!devmode) {
6174 result = WERR_NOMEM;
6175 goto out;
6178 result = fill_job_info2(info,
6179 &info[i].info2,
6180 &queue[i],
6182 snum,
6183 ntprinter,
6184 devmode);
6185 if (!W_ERROR_IS_OK(result)) {
6186 goto out;
6190 out:
6191 if (!W_ERROR_IS_OK(result)) {
6192 TALLOC_FREE(info);
6193 *count = 0;
6194 return result;
6197 *info_p = info;
6199 return WERR_OK;
6202 /****************************************************************************
6203 Enumjobs at level 3.
6204 ****************************************************************************/
6206 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6207 const print_queue_struct *queue,
6208 uint32_t num_queues, int snum,
6209 const NT_PRINTER_INFO_LEVEL *ntprinter,
6210 union spoolss_JobInfo **info_p,
6211 uint32_t *count)
6213 union spoolss_JobInfo *info;
6214 int i;
6215 WERROR result = WERR_OK;
6217 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6218 W_ERROR_HAVE_NO_MEMORY(info);
6220 *count = num_queues;
6222 for (i=0; i<*count; i++) {
6223 const print_queue_struct *next_queue = NULL;
6225 if (i+1 < *count) {
6226 next_queue = &queue[i+1];
6229 result = fill_job_info3(info,
6230 &info[i].info3,
6231 &queue[i],
6232 next_queue,
6234 snum,
6235 ntprinter);
6236 if (!W_ERROR_IS_OK(result)) {
6237 goto out;
6241 out:
6242 if (!W_ERROR_IS_OK(result)) {
6243 TALLOC_FREE(info);
6244 *count = 0;
6245 return result;
6248 *info_p = info;
6250 return WERR_OK;
6253 /****************************************************************
6254 _spoolss_EnumJobs
6255 ****************************************************************/
6257 WERROR _spoolss_EnumJobs(pipes_struct *p,
6258 struct spoolss_EnumJobs *r)
6260 WERROR result;
6261 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6262 int snum;
6263 print_status_struct prt_status;
6264 print_queue_struct *queue = NULL;
6265 uint32_t count;
6267 /* that's an [in out] buffer */
6269 if (!r->in.buffer && (r->in.offered != 0)) {
6270 return WERR_INVALID_PARAM;
6273 DEBUG(4,("_spoolss_EnumJobs\n"));
6275 *r->out.needed = 0;
6276 *r->out.count = 0;
6277 *r->out.info = NULL;
6279 /* lookup the printer snum and tdb entry */
6281 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6282 return WERR_BADFID;
6285 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6286 if (!W_ERROR_IS_OK(result)) {
6287 return result;
6290 count = print_queue_status(snum, &queue, &prt_status);
6291 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6292 count, prt_status.status, prt_status.message));
6294 if (count == 0) {
6295 SAFE_FREE(queue);
6296 free_a_printer(&ntprinter, 2);
6297 return WERR_OK;
6300 switch (r->in.level) {
6301 case 1:
6302 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6303 ntprinter, r->out.info, r->out.count);
6304 break;
6305 case 2:
6306 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6307 ntprinter, r->out.info, r->out.count);
6308 break;
6309 case 3:
6310 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6311 ntprinter, r->out.info, r->out.count);
6312 break;
6313 default:
6314 result = WERR_UNKNOWN_LEVEL;
6315 break;
6318 SAFE_FREE(queue);
6319 free_a_printer(&ntprinter, 2);
6321 if (!W_ERROR_IS_OK(result)) {
6322 return result;
6325 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6326 spoolss_EnumJobs,
6327 *r->out.info, r->in.level,
6328 *r->out.count);
6329 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6330 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6332 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6335 /****************************************************************
6336 _spoolss_ScheduleJob
6337 ****************************************************************/
6339 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6340 struct spoolss_ScheduleJob *r)
6342 return WERR_OK;
6345 /****************************************************************
6346 ****************************************************************/
6348 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6349 const char *printer_name,
6350 uint32_t job_id,
6351 struct spoolss_SetJobInfo1 *r)
6353 char *old_doc_name;
6355 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6356 return WERR_BADFID;
6359 if (strequal(old_doc_name, r->document_name)) {
6360 return WERR_OK;
6363 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6364 return WERR_BADFID;
6367 return WERR_OK;
6370 /****************************************************************
6371 _spoolss_SetJob
6372 ****************************************************************/
6374 WERROR _spoolss_SetJob(pipes_struct *p,
6375 struct spoolss_SetJob *r)
6377 int snum;
6378 WERROR errcode = WERR_BADFUNC;
6380 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6381 return WERR_BADFID;
6384 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6385 return WERR_INVALID_PRINTER_NAME;
6388 switch (r->in.command) {
6389 case SPOOLSS_JOB_CONTROL_CANCEL:
6390 case SPOOLSS_JOB_CONTROL_DELETE:
6391 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6392 errcode = WERR_OK;
6394 break;
6395 case SPOOLSS_JOB_CONTROL_PAUSE:
6396 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6397 errcode = WERR_OK;
6399 break;
6400 case SPOOLSS_JOB_CONTROL_RESTART:
6401 case SPOOLSS_JOB_CONTROL_RESUME:
6402 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6403 errcode = WERR_OK;
6405 break;
6406 case 0:
6407 errcode = WERR_OK;
6408 break;
6409 default:
6410 return WERR_UNKNOWN_LEVEL;
6413 if (!W_ERROR_IS_OK(errcode)) {
6414 return errcode;
6417 if (r->in.ctr == NULL) {
6418 return errcode;
6421 switch (r->in.ctr->level) {
6422 case 1:
6423 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6424 r->in.job_id,
6425 r->in.ctr->info.info1);
6426 break;
6427 case 2:
6428 case 3:
6429 case 4:
6430 default:
6431 return WERR_UNKNOWN_LEVEL;
6434 return errcode;
6437 /****************************************************************************
6438 Enumerates all printer drivers by level and architecture.
6439 ****************************************************************************/
6441 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6442 const char *servername,
6443 const char *architecture,
6444 uint32_t level,
6445 union spoolss_DriverInfo **info_p,
6446 uint32_t *count_p)
6448 int i;
6449 int ndrivers;
6450 uint32_t version;
6451 fstring *list = NULL;
6452 struct spoolss_DriverInfo8 *driver;
6453 union spoolss_DriverInfo *info = NULL;
6454 uint32_t count = 0;
6455 WERROR result = WERR_OK;
6457 *count_p = 0;
6458 *info_p = NULL;
6460 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6461 list = NULL;
6462 ndrivers = get_ntdrivers(&list, architecture, version);
6463 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6464 ndrivers, architecture, version));
6466 if (ndrivers == -1) {
6467 result = WERR_NOMEM;
6468 goto out;
6471 if (ndrivers != 0) {
6472 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6473 union spoolss_DriverInfo,
6474 count + ndrivers);
6475 if (!info) {
6476 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6477 "failed to enlarge driver info buffer!\n"));
6478 result = WERR_NOMEM;
6479 goto out;
6483 for (i=0; i<ndrivers; i++) {
6484 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6485 ZERO_STRUCT(driver);
6486 result = get_a_printer_driver(mem_ctx, &driver, list[i],
6487 architecture, version);
6488 if (!W_ERROR_IS_OK(result)) {
6489 goto out;
6492 switch (level) {
6493 case 1:
6494 result = fill_printer_driver_info1(info, &info[count+i].info1,
6495 driver, servername);
6496 break;
6497 case 2:
6498 result = fill_printer_driver_info2(info, &info[count+i].info2,
6499 driver, servername);
6500 break;
6501 case 3:
6502 result = fill_printer_driver_info3(info, &info[count+i].info3,
6503 driver, servername);
6504 break;
6505 case 4:
6506 result = fill_printer_driver_info4(info, &info[count+i].info4,
6507 driver, servername);
6508 break;
6509 case 5:
6510 result = fill_printer_driver_info5(info, &info[count+i].info5,
6511 driver, servername);
6512 break;
6513 case 6:
6514 result = fill_printer_driver_info6(info, &info[count+i].info6,
6515 driver, servername);
6516 break;
6517 case 8:
6518 result = fill_printer_driver_info8(info, &info[count+i].info8,
6519 driver, servername);
6520 break;
6521 default:
6522 result = WERR_UNKNOWN_LEVEL;
6523 break;
6526 free_a_printer_driver(driver);
6528 if (!W_ERROR_IS_OK(result)) {
6529 goto out;
6533 count += ndrivers;
6534 SAFE_FREE(list);
6537 out:
6538 SAFE_FREE(list);
6540 if (!W_ERROR_IS_OK(result)) {
6541 TALLOC_FREE(info);
6542 return result;
6545 *info_p = info;
6546 *count_p = count;
6548 return WERR_OK;
6551 /****************************************************************************
6552 Enumerates all printer drivers by level.
6553 ****************************************************************************/
6555 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6556 const char *servername,
6557 const char *architecture,
6558 uint32_t level,
6559 union spoolss_DriverInfo **info_p,
6560 uint32_t *count_p)
6562 uint32_t a,i;
6563 WERROR result = WERR_OK;
6565 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6567 for (a=0; archi_table[a].long_archi != NULL; a++) {
6569 union spoolss_DriverInfo *info = NULL;
6570 uint32_t count = 0;
6572 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6573 servername,
6574 archi_table[a].long_archi,
6575 level,
6576 &info,
6577 &count);
6578 if (!W_ERROR_IS_OK(result)) {
6579 continue;
6582 for (i=0; i < count; i++) {
6583 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6584 info[i], info_p, count_p);
6588 return result;
6591 return enumprinterdrivers_level_by_architecture(mem_ctx,
6592 servername,
6593 architecture,
6594 level,
6595 info_p,
6596 count_p);
6599 /****************************************************************
6600 _spoolss_EnumPrinterDrivers
6601 ****************************************************************/
6603 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6604 struct spoolss_EnumPrinterDrivers *r)
6606 const char *cservername;
6607 WERROR result;
6609 /* that's an [in out] buffer */
6611 if (!r->in.buffer && (r->in.offered != 0)) {
6612 return WERR_INVALID_PARAM;
6615 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6617 *r->out.needed = 0;
6618 *r->out.count = 0;
6619 *r->out.info = NULL;
6621 cservername = canon_servername(r->in.server);
6623 if (!is_myname_or_ipaddr(cservername)) {
6624 return WERR_UNKNOWN_PRINTER_DRIVER;
6627 result = enumprinterdrivers_level(p->mem_ctx, cservername,
6628 r->in.environment,
6629 r->in.level,
6630 r->out.info,
6631 r->out.count);
6632 if (!W_ERROR_IS_OK(result)) {
6633 return result;
6636 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6637 spoolss_EnumPrinterDrivers,
6638 *r->out.info, r->in.level,
6639 *r->out.count);
6640 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6641 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6643 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6646 /****************************************************************************
6647 ****************************************************************************/
6649 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6650 struct spoolss_FormInfo1 *r,
6651 const nt_forms_struct *form)
6653 r->form_name = talloc_strdup(mem_ctx, form->name);
6654 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6656 r->flags = form->flag;
6657 r->size.width = form->width;
6658 r->size.height = form->length;
6659 r->area.left = form->left;
6660 r->area.top = form->top;
6661 r->area.right = form->right;
6662 r->area.bottom = form->bottom;
6664 return WERR_OK;
6667 /****************************************************************
6668 spoolss_enumforms_level1
6669 ****************************************************************/
6671 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6672 const nt_forms_struct *builtin_forms,
6673 uint32_t num_builtin_forms,
6674 const nt_forms_struct *user_forms,
6675 uint32_t num_user_forms,
6676 union spoolss_FormInfo **info_p,
6677 uint32_t *count)
6679 union spoolss_FormInfo *info;
6680 WERROR result = WERR_OK;
6681 int i;
6683 *count = num_builtin_forms + num_user_forms;
6685 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6686 W_ERROR_HAVE_NO_MEMORY(info);
6688 /* construct the list of form structures */
6689 for (i=0; i<num_builtin_forms; i++) {
6690 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6691 result = fill_form_info_1(info, &info[i].info1,
6692 &builtin_forms[i]);
6693 if (!W_ERROR_IS_OK(result)) {
6694 goto out;
6698 for (i=0; i<num_user_forms; i++) {
6699 DEBUGADD(6,("Filling user form number [%d]\n",i));
6700 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6701 &user_forms[i]);
6702 if (!W_ERROR_IS_OK(result)) {
6703 goto out;
6707 out:
6708 if (!W_ERROR_IS_OK(result)) {
6709 TALLOC_FREE(info);
6710 *count = 0;
6711 return result;
6714 *info_p = info;
6716 return WERR_OK;
6719 /****************************************************************
6720 _spoolss_EnumForms
6721 ****************************************************************/
6723 WERROR _spoolss_EnumForms(pipes_struct *p,
6724 struct spoolss_EnumForms *r)
6726 WERROR result;
6727 nt_forms_struct *user_forms = NULL;
6728 nt_forms_struct *builtin_forms = NULL;
6729 uint32_t num_user_forms;
6730 uint32_t num_builtin_forms;
6732 *r->out.count = 0;
6733 *r->out.needed = 0;
6734 *r->out.info = NULL;
6736 /* that's an [in out] buffer */
6738 if (!r->in.buffer && (r->in.offered != 0) ) {
6739 return WERR_INVALID_PARAM;
6742 DEBUG(4,("_spoolss_EnumForms\n"));
6743 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6744 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6746 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6747 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6748 num_user_forms = get_ntforms(&user_forms);
6749 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6751 if (num_user_forms + num_builtin_forms == 0) {
6752 SAFE_FREE(builtin_forms);
6753 SAFE_FREE(user_forms);
6754 return WERR_NO_MORE_ITEMS;
6757 switch (r->in.level) {
6758 case 1:
6759 result = spoolss_enumforms_level1(p->mem_ctx,
6760 builtin_forms,
6761 num_builtin_forms,
6762 user_forms,
6763 num_user_forms,
6764 r->out.info,
6765 r->out.count);
6766 break;
6767 default:
6768 result = WERR_UNKNOWN_LEVEL;
6769 break;
6772 SAFE_FREE(user_forms);
6773 SAFE_FREE(builtin_forms);
6775 if (!W_ERROR_IS_OK(result)) {
6776 return result;
6779 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6780 spoolss_EnumForms,
6781 *r->out.info, r->in.level,
6782 *r->out.count);
6783 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6784 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6786 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6789 /****************************************************************
6790 ****************************************************************/
6792 static WERROR find_form_byname(const char *name,
6793 nt_forms_struct *form)
6795 nt_forms_struct *list = NULL;
6796 int num_forms = 0, i = 0;
6798 if (get_a_builtin_ntform_by_string(name, form)) {
6799 return WERR_OK;
6802 num_forms = get_ntforms(&list);
6803 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6805 if (num_forms == 0) {
6806 return WERR_BADFID;
6809 /* Check if the requested name is in the list of form structures */
6810 for (i = 0; i < num_forms; i++) {
6812 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6814 if (strequal(name, list[i].name)) {
6815 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6816 *form = list[i];
6817 SAFE_FREE(list);
6818 return WERR_OK;
6822 SAFE_FREE(list);
6824 return WERR_BADFID;
6827 /****************************************************************
6828 _spoolss_GetForm
6829 ****************************************************************/
6831 WERROR _spoolss_GetForm(pipes_struct *p,
6832 struct spoolss_GetForm *r)
6834 WERROR result;
6835 nt_forms_struct form;
6837 /* that's an [in out] buffer */
6839 if (!r->in.buffer && (r->in.offered != 0)) {
6840 return WERR_INVALID_PARAM;
6843 DEBUG(4,("_spoolss_GetForm\n"));
6844 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6845 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6847 result = find_form_byname(r->in.form_name, &form);
6848 if (!W_ERROR_IS_OK(result)) {
6849 TALLOC_FREE(r->out.info);
6850 return result;
6853 switch (r->in.level) {
6854 case 1:
6855 result = fill_form_info_1(p->mem_ctx,
6856 &r->out.info->info1,
6857 &form);
6858 break;
6860 default:
6861 result = WERR_UNKNOWN_LEVEL;
6862 break;
6865 if (!W_ERROR_IS_OK(result)) {
6866 TALLOC_FREE(r->out.info);
6867 return result;
6870 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6871 r->out.info, r->in.level);
6872 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6874 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6877 /****************************************************************************
6878 ****************************************************************************/
6880 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6881 struct spoolss_PortInfo1 *r,
6882 const char *name)
6884 r->port_name = talloc_strdup(mem_ctx, name);
6885 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6887 return WERR_OK;
6890 /****************************************************************************
6891 TODO: This probably needs distinguish between TCP/IP and Local ports
6892 somehow.
6893 ****************************************************************************/
6895 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6896 struct spoolss_PortInfo2 *r,
6897 const char *name)
6899 r->port_name = talloc_strdup(mem_ctx, name);
6900 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6902 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6903 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6905 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6906 W_ERROR_HAVE_NO_MEMORY(r->description);
6908 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6909 r->reserved = 0;
6911 return WERR_OK;
6915 /****************************************************************************
6916 wrapper around the enumer ports command
6917 ****************************************************************************/
6919 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6921 char *cmd = lp_enumports_cmd();
6922 char **qlines = NULL;
6923 char *command = NULL;
6924 int numlines;
6925 int ret;
6926 int fd;
6928 *count = 0;
6929 *lines = NULL;
6931 /* if no hook then just fill in the default port */
6933 if ( !*cmd ) {
6934 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6935 return WERR_NOMEM;
6937 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6938 TALLOC_FREE(qlines);
6939 return WERR_NOMEM;
6941 qlines[1] = NULL;
6942 numlines = 1;
6944 else {
6945 /* we have a valid enumport command */
6947 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6948 if (!command) {
6949 return WERR_NOMEM;
6952 DEBUG(10,("Running [%s]\n", command));
6953 ret = smbrun(command, &fd);
6954 DEBUG(10,("Returned [%d]\n", ret));
6955 TALLOC_FREE(command);
6956 if (ret != 0) {
6957 if (fd != -1) {
6958 close(fd);
6960 return WERR_ACCESS_DENIED;
6963 numlines = 0;
6964 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6965 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6966 close(fd);
6969 *count = numlines;
6970 *lines = qlines;
6972 return WERR_OK;
6975 /****************************************************************************
6976 enumports level 1.
6977 ****************************************************************************/
6979 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6980 union spoolss_PortInfo **info_p,
6981 uint32_t *count)
6983 union spoolss_PortInfo *info = NULL;
6984 int i=0;
6985 WERROR result = WERR_OK;
6986 char **qlines = NULL;
6987 int numlines = 0;
6989 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6990 if (!W_ERROR_IS_OK(result)) {
6991 goto out;
6994 if (numlines) {
6995 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6996 if (!info) {
6997 DEBUG(10,("Returning WERR_NOMEM\n"));
6998 result = WERR_NOMEM;
6999 goto out;
7002 for (i=0; i<numlines; i++) {
7003 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7004 result = fill_port_1(info, &info[i].info1, qlines[i]);
7005 if (!W_ERROR_IS_OK(result)) {
7006 goto out;
7010 TALLOC_FREE(qlines);
7012 out:
7013 if (!W_ERROR_IS_OK(result)) {
7014 TALLOC_FREE(info);
7015 TALLOC_FREE(qlines);
7016 *count = 0;
7017 *info_p = NULL;
7018 return result;
7021 *info_p = info;
7022 *count = numlines;
7024 return WERR_OK;
7027 /****************************************************************************
7028 enumports level 2.
7029 ****************************************************************************/
7031 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7032 union spoolss_PortInfo **info_p,
7033 uint32_t *count)
7035 union spoolss_PortInfo *info = NULL;
7036 int i=0;
7037 WERROR result = WERR_OK;
7038 char **qlines = NULL;
7039 int numlines = 0;
7041 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7042 if (!W_ERROR_IS_OK(result)) {
7043 goto out;
7046 if (numlines) {
7047 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7048 if (!info) {
7049 DEBUG(10,("Returning WERR_NOMEM\n"));
7050 result = WERR_NOMEM;
7051 goto out;
7054 for (i=0; i<numlines; i++) {
7055 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7056 result = fill_port_2(info, &info[i].info2, qlines[i]);
7057 if (!W_ERROR_IS_OK(result)) {
7058 goto out;
7062 TALLOC_FREE(qlines);
7064 out:
7065 if (!W_ERROR_IS_OK(result)) {
7066 TALLOC_FREE(info);
7067 TALLOC_FREE(qlines);
7068 *count = 0;
7069 *info_p = NULL;
7070 return result;
7073 *info_p = info;
7074 *count = numlines;
7076 return WERR_OK;
7079 /****************************************************************
7080 _spoolss_EnumPorts
7081 ****************************************************************/
7083 WERROR _spoolss_EnumPorts(pipes_struct *p,
7084 struct spoolss_EnumPorts *r)
7086 WERROR result;
7088 /* that's an [in out] buffer */
7090 if (!r->in.buffer && (r->in.offered != 0)) {
7091 return WERR_INVALID_PARAM;
7094 DEBUG(4,("_spoolss_EnumPorts\n"));
7096 *r->out.count = 0;
7097 *r->out.needed = 0;
7098 *r->out.info = NULL;
7100 switch (r->in.level) {
7101 case 1:
7102 result = enumports_level_1(p->mem_ctx, r->out.info,
7103 r->out.count);
7104 break;
7105 case 2:
7106 result = enumports_level_2(p->mem_ctx, r->out.info,
7107 r->out.count);
7108 break;
7109 default:
7110 return WERR_UNKNOWN_LEVEL;
7113 if (!W_ERROR_IS_OK(result)) {
7114 return result;
7117 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7118 spoolss_EnumPorts,
7119 *r->out.info, r->in.level,
7120 *r->out.count);
7121 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7122 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7124 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7127 /****************************************************************************
7128 ****************************************************************************/
7130 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7131 const char *server,
7132 struct spoolss_SetPrinterInfoCtr *info_ctr,
7133 struct spoolss_DeviceMode *devmode,
7134 struct security_descriptor *sec_desc,
7135 struct spoolss_UserLevelCtr *user_ctr,
7136 struct policy_handle *handle)
7138 NT_PRINTER_INFO_LEVEL *printer = NULL;
7139 fstring name;
7140 int snum;
7141 WERROR err = WERR_OK;
7143 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7144 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7145 return WERR_NOMEM;
7148 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7149 if (!convert_printer_info(info_ctr, printer)) {
7150 free_a_printer(&printer, 2);
7151 return WERR_NOMEM;
7154 /* samba does not have a concept of local, non-shared printers yet, so
7155 * make sure we always setup sharename - gd */
7156 if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7157 DEBUG(5, ("spoolss_addprinterex_level_2: "
7158 "no sharename has been set, setting printername %s as sharename\n",
7159 printer->info_2->printername));
7160 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7163 /* check to see if the printer already exists */
7165 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7166 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7167 printer->info_2->sharename));
7168 free_a_printer(&printer, 2);
7169 return WERR_PRINTER_ALREADY_EXISTS;
7172 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7173 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7174 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7175 printer->info_2->printername));
7176 free_a_printer(&printer, 2);
7177 return WERR_PRINTER_ALREADY_EXISTS;
7181 /* validate printer info struct */
7182 if (!info_ctr->info.info2->printername ||
7183 strlen(info_ctr->info.info2->printername) == 0) {
7184 free_a_printer(&printer,2);
7185 return WERR_INVALID_PRINTER_NAME;
7187 if (!info_ctr->info.info2->portname ||
7188 strlen(info_ctr->info.info2->portname) == 0) {
7189 free_a_printer(&printer,2);
7190 return WERR_UNKNOWN_PORT;
7192 if (!info_ctr->info.info2->drivername ||
7193 strlen(info_ctr->info.info2->drivername) == 0) {
7194 free_a_printer(&printer,2);
7195 return WERR_UNKNOWN_PRINTER_DRIVER;
7197 if (!info_ctr->info.info2->printprocessor ||
7198 strlen(info_ctr->info.info2->printprocessor) == 0) {
7199 free_a_printer(&printer,2);
7200 return WERR_UNKNOWN_PRINTPROCESSOR;
7203 /* FIXME!!! smbd should check to see if the driver is installed before
7204 trying to add a printer like this --jerry */
7206 if (*lp_addprinter_cmd() ) {
7207 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7208 printer) ) {
7209 free_a_printer(&printer,2);
7210 return WERR_ACCESS_DENIED;
7212 } else {
7213 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7214 "smb.conf parameter \"addprinter command\" is defined. This"
7215 "parameter must exist for this call to succeed\n",
7216 printer->info_2->sharename ));
7219 /* use our primary netbios name since get_a_printer() will convert
7220 it to what the client expects on a case by case basis */
7222 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7223 printer->info_2->sharename);
7226 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7227 free_a_printer(&printer,2);
7228 return WERR_ACCESS_DENIED;
7231 /* you must be a printer admin to add a new printer */
7232 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7233 free_a_printer(&printer,2);
7234 return WERR_ACCESS_DENIED;
7238 * Do sanity check on the requested changes for Samba.
7241 if (!check_printer_ok(printer->info_2, snum)) {
7242 free_a_printer(&printer,2);
7243 return WERR_INVALID_PARAM;
7247 * When a printer is created, the drivername bound to the printer is used
7248 * to lookup previously saved driver initialization info, which is then
7249 * bound to the new printer, simulating what happens in the Windows arch.
7252 if (devmode)
7254 /* A valid devmode was included, convert and link it
7256 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7258 if (!convert_devicemode(printer->info_2->printername, devmode,
7259 &printer->info_2->devmode)) {
7260 return WERR_NOMEM;
7264 /* write the ASCII on disk */
7265 err = mod_a_printer(printer, 2);
7266 if (!W_ERROR_IS_OK(err)) {
7267 free_a_printer(&printer,2);
7268 return err;
7271 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7272 /* Handle open failed - remove addition. */
7273 del_a_printer(printer->info_2->sharename);
7274 free_a_printer(&printer,2);
7275 ZERO_STRUCTP(handle);
7276 return WERR_ACCESS_DENIED;
7279 update_c_setprinter(false);
7280 free_a_printer(&printer,2);
7282 return WERR_OK;
7285 /****************************************************************
7286 _spoolss_AddPrinterEx
7287 ****************************************************************/
7289 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7290 struct spoolss_AddPrinterEx *r)
7292 switch (r->in.info_ctr->level) {
7293 case 1:
7294 /* we don't handle yet */
7295 /* but I know what to do ... */
7296 return WERR_UNKNOWN_LEVEL;
7297 case 2:
7298 return spoolss_addprinterex_level_2(p, r->in.server,
7299 r->in.info_ctr,
7300 r->in.devmode_ctr->devmode,
7301 r->in.secdesc_ctr->sd,
7302 r->in.userlevel_ctr,
7303 r->out.handle);
7304 default:
7305 return WERR_UNKNOWN_LEVEL;
7309 /****************************************************************
7310 _spoolss_AddPrinter
7311 ****************************************************************/
7313 WERROR _spoolss_AddPrinter(pipes_struct *p,
7314 struct spoolss_AddPrinter *r)
7316 struct spoolss_AddPrinterEx a;
7317 struct spoolss_UserLevelCtr userlevel_ctr;
7319 ZERO_STRUCT(userlevel_ctr);
7321 userlevel_ctr.level = 1;
7323 a.in.server = r->in.server;
7324 a.in.info_ctr = r->in.info_ctr;
7325 a.in.devmode_ctr = r->in.devmode_ctr;
7326 a.in.secdesc_ctr = r->in.secdesc_ctr;
7327 a.in.userlevel_ctr = &userlevel_ctr;
7328 a.out.handle = r->out.handle;
7330 return _spoolss_AddPrinterEx(p, &a);
7333 /****************************************************************
7334 _spoolss_AddPrinterDriverEx
7335 ****************************************************************/
7337 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7338 struct spoolss_AddPrinterDriverEx *r)
7340 WERROR err = WERR_OK;
7341 char *driver_name = NULL;
7342 uint32_t version;
7343 const char *fn;
7345 switch (p->hdr_req.opnum) {
7346 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7347 fn = "_spoolss_AddPrinterDriver";
7348 break;
7349 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7350 fn = "_spoolss_AddPrinterDriverEx";
7351 break;
7352 default:
7353 return WERR_INVALID_PARAM;
7357 * we only support the semantics of AddPrinterDriver()
7358 * i.e. only copy files that are newer than existing ones
7361 if (r->in.flags == 0) {
7362 return WERR_INVALID_PARAM;
7365 if (r->in.flags != APD_COPY_NEW_FILES) {
7366 return WERR_ACCESS_DENIED;
7369 /* FIXME */
7370 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7371 /* Clever hack from Martin Zielinski <mz@seh.de>
7372 * to allow downgrade from level 8 (Vista).
7374 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7375 r->in.info_ctr->level));
7376 return WERR_UNKNOWN_LEVEL;
7379 DEBUG(5,("Cleaning driver's information\n"));
7380 err = clean_up_driver_struct(p, r->in.info_ctr);
7381 if (!W_ERROR_IS_OK(err))
7382 goto done;
7384 DEBUG(5,("Moving driver to final destination\n"));
7385 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7386 &err)) ) {
7387 goto done;
7390 if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7391 err = WERR_ACCESS_DENIED;
7392 goto done;
7396 * I think this is where he DrvUpgradePrinter() hook would be
7397 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7398 * server. Right now, we just need to send ourselves a message
7399 * to update each printer bound to this driver. --jerry
7402 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7403 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7404 fn, driver_name));
7407 done:
7408 return err;
7411 /****************************************************************
7412 _spoolss_AddPrinterDriver
7413 ****************************************************************/
7415 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7416 struct spoolss_AddPrinterDriver *r)
7418 struct spoolss_AddPrinterDriverEx a;
7420 switch (r->in.info_ctr->level) {
7421 case 2:
7422 case 3:
7423 case 4:
7424 case 5:
7425 break;
7426 default:
7427 return WERR_UNKNOWN_LEVEL;
7430 a.in.servername = r->in.servername;
7431 a.in.info_ctr = r->in.info_ctr;
7432 a.in.flags = APD_COPY_NEW_FILES;
7434 return _spoolss_AddPrinterDriverEx(p, &a);
7437 /****************************************************************************
7438 ****************************************************************************/
7440 struct _spoolss_paths {
7441 int type;
7442 const char *share;
7443 const char *dir;
7446 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7448 static const struct _spoolss_paths spoolss_paths[]= {
7449 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7450 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7453 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7454 const char *servername,
7455 const char *environment,
7456 int component,
7457 char **path)
7459 const char *pservername = NULL;
7460 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7461 const char *short_archi;
7463 *path = NULL;
7465 /* environment may be empty */
7466 if (environment && strlen(environment)) {
7467 long_archi = environment;
7470 /* servername may be empty */
7471 if (servername && strlen(servername)) {
7472 pservername = canon_servername(servername);
7474 if (!is_myname_or_ipaddr(pservername)) {
7475 return WERR_INVALID_PARAM;
7479 if (!(short_archi = get_short_archi(long_archi))) {
7480 return WERR_INVALID_ENVIRONMENT;
7483 switch (component) {
7484 case SPOOLSS_PRTPROCS_PATH:
7485 case SPOOLSS_DRIVER_PATH:
7486 if (pservername) {
7487 *path = talloc_asprintf(mem_ctx,
7488 "\\\\%s\\%s\\%s",
7489 pservername,
7490 spoolss_paths[component].share,
7491 short_archi);
7492 } else {
7493 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7494 SPOOLSS_DEFAULT_SERVER_PATH,
7495 spoolss_paths[component].dir,
7496 short_archi);
7498 break;
7499 default:
7500 return WERR_INVALID_PARAM;
7503 if (!*path) {
7504 return WERR_NOMEM;
7507 return WERR_OK;
7510 /****************************************************************************
7511 ****************************************************************************/
7513 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7514 const char *servername,
7515 const char *environment,
7516 struct spoolss_DriverDirectoryInfo1 *r)
7518 WERROR werr;
7519 char *path = NULL;
7521 werr = compose_spoolss_server_path(mem_ctx,
7522 servername,
7523 environment,
7524 SPOOLSS_DRIVER_PATH,
7525 &path);
7526 if (!W_ERROR_IS_OK(werr)) {
7527 return werr;
7530 DEBUG(4,("printer driver directory: [%s]\n", path));
7532 r->directory_name = path;
7534 return WERR_OK;
7537 /****************************************************************
7538 _spoolss_GetPrinterDriverDirectory
7539 ****************************************************************/
7541 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7542 struct spoolss_GetPrinterDriverDirectory *r)
7544 WERROR werror;
7546 /* that's an [in out] buffer */
7548 if (!r->in.buffer && (r->in.offered != 0)) {
7549 return WERR_INVALID_PARAM;
7552 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7553 r->in.level));
7555 *r->out.needed = 0;
7557 /* r->in.level is ignored */
7559 werror = getprinterdriverdir_level_1(p->mem_ctx,
7560 r->in.server,
7561 r->in.environment,
7562 &r->out.info->info1);
7563 if (!W_ERROR_IS_OK(werror)) {
7564 TALLOC_FREE(r->out.info);
7565 return werror;
7568 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7569 r->out.info, r->in.level);
7570 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7572 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7575 /****************************************************************
7576 _spoolss_EnumPrinterData
7577 ****************************************************************/
7579 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7580 struct spoolss_EnumPrinterData *r)
7582 WERROR result;
7583 struct spoolss_EnumPrinterDataEx r2;
7584 uint32_t count;
7585 struct spoolss_PrinterEnumValues *info, *val = NULL;
7586 uint32_t needed;
7588 r2.in.handle = r->in.handle;
7589 r2.in.key_name = "PrinterDriverData";
7590 r2.in.offered = 0;
7591 r2.out.count = &count;
7592 r2.out.info = &info;
7593 r2.out.needed = &needed;
7595 result = _spoolss_EnumPrinterDataEx(p, &r2);
7596 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7597 r2.in.offered = needed;
7598 result = _spoolss_EnumPrinterDataEx(p, &r2);
7600 if (!W_ERROR_IS_OK(result)) {
7601 return result;
7605 * The NT machine wants to know the biggest size of value and data
7607 * cf: MSDN EnumPrinterData remark section
7610 if (!r->in.value_offered && !r->in.data_offered) {
7611 uint32_t biggest_valuesize = 0;
7612 uint32_t biggest_datasize = 0;
7613 int i, name_length;
7615 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7617 for (i=0; i<count; i++) {
7619 name_length = strlen(info[i].value_name);
7620 if (strlen(info[i].value_name) > biggest_valuesize) {
7621 biggest_valuesize = name_length;
7624 if (info[i].data_length > biggest_datasize) {
7625 biggest_datasize = info[i].data_length;
7628 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7629 biggest_datasize));
7632 /* the value is an UNICODE string but real_value_size is the length
7633 in bytes including the trailing 0 */
7635 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7636 *r->out.data_needed = biggest_datasize;
7638 DEBUG(6,("final values: [%d], [%d]\n",
7639 *r->out.value_needed, *r->out.data_needed));
7641 return WERR_OK;
7644 if (r->in.enum_index < count) {
7645 val = &info[r->in.enum_index];
7648 if (val == NULL) {
7649 /* out_value should default to "" or else NT4 has
7650 problems unmarshalling the response */
7652 if (r->in.value_offered) {
7653 *r->out.value_needed = 1;
7654 r->out.value_name = talloc_strdup(r, "");
7655 if (!r->out.value_name) {
7656 return WERR_NOMEM;
7658 } else {
7659 r->out.value_name = NULL;
7660 *r->out.value_needed = 0;
7663 /* the data is counted in bytes */
7665 *r->out.data_needed = r->in.data_offered;
7667 result = WERR_NO_MORE_ITEMS;
7668 } else {
7670 * the value is:
7671 * - counted in bytes in the request
7672 * - counted in UNICODE chars in the max reply
7673 * - counted in bytes in the real size
7675 * take a pause *before* coding not *during* coding
7678 /* name */
7679 if (r->in.value_offered) {
7680 r->out.value_name = talloc_strdup(r, val->value_name);
7681 if (!r->out.value_name) {
7682 return WERR_NOMEM;
7684 *r->out.value_needed = val->value_name_len;
7685 } else {
7686 r->out.value_name = NULL;
7687 *r->out.value_needed = 0;
7690 /* type */
7692 *r->out.type = val->type;
7694 /* data - counted in bytes */
7697 * See the section "Dynamically Typed Query Parameters"
7698 * in MS-RPRN.
7701 if (r->out.data && val->data && val->data->data &&
7702 val->data_length && r->in.data_offered) {
7703 memcpy(r->out.data, val->data->data,
7704 MIN(val->data_length,r->in.data_offered));
7707 *r->out.data_needed = val->data_length;
7709 result = WERR_OK;
7712 return result;
7715 /****************************************************************
7716 _spoolss_SetPrinterData
7717 ****************************************************************/
7719 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7720 struct spoolss_SetPrinterData *r)
7722 struct spoolss_SetPrinterDataEx r2;
7724 r2.in.handle = r->in.handle;
7725 r2.in.key_name = "PrinterDriverData";
7726 r2.in.value_name = r->in.value_name;
7727 r2.in.type = r->in.type;
7728 r2.in.data = r->in.data;
7729 r2.in.offered = r->in.offered;
7731 return _spoolss_SetPrinterDataEx(p, &r2);
7734 /****************************************************************
7735 _spoolss_ResetPrinter
7736 ****************************************************************/
7738 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7739 struct spoolss_ResetPrinter *r)
7741 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7742 int snum;
7744 DEBUG(5,("_spoolss_ResetPrinter\n"));
7747 * All we do is to check to see if the handle and queue is valid.
7748 * This call really doesn't mean anything to us because we only
7749 * support RAW printing. --jerry
7752 if (!Printer) {
7753 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7754 OUR_HANDLE(r->in.handle)));
7755 return WERR_BADFID;
7758 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7759 return WERR_BADFID;
7762 /* blindly return success */
7763 return WERR_OK;
7766 /****************************************************************
7767 _spoolss_DeletePrinterData
7768 ****************************************************************/
7770 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7771 struct spoolss_DeletePrinterData *r)
7773 struct spoolss_DeletePrinterDataEx r2;
7775 r2.in.handle = r->in.handle;
7776 r2.in.key_name = "PrinterDriverData";
7777 r2.in.value_name = r->in.value_name;
7779 return _spoolss_DeletePrinterDataEx(p, &r2);
7782 /****************************************************************
7783 _spoolss_AddForm
7784 ****************************************************************/
7786 WERROR _spoolss_AddForm(pipes_struct *p,
7787 struct spoolss_AddForm *r)
7789 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7790 nt_forms_struct tmpForm;
7791 int snum = -1;
7792 WERROR status = WERR_OK;
7793 NT_PRINTER_INFO_LEVEL *printer = NULL;
7794 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7796 int count=0;
7797 nt_forms_struct *list=NULL;
7798 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7799 int i;
7801 DEBUG(5,("_spoolss_AddForm\n"));
7803 if (!Printer) {
7804 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7805 OUR_HANDLE(r->in.handle)));
7806 return WERR_BADFID;
7810 /* forms can be added on printer or on the print server handle */
7812 if ( Printer->printer_type == SPLHND_PRINTER )
7814 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7815 return WERR_BADFID;
7817 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7818 if (!W_ERROR_IS_OK(status))
7819 goto done;
7822 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7823 and not a printer admin, then fail */
7825 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7826 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7827 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7828 NULL, NULL,
7829 p->server_info->ptok,
7830 lp_printer_admin(snum))) {
7831 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7832 status = WERR_ACCESS_DENIED;
7833 goto done;
7836 switch (form->flags) {
7837 case SPOOLSS_FORM_USER:
7838 case SPOOLSS_FORM_BUILTIN:
7839 case SPOOLSS_FORM_PRINTER:
7840 break;
7841 default:
7842 status = WERR_INVALID_PARAM;
7843 goto done;
7846 /* can't add if builtin */
7848 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7849 status = WERR_FILE_EXISTS;
7850 goto done;
7853 count = get_ntforms(&list);
7855 for (i=0; i < count; i++) {
7856 if (strequal(form->form_name, list[i].name)) {
7857 status = WERR_FILE_EXISTS;
7858 goto done;
7862 if(!add_a_form(&list, form, &count)) {
7863 status = WERR_NOMEM;
7864 goto done;
7867 become_root();
7868 write_ntforms(&list, count);
7869 unbecome_root();
7872 * ChangeID must always be set if this is a printer
7875 if ( Printer->printer_type == SPLHND_PRINTER )
7876 status = mod_a_printer(printer, 2);
7878 done:
7879 if ( printer )
7880 free_a_printer(&printer, 2);
7881 SAFE_FREE(list);
7883 return status;
7886 /****************************************************************
7887 _spoolss_DeleteForm
7888 ****************************************************************/
7890 WERROR _spoolss_DeleteForm(pipes_struct *p,
7891 struct spoolss_DeleteForm *r)
7893 const char *form_name = r->in.form_name;
7894 nt_forms_struct tmpForm;
7895 int count=0;
7896 nt_forms_struct *list=NULL;
7897 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7898 int snum = -1;
7899 WERROR status = WERR_OK;
7900 NT_PRINTER_INFO_LEVEL *printer = NULL;
7901 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7902 bool ret = false;
7904 DEBUG(5,("_spoolss_DeleteForm\n"));
7906 if (!Printer) {
7907 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7908 OUR_HANDLE(r->in.handle)));
7909 return WERR_BADFID;
7912 /* forms can be deleted on printer of on the print server handle */
7914 if ( Printer->printer_type == SPLHND_PRINTER )
7916 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7917 return WERR_BADFID;
7919 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7920 if (!W_ERROR_IS_OK(status))
7921 goto done;
7924 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7925 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7926 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7927 NULL, NULL,
7928 p->server_info->ptok,
7929 lp_printer_admin(snum))) {
7930 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7931 return WERR_ACCESS_DENIED;
7935 /* can't delete if builtin */
7937 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7938 status = WERR_INVALID_PARAM;
7939 goto done;
7942 count = get_ntforms(&list);
7944 become_root();
7945 ret = delete_a_form(&list, form_name, &count, &status);
7946 unbecome_root();
7947 if (ret == false) {
7948 goto done;
7952 * ChangeID must always be set if this is a printer
7955 if ( Printer->printer_type == SPLHND_PRINTER )
7956 status = mod_a_printer(printer, 2);
7958 done:
7959 if ( printer )
7960 free_a_printer(&printer, 2);
7961 SAFE_FREE(list);
7963 return status;
7966 /****************************************************************
7967 _spoolss_SetForm
7968 ****************************************************************/
7970 WERROR _spoolss_SetForm(pipes_struct *p,
7971 struct spoolss_SetForm *r)
7973 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7974 nt_forms_struct tmpForm;
7975 int snum = -1;
7976 WERROR status = WERR_OK;
7977 NT_PRINTER_INFO_LEVEL *printer = NULL;
7978 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7980 int count=0;
7981 nt_forms_struct *list=NULL;
7982 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7984 DEBUG(5,("_spoolss_SetForm\n"));
7986 if (!Printer) {
7987 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7988 OUR_HANDLE(r->in.handle)));
7989 return WERR_BADFID;
7992 /* forms can be modified on printer of on the print server handle */
7994 if ( Printer->printer_type == SPLHND_PRINTER )
7996 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7997 return WERR_BADFID;
7999 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8000 if (!W_ERROR_IS_OK(status))
8001 goto done;
8004 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8005 and not a printer admin, then fail */
8007 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8008 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8009 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8010 NULL, NULL,
8011 p->server_info->ptok,
8012 lp_printer_admin(snum))) {
8013 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8014 status = WERR_ACCESS_DENIED;
8015 goto done;
8018 /* can't set if builtin */
8019 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8020 status = WERR_INVALID_PARAM;
8021 goto done;
8024 count = get_ntforms(&list);
8025 update_a_form(&list, form, count);
8026 become_root();
8027 write_ntforms(&list, count);
8028 unbecome_root();
8031 * ChangeID must always be set if this is a printer
8034 if ( Printer->printer_type == SPLHND_PRINTER )
8035 status = mod_a_printer(printer, 2);
8038 done:
8039 if ( printer )
8040 free_a_printer(&printer, 2);
8041 SAFE_FREE(list);
8043 return status;
8046 /****************************************************************************
8047 fill_print_processor1
8048 ****************************************************************************/
8050 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8051 struct spoolss_PrintProcessorInfo1 *r,
8052 const char *print_processor_name)
8054 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8055 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8057 return WERR_OK;
8060 /****************************************************************************
8061 enumprintprocessors level 1.
8062 ****************************************************************************/
8064 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8065 union spoolss_PrintProcessorInfo **info_p,
8066 uint32_t *count)
8068 union spoolss_PrintProcessorInfo *info;
8069 WERROR result;
8071 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8072 W_ERROR_HAVE_NO_MEMORY(info);
8074 *count = 1;
8076 result = fill_print_processor1(info, &info[0].info1, "winprint");
8077 if (!W_ERROR_IS_OK(result)) {
8078 goto out;
8081 out:
8082 if (!W_ERROR_IS_OK(result)) {
8083 TALLOC_FREE(info);
8084 *count = 0;
8085 return result;
8088 *info_p = info;
8090 return WERR_OK;
8093 /****************************************************************
8094 _spoolss_EnumPrintProcessors
8095 ****************************************************************/
8097 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8098 struct spoolss_EnumPrintProcessors *r)
8100 WERROR result;
8102 /* that's an [in out] buffer */
8104 if (!r->in.buffer && (r->in.offered != 0)) {
8105 return WERR_INVALID_PARAM;
8108 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8111 * Enumerate the print processors ...
8113 * Just reply with "winprint", to keep NT happy
8114 * and I can use my nice printer checker.
8117 *r->out.count = 0;
8118 *r->out.needed = 0;
8119 *r->out.info = NULL;
8121 switch (r->in.level) {
8122 case 1:
8123 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8124 r->out.count);
8125 break;
8126 default:
8127 return WERR_UNKNOWN_LEVEL;
8130 if (!W_ERROR_IS_OK(result)) {
8131 return result;
8134 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8135 spoolss_EnumPrintProcessors,
8136 *r->out.info, r->in.level,
8137 *r->out.count);
8138 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8139 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8141 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8144 /****************************************************************************
8145 fill_printprocdatatype1
8146 ****************************************************************************/
8148 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8149 struct spoolss_PrintProcDataTypesInfo1 *r,
8150 const char *name_array)
8152 r->name_array = talloc_strdup(mem_ctx, name_array);
8153 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8155 return WERR_OK;
8158 /****************************************************************************
8159 enumprintprocdatatypes level 1.
8160 ****************************************************************************/
8162 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8163 union spoolss_PrintProcDataTypesInfo **info_p,
8164 uint32_t *count)
8166 WERROR result;
8167 union spoolss_PrintProcDataTypesInfo *info;
8169 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8170 W_ERROR_HAVE_NO_MEMORY(info);
8172 *count = 1;
8174 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8175 if (!W_ERROR_IS_OK(result)) {
8176 goto out;
8179 out:
8180 if (!W_ERROR_IS_OK(result)) {
8181 TALLOC_FREE(info);
8182 *count = 0;
8183 return result;
8186 *info_p = info;
8188 return WERR_OK;
8191 /****************************************************************
8192 _spoolss_EnumPrintProcDataTypes
8193 ****************************************************************/
8195 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8196 struct spoolss_EnumPrintProcDataTypes *r)
8198 WERROR result;
8200 /* that's an [in out] buffer */
8202 if (!r->in.buffer && (r->in.offered != 0)) {
8203 return WERR_INVALID_PARAM;
8206 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8208 *r->out.count = 0;
8209 *r->out.needed = 0;
8210 *r->out.info = NULL;
8212 switch (r->in.level) {
8213 case 1:
8214 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8215 r->out.count);
8216 break;
8217 default:
8218 return WERR_UNKNOWN_LEVEL;
8221 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8222 spoolss_EnumPrintProcDataTypes,
8223 *r->out.info, r->in.level,
8224 *r->out.count);
8225 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8226 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8228 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8231 /****************************************************************************
8232 fill_monitor_1
8233 ****************************************************************************/
8235 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8236 struct spoolss_MonitorInfo1 *r,
8237 const char *monitor_name)
8239 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8240 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8242 return WERR_OK;
8245 /****************************************************************************
8246 fill_monitor_2
8247 ****************************************************************************/
8249 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8250 struct spoolss_MonitorInfo2 *r,
8251 const char *monitor_name,
8252 const char *environment,
8253 const char *dll_name)
8255 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8256 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8257 r->environment = talloc_strdup(mem_ctx, environment);
8258 W_ERROR_HAVE_NO_MEMORY(r->environment);
8259 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8260 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8262 return WERR_OK;
8265 /****************************************************************************
8266 enumprintmonitors level 1.
8267 ****************************************************************************/
8269 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8270 union spoolss_MonitorInfo **info_p,
8271 uint32_t *count)
8273 union spoolss_MonitorInfo *info;
8274 WERROR result = WERR_OK;
8276 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8277 W_ERROR_HAVE_NO_MEMORY(info);
8279 *count = 2;
8281 result = fill_monitor_1(info, &info[0].info1,
8282 SPL_LOCAL_PORT);
8283 if (!W_ERROR_IS_OK(result)) {
8284 goto out;
8287 result = fill_monitor_1(info, &info[1].info1,
8288 SPL_TCPIP_PORT);
8289 if (!W_ERROR_IS_OK(result)) {
8290 goto out;
8293 out:
8294 if (!W_ERROR_IS_OK(result)) {
8295 TALLOC_FREE(info);
8296 *count = 0;
8297 return result;
8300 *info_p = info;
8302 return WERR_OK;
8305 /****************************************************************************
8306 enumprintmonitors level 2.
8307 ****************************************************************************/
8309 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8310 union spoolss_MonitorInfo **info_p,
8311 uint32_t *count)
8313 union spoolss_MonitorInfo *info;
8314 WERROR result = WERR_OK;
8316 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8317 W_ERROR_HAVE_NO_MEMORY(info);
8319 *count = 2;
8321 result = fill_monitor_2(info, &info[0].info2,
8322 SPL_LOCAL_PORT,
8323 "Windows NT X86", /* FIXME */
8324 "localmon.dll");
8325 if (!W_ERROR_IS_OK(result)) {
8326 goto out;
8329 result = fill_monitor_2(info, &info[1].info2,
8330 SPL_TCPIP_PORT,
8331 "Windows NT X86", /* FIXME */
8332 "tcpmon.dll");
8333 if (!W_ERROR_IS_OK(result)) {
8334 goto out;
8337 out:
8338 if (!W_ERROR_IS_OK(result)) {
8339 TALLOC_FREE(info);
8340 *count = 0;
8341 return result;
8344 *info_p = info;
8346 return WERR_OK;
8349 /****************************************************************
8350 _spoolss_EnumMonitors
8351 ****************************************************************/
8353 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8354 struct spoolss_EnumMonitors *r)
8356 WERROR result;
8358 /* that's an [in out] buffer */
8360 if (!r->in.buffer && (r->in.offered != 0)) {
8361 return WERR_INVALID_PARAM;
8364 DEBUG(5,("_spoolss_EnumMonitors\n"));
8367 * Enumerate the print monitors ...
8369 * Just reply with "Local Port", to keep NT happy
8370 * and I can use my nice printer checker.
8373 *r->out.count = 0;
8374 *r->out.needed = 0;
8375 *r->out.info = NULL;
8377 switch (r->in.level) {
8378 case 1:
8379 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8380 r->out.count);
8381 break;
8382 case 2:
8383 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8384 r->out.count);
8385 break;
8386 default:
8387 return WERR_UNKNOWN_LEVEL;
8390 if (!W_ERROR_IS_OK(result)) {
8391 return result;
8394 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8395 spoolss_EnumMonitors,
8396 *r->out.info, r->in.level,
8397 *r->out.count);
8398 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8399 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8401 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8404 /****************************************************************************
8405 ****************************************************************************/
8407 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8408 const print_queue_struct *queue,
8409 int count, int snum,
8410 const NT_PRINTER_INFO_LEVEL *ntprinter,
8411 uint32_t jobid,
8412 struct spoolss_JobInfo1 *r)
8414 int i = 0;
8415 bool found = false;
8417 for (i=0; i<count; i++) {
8418 if (queue[i].job == (int)jobid) {
8419 found = true;
8420 break;
8424 if (found == false) {
8425 /* NT treats not found as bad param... yet another bad choice */
8426 return WERR_INVALID_PARAM;
8429 return fill_job_info1(mem_ctx,
8431 &queue[i],
8433 snum,
8434 ntprinter);
8437 /****************************************************************************
8438 ****************************************************************************/
8440 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8441 const print_queue_struct *queue,
8442 int count, int snum,
8443 const NT_PRINTER_INFO_LEVEL *ntprinter,
8444 uint32_t jobid,
8445 struct spoolss_JobInfo2 *r)
8447 int i = 0;
8448 bool found = false;
8449 struct spoolss_DeviceMode *devmode;
8450 NT_DEVICEMODE *nt_devmode;
8451 WERROR result;
8453 for (i=0; i<count; i++) {
8454 if (queue[i].job == (int)jobid) {
8455 found = true;
8456 break;
8460 if (found == false) {
8461 /* NT treats not found as bad param... yet another bad
8462 choice */
8463 return WERR_INVALID_PARAM;
8467 * if the print job does not have a DEVMODE associated with it,
8468 * just use the one for the printer. A NULL devicemode is not
8469 * a failure condition
8472 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8473 if (nt_devmode) {
8474 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8475 W_ERROR_HAVE_NO_MEMORY(devmode);
8476 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8477 if (!W_ERROR_IS_OK(result)) {
8478 return result;
8480 } else {
8481 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8482 W_ERROR_HAVE_NO_MEMORY(devmode);
8485 return fill_job_info2(mem_ctx,
8487 &queue[i],
8489 snum,
8490 ntprinter,
8491 devmode);
8494 /****************************************************************
8495 _spoolss_GetJob
8496 ****************************************************************/
8498 WERROR _spoolss_GetJob(pipes_struct *p,
8499 struct spoolss_GetJob *r)
8501 WERROR result = WERR_OK;
8502 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8503 int snum;
8504 int count;
8505 print_queue_struct *queue = NULL;
8506 print_status_struct prt_status;
8508 /* that's an [in out] buffer */
8510 if (!r->in.buffer && (r->in.offered != 0)) {
8511 return WERR_INVALID_PARAM;
8514 DEBUG(5,("_spoolss_GetJob\n"));
8516 *r->out.needed = 0;
8518 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8519 return WERR_BADFID;
8522 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8523 if (!W_ERROR_IS_OK(result)) {
8524 return result;
8527 count = print_queue_status(snum, &queue, &prt_status);
8529 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8530 count, prt_status.status, prt_status.message));
8532 switch (r->in.level) {
8533 case 1:
8534 result = getjob_level_1(p->mem_ctx,
8535 queue, count, snum, ntprinter,
8536 r->in.job_id, &r->out.info->info1);
8537 break;
8538 case 2:
8539 result = getjob_level_2(p->mem_ctx,
8540 queue, count, snum, ntprinter,
8541 r->in.job_id, &r->out.info->info2);
8542 break;
8543 default:
8544 result = WERR_UNKNOWN_LEVEL;
8545 break;
8548 SAFE_FREE(queue);
8549 free_a_printer(&ntprinter, 2);
8551 if (!W_ERROR_IS_OK(result)) {
8552 TALLOC_FREE(r->out.info);
8553 return result;
8556 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8557 r->in.level);
8558 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8560 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8563 /****************************************************************
8564 _spoolss_GetPrinterDataEx
8565 ****************************************************************/
8567 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8568 struct spoolss_GetPrinterDataEx *r)
8571 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8572 struct regval_blob *val = NULL;
8573 NT_PRINTER_INFO_LEVEL *printer = NULL;
8574 int snum = 0;
8575 WERROR result = WERR_OK;
8576 DATA_BLOB blob;
8578 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8580 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8581 r->in.key_name, r->in.value_name));
8583 /* in case of problem, return some default values */
8585 *r->out.needed = 0;
8586 *r->out.type = REG_NONE;
8588 if (!Printer) {
8589 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8590 OUR_HANDLE(r->in.handle)));
8591 result = WERR_BADFID;
8592 goto done;
8595 /* Is the handle to a printer or to the server? */
8597 if (Printer->printer_type == SPLHND_SERVER) {
8599 union spoolss_PrinterData data;
8601 result = getprinterdata_printer_server(p->mem_ctx,
8602 r->in.value_name,
8603 r->out.type,
8604 &data);
8605 if (!W_ERROR_IS_OK(result)) {
8606 goto done;
8609 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8610 *r->out.type, &data);
8611 if (!W_ERROR_IS_OK(result)) {
8612 goto done;
8615 *r->out.needed = blob.length;
8617 if (r->in.offered >= *r->out.needed) {
8618 memcpy(r->out.data, blob.data, blob.length);
8621 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8624 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8625 result = WERR_BADFID;
8626 goto done;
8629 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8630 if (!W_ERROR_IS_OK(result)) {
8631 goto done;
8634 /* check to see if the keyname is valid */
8635 if (!strlen(r->in.key_name)) {
8636 result = WERR_INVALID_PARAM;
8637 goto done;
8640 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8642 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8643 strequal(r->in.value_name, "ChangeId")) {
8644 *r->out.type = REG_DWORD;
8645 *r->out.needed = 4;
8646 if (r->in.offered >= *r->out.needed) {
8647 SIVAL(r->out.data, 0, printer->info_2->changeid);
8648 result = WERR_OK;
8650 goto done;
8653 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8654 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8655 "Invalid keyname [%s]\n", r->in.key_name ));
8656 result = WERR_BADFILE;
8657 goto done;
8660 val = get_printer_data(printer->info_2,
8661 r->in.key_name, r->in.value_name);
8662 if (!val) {
8663 result = WERR_BADFILE;
8664 goto done;
8667 *r->out.needed = regval_size(val);
8668 *r->out.type = regval_type(val);
8670 if (r->in.offered >= *r->out.needed) {
8671 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8673 done:
8674 if (printer) {
8675 free_a_printer(&printer, 2);
8678 if (!W_ERROR_IS_OK(result)) {
8679 return result;
8682 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8683 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8685 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8688 /****************************************************************
8689 _spoolss_SetPrinterDataEx
8690 ****************************************************************/
8692 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8693 struct spoolss_SetPrinterDataEx *r)
8695 NT_PRINTER_INFO_LEVEL *printer = NULL;
8696 int snum = 0;
8697 WERROR result = WERR_OK;
8698 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8699 char *oid_string;
8701 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8703 /* From MSDN documentation of SetPrinterDataEx: pass request to
8704 SetPrinterData if key is "PrinterDriverData" */
8706 if (!Printer) {
8707 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8708 OUR_HANDLE(r->in.handle)));
8709 return WERR_BADFID;
8712 if (Printer->printer_type == SPLHND_SERVER) {
8713 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8714 "Not implemented for server handles yet\n"));
8715 return WERR_INVALID_PARAM;
8718 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8719 return WERR_BADFID;
8723 * Access check : NT returns "access denied" if you make a
8724 * SetPrinterData call without the necessary privildge.
8725 * we were originally returning OK if nothing changed
8726 * which made Win2k issue **a lot** of SetPrinterData
8727 * when connecting to a printer --jerry
8730 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8731 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8732 "change denied by handle access permissions\n"));
8733 return WERR_ACCESS_DENIED;
8736 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8737 if (!W_ERROR_IS_OK(result)) {
8738 return result;
8741 /* check for OID in valuename */
8743 oid_string = strchr(r->in.value_name, ',');
8744 if (oid_string) {
8745 *oid_string = '\0';
8746 oid_string++;
8749 /* save the registry data */
8751 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8752 r->in.type, r->in.data, r->in.offered);
8754 if (W_ERROR_IS_OK(result)) {
8755 /* save the OID if one was specified */
8756 if (oid_string) {
8757 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8758 r->in.key_name, SPOOL_OID_KEY);
8759 if (!str) {
8760 result = WERR_NOMEM;
8761 goto done;
8765 * I'm not checking the status here on purpose. Don't know
8766 * if this is right, but I'm returning the status from the
8767 * previous set_printer_dataex() call. I have no idea if
8768 * this is right. --jerry
8771 set_printer_dataex(printer, str, r->in.value_name,
8772 REG_SZ, (uint8_t *)oid_string,
8773 strlen(oid_string)+1);
8776 result = mod_a_printer(printer, 2);
8779 done:
8780 free_a_printer(&printer, 2);
8782 return result;
8785 /****************************************************************
8786 _spoolss_DeletePrinterDataEx
8787 ****************************************************************/
8789 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8790 struct spoolss_DeletePrinterDataEx *r)
8792 NT_PRINTER_INFO_LEVEL *printer = NULL;
8793 int snum=0;
8794 WERROR status = WERR_OK;
8795 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8797 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8799 if (!Printer) {
8800 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8801 "Invalid handle (%s:%u:%u).\n",
8802 OUR_HANDLE(r->in.handle)));
8803 return WERR_BADFID;
8806 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8807 return WERR_BADFID;
8809 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8810 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8811 "printer properties change denied by handle\n"));
8812 return WERR_ACCESS_DENIED;
8815 if (!r->in.value_name || !r->in.key_name) {
8816 return WERR_NOMEM;
8819 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8820 if (!W_ERROR_IS_OK(status))
8821 return status;
8823 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8825 if ( W_ERROR_IS_OK(status) )
8826 mod_a_printer( printer, 2 );
8828 free_a_printer(&printer, 2);
8830 return status;
8833 /****************************************************************
8834 _spoolss_EnumPrinterKey
8835 ****************************************************************/
8837 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8838 struct spoolss_EnumPrinterKey *r)
8840 fstring *keynames = NULL;
8841 int num_keys;
8842 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8843 NT_PRINTER_DATA *data;
8844 NT_PRINTER_INFO_LEVEL *printer = NULL;
8845 int snum = 0;
8846 WERROR result = WERR_BADFILE;
8847 int i;
8848 const char **array = NULL;
8849 DATA_BLOB blob;
8851 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8853 if (!Printer) {
8854 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8855 OUR_HANDLE(r->in.handle)));
8856 return WERR_BADFID;
8859 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8860 return WERR_BADFID;
8863 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8864 if (!W_ERROR_IS_OK(result)) {
8865 return result;
8868 /* get the list of subkey names */
8870 data = printer->info_2->data;
8872 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8873 if (num_keys == -1) {
8874 result = WERR_BADFILE;
8875 goto done;
8878 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8879 if (!array) {
8880 result = WERR_NOMEM;
8881 goto done;
8884 if (!num_keys) {
8885 array[0] = talloc_strdup(array, "");
8886 if (!array[0]) {
8887 result = WERR_NOMEM;
8888 goto done;
8892 for (i=0; i < num_keys; i++) {
8894 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8895 keynames[i]));
8897 array[i] = talloc_strdup(array, keynames[i]);
8898 if (!array[i]) {
8899 result = WERR_NOMEM;
8900 goto done;
8904 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8905 result = WERR_NOMEM;
8906 goto done;
8909 *r->out._ndr_size = r->in.offered / 2;
8910 *r->out.needed = blob.length;
8912 if (r->in.offered < *r->out.needed) {
8913 result = WERR_MORE_DATA;
8914 } else {
8915 result = WERR_OK;
8916 r->out.key_buffer->string_array = array;
8919 done:
8920 if (!W_ERROR_IS_OK(result)) {
8921 TALLOC_FREE(array);
8922 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8923 *r->out.needed = 0;
8927 free_a_printer(&printer, 2);
8928 SAFE_FREE(keynames);
8930 return result;
8933 /****************************************************************
8934 _spoolss_DeletePrinterKey
8935 ****************************************************************/
8937 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8938 struct spoolss_DeletePrinterKey *r)
8940 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8941 NT_PRINTER_INFO_LEVEL *printer = NULL;
8942 int snum=0;
8943 WERROR status;
8945 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8947 if (!Printer) {
8948 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8949 OUR_HANDLE(r->in.handle)));
8950 return WERR_BADFID;
8953 /* if keyname == NULL, return error */
8955 if ( !r->in.key_name )
8956 return WERR_INVALID_PARAM;
8958 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8959 return WERR_BADFID;
8961 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8962 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8963 "printer properties change denied by handle\n"));
8964 return WERR_ACCESS_DENIED;
8967 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8968 if (!W_ERROR_IS_OK(status))
8969 return status;
8971 /* delete the key and all subneys */
8973 status = delete_all_printer_data( printer->info_2, r->in.key_name );
8975 if ( W_ERROR_IS_OK(status) )
8976 status = mod_a_printer(printer, 2);
8978 free_a_printer( &printer, 2 );
8980 return status;
8983 /****************************************************************
8984 ****************************************************************/
8986 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8987 struct regval_blob *v,
8988 struct spoolss_PrinterEnumValues *r)
8990 r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
8991 W_ERROR_HAVE_NO_MEMORY(r->data);
8993 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
8994 W_ERROR_HAVE_NO_MEMORY(r->value_name);
8996 r->value_name_len = strlen_m_term(regval_name(v)) * 2;
8998 r->type = regval_type(v);
8999 r->data_length = regval_size(v);
9001 if (r->data_length) {
9002 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9005 return WERR_OK;
9008 /****************************************************************
9009 _spoolss_EnumPrinterDataEx
9010 ****************************************************************/
9012 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9013 struct spoolss_EnumPrinterDataEx *r)
9015 uint32_t count = 0;
9016 NT_PRINTER_INFO_LEVEL *printer = NULL;
9017 struct spoolss_PrinterEnumValues *info = NULL;
9018 NT_PRINTER_DATA *p_data;
9019 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9020 int snum;
9021 WERROR result;
9022 int key_index;
9023 int i;
9025 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9027 *r->out.count = 0;
9028 *r->out.needed = 0;
9029 *r->out.info = NULL;
9031 if (!Printer) {
9032 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9033 OUR_HANDLE(r->in.handle)));
9034 return WERR_BADFID;
9038 * first check for a keyname of NULL or "". Win2k seems to send
9039 * this a lot and we should send back WERR_INVALID_PARAM
9040 * no need to spend time looking up the printer in this case.
9041 * --jerry
9044 if (!strlen(r->in.key_name)) {
9045 result = WERR_INVALID_PARAM;
9046 goto done;
9049 /* get the printer off of disk */
9051 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9052 return WERR_BADFID;
9055 ZERO_STRUCT(printer);
9056 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9057 if (!W_ERROR_IS_OK(result)) {
9058 return result;
9061 /* now look for a match on the key name */
9063 p_data = printer->info_2->data;
9065 key_index = lookup_printerkey(p_data, r->in.key_name);
9066 if (key_index == -1) {
9067 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9068 r->in.key_name));
9069 result = WERR_INVALID_PARAM;
9070 goto done;
9073 /* allocate the memory for the array of pointers -- if necessary */
9075 count = regval_ctr_numvals(p_data->keys[key_index].values);
9076 if (!count) {
9077 result = WERR_OK; /* ??? */
9078 goto done;
9081 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9082 struct spoolss_PrinterEnumValues,
9083 count);
9084 if (!info) {
9085 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9086 result = WERR_NOMEM;
9087 goto done;
9091 * loop through all params and build the array to pass
9092 * back to the client
9095 for (i=0; i < count; i++) {
9097 struct regval_blob *val;
9099 /* lookup the registry value */
9101 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9103 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9105 /* copy the data */
9107 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9108 if (!W_ERROR_IS_OK(result)) {
9109 goto done;
9113 #if 0 /* FIXME - gd */
9114 /* housekeeping information in the reply */
9116 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9117 * the hand marshalled container size is a multiple
9118 * of 4 bytes for RPC alignment.
9121 if (needed % 4) {
9122 needed += 4-(needed % 4);
9124 #endif
9125 *r->out.count = count;
9126 *r->out.info = info;
9128 done:
9130 if (printer) {
9131 free_a_printer(&printer, 2);
9134 if (!W_ERROR_IS_OK(result)) {
9135 return result;
9138 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9139 spoolss_EnumPrinterDataEx,
9140 *r->out.info,
9141 *r->out.count);
9142 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9143 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9145 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9148 /****************************************************************************
9149 ****************************************************************************/
9151 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9152 const char *servername,
9153 const char *environment,
9154 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9156 WERROR werr;
9157 char *path = NULL;
9159 werr = compose_spoolss_server_path(mem_ctx,
9160 servername,
9161 environment,
9162 SPOOLSS_PRTPROCS_PATH,
9163 &path);
9164 if (!W_ERROR_IS_OK(werr)) {
9165 return werr;
9168 DEBUG(4,("print processor directory: [%s]\n", path));
9170 r->directory_name = path;
9172 return WERR_OK;
9175 /****************************************************************
9176 _spoolss_GetPrintProcessorDirectory
9177 ****************************************************************/
9179 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9180 struct spoolss_GetPrintProcessorDirectory *r)
9182 WERROR result;
9184 /* that's an [in out] buffer */
9186 if (!r->in.buffer && (r->in.offered != 0)) {
9187 return WERR_INVALID_PARAM;
9190 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9191 r->in.level));
9193 *r->out.needed = 0;
9195 /* r->in.level is ignored */
9197 /* We always should reply with a local print processor directory so that
9198 * users are not forced to have a [prnproc$] share on the Samba spoolss
9199 * server - Guenther */
9201 result = getprintprocessordirectory_level_1(p->mem_ctx,
9202 NULL, /* r->in.server */
9203 r->in.environment,
9204 &r->out.info->info1);
9205 if (!W_ERROR_IS_OK(result)) {
9206 TALLOC_FREE(r->out.info);
9207 return result;
9210 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9211 r->out.info, r->in.level);
9212 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9214 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9217 /*******************************************************************
9218 ********************************************************************/
9220 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9221 const char *dllname)
9223 enum ndr_err_code ndr_err;
9224 struct spoolss_MonitorUi ui;
9226 ui.dll_name = dllname;
9228 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9229 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9230 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9231 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9233 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9236 /*******************************************************************
9237 Streams the monitor UI DLL name in UNICODE
9238 *******************************************************************/
9240 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9241 NT_USER_TOKEN *token, DATA_BLOB *in,
9242 DATA_BLOB *out, uint32_t *needed)
9244 const char *dllname = "tcpmonui.dll";
9246 *needed = (strlen(dllname)+1) * 2;
9248 if (out->length < *needed) {
9249 return WERR_INSUFFICIENT_BUFFER;
9252 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9253 return WERR_NOMEM;
9256 return WERR_OK;
9259 /*******************************************************************
9260 ********************************************************************/
9262 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9263 struct spoolss_PortData1 *port1,
9264 const DATA_BLOB *buf)
9266 enum ndr_err_code ndr_err;
9267 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9268 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9269 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9270 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9272 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9275 /*******************************************************************
9276 ********************************************************************/
9278 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9279 struct spoolss_PortData2 *port2,
9280 const DATA_BLOB *buf)
9282 enum ndr_err_code ndr_err;
9283 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9284 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9285 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9286 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9288 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9291 /*******************************************************************
9292 Create a new TCP/IP port
9293 *******************************************************************/
9295 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9296 NT_USER_TOKEN *token, DATA_BLOB *in,
9297 DATA_BLOB *out, uint32_t *needed)
9299 struct spoolss_PortData1 port1;
9300 struct spoolss_PortData2 port2;
9301 char *device_uri = NULL;
9302 uint32_t version;
9304 const char *portname;
9305 const char *hostaddress;
9306 const char *queue;
9307 uint32_t port_number;
9308 uint32_t protocol;
9310 /* peek for spoolss_PortData version */
9312 if (!in || (in->length < (128 + 4))) {
9313 return WERR_GENERAL_FAILURE;
9316 version = IVAL(in->data, 128);
9318 switch (version) {
9319 case 1:
9320 ZERO_STRUCT(port1);
9322 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9323 return WERR_NOMEM;
9326 portname = port1.portname;
9327 hostaddress = port1.hostaddress;
9328 queue = port1.queue;
9329 protocol = port1.protocol;
9330 port_number = port1.port_number;
9332 break;
9333 case 2:
9334 ZERO_STRUCT(port2);
9336 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9337 return WERR_NOMEM;
9340 portname = port2.portname;
9341 hostaddress = port2.hostaddress;
9342 queue = port2.queue;
9343 protocol = port2.protocol;
9344 port_number = port2.port_number;
9346 break;
9347 default:
9348 DEBUG(1,("xcvtcp_addport: "
9349 "unknown version of port_data: %d\n", version));
9350 return WERR_UNKNOWN_PORT;
9353 /* create the device URI and call the add_port_hook() */
9355 switch (protocol) {
9356 case PROTOCOL_RAWTCP_TYPE:
9357 device_uri = talloc_asprintf(mem_ctx,
9358 "socket://%s:%d/", hostaddress,
9359 port_number);
9360 break;
9362 case PROTOCOL_LPR_TYPE:
9363 device_uri = talloc_asprintf(mem_ctx,
9364 "lpr://%s/%s", hostaddress, queue );
9365 break;
9367 default:
9368 return WERR_UNKNOWN_PORT;
9371 if (!device_uri) {
9372 return WERR_NOMEM;
9375 return add_port_hook(mem_ctx, token, portname, device_uri);
9378 /*******************************************************************
9379 *******************************************************************/
9381 struct xcv_api_table xcvtcp_cmds[] = {
9382 { "MonitorUI", xcvtcp_monitorui },
9383 { "AddPort", xcvtcp_addport},
9384 { NULL, NULL }
9387 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9388 NT_USER_TOKEN *token, const char *command,
9389 DATA_BLOB *inbuf,
9390 DATA_BLOB *outbuf,
9391 uint32_t *needed )
9393 int i;
9395 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9397 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9398 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9399 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9402 return WERR_BADFUNC;
9405 /*******************************************************************
9406 *******************************************************************/
9407 #if 0 /* don't support management using the "Local Port" monitor */
9409 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9410 NT_USER_TOKEN *token, DATA_BLOB *in,
9411 DATA_BLOB *out, uint32_t *needed)
9413 const char *dllname = "localui.dll";
9415 *needed = (strlen(dllname)+1) * 2;
9417 if (out->length < *needed) {
9418 return WERR_INSUFFICIENT_BUFFER;
9421 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9422 return WERR_NOMEM;
9425 return WERR_OK;
9428 /*******************************************************************
9429 *******************************************************************/
9431 struct xcv_api_table xcvlocal_cmds[] = {
9432 { "MonitorUI", xcvlocal_monitorui },
9433 { NULL, NULL }
9435 #else
9436 struct xcv_api_table xcvlocal_cmds[] = {
9437 { NULL, NULL }
9439 #endif
9443 /*******************************************************************
9444 *******************************************************************/
9446 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9447 NT_USER_TOKEN *token, const char *command,
9448 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9449 uint32_t *needed)
9451 int i;
9453 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9455 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9456 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9457 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9459 return WERR_BADFUNC;
9462 /****************************************************************
9463 _spoolss_XcvData
9464 ****************************************************************/
9466 WERROR _spoolss_XcvData(pipes_struct *p,
9467 struct spoolss_XcvData *r)
9469 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9470 DATA_BLOB out_data = data_blob_null;
9471 WERROR werror;
9473 if (!Printer) {
9474 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9475 OUR_HANDLE(r->in.handle)));
9476 return WERR_BADFID;
9479 /* Has to be a handle to the TCP/IP port monitor */
9481 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9482 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9483 return WERR_BADFID;
9486 /* requires administrative access to the server */
9488 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9489 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9490 return WERR_ACCESS_DENIED;
9493 /* Allocate the outgoing buffer */
9495 if (r->in.out_data_size) {
9496 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9497 if (out_data.data == NULL) {
9498 return WERR_NOMEM;
9502 switch ( Printer->printer_type ) {
9503 case SPLHND_PORTMON_TCP:
9504 werror = process_xcvtcp_command(p->mem_ctx,
9505 p->server_info->ptok,
9506 r->in.function_name,
9507 &r->in.in_data, &out_data,
9508 r->out.needed);
9509 break;
9510 case SPLHND_PORTMON_LOCAL:
9511 werror = process_xcvlocal_command(p->mem_ctx,
9512 p->server_info->ptok,
9513 r->in.function_name,
9514 &r->in.in_data, &out_data,
9515 r->out.needed);
9516 break;
9517 default:
9518 werror = WERR_INVALID_PRINT_MONITOR;
9521 if (!W_ERROR_IS_OK(werror)) {
9522 return werror;
9525 *r->out.status_code = 0;
9527 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9528 memcpy(r->out.out_data, out_data.data,
9529 MIN(r->in.out_data_size, out_data.length));
9532 return WERR_OK;
9535 /****************************************************************
9536 _spoolss_AddPrintProcessor
9537 ****************************************************************/
9539 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9540 struct spoolss_AddPrintProcessor *r)
9542 /* for now, just indicate success and ignore the add. We'll
9543 automatically set the winprint processor for printer
9544 entries later. Used to debug the LexMark Optra S 1855 PCL
9545 driver --jerry */
9547 return WERR_OK;
9550 /****************************************************************
9551 _spoolss_AddPort
9552 ****************************************************************/
9554 WERROR _spoolss_AddPort(pipes_struct *p,
9555 struct spoolss_AddPort *r)
9557 /* do what w2k3 does */
9559 return WERR_NOT_SUPPORTED;
9562 /****************************************************************
9563 _spoolss_GetPrinterDriver
9564 ****************************************************************/
9566 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9567 struct spoolss_GetPrinterDriver *r)
9569 p->rng_fault_state = true;
9570 return WERR_NOT_SUPPORTED;
9573 /****************************************************************
9574 _spoolss_ReadPrinter
9575 ****************************************************************/
9577 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9578 struct spoolss_ReadPrinter *r)
9580 p->rng_fault_state = true;
9581 return WERR_NOT_SUPPORTED;
9584 /****************************************************************
9585 _spoolss_WaitForPrinterChange
9586 ****************************************************************/
9588 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9589 struct spoolss_WaitForPrinterChange *r)
9591 p->rng_fault_state = true;
9592 return WERR_NOT_SUPPORTED;
9595 /****************************************************************
9596 _spoolss_ConfigurePort
9597 ****************************************************************/
9599 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9600 struct spoolss_ConfigurePort *r)
9602 p->rng_fault_state = true;
9603 return WERR_NOT_SUPPORTED;
9606 /****************************************************************
9607 _spoolss_DeletePort
9608 ****************************************************************/
9610 WERROR _spoolss_DeletePort(pipes_struct *p,
9611 struct spoolss_DeletePort *r)
9613 p->rng_fault_state = true;
9614 return WERR_NOT_SUPPORTED;
9617 /****************************************************************
9618 _spoolss_CreatePrinterIC
9619 ****************************************************************/
9621 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9622 struct spoolss_CreatePrinterIC *r)
9624 p->rng_fault_state = true;
9625 return WERR_NOT_SUPPORTED;
9628 /****************************************************************
9629 _spoolss_PlayGDIScriptOnPrinterIC
9630 ****************************************************************/
9632 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9633 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9635 p->rng_fault_state = true;
9636 return WERR_NOT_SUPPORTED;
9639 /****************************************************************
9640 _spoolss_DeletePrinterIC
9641 ****************************************************************/
9643 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9644 struct spoolss_DeletePrinterIC *r)
9646 p->rng_fault_state = true;
9647 return WERR_NOT_SUPPORTED;
9650 /****************************************************************
9651 _spoolss_AddPrinterConnection
9652 ****************************************************************/
9654 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9655 struct spoolss_AddPrinterConnection *r)
9657 p->rng_fault_state = true;
9658 return WERR_NOT_SUPPORTED;
9661 /****************************************************************
9662 _spoolss_DeletePrinterConnection
9663 ****************************************************************/
9665 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9666 struct spoolss_DeletePrinterConnection *r)
9668 p->rng_fault_state = true;
9669 return WERR_NOT_SUPPORTED;
9672 /****************************************************************
9673 _spoolss_PrinterMessageBox
9674 ****************************************************************/
9676 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9677 struct spoolss_PrinterMessageBox *r)
9679 p->rng_fault_state = true;
9680 return WERR_NOT_SUPPORTED;
9683 /****************************************************************
9684 _spoolss_AddMonitor
9685 ****************************************************************/
9687 WERROR _spoolss_AddMonitor(pipes_struct *p,
9688 struct spoolss_AddMonitor *r)
9690 p->rng_fault_state = true;
9691 return WERR_NOT_SUPPORTED;
9694 /****************************************************************
9695 _spoolss_DeleteMonitor
9696 ****************************************************************/
9698 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9699 struct spoolss_DeleteMonitor *r)
9701 p->rng_fault_state = true;
9702 return WERR_NOT_SUPPORTED;
9705 /****************************************************************
9706 _spoolss_DeletePrintProcessor
9707 ****************************************************************/
9709 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9710 struct spoolss_DeletePrintProcessor *r)
9712 p->rng_fault_state = true;
9713 return WERR_NOT_SUPPORTED;
9716 /****************************************************************
9717 _spoolss_AddPrintProvidor
9718 ****************************************************************/
9720 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9721 struct spoolss_AddPrintProvidor *r)
9723 p->rng_fault_state = true;
9724 return WERR_NOT_SUPPORTED;
9727 /****************************************************************
9728 _spoolss_DeletePrintProvidor
9729 ****************************************************************/
9731 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9732 struct spoolss_DeletePrintProvidor *r)
9734 p->rng_fault_state = true;
9735 return WERR_NOT_SUPPORTED;
9738 /****************************************************************
9739 _spoolss_FindFirstPrinterChangeNotification
9740 ****************************************************************/
9742 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9743 struct spoolss_FindFirstPrinterChangeNotification *r)
9745 p->rng_fault_state = true;
9746 return WERR_NOT_SUPPORTED;
9749 /****************************************************************
9750 _spoolss_FindNextPrinterChangeNotification
9751 ****************************************************************/
9753 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9754 struct spoolss_FindNextPrinterChangeNotification *r)
9756 p->rng_fault_state = true;
9757 return WERR_NOT_SUPPORTED;
9760 /****************************************************************
9761 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9762 ****************************************************************/
9764 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9765 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9767 p->rng_fault_state = true;
9768 return WERR_NOT_SUPPORTED;
9771 /****************************************************************
9772 _spoolss_ReplyOpenPrinter
9773 ****************************************************************/
9775 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9776 struct spoolss_ReplyOpenPrinter *r)
9778 p->rng_fault_state = true;
9779 return WERR_NOT_SUPPORTED;
9782 /****************************************************************
9783 _spoolss_RouterReplyPrinter
9784 ****************************************************************/
9786 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9787 struct spoolss_RouterReplyPrinter *r)
9789 p->rng_fault_state = true;
9790 return WERR_NOT_SUPPORTED;
9793 /****************************************************************
9794 _spoolss_ReplyClosePrinter
9795 ****************************************************************/
9797 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9798 struct spoolss_ReplyClosePrinter *r)
9800 p->rng_fault_state = true;
9801 return WERR_NOT_SUPPORTED;
9804 /****************************************************************
9805 _spoolss_AddPortEx
9806 ****************************************************************/
9808 WERROR _spoolss_AddPortEx(pipes_struct *p,
9809 struct spoolss_AddPortEx *r)
9811 p->rng_fault_state = true;
9812 return WERR_NOT_SUPPORTED;
9815 /****************************************************************
9816 _spoolss_RouterFindFirstPrinterChangeNotification
9817 ****************************************************************/
9819 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9820 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9822 p->rng_fault_state = true;
9823 return WERR_NOT_SUPPORTED;
9826 /****************************************************************
9827 _spoolss_SpoolerInit
9828 ****************************************************************/
9830 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9831 struct spoolss_SpoolerInit *r)
9833 p->rng_fault_state = true;
9834 return WERR_NOT_SUPPORTED;
9837 /****************************************************************
9838 _spoolss_ResetPrinterEx
9839 ****************************************************************/
9841 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9842 struct spoolss_ResetPrinterEx *r)
9844 p->rng_fault_state = true;
9845 return WERR_NOT_SUPPORTED;
9848 /****************************************************************
9849 _spoolss_RouterReplyPrinterEx
9850 ****************************************************************/
9852 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9853 struct spoolss_RouterReplyPrinterEx *r)
9855 p->rng_fault_state = true;
9856 return WERR_NOT_SUPPORTED;
9859 /****************************************************************
9860 _spoolss_44
9861 ****************************************************************/
9863 WERROR _spoolss_44(pipes_struct *p,
9864 struct spoolss_44 *r)
9866 p->rng_fault_state = true;
9867 return WERR_NOT_SUPPORTED;
9870 /****************************************************************
9871 _spoolss_47
9872 ****************************************************************/
9874 WERROR _spoolss_47(pipes_struct *p,
9875 struct spoolss_47 *r)
9877 p->rng_fault_state = true;
9878 return WERR_NOT_SUPPORTED;
9881 /****************************************************************
9882 _spoolss_4a
9883 ****************************************************************/
9885 WERROR _spoolss_4a(pipes_struct *p,
9886 struct spoolss_4a *r)
9888 p->rng_fault_state = true;
9889 return WERR_NOT_SUPPORTED;
9892 /****************************************************************
9893 _spoolss_4b
9894 ****************************************************************/
9896 WERROR _spoolss_4b(pipes_struct *p,
9897 struct spoolss_4b *r)
9899 p->rng_fault_state = true;
9900 return WERR_NOT_SUPPORTED;
9903 /****************************************************************
9904 _spoolss_4c
9905 ****************************************************************/
9907 WERROR _spoolss_4c(pipes_struct *p,
9908 struct spoolss_4c *r)
9910 p->rng_fault_state = true;
9911 return WERR_NOT_SUPPORTED;
9914 /****************************************************************
9915 _spoolss_53
9916 ****************************************************************/
9918 WERROR _spoolss_53(pipes_struct *p,
9919 struct spoolss_53 *r)
9921 p->rng_fault_state = true;
9922 return WERR_NOT_SUPPORTED;
9925 /****************************************************************
9926 _spoolss_55
9927 ****************************************************************/
9929 WERROR _spoolss_55(pipes_struct *p,
9930 struct spoolss_55 *r)
9932 p->rng_fault_state = true;
9933 return WERR_NOT_SUPPORTED;
9936 /****************************************************************
9937 _spoolss_56
9938 ****************************************************************/
9940 WERROR _spoolss_56(pipes_struct *p,
9941 struct spoolss_56 *r)
9943 p->rng_fault_state = true;
9944 return WERR_NOT_SUPPORTED;
9947 /****************************************************************
9948 _spoolss_57
9949 ****************************************************************/
9951 WERROR _spoolss_57(pipes_struct *p,
9952 struct spoolss_57 *r)
9954 p->rng_fault_state = true;
9955 return WERR_NOT_SUPPORTED;
9958 /****************************************************************
9959 _spoolss_5a
9960 ****************************************************************/
9962 WERROR _spoolss_5a(pipes_struct *p,
9963 struct spoolss_5a *r)
9965 p->rng_fault_state = true;
9966 return WERR_NOT_SUPPORTED;
9969 /****************************************************************
9970 _spoolss_5b
9971 ****************************************************************/
9973 WERROR _spoolss_5b(pipes_struct *p,
9974 struct spoolss_5b *r)
9976 p->rng_fault_state = true;
9977 return WERR_NOT_SUPPORTED;
9980 /****************************************************************
9981 _spoolss_5c
9982 ****************************************************************/
9984 WERROR _spoolss_5c(pipes_struct *p,
9985 struct spoolss_5c *r)
9987 p->rng_fault_state = true;
9988 return WERR_NOT_SUPPORTED;
9991 /****************************************************************
9992 _spoolss_5d
9993 ****************************************************************/
9995 WERROR _spoolss_5d(pipes_struct *p,
9996 struct spoolss_5d *r)
9998 p->rng_fault_state = true;
9999 return WERR_NOT_SUPPORTED;
10002 /****************************************************************
10003 _spoolss_5e
10004 ****************************************************************/
10006 WERROR _spoolss_5e(pipes_struct *p,
10007 struct spoolss_5e *r)
10009 p->rng_fault_state = true;
10010 return WERR_NOT_SUPPORTED;
10013 /****************************************************************
10014 _spoolss_5f
10015 ****************************************************************/
10017 WERROR _spoolss_5f(pipes_struct *p,
10018 struct spoolss_5f *r)
10020 p->rng_fault_state = true;
10021 return WERR_NOT_SUPPORTED;
10024 /****************************************************************
10025 _spoolss_60
10026 ****************************************************************/
10028 WERROR _spoolss_60(pipes_struct *p,
10029 struct spoolss_60 *r)
10031 p->rng_fault_state = true;
10032 return WERR_NOT_SUPPORTED;
10035 /****************************************************************
10036 _spoolss_61
10037 ****************************************************************/
10039 WERROR _spoolss_61(pipes_struct *p,
10040 struct spoolss_61 *r)
10042 p->rng_fault_state = true;
10043 return WERR_NOT_SUPPORTED;
10046 /****************************************************************
10047 _spoolss_62
10048 ****************************************************************/
10050 WERROR _spoolss_62(pipes_struct *p,
10051 struct spoolss_62 *r)
10053 p->rng_fault_state = true;
10054 return WERR_NOT_SUPPORTED;
10057 /****************************************************************
10058 _spoolss_63
10059 ****************************************************************/
10061 WERROR _spoolss_63(pipes_struct *p,
10062 struct spoolss_63 *r)
10064 p->rng_fault_state = true;
10065 return WERR_NOT_SUPPORTED;
10068 /****************************************************************
10069 _spoolss_64
10070 ****************************************************************/
10072 WERROR _spoolss_64(pipes_struct *p,
10073 struct spoolss_64 *r)
10075 p->rng_fault_state = true;
10076 return WERR_NOT_SUPPORTED;
10079 /****************************************************************
10080 _spoolss_65
10081 ****************************************************************/
10083 WERROR _spoolss_65(pipes_struct *p,
10084 struct spoolss_65 *r)
10086 p->rng_fault_state = true;
10087 return WERR_NOT_SUPPORTED;
10090 /****************************************************************
10091 _spoolss_GetCorePrinterDrivers
10092 ****************************************************************/
10094 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10095 struct spoolss_GetCorePrinterDrivers *r)
10097 p->rng_fault_state = true;
10098 return WERR_NOT_SUPPORTED;
10101 /****************************************************************
10102 _spoolss_67
10103 ****************************************************************/
10105 WERROR _spoolss_67(pipes_struct *p,
10106 struct spoolss_67 *r)
10108 p->rng_fault_state = true;
10109 return WERR_NOT_SUPPORTED;
10112 /****************************************************************
10113 _spoolss_GetPrinterDriverPackagePath
10114 ****************************************************************/
10116 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10117 struct spoolss_GetPrinterDriverPackagePath *r)
10119 p->rng_fault_state = true;
10120 return WERR_NOT_SUPPORTED;
10123 /****************************************************************
10124 _spoolss_69
10125 ****************************************************************/
10127 WERROR _spoolss_69(pipes_struct *p,
10128 struct spoolss_69 *r)
10130 p->rng_fault_state = true;
10131 return WERR_NOT_SUPPORTED;
10134 /****************************************************************
10135 _spoolss_6a
10136 ****************************************************************/
10138 WERROR _spoolss_6a(pipes_struct *p,
10139 struct spoolss_6a *r)
10141 p->rng_fault_state = true;
10142 return WERR_NOT_SUPPORTED;
10145 /****************************************************************
10146 _spoolss_6b
10147 ****************************************************************/
10149 WERROR _spoolss_6b(pipes_struct *p,
10150 struct spoolss_6b *r)
10152 p->rng_fault_state = true;
10153 return WERR_NOT_SUPPORTED;
10156 /****************************************************************
10157 _spoolss_6c
10158 ****************************************************************/
10160 WERROR _spoolss_6c(pipes_struct *p,
10161 struct spoolss_6c *r)
10163 p->rng_fault_state = true;
10164 return WERR_NOT_SUPPORTED;
10167 /****************************************************************
10168 _spoolss_6d
10169 ****************************************************************/
10171 WERROR _spoolss_6d(pipes_struct *p,
10172 struct spoolss_6d *r)
10174 p->rng_fault_state = true;
10175 return WERR_NOT_SUPPORTED;