s3-rpc_client: move protos to init_spoolss.h
[Samba/ekacnet.git] / source3 / rpc_server / srv_spoolss_nt.c
blob37d1044ef639905f67bd53874394c884d3cfa56e
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"
36 /* macros stolen from s4 spoolss server */
37 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
38 ((info)?ndr_size_##fn(info, level, 0):0)
40 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
41 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
43 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
44 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
46 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
49 extern userdom_struct current_user_info;
51 #undef DBGC_CLASS
52 #define DBGC_CLASS DBGC_RPC_SRV
54 #ifndef MAX_OPEN_PRINTER_EXS
55 #define MAX_OPEN_PRINTER_EXS 50
56 #endif
58 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
60 static Printer_entry *printers_list;
62 typedef struct _counter_printer_0 {
63 struct _counter_printer_0 *next;
64 struct _counter_printer_0 *prev;
66 int snum;
67 uint32_t counter;
68 } counter_printer_0;
70 static counter_printer_0 *counter_list;
72 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
73 static uint32_t smb_connections = 0;
76 /* in printing/nt_printing.c */
78 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
80 /* API table for Xcv Monitor functions */
82 struct xcv_api_table {
83 const char *name;
84 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
87 /********************************************************************
88 * Canonicalize servername.
89 ********************************************************************/
91 static const char *canon_servername(const char *servername)
93 const char *pservername = servername;
94 while (*pservername == '\\') {
95 pservername++;
97 return pservername;
100 /* translate between internal status numbers and NT status numbers */
101 static int nt_printj_status(int v)
103 switch (v) {
104 case LPQ_QUEUED:
105 return 0;
106 case LPQ_PAUSED:
107 return JOB_STATUS_PAUSED;
108 case LPQ_SPOOLING:
109 return JOB_STATUS_SPOOLING;
110 case LPQ_PRINTING:
111 return JOB_STATUS_PRINTING;
112 case LPQ_ERROR:
113 return JOB_STATUS_ERROR;
114 case LPQ_DELETING:
115 return JOB_STATUS_DELETING;
116 case LPQ_OFFLINE:
117 return JOB_STATUS_OFFLINE;
118 case LPQ_PAPEROUT:
119 return JOB_STATUS_PAPEROUT;
120 case LPQ_PRINTED:
121 return JOB_STATUS_PRINTED;
122 case LPQ_DELETED:
123 return JOB_STATUS_DELETED;
124 case LPQ_BLOCKED:
125 return JOB_STATUS_BLOCKED_DEVQ;
126 case LPQ_USER_INTERVENTION:
127 return JOB_STATUS_USER_INTERVENTION;
129 return 0;
132 static int nt_printq_status(int v)
134 switch (v) {
135 case LPQ_PAUSED:
136 return PRINTER_STATUS_PAUSED;
137 case LPQ_QUEUED:
138 case LPQ_SPOOLING:
139 case LPQ_PRINTING:
140 return 0;
142 return 0;
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
151 WERROR result;
152 NTSTATUS status;
155 * Tell the specific printing tdb we no longer want messages for this printer
156 * by deregistering our PID.
159 if (!print_notify_deregister_pid(snum))
160 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162 /* weird if the test succeds !!! */
163 if (smb_connections==0) {
164 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
165 return;
168 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
169 handle,
170 &result);
171 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 win_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
178 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
179 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181 messaging_deregister(smbd_messaging_context(),
182 MSG_PRINTER_NOTIFY2, NULL);
184 /* Tell the connections db we're no longer interested in
185 * printer notify messages. */
187 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
190 smb_connections--;
193 /****************************************************************************
194 Functions to free a printer entry datastruct.
195 ****************************************************************************/
197 static int printer_entry_destructor(Printer_entry *Printer)
199 if (Printer->notify.client_connected == true) {
200 int snum = -1;
202 if ( Printer->printer_type == SPLHND_SERVER) {
203 snum = -1;
204 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
205 } else if (Printer->printer_type == SPLHND_PRINTER) {
206 snum = print_queue_snum(Printer->sharename);
207 if (snum != -1)
208 srv_spoolss_replycloseprinter(snum,
209 &Printer->notify.client_hnd);
213 Printer->notify.flags=0;
214 Printer->notify.options=0;
215 Printer->notify.localmachine[0]='\0';
216 Printer->notify.printerlocal=0;
217 TALLOC_FREE(Printer->notify.option);
218 Printer->notify.client_connected = false;
220 free_nt_devicemode( &Printer->nt_devmode );
221 free_a_printer( &Printer->printer_info, 2 );
223 /* Remove from the internal list. */
224 DLIST_REMOVE(printers_list, Printer);
225 return 0;
228 /****************************************************************************
229 find printer index by handle
230 ****************************************************************************/
232 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
233 struct policy_handle *hnd)
235 Printer_entry *find_printer = NULL;
237 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
238 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
239 return NULL;
242 return find_printer;
245 /****************************************************************************
246 Close printer index by handle.
247 ****************************************************************************/
249 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
251 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
253 if (!Printer) {
254 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
255 OUR_HANDLE(hnd)));
256 return false;
259 close_policy_hnd(p, hnd);
261 return true;
264 /****************************************************************************
265 Delete a printer given a handle.
266 ****************************************************************************/
268 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
270 char *cmd = lp_deleteprinter_cmd();
271 char *command = NULL;
272 int ret;
273 SE_PRIV se_printop = SE_PRINT_OPERATOR;
274 bool is_print_op = false;
276 /* can't fail if we don't try */
278 if ( !*cmd )
279 return WERR_OK;
281 command = talloc_asprintf(ctx,
282 "%s \"%s\"",
283 cmd, sharename);
284 if (!command) {
285 return WERR_NOMEM;
287 if ( token )
288 is_print_op = user_has_privileges( token, &se_printop );
290 DEBUG(10,("Running [%s]\n", command));
292 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
294 if ( is_print_op )
295 become_root();
297 if ( (ret = smbrun(command, NULL)) == 0 ) {
298 /* Tell everyone we updated smb.conf. */
299 message_send_all(smbd_messaging_context(),
300 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
303 if ( is_print_op )
304 unbecome_root();
306 /********** END SePrintOperatorPrivlege BLOCK **********/
308 DEBUGADD(10,("returned [%d]\n", ret));
310 TALLOC_FREE(command);
312 if (ret != 0)
313 return WERR_BADFID; /* What to return here? */
315 /* go ahead and re-read the services immediately */
316 become_root();
317 reload_services(false);
318 unbecome_root();
320 if ( lp_servicenumber( sharename ) > 0 )
321 return WERR_ACCESS_DENIED;
323 return WERR_OK;
326 /****************************************************************************
327 Delete a printer given a handle.
328 ****************************************************************************/
330 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
332 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
334 if (!Printer) {
335 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
336 OUR_HANDLE(hnd)));
337 return WERR_BADFID;
341 * It turns out that Windows allows delete printer on a handle
342 * opened by an admin user, then used on a pipe handle created
343 * by an anonymous user..... but they're working on security.... riiight !
344 * JRA.
347 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
348 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
349 return WERR_ACCESS_DENIED;
352 /* this does not need a become root since the access check has been
353 done on the handle already */
355 if (del_a_printer( Printer->sharename ) != 0) {
356 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
357 return WERR_BADFID;
360 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
361 Printer->sharename );
364 /****************************************************************************
365 Return the snum of a printer corresponding to an handle.
366 ****************************************************************************/
368 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
369 int *number, struct share_params **params)
371 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
373 if (!Printer) {
374 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
375 OUR_HANDLE(hnd)));
376 return false;
379 switch (Printer->printer_type) {
380 case SPLHND_PRINTER:
381 DEBUG(4,("short name:%s\n", Printer->sharename));
382 *number = print_queue_snum(Printer->sharename);
383 return (*number != -1);
384 case SPLHND_SERVER:
385 return false;
386 default:
387 return false;
391 /****************************************************************************
392 Set printer handle type.
393 Check if it's \\server or \\server\printer
394 ****************************************************************************/
396 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
398 DEBUG(3,("Setting printer type=%s\n", handlename));
400 if ( strlen(handlename) < 3 ) {
401 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
402 return false;
405 /* it's a print server */
406 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
407 DEBUGADD(4,("Printer is a print server\n"));
408 Printer->printer_type = SPLHND_SERVER;
410 /* it's a printer (set_printer_hnd_name() will handle port monitors */
411 else {
412 DEBUGADD(4,("Printer is a printer\n"));
413 Printer->printer_type = SPLHND_PRINTER;
416 return true;
419 /****************************************************************************
420 Set printer handle name.. Accept names like \\server, \\server\printer,
421 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
422 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
423 XcvDataPort() interface.
424 ****************************************************************************/
426 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
428 int snum;
429 int n_services=lp_numservices();
430 char *aprinter, *printername;
431 const char *servername;
432 fstring sname;
433 bool found = false;
434 NT_PRINTER_INFO_LEVEL *printer = NULL;
435 WERROR result;
437 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
438 (unsigned long)strlen(handlename)));
440 aprinter = CONST_DISCARD(char *, handlename);
441 if ( *handlename == '\\' ) {
442 servername = canon_servername(handlename);
443 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
444 *aprinter = '\0';
445 aprinter++;
447 } else {
448 servername = global_myname();
451 /* save the servername to fill in replies on this handle */
453 if ( !is_myname_or_ipaddr( servername ) )
454 return false;
456 fstrcpy( Printer->servername, servername );
458 if ( Printer->printer_type == SPLHND_SERVER )
459 return true;
461 if ( Printer->printer_type != SPLHND_PRINTER )
462 return false;
464 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
466 /* check for the Port Monitor Interface */
468 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
469 Printer->printer_type = SPLHND_PORTMON_TCP;
470 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
471 found = true;
473 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
474 Printer->printer_type = SPLHND_PORTMON_LOCAL;
475 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
476 found = true;
479 /* Search all sharenames first as this is easier than pulling
480 the printer_info_2 off of disk. Don't use find_service() since
481 that calls out to map_username() */
483 /* do another loop to look for printernames */
485 for (snum=0; !found && snum<n_services; snum++) {
487 /* no point going on if this is not a printer */
489 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
490 continue;
492 fstrcpy(sname, lp_servicename(snum));
493 if ( strequal( aprinter, sname ) ) {
494 found = true;
495 break;
498 /* no point looking up the printer object if
499 we aren't allowing printername != sharename */
501 if ( lp_force_printername(snum) )
502 continue;
504 fstrcpy(sname, lp_servicename(snum));
506 printer = NULL;
508 /* This call doesn't fill in the location or comment from
509 * a CUPS server for efficiency with large numbers of printers.
510 * JRA.
513 result = get_a_printer_search( NULL, &printer, 2, sname );
514 if ( !W_ERROR_IS_OK(result) ) {
515 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
516 sname, win_errstr(result)));
517 continue;
520 /* printername is always returned as \\server\printername */
521 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
522 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
523 printer->info_2->printername));
524 free_a_printer( &printer, 2);
525 continue;
528 printername++;
530 if ( strequal(printername, aprinter) ) {
531 free_a_printer( &printer, 2);
532 found = true;
533 break;
536 DEBUGADD(10, ("printername: %s\n", printername));
538 free_a_printer( &printer, 2);
541 free_a_printer( &printer, 2);
543 if ( !found ) {
544 DEBUGADD(4,("Printer not found\n"));
545 return false;
548 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
550 fstrcpy(Printer->sharename, sname);
552 return true;
555 /****************************************************************************
556 Find first available printer slot. creates a printer handle for you.
557 ****************************************************************************/
559 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
560 const char *name, uint32_t access_granted)
562 Printer_entry *new_printer;
564 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
566 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
567 if (new_printer == NULL) {
568 return false;
570 talloc_set_destructor(new_printer, printer_entry_destructor);
572 if (!create_policy_hnd(p, hnd, new_printer)) {
573 TALLOC_FREE(new_printer);
574 return false;
577 /* Add to the internal list. */
578 DLIST_ADD(printers_list, new_printer);
580 new_printer->notify.option=NULL;
582 if (!set_printer_hnd_printertype(new_printer, name)) {
583 close_printer_handle(p, hnd);
584 return false;
587 if (!set_printer_hnd_name(new_printer, name)) {
588 close_printer_handle(p, hnd);
589 return false;
592 new_printer->access_granted = access_granted;
594 DEBUG(5, ("%d printer handles active\n",
595 (int)num_pipe_handles(p->pipe_handles)));
597 return true;
600 /***************************************************************************
601 check to see if the client motify handle is monitoring the notification
602 given by (notify_type, notify_field).
603 **************************************************************************/
605 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
606 uint16_t notify_field)
608 return true;
611 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
612 uint16_t notify_field)
614 struct spoolss_NotifyOption *option = p->notify.option;
615 uint32_t i, j;
618 * Flags should always be zero when the change notify
619 * is registered by the client's spooler. A user Win32 app
620 * might use the flags though instead of the NOTIFY_OPTION_INFO
621 * --jerry
624 if (!option) {
625 return false;
628 if (p->notify.flags)
629 return is_monitoring_event_flags(
630 p->notify.flags, notify_type, notify_field);
632 for (i = 0; i < option->count; i++) {
634 /* Check match for notify_type */
636 if (option->types[i].type != notify_type)
637 continue;
639 /* Check match for field */
641 for (j = 0; j < option->types[i].count; j++) {
642 if (option->types[i].fields[j].field == notify_field) {
643 return true;
648 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
649 p->servername, p->sharename, notify_type, notify_field));
651 return false;
654 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
655 _data->data.integer[0] = _integer; \
656 _data->data.integer[1] = 0;
659 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
660 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
661 if (!_data->data.string.string) {\
662 _data->data.string.size = 0; \
664 _data->data.string.size = strlen_m_term(_p) * 2;
666 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
667 _data->data.devmode.devmode = _devmode;
669 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
670 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
671 if (!_data->data.sd.sd) { \
672 _data->data.sd.sd_size = 0; \
674 _data->data.sd.sd_size = _size;
676 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
677 struct tm *t,
678 const char **pp,
679 uint32_t *plen)
681 struct spoolss_Time st;
682 uint32_t len = 16;
683 char *p;
685 if (!init_systemtime(&st, t)) {
686 return;
689 p = talloc_array(mem_ctx, char, len);
690 if (!p) {
691 return;
695 * Systemtime must be linearized as a set of UINT16's.
696 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
699 SSVAL(p, 0, st.year);
700 SSVAL(p, 2, st.month);
701 SSVAL(p, 4, st.day_of_week);
702 SSVAL(p, 6, st.day);
703 SSVAL(p, 8, st.hour);
704 SSVAL(p, 10, st.minute);
705 SSVAL(p, 12, st.second);
706 SSVAL(p, 14, st.millisecond);
708 *pp = p;
709 *plen = len;
712 /* Convert a notification message to a struct spoolss_Notify */
714 static void notify_one_value(struct spoolss_notify_msg *msg,
715 struct spoolss_Notify *data,
716 TALLOC_CTX *mem_ctx)
718 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
721 static void notify_string(struct spoolss_notify_msg *msg,
722 struct spoolss_Notify *data,
723 TALLOC_CTX *mem_ctx)
725 /* The length of the message includes the trailing \0 */
727 data->data.string.size = msg->len * 2;
728 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
729 if (!data->data.string.string) {
730 data->data.string.size = 0;
731 return;
735 static void notify_system_time(struct spoolss_notify_msg *msg,
736 struct spoolss_Notify *data,
737 TALLOC_CTX *mem_ctx)
739 data->data.string.string = NULL;
740 data->data.string.size = 0;
742 if (msg->len != sizeof(time_t)) {
743 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
744 msg->len));
745 return;
748 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
749 &data->data.string.string,
750 &data->data.string.size);
753 struct notify2_message_table {
754 const char *name;
755 void (*fn)(struct spoolss_notify_msg *msg,
756 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
759 static struct notify2_message_table printer_notify_table[] = {
760 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
761 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
762 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
763 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
764 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
765 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
766 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
767 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
768 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
769 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
770 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
771 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
772 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
773 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
774 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
775 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
776 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
777 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
778 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
781 static struct notify2_message_table job_notify_table[] = {
782 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
783 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
784 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
785 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
786 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
787 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
788 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
789 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
790 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
791 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
792 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
793 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
794 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
795 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
796 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
797 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
798 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
799 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
800 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
801 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
802 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
803 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
804 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
805 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
809 /***********************************************************************
810 Allocate talloc context for container object
811 **********************************************************************/
813 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
815 if ( !ctr )
816 return;
818 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
820 return;
823 /***********************************************************************
824 release all allocated memory and zero out structure
825 **********************************************************************/
827 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
829 if ( !ctr )
830 return;
832 if ( ctr->ctx )
833 talloc_destroy(ctr->ctx);
835 ZERO_STRUCTP(ctr);
837 return;
840 /***********************************************************************
841 **********************************************************************/
843 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
845 if ( !ctr )
846 return NULL;
848 return ctr->ctx;
851 /***********************************************************************
852 **********************************************************************/
854 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
856 if ( !ctr || !ctr->msg_groups )
857 return NULL;
859 if ( idx >= ctr->num_groups )
860 return NULL;
862 return &ctr->msg_groups[idx];
866 /***********************************************************************
867 How many groups of change messages do we have ?
868 **********************************************************************/
870 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
872 if ( !ctr )
873 return 0;
875 return ctr->num_groups;
878 /***********************************************************************
879 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
880 **********************************************************************/
882 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
884 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
885 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
886 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
887 int i, new_slot;
889 if ( !ctr || !msg )
890 return 0;
892 /* loop over all groups looking for a matching printer name */
894 for ( i=0; i<ctr->num_groups; i++ ) {
895 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
896 break;
899 /* add a new group? */
901 if ( i == ctr->num_groups ) {
902 ctr->num_groups++;
904 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
905 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
906 return 0;
908 ctr->msg_groups = groups;
910 /* clear the new entry and set the printer name */
912 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
913 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
916 /* add the change messages; 'i' is the correct index now regardless */
918 msg_grp = &ctr->msg_groups[i];
920 msg_grp->num_msgs++;
922 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
923 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
924 return 0;
926 msg_grp->msgs = msg_list;
928 new_slot = msg_grp->num_msgs-1;
929 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
931 /* need to allocate own copy of data */
933 if ( msg->len != 0 )
934 msg_grp->msgs[new_slot].notify.data = (char *)
935 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
937 return ctr->num_groups;
940 void construct_info_data(struct spoolss_Notify *info_data,
941 enum spoolss_NotifyType type,
942 uint16_t field,
943 int id);
945 /***********************************************************************
946 Send a change notication message on all handles which have a call
947 back registered
948 **********************************************************************/
950 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
952 Printer_entry *p;
953 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
954 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
955 SPOOLSS_NOTIFY_MSG *messages;
956 int sending_msg_count;
958 if ( !msg_group ) {
959 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
960 return;
963 messages = msg_group->msgs;
965 if ( !messages ) {
966 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
967 return;
970 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
972 /* loop over all printers */
974 for (p = printers_list; p; p = p->next) {
975 struct spoolss_Notify *notifies;
976 uint32_t count = 0;
977 uint32_t id;
978 int i;
980 /* Is there notification on this handle? */
982 if ( !p->notify.client_connected )
983 continue;
985 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
987 /* For this printer? Print servers always receive
988 notifications. */
990 if ( ( p->printer_type == SPLHND_PRINTER ) &&
991 ( !strequal(msg_group->printername, p->sharename) ) )
992 continue;
994 DEBUG(10,("Our printer\n"));
996 /* allocate the max entries possible */
998 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
999 if (!notifies) {
1000 return;
1003 /* build the array of change notifications */
1005 sending_msg_count = 0;
1007 for ( i=0; i<msg_group->num_msgs; i++ ) {
1008 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1010 /* Are we monitoring this event? */
1012 if (!is_monitoring_event(p, msg->type, msg->field))
1013 continue;
1015 sending_msg_count++;
1018 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1019 msg->type, msg->field, p->sharename));
1022 * if the is a printer notification handle and not a job notification
1023 * type, then set the id to 0. Other wise just use what was specified
1024 * in the message.
1026 * When registering change notification on a print server handle
1027 * we always need to send back the id (snum) matching the printer
1028 * for which the change took place. For change notify registered
1029 * on a printer handle, this does not matter and the id should be 0.
1031 * --jerry
1034 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1035 id = 0;
1036 else
1037 id = msg->id;
1040 /* Convert unix jobid to smb jobid */
1042 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1043 id = sysjob_to_jobid(msg->id);
1045 if (id == -1) {
1046 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1047 goto done;
1051 construct_info_data( &notifies[count], msg->type, msg->field, id );
1053 switch(msg->type) {
1054 case PRINTER_NOTIFY_TYPE:
1055 if ( printer_notify_table[msg->field].fn )
1056 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1057 break;
1059 case JOB_NOTIFY_TYPE:
1060 if ( job_notify_table[msg->field].fn )
1061 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1062 break;
1064 default:
1065 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1066 goto done;
1069 count++;
1072 if ( sending_msg_count ) {
1073 NTSTATUS status;
1074 WERROR werr;
1075 union spoolss_ReplyPrinterInfo info;
1076 struct spoolss_NotifyInfo info0;
1077 uint32_t reply_result;
1079 info0.version = 0x2;
1080 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1081 info0.count = count;
1082 info0.notifies = notifies;
1084 info.info0 = &info0;
1086 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1087 &p->notify.client_hnd,
1088 p->notify.change, /* color */
1089 p->notify.flags,
1090 &reply_result,
1091 0, /* reply_type, must be 0 */
1092 info,
1093 &werr);
1094 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1095 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1096 notify_cli_pipe->srv_name_slash,
1097 win_errstr(werr)));
1099 switch (reply_result) {
1100 case 0:
1101 break;
1102 case PRINTER_NOTIFY_INFO_DISCARDED:
1103 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1104 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1105 break;
1106 default:
1107 break;
1112 done:
1113 DEBUG(8,("send_notify2_changes: Exit...\n"));
1114 return;
1117 /***********************************************************************
1118 **********************************************************************/
1120 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1123 uint32_t tv_sec, tv_usec;
1124 size_t offset = 0;
1126 /* Unpack message */
1128 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1129 msg->printer);
1131 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1132 &tv_sec, &tv_usec,
1133 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1135 if (msg->len == 0)
1136 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1137 &msg->notify.value[0], &msg->notify.value[1]);
1138 else
1139 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1140 &msg->len, &msg->notify.data);
1142 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1143 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1145 tv->tv_sec = tv_sec;
1146 tv->tv_usec = tv_usec;
1148 if (msg->len == 0)
1149 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1150 msg->notify.value[1]));
1151 else
1152 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1154 return true;
1157 /********************************************************************
1158 Receive a notify2 message list
1159 ********************************************************************/
1161 static void receive_notify2_message_list(struct messaging_context *msg,
1162 void *private_data,
1163 uint32_t msg_type,
1164 struct server_id server_id,
1165 DATA_BLOB *data)
1167 size_t msg_count, i;
1168 char *buf = (char *)data->data;
1169 char *msg_ptr;
1170 size_t msg_len;
1171 SPOOLSS_NOTIFY_MSG notify;
1172 SPOOLSS_NOTIFY_MSG_CTR messages;
1173 int num_groups;
1175 if (data->length < 4) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1177 return;
1180 msg_count = IVAL(buf, 0);
1181 msg_ptr = buf + 4;
1183 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1185 if (msg_count == 0) {
1186 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1187 return;
1190 /* initialize the container */
1192 ZERO_STRUCT( messages );
1193 notify_msg_ctr_init( &messages );
1196 * build message groups for each printer identified
1197 * in a change_notify msg. Remember that a PCN message
1198 * includes the handle returned for the srv_spoolss_replyopenprinter()
1199 * call. Therefore messages are grouped according to printer handle.
1202 for ( i=0; i<msg_count; i++ ) {
1203 struct timeval msg_tv;
1205 if (msg_ptr + 4 - buf > data->length) {
1206 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1207 return;
1210 msg_len = IVAL(msg_ptr,0);
1211 msg_ptr += 4;
1213 if (msg_ptr + msg_len - buf > data->length) {
1214 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1215 return;
1218 /* unpack messages */
1220 ZERO_STRUCT( notify );
1221 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1222 msg_ptr += msg_len;
1224 /* add to correct list in container */
1226 notify_msg_ctr_addmsg( &messages, &notify );
1228 /* free memory that might have been allocated by notify2_unpack_msg() */
1230 if ( notify.len != 0 )
1231 SAFE_FREE( notify.notify.data );
1234 /* process each group of messages */
1236 num_groups = notify_msg_ctr_numgroups( &messages );
1237 for ( i=0; i<num_groups; i++ )
1238 send_notify2_changes( &messages, i );
1241 /* cleanup */
1243 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1244 (uint32_t)msg_count ));
1246 notify_msg_ctr_destroy( &messages );
1248 return;
1251 /********************************************************************
1252 Send a message to ourself about new driver being installed
1253 so we can upgrade the information for each printer bound to this
1254 driver
1255 ********************************************************************/
1257 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1259 int len = strlen(drivername);
1261 if (!len)
1262 return false;
1264 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1265 drivername));
1267 messaging_send_buf(smbd_messaging_context(), procid_self(),
1268 MSG_PRINTER_DRVUPGRADE,
1269 (uint8_t *)drivername, len+1);
1271 return true;
1274 /**********************************************************************
1275 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1276 over all printers, upgrading ones as necessary
1277 **********************************************************************/
1279 void do_drv_upgrade_printer(struct messaging_context *msg,
1280 void *private_data,
1281 uint32_t msg_type,
1282 struct server_id server_id,
1283 DATA_BLOB *data)
1285 fstring drivername;
1286 int snum;
1287 int n_services = lp_numservices();
1288 size_t len;
1290 len = MIN(data->length,sizeof(drivername)-1);
1291 strncpy(drivername, (const char *)data->data, len);
1293 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1295 /* Iterate the printer list */
1297 for (snum=0; snum<n_services; snum++)
1299 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1301 WERROR result;
1302 NT_PRINTER_INFO_LEVEL *printer = NULL;
1304 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1305 if (!W_ERROR_IS_OK(result))
1306 continue;
1308 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1310 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1312 /* all we care about currently is the change_id */
1314 result = mod_a_printer(printer, 2);
1315 if (!W_ERROR_IS_OK(result)) {
1316 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1317 win_errstr(result)));
1321 free_a_printer(&printer, 2);
1325 /* all done */
1328 /********************************************************************
1329 Update the cache for all printq's with a registered client
1330 connection
1331 ********************************************************************/
1333 void update_monitored_printq_cache( void )
1335 Printer_entry *printer = printers_list;
1336 int snum;
1338 /* loop through all printers and update the cache where
1339 client_connected == true */
1340 while ( printer )
1342 if ( (printer->printer_type == SPLHND_PRINTER)
1343 && printer->notify.client_connected )
1345 snum = print_queue_snum(printer->sharename);
1346 print_queue_status( snum, NULL, NULL );
1349 printer = printer->next;
1352 return;
1355 /****************************************************************
1356 _spoolss_OpenPrinter
1357 ****************************************************************/
1359 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1360 struct spoolss_OpenPrinter *r)
1362 struct spoolss_OpenPrinterEx e;
1363 WERROR werr;
1365 ZERO_STRUCT(e.in.userlevel);
1367 e.in.printername = r->in.printername;
1368 e.in.datatype = r->in.datatype;
1369 e.in.devmode_ctr = r->in.devmode_ctr;
1370 e.in.access_mask = r->in.access_mask;
1371 e.in.level = 0;
1373 e.out.handle = r->out.handle;
1375 werr = _spoolss_OpenPrinterEx(p, &e);
1377 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1378 /* OpenPrinterEx returns this for a bad
1379 * printer name. We must return WERR_INVALID_PRINTER_NAME
1380 * instead.
1382 werr = WERR_INVALID_PRINTER_NAME;
1385 return werr;
1388 /********************************************************************
1389 ********************************************************************/
1391 bool convert_devicemode(const char *printername,
1392 const struct spoolss_DeviceMode *devmode,
1393 NT_DEVICEMODE **pp_nt_devmode)
1395 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1398 * Ensure nt_devmode is a valid pointer
1399 * as we will be overwriting it.
1402 if (nt_devmode == NULL) {
1403 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1404 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1405 return false;
1408 fstrcpy(nt_devmode->devicename, devmode->devicename);
1409 fstrcpy(nt_devmode->formname, devmode->formname);
1411 nt_devmode->devicename[31] = '\0';
1412 nt_devmode->formname[31] = '\0';
1414 nt_devmode->specversion = devmode->specversion;
1415 nt_devmode->driverversion = devmode->driverversion;
1416 nt_devmode->size = devmode->size;
1417 nt_devmode->fields = devmode->fields;
1418 nt_devmode->orientation = devmode->orientation;
1419 nt_devmode->papersize = devmode->papersize;
1420 nt_devmode->paperlength = devmode->paperlength;
1421 nt_devmode->paperwidth = devmode->paperwidth;
1422 nt_devmode->scale = devmode->scale;
1423 nt_devmode->copies = devmode->copies;
1424 nt_devmode->defaultsource = devmode->defaultsource;
1425 nt_devmode->printquality = devmode->printquality;
1426 nt_devmode->color = devmode->color;
1427 nt_devmode->duplex = devmode->duplex;
1428 nt_devmode->yresolution = devmode->yresolution;
1429 nt_devmode->ttoption = devmode->ttoption;
1430 nt_devmode->collate = devmode->collate;
1432 nt_devmode->logpixels = devmode->logpixels;
1433 nt_devmode->bitsperpel = devmode->bitsperpel;
1434 nt_devmode->pelswidth = devmode->pelswidth;
1435 nt_devmode->pelsheight = devmode->pelsheight;
1436 nt_devmode->displayflags = devmode->displayflags;
1437 nt_devmode->displayfrequency = devmode->displayfrequency;
1438 nt_devmode->icmmethod = devmode->icmmethod;
1439 nt_devmode->icmintent = devmode->icmintent;
1440 nt_devmode->mediatype = devmode->mediatype;
1441 nt_devmode->dithertype = devmode->dithertype;
1442 nt_devmode->reserved1 = devmode->reserved1;
1443 nt_devmode->reserved2 = devmode->reserved2;
1444 nt_devmode->panningwidth = devmode->panningwidth;
1445 nt_devmode->panningheight = devmode->panningheight;
1448 * Only change private and driverextra if the incoming devmode
1449 * has a new one. JRA.
1452 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1453 SAFE_FREE(nt_devmode->nt_dev_private);
1454 nt_devmode->driverextra = devmode->__driverextra_length;
1455 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1456 return false;
1457 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1460 *pp_nt_devmode = nt_devmode;
1462 return true;
1465 /****************************************************************
1466 _spoolss_OpenPrinterEx
1467 ****************************************************************/
1469 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1470 struct spoolss_OpenPrinterEx *r)
1472 int snum;
1473 Printer_entry *Printer=NULL;
1475 if (!r->in.printername) {
1476 return WERR_INVALID_PARAM;
1479 /* some sanity check because you can open a printer or a print server */
1480 /* aka: \\server\printer or \\server */
1482 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1484 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1485 ZERO_STRUCTP(r->out.handle);
1486 return WERR_INVALID_PARAM;
1489 Printer = find_printer_index_by_hnd(p, r->out.handle);
1490 if ( !Printer ) {
1491 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1492 "handle we created for printer %s\n", r->in.printername));
1493 close_printer_handle(p, r->out.handle);
1494 ZERO_STRUCTP(r->out.handle);
1495 return WERR_INVALID_PARAM;
1499 * First case: the user is opening the print server:
1501 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1502 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1504 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1505 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1506 * or if the user is listed in the smb.conf printer admin parameter.
1508 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1509 * client view printer folder, but does not show the MSAPW.
1511 * Note: this test needs code to check access rights here too. Jeremy
1512 * could you look at this?
1514 * Second case: the user is opening a printer:
1515 * NT doesn't let us connect to a printer if the connecting user
1516 * doesn't have print permission.
1518 * Third case: user is opening a Port Monitor
1519 * access checks same as opening a handle to the print server.
1522 switch (Printer->printer_type )
1524 case SPLHND_SERVER:
1525 case SPLHND_PORTMON_TCP:
1526 case SPLHND_PORTMON_LOCAL:
1527 /* Printserver handles use global struct... */
1529 snum = -1;
1531 /* Map standard access rights to object specific access rights */
1533 se_map_standard(&r->in.access_mask,
1534 &printserver_std_mapping);
1536 /* Deny any object specific bits that don't apply to print
1537 servers (i.e printer and job specific bits) */
1539 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1541 if (r->in.access_mask &
1542 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1543 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1544 close_printer_handle(p, r->out.handle);
1545 ZERO_STRUCTP(r->out.handle);
1546 return WERR_ACCESS_DENIED;
1549 /* Allow admin access */
1551 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1553 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1555 if (!lp_ms_add_printer_wizard()) {
1556 close_printer_handle(p, r->out.handle);
1557 ZERO_STRUCTP(r->out.handle);
1558 return WERR_ACCESS_DENIED;
1561 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1562 and not a printer admin, then fail */
1564 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1565 !user_has_privileges(p->server_info->ptok,
1566 &se_printop ) &&
1567 !token_contains_name_in_list(
1568 uidtoname(p->server_info->utok.uid),
1569 NULL, NULL,
1570 p->server_info->ptok,
1571 lp_printer_admin(snum))) {
1572 close_printer_handle(p, r->out.handle);
1573 ZERO_STRUCTP(r->out.handle);
1574 return WERR_ACCESS_DENIED;
1577 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1579 else
1581 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1584 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1585 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1587 /* We fall through to return WERR_OK */
1588 break;
1590 case SPLHND_PRINTER:
1591 /* NT doesn't let us connect to a printer if the connecting user
1592 doesn't have print permission. */
1594 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1595 close_printer_handle(p, r->out.handle);
1596 ZERO_STRUCTP(r->out.handle);
1597 return WERR_BADFID;
1600 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1601 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1604 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1606 /* map an empty access mask to the minimum access mask */
1607 if (r->in.access_mask == 0x0)
1608 r->in.access_mask = PRINTER_ACCESS_USE;
1611 * If we are not serving the printer driver for this printer,
1612 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1613 * will keep NT clients happy --jerry
1616 if (lp_use_client_driver(snum)
1617 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1619 r->in.access_mask = PRINTER_ACCESS_USE;
1622 /* check smb.conf parameters and the the sec_desc */
1624 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1625 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1626 ZERO_STRUCTP(r->out.handle);
1627 return WERR_ACCESS_DENIED;
1630 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1631 p->server_info->ptok, snum) ||
1632 !print_access_check(p->server_info, snum,
1633 r->in.access_mask)) {
1634 DEBUG(3, ("access DENIED for printer open\n"));
1635 close_printer_handle(p, r->out.handle);
1636 ZERO_STRUCTP(r->out.handle);
1637 return WERR_ACCESS_DENIED;
1640 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1641 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1642 close_printer_handle(p, r->out.handle);
1643 ZERO_STRUCTP(r->out.handle);
1644 return WERR_ACCESS_DENIED;
1647 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1648 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1649 else
1650 r->in.access_mask = PRINTER_ACCESS_USE;
1652 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1653 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1655 break;
1657 default:
1658 /* sanity check to prevent programmer error */
1659 ZERO_STRUCTP(r->out.handle);
1660 return WERR_BADFID;
1663 Printer->access_granted = r->in.access_mask;
1666 * If the client sent a devmode in the OpenPrinter() call, then
1667 * save it here in case we get a job submission on this handle
1670 if ((Printer->printer_type != SPLHND_SERVER) &&
1671 r->in.devmode_ctr.devmode) {
1672 convert_devicemode(Printer->sharename,
1673 r->in.devmode_ctr.devmode,
1674 &Printer->nt_devmode);
1677 #if 0 /* JERRY -- I'm doubtful this is really effective */
1678 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1679 optimization in Windows 2000 clients --jerry */
1681 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1682 && (RA_WIN2K == get_remote_arch()) )
1684 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1685 sys_usleep( 500000 );
1687 #endif
1689 return WERR_OK;
1692 /****************************************************************************
1693 ****************************************************************************/
1695 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1696 NT_PRINTER_INFO_LEVEL_2 *d)
1698 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1700 if (!r || !d) {
1701 return false;
1704 d->attributes = r->attributes;
1705 d->priority = r->priority;
1706 d->default_priority = r->defaultpriority;
1707 d->starttime = r->starttime;
1708 d->untiltime = r->untiltime;
1709 d->status = r->status;
1710 d->cjobs = r->cjobs;
1712 fstrcpy(d->servername, r->servername);
1713 fstrcpy(d->printername, r->printername);
1714 fstrcpy(d->sharename, r->sharename);
1715 fstrcpy(d->portname, r->portname);
1716 fstrcpy(d->drivername, r->drivername);
1717 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1718 fstrcpy(d->location, r->location);
1719 fstrcpy(d->sepfile, r->sepfile);
1720 fstrcpy(d->printprocessor, r->printprocessor);
1721 fstrcpy(d->datatype, r->datatype);
1722 fstrcpy(d->parameters, r->parameters);
1724 return true;
1727 /****************************************************************************
1728 ****************************************************************************/
1730 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1731 NT_PRINTER_INFO_LEVEL *printer)
1733 bool ret;
1735 switch (info_ctr->level) {
1736 case 2:
1737 /* allocate memory if needed. Messy because
1738 convert_printer_info is used to update an existing
1739 printer or build a new one */
1741 if (!printer->info_2) {
1742 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1743 if (!printer->info_2) {
1744 DEBUG(0,("convert_printer_info: "
1745 "talloc() failed!\n"));
1746 return false;
1750 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1751 printer->info_2);
1752 printer->info_2->setuptime = time(NULL);
1753 return ret;
1756 return false;
1759 /****************************************************************
1760 _spoolss_ClosePrinter
1761 ****************************************************************/
1763 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1764 struct spoolss_ClosePrinter *r)
1766 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1768 if (Printer && Printer->document_started) {
1769 struct spoolss_EndDocPrinter e;
1771 e.in.handle = r->in.handle;
1773 _spoolss_EndDocPrinter(p, &e);
1776 if (!close_printer_handle(p, r->in.handle))
1777 return WERR_BADFID;
1779 /* clear the returned printer handle. Observed behavior
1780 from Win2k server. Don't think this really matters.
1781 Previous code just copied the value of the closed
1782 handle. --jerry */
1784 ZERO_STRUCTP(r->out.handle);
1786 return WERR_OK;
1789 /****************************************************************
1790 _spoolss_DeletePrinter
1791 ****************************************************************/
1793 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1794 struct spoolss_DeletePrinter *r)
1796 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1797 WERROR result;
1799 if (Printer && Printer->document_started) {
1800 struct spoolss_EndDocPrinter e;
1802 e.in.handle = r->in.handle;
1804 _spoolss_EndDocPrinter(p, &e);
1807 result = delete_printer_handle(p, r->in.handle);
1809 update_c_setprinter(false);
1811 return result;
1814 /*******************************************************************
1815 * static function to lookup the version id corresponding to an
1816 * long architecture string
1817 ******************************************************************/
1819 static const struct print_architecture_table_node archi_table[]= {
1821 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1822 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1823 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1824 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1825 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1826 {"Windows IA64", SPL_ARCH_IA64, 3 },
1827 {"Windows x64", SPL_ARCH_X64, 3 },
1828 {NULL, "", -1 }
1831 static int get_version_id(const char *arch)
1833 int i;
1835 for (i=0; archi_table[i].long_archi != NULL; i++)
1837 if (strcmp(arch, archi_table[i].long_archi) == 0)
1838 return (archi_table[i].version);
1841 return -1;
1844 /****************************************************************
1845 _spoolss_DeletePrinterDriver
1846 ****************************************************************/
1848 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1849 struct spoolss_DeletePrinterDriver *r)
1852 struct spoolss_DriverInfo8 *info = NULL;
1853 struct spoolss_DriverInfo8 *info_win2k = NULL;
1854 int version;
1855 WERROR status;
1856 WERROR status_win2k = WERR_ACCESS_DENIED;
1857 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1859 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1860 and not a printer admin, then fail */
1862 if ( (p->server_info->utok.uid != sec_initial_uid())
1863 && !user_has_privileges(p->server_info->ptok, &se_printop )
1864 && !token_contains_name_in_list(
1865 uidtoname(p->server_info->utok.uid), NULL,
1866 NULL, p->server_info->ptok,
1867 lp_printer_admin(-1)) )
1869 return WERR_ACCESS_DENIED;
1872 /* check that we have a valid driver name first */
1874 if ((version = get_version_id(r->in.architecture)) == -1)
1875 return WERR_INVALID_ENVIRONMENT;
1877 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1878 r->in.architecture,
1879 version)))
1881 /* try for Win2k driver if "Windows NT x86" */
1883 if ( version == 2 ) {
1884 version = 3;
1885 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1886 &info,
1887 r->in.driver,
1888 r->in.architecture,
1889 version))) {
1890 status = WERR_UNKNOWN_PRINTER_DRIVER;
1891 goto done;
1894 /* otherwise it was a failure */
1895 else {
1896 status = WERR_UNKNOWN_PRINTER_DRIVER;
1897 goto done;
1902 if (printer_driver_in_use(info)) {
1903 status = WERR_PRINTER_DRIVER_IN_USE;
1904 goto done;
1907 if ( version == 2 )
1909 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1910 &info_win2k,
1911 r->in.driver,
1912 r->in.architecture, 3)))
1914 /* if we get to here, we now have 2 driver info structures to remove */
1915 /* remove the Win2k driver first*/
1917 status_win2k = delete_printer_driver(
1918 p, info_win2k, 3, false);
1919 free_a_printer_driver(info_win2k);
1921 /* this should not have failed---if it did, report to client */
1922 if ( !W_ERROR_IS_OK(status_win2k) )
1924 status = status_win2k;
1925 goto done;
1930 status = delete_printer_driver(p, info, version, false);
1932 /* if at least one of the deletes succeeded return OK */
1934 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1935 status = WERR_OK;
1937 done:
1938 free_a_printer_driver(info);
1940 return status;
1943 /****************************************************************
1944 _spoolss_DeletePrinterDriverEx
1945 ****************************************************************/
1947 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1948 struct spoolss_DeletePrinterDriverEx *r)
1950 struct spoolss_DriverInfo8 *info = NULL;
1951 struct spoolss_DriverInfo8 *info_win2k = NULL;
1952 int version;
1953 bool delete_files;
1954 WERROR status;
1955 WERROR status_win2k = WERR_ACCESS_DENIED;
1956 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1958 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1959 and not a printer admin, then fail */
1961 if ( (p->server_info->utok.uid != sec_initial_uid())
1962 && !user_has_privileges(p->server_info->ptok, &se_printop )
1963 && !token_contains_name_in_list(
1964 uidtoname(p->server_info->utok.uid), NULL, NULL,
1965 p->server_info->ptok, lp_printer_admin(-1)) )
1967 return WERR_ACCESS_DENIED;
1970 /* check that we have a valid driver name first */
1971 if ((version = get_version_id(r->in.architecture)) == -1) {
1972 /* this is what NT returns */
1973 return WERR_INVALID_ENVIRONMENT;
1976 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1977 version = r->in.version;
1979 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1980 r->in.architecture, version);
1982 if ( !W_ERROR_IS_OK(status) )
1985 * if the client asked for a specific version,
1986 * or this is something other than Windows NT x86,
1987 * then we've failed
1990 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1991 goto done;
1993 /* try for Win2k driver if "Windows NT x86" */
1995 version = 3;
1996 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1997 r->in.architecture,
1998 version))) {
1999 status = WERR_UNKNOWN_PRINTER_DRIVER;
2000 goto done;
2004 if (printer_driver_in_use(info)) {
2005 status = WERR_PRINTER_DRIVER_IN_USE;
2006 goto done;
2010 * we have a couple of cases to consider.
2011 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2012 * then the delete should fail if **any** files overlap with
2013 * other drivers
2014 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2015 * non-overlapping files
2016 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2017 * is set, the do not delete any files
2018 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2021 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2023 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2025 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2026 /* no idea of the correct error here */
2027 status = WERR_ACCESS_DENIED;
2028 goto done;
2032 /* also check for W32X86/3 if necessary; maybe we already have? */
2034 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2035 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2036 r->in.driver,
2037 r->in.architecture, 3)))
2040 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2041 /* no idea of the correct error here */
2042 free_a_printer_driver(info_win2k);
2043 status = WERR_ACCESS_DENIED;
2044 goto done;
2047 /* if we get to here, we now have 2 driver info structures to remove */
2048 /* remove the Win2k driver first*/
2050 status_win2k = delete_printer_driver(
2051 p, info_win2k, 3, delete_files);
2052 free_a_printer_driver(info_win2k);
2054 /* this should not have failed---if it did, report to client */
2056 if ( !W_ERROR_IS_OK(status_win2k) )
2057 goto done;
2061 status = delete_printer_driver(p, info, version, delete_files);
2063 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2064 status = WERR_OK;
2065 done:
2066 free_a_printer_driver(info);
2068 return status;
2072 /****************************************************************************
2073 Internal routine for removing printerdata
2074 ***************************************************************************/
2076 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2078 return delete_printer_data( printer->info_2, key, value );
2081 /****************************************************************************
2082 Internal routine for storing printerdata
2083 ***************************************************************************/
2085 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2086 const char *key, const char *value,
2087 uint32_t type, uint8_t *data, int real_len)
2089 /* the registry objects enforce uniqueness based on value name */
2091 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2094 /********************************************************************
2095 GetPrinterData on a printer server Handle.
2096 ********************************************************************/
2098 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2099 const char *value,
2100 enum winreg_Type *type,
2101 union spoolss_PrinterData *data)
2103 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2105 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2106 *type = REG_DWORD;
2107 data->value = 0x00;
2108 return WERR_OK;
2111 if (!StrCaseCmp(value, "BeepEnabled")) {
2112 *type = REG_DWORD;
2113 data->value = 0x00;
2114 return WERR_OK;
2117 if (!StrCaseCmp(value, "EventLog")) {
2118 *type = REG_DWORD;
2119 /* formally was 0x1b */
2120 data->value = 0x00;
2121 return WERR_OK;
2124 if (!StrCaseCmp(value, "NetPopup")) {
2125 *type = REG_DWORD;
2126 data->value = 0x00;
2127 return WERR_OK;
2130 if (!StrCaseCmp(value, "MajorVersion")) {
2131 *type = REG_DWORD;
2133 /* Windows NT 4.0 seems to not allow uploading of drivers
2134 to a server that reports 0x3 as the MajorVersion.
2135 need to investigate more how Win2k gets around this .
2136 -- jerry */
2138 if (RA_WINNT == get_remote_arch()) {
2139 data->value = 0x02;
2140 } else {
2141 data->value = 0x03;
2144 return WERR_OK;
2147 if (!StrCaseCmp(value, "MinorVersion")) {
2148 *type = REG_DWORD;
2149 data->value = 0x00;
2150 return WERR_OK;
2153 /* REG_BINARY
2154 * uint32_t size = 0x114
2155 * uint32_t major = 5
2156 * uint32_t minor = [0|1]
2157 * uint32_t build = [2195|2600]
2158 * extra unicode string = e.g. "Service Pack 3"
2160 if (!StrCaseCmp(value, "OSVersion")) {
2161 DATA_BLOB blob;
2162 enum ndr_err_code ndr_err;
2163 struct spoolss_OSVersion os;
2165 os.major = 5; /* Windows 2000 == 5.0 */
2166 os.minor = 0;
2167 os.build = 2195; /* build */
2168 os.extra_string = ""; /* leave extra string empty */
2170 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2171 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2172 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2173 return WERR_GENERAL_FAILURE;
2176 *type = REG_BINARY;
2177 data->binary = blob;
2179 return WERR_OK;
2183 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2184 *type = REG_SZ;
2186 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2187 W_ERROR_HAVE_NO_MEMORY(data->string);
2189 return WERR_OK;
2192 if (!StrCaseCmp(value, "Architecture")) {
2193 *type = REG_SZ;
2194 data->string = talloc_strdup(mem_ctx,
2195 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2196 W_ERROR_HAVE_NO_MEMORY(data->string);
2198 return WERR_OK;
2201 if (!StrCaseCmp(value, "DsPresent")) {
2202 *type = REG_DWORD;
2204 /* only show the publish check box if we are a
2205 member of a AD domain */
2207 if (lp_security() == SEC_ADS) {
2208 data->value = 0x01;
2209 } else {
2210 data->value = 0x00;
2212 return WERR_OK;
2215 if (!StrCaseCmp(value, "DNSMachineName")) {
2216 const char *hostname = get_mydnsfullname();
2218 if (!hostname) {
2219 return WERR_BADFILE;
2222 *type = REG_SZ;
2223 data->string = talloc_strdup(mem_ctx, hostname);
2224 W_ERROR_HAVE_NO_MEMORY(data->string);
2226 return WERR_OK;
2229 *type = REG_NONE;
2231 return WERR_INVALID_PARAM;
2234 /****************************************************************
2235 _spoolss_GetPrinterData
2236 ****************************************************************/
2238 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2239 struct spoolss_GetPrinterData *r)
2241 struct spoolss_GetPrinterDataEx r2;
2243 r2.in.handle = r->in.handle;
2244 r2.in.key_name = "PrinterDriverData";
2245 r2.in.value_name = r->in.value_name;
2246 r2.in.offered = r->in.offered;
2247 r2.out.type = r->out.type;
2248 r2.out.data = r->out.data;
2249 r2.out.needed = r->out.needed;
2251 return _spoolss_GetPrinterDataEx(p, &r2);
2254 /*********************************************************
2255 Connect to the client machine.
2256 **********************************************************/
2258 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2259 struct sockaddr_storage *client_ss, const char *remote_machine)
2261 NTSTATUS ret;
2262 struct cli_state *the_cli;
2263 struct sockaddr_storage rm_addr;
2264 char addr[INET6_ADDRSTRLEN];
2266 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2267 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2268 remote_machine));
2269 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2270 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2271 return false;
2273 print_sockaddr(addr, sizeof(addr), &rm_addr);
2274 } else {
2275 rm_addr = *client_ss;
2276 print_sockaddr(addr, sizeof(addr), &rm_addr);
2277 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2278 addr));
2281 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2282 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2283 addr));
2284 return false;
2287 /* setup the connection */
2288 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2289 &rm_addr, 0, "IPC$", "IPC",
2290 "", /* username */
2291 "", /* domain */
2292 "", /* password */
2293 0, lp_client_signing(), NULL );
2295 if ( !NT_STATUS_IS_OK( ret ) ) {
2296 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2297 remote_machine ));
2298 return false;
2301 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2302 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2303 cli_shutdown(the_cli);
2304 return false;
2308 * Ok - we have an anonymous connection to the IPC$ share.
2309 * Now start the NT Domain stuff :-).
2312 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2313 if (!NT_STATUS_IS_OK(ret)) {
2314 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2315 remote_machine, nt_errstr(ret)));
2316 cli_shutdown(the_cli);
2317 return false;
2320 return true;
2323 /***************************************************************************
2324 Connect to the client.
2325 ****************************************************************************/
2327 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2328 uint32_t localprinter, uint32_t type,
2329 struct policy_handle *handle,
2330 struct sockaddr_storage *client_ss)
2332 WERROR result;
2333 NTSTATUS status;
2336 * If it's the first connection, contact the client
2337 * and connect to the IPC$ share anonymously
2339 if (smb_connections==0) {
2340 fstring unix_printer;
2342 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2344 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2345 return false;
2347 messaging_register(smbd_messaging_context(), NULL,
2348 MSG_PRINTER_NOTIFY2,
2349 receive_notify2_message_list);
2350 /* Tell the connections db we're now interested in printer
2351 * notify messages. */
2352 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2356 * Tell the specific printing tdb we want messages for this printer
2357 * by registering our PID.
2360 if (!print_notify_register_pid(snum))
2361 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2363 smb_connections++;
2365 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2366 printer,
2367 localprinter,
2368 type,
2370 NULL,
2371 handle,
2372 &result);
2373 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2374 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2375 win_errstr(result)));
2377 return (W_ERROR_IS_OK(result));
2380 /****************************************************************
2381 ****************************************************************/
2383 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2384 const struct spoolss_NotifyOption *r)
2386 struct spoolss_NotifyOption *option;
2387 uint32_t i,k;
2389 if (!r) {
2390 return NULL;
2393 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2394 if (!option) {
2395 return NULL;
2398 *option = *r;
2400 if (!option->count) {
2401 return option;
2404 option->types = talloc_zero_array(option,
2405 struct spoolss_NotifyOptionType, option->count);
2406 if (!option->types) {
2407 talloc_free(option);
2408 return NULL;
2411 for (i=0; i < option->count; i++) {
2412 option->types[i] = r->types[i];
2414 if (option->types[i].count) {
2415 option->types[i].fields = talloc_zero_array(option,
2416 union spoolss_Field, option->types[i].count);
2417 if (!option->types[i].fields) {
2418 talloc_free(option);
2419 return NULL;
2421 for (k=0; k<option->types[i].count; k++) {
2422 option->types[i].fields[k] =
2423 r->types[i].fields[k];
2428 return option;
2431 /****************************************************************
2432 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2434 * before replying OK: status=0 a rpc call is made to the workstation
2435 * asking ReplyOpenPrinter
2437 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2438 * called from api_spoolss_rffpcnex
2439 ****************************************************************/
2441 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2442 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2444 int snum = -1;
2445 struct spoolss_NotifyOption *option = r->in.notify_options;
2446 struct sockaddr_storage client_ss;
2448 /* store the notify value in the printer struct */
2450 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2452 if (!Printer) {
2453 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2454 "Invalid handle (%s:%u:%u).\n",
2455 OUR_HANDLE(r->in.handle)));
2456 return WERR_BADFID;
2459 Printer->notify.flags = r->in.flags;
2460 Printer->notify.options = r->in.options;
2461 Printer->notify.printerlocal = r->in.printer_local;
2463 TALLOC_FREE(Printer->notify.option);
2464 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2466 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2468 /* Connect to the client machine and send a ReplyOpenPrinter */
2470 if ( Printer->printer_type == SPLHND_SERVER)
2471 snum = -1;
2472 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2473 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2474 return WERR_BADFID;
2476 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2477 "client_address is %s\n", p->client_address));
2479 if (!interpret_string_addr(&client_ss, p->client_address,
2480 AI_NUMERICHOST)) {
2481 return WERR_SERVER_UNAVAILABLE;
2484 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2485 Printer->notify.printerlocal, 1,
2486 &Printer->notify.client_hnd, &client_ss))
2487 return WERR_SERVER_UNAVAILABLE;
2489 Printer->notify.client_connected = true;
2491 return WERR_OK;
2494 /*******************************************************************
2495 * fill a notify_info_data with the servername
2496 ********************************************************************/
2498 static void spoolss_notify_server_name(int snum,
2499 struct spoolss_Notify *data,
2500 print_queue_struct *queue,
2501 NT_PRINTER_INFO_LEVEL *printer,
2502 TALLOC_CTX *mem_ctx)
2504 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2507 /*******************************************************************
2508 * fill a notify_info_data with the printername (not including the servername).
2509 ********************************************************************/
2511 static void spoolss_notify_printer_name(int snum,
2512 struct spoolss_Notify *data,
2513 print_queue_struct *queue,
2514 NT_PRINTER_INFO_LEVEL *printer,
2515 TALLOC_CTX *mem_ctx)
2517 /* the notify name should not contain the \\server\ part */
2518 char *p = strrchr(printer->info_2->printername, '\\');
2520 if (!p) {
2521 p = printer->info_2->printername;
2522 } else {
2523 p++;
2526 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2529 /*******************************************************************
2530 * fill a notify_info_data with the servicename
2531 ********************************************************************/
2533 static void spoolss_notify_share_name(int snum,
2534 struct spoolss_Notify *data,
2535 print_queue_struct *queue,
2536 NT_PRINTER_INFO_LEVEL *printer,
2537 TALLOC_CTX *mem_ctx)
2539 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2542 /*******************************************************************
2543 * fill a notify_info_data with the port name
2544 ********************************************************************/
2546 static void spoolss_notify_port_name(int snum,
2547 struct spoolss_Notify *data,
2548 print_queue_struct *queue,
2549 NT_PRINTER_INFO_LEVEL *printer,
2550 TALLOC_CTX *mem_ctx)
2552 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2555 /*******************************************************************
2556 * fill a notify_info_data with the printername
2557 * but it doesn't exist, have to see what to do
2558 ********************************************************************/
2560 static void spoolss_notify_driver_name(int snum,
2561 struct spoolss_Notify *data,
2562 print_queue_struct *queue,
2563 NT_PRINTER_INFO_LEVEL *printer,
2564 TALLOC_CTX *mem_ctx)
2566 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2569 /*******************************************************************
2570 * fill a notify_info_data with the comment
2571 ********************************************************************/
2573 static void spoolss_notify_comment(int snum,
2574 struct spoolss_Notify *data,
2575 print_queue_struct *queue,
2576 NT_PRINTER_INFO_LEVEL *printer,
2577 TALLOC_CTX *mem_ctx)
2579 char *p;
2581 if (*printer->info_2->comment == '\0') {
2582 p = lp_comment(snum);
2583 } else {
2584 p = printer->info_2->comment;
2587 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2590 /*******************************************************************
2591 * fill a notify_info_data with the comment
2592 * location = "Room 1, floor 2, building 3"
2593 ********************************************************************/
2595 static void spoolss_notify_location(int snum,
2596 struct spoolss_Notify *data,
2597 print_queue_struct *queue,
2598 NT_PRINTER_INFO_LEVEL *printer,
2599 TALLOC_CTX *mem_ctx)
2601 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2604 /*******************************************************************
2605 * fill a notify_info_data with the device mode
2606 * jfm:xxxx don't to it for know but that's a real problem !!!
2607 ********************************************************************/
2609 static void spoolss_notify_devmode(int snum,
2610 struct spoolss_Notify *data,
2611 print_queue_struct *queue,
2612 NT_PRINTER_INFO_LEVEL *printer,
2613 TALLOC_CTX *mem_ctx)
2615 /* for a dummy implementation we have to zero the fields */
2616 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2619 /*******************************************************************
2620 * fill a notify_info_data with the separator file name
2621 ********************************************************************/
2623 static void spoolss_notify_sepfile(int snum,
2624 struct spoolss_Notify *data,
2625 print_queue_struct *queue,
2626 NT_PRINTER_INFO_LEVEL *printer,
2627 TALLOC_CTX *mem_ctx)
2629 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2632 /*******************************************************************
2633 * fill a notify_info_data with the print processor
2634 * jfm:xxxx return always winprint to indicate we don't do anything to it
2635 ********************************************************************/
2637 static void spoolss_notify_print_processor(int snum,
2638 struct spoolss_Notify *data,
2639 print_queue_struct *queue,
2640 NT_PRINTER_INFO_LEVEL *printer,
2641 TALLOC_CTX *mem_ctx)
2643 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2646 /*******************************************************************
2647 * fill a notify_info_data with the print processor options
2648 * jfm:xxxx send an empty string
2649 ********************************************************************/
2651 static void spoolss_notify_parameters(int snum,
2652 struct spoolss_Notify *data,
2653 print_queue_struct *queue,
2654 NT_PRINTER_INFO_LEVEL *printer,
2655 TALLOC_CTX *mem_ctx)
2657 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2660 /*******************************************************************
2661 * fill a notify_info_data with the data type
2662 * jfm:xxxx always send RAW as data type
2663 ********************************************************************/
2665 static void spoolss_notify_datatype(int snum,
2666 struct spoolss_Notify *data,
2667 print_queue_struct *queue,
2668 NT_PRINTER_INFO_LEVEL *printer,
2669 TALLOC_CTX *mem_ctx)
2671 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2674 /*******************************************************************
2675 * fill a notify_info_data with the security descriptor
2676 * jfm:xxxx send an null pointer to say no security desc
2677 * have to implement security before !
2678 ********************************************************************/
2680 static void spoolss_notify_security_desc(int snum,
2681 struct spoolss_Notify *data,
2682 print_queue_struct *queue,
2683 NT_PRINTER_INFO_LEVEL *printer,
2684 TALLOC_CTX *mem_ctx)
2686 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2687 printer->info_2->secdesc_buf->sd_size,
2688 printer->info_2->secdesc_buf->sd);
2691 /*******************************************************************
2692 * fill a notify_info_data with the attributes
2693 * jfm:xxxx a samba printer is always shared
2694 ********************************************************************/
2696 static void spoolss_notify_attributes(int snum,
2697 struct spoolss_Notify *data,
2698 print_queue_struct *queue,
2699 NT_PRINTER_INFO_LEVEL *printer,
2700 TALLOC_CTX *mem_ctx)
2702 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2705 /*******************************************************************
2706 * fill a notify_info_data with the priority
2707 ********************************************************************/
2709 static void spoolss_notify_priority(int snum,
2710 struct spoolss_Notify *data,
2711 print_queue_struct *queue,
2712 NT_PRINTER_INFO_LEVEL *printer,
2713 TALLOC_CTX *mem_ctx)
2715 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2718 /*******************************************************************
2719 * fill a notify_info_data with the default priority
2720 ********************************************************************/
2722 static void spoolss_notify_default_priority(int snum,
2723 struct spoolss_Notify *data,
2724 print_queue_struct *queue,
2725 NT_PRINTER_INFO_LEVEL *printer,
2726 TALLOC_CTX *mem_ctx)
2728 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2731 /*******************************************************************
2732 * fill a notify_info_data with the start time
2733 ********************************************************************/
2735 static void spoolss_notify_start_time(int snum,
2736 struct spoolss_Notify *data,
2737 print_queue_struct *queue,
2738 NT_PRINTER_INFO_LEVEL *printer,
2739 TALLOC_CTX *mem_ctx)
2741 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2744 /*******************************************************************
2745 * fill a notify_info_data with the until time
2746 ********************************************************************/
2748 static void spoolss_notify_until_time(int snum,
2749 struct spoolss_Notify *data,
2750 print_queue_struct *queue,
2751 NT_PRINTER_INFO_LEVEL *printer,
2752 TALLOC_CTX *mem_ctx)
2754 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2757 /*******************************************************************
2758 * fill a notify_info_data with the status
2759 ********************************************************************/
2761 static void spoolss_notify_status(int snum,
2762 struct spoolss_Notify *data,
2763 print_queue_struct *queue,
2764 NT_PRINTER_INFO_LEVEL *printer,
2765 TALLOC_CTX *mem_ctx)
2767 print_status_struct status;
2769 print_queue_length(snum, &status);
2770 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2773 /*******************************************************************
2774 * fill a notify_info_data with the number of jobs queued
2775 ********************************************************************/
2777 static void spoolss_notify_cjobs(int snum,
2778 struct spoolss_Notify *data,
2779 print_queue_struct *queue,
2780 NT_PRINTER_INFO_LEVEL *printer,
2781 TALLOC_CTX *mem_ctx)
2783 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2786 /*******************************************************************
2787 * fill a notify_info_data with the average ppm
2788 ********************************************************************/
2790 static void spoolss_notify_average_ppm(int snum,
2791 struct spoolss_Notify *data,
2792 print_queue_struct *queue,
2793 NT_PRINTER_INFO_LEVEL *printer,
2794 TALLOC_CTX *mem_ctx)
2796 /* always respond 8 pages per minutes */
2797 /* a little hard ! */
2798 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2801 /*******************************************************************
2802 * fill a notify_info_data with username
2803 ********************************************************************/
2805 static void spoolss_notify_username(int snum,
2806 struct spoolss_Notify *data,
2807 print_queue_struct *queue,
2808 NT_PRINTER_INFO_LEVEL *printer,
2809 TALLOC_CTX *mem_ctx)
2811 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2814 /*******************************************************************
2815 * fill a notify_info_data with job status
2816 ********************************************************************/
2818 static void spoolss_notify_job_status(int snum,
2819 struct spoolss_Notify *data,
2820 print_queue_struct *queue,
2821 NT_PRINTER_INFO_LEVEL *printer,
2822 TALLOC_CTX *mem_ctx)
2824 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2827 /*******************************************************************
2828 * fill a notify_info_data with job name
2829 ********************************************************************/
2831 static void spoolss_notify_job_name(int snum,
2832 struct spoolss_Notify *data,
2833 print_queue_struct *queue,
2834 NT_PRINTER_INFO_LEVEL *printer,
2835 TALLOC_CTX *mem_ctx)
2837 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2840 /*******************************************************************
2841 * fill a notify_info_data with job status
2842 ********************************************************************/
2844 static void spoolss_notify_job_status_string(int snum,
2845 struct spoolss_Notify *data,
2846 print_queue_struct *queue,
2847 NT_PRINTER_INFO_LEVEL *printer,
2848 TALLOC_CTX *mem_ctx)
2851 * Now we're returning job status codes we just return a "" here. JRA.
2854 const char *p = "";
2856 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2857 p = "unknown";
2859 switch (queue->status) {
2860 case LPQ_QUEUED:
2861 p = "Queued";
2862 break;
2863 case LPQ_PAUSED:
2864 p = ""; /* NT provides the paused string */
2865 break;
2866 case LPQ_SPOOLING:
2867 p = "Spooling";
2868 break;
2869 case LPQ_PRINTING:
2870 p = "Printing";
2871 break;
2873 #endif /* NO LONGER NEEDED. */
2875 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2878 /*******************************************************************
2879 * fill a notify_info_data with job time
2880 ********************************************************************/
2882 static void spoolss_notify_job_time(int snum,
2883 struct spoolss_Notify *data,
2884 print_queue_struct *queue,
2885 NT_PRINTER_INFO_LEVEL *printer,
2886 TALLOC_CTX *mem_ctx)
2888 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2891 /*******************************************************************
2892 * fill a notify_info_data with job size
2893 ********************************************************************/
2895 static void spoolss_notify_job_size(int snum,
2896 struct spoolss_Notify *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2901 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2904 /*******************************************************************
2905 * fill a notify_info_data with page info
2906 ********************************************************************/
2907 static void spoolss_notify_total_pages(int snum,
2908 struct spoolss_Notify *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2913 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2916 /*******************************************************************
2917 * fill a notify_info_data with pages printed info.
2918 ********************************************************************/
2919 static void spoolss_notify_pages_printed(int snum,
2920 struct spoolss_Notify *data,
2921 print_queue_struct *queue,
2922 NT_PRINTER_INFO_LEVEL *printer,
2923 TALLOC_CTX *mem_ctx)
2925 /* Add code when back-end tracks this */
2926 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2929 /*******************************************************************
2930 Fill a notify_info_data with job position.
2931 ********************************************************************/
2933 static void spoolss_notify_job_position(int snum,
2934 struct spoolss_Notify *data,
2935 print_queue_struct *queue,
2936 NT_PRINTER_INFO_LEVEL *printer,
2937 TALLOC_CTX *mem_ctx)
2939 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2942 /*******************************************************************
2943 Fill a notify_info_data with submitted time.
2944 ********************************************************************/
2946 static void spoolss_notify_submitted_time(int snum,
2947 struct spoolss_Notify *data,
2948 print_queue_struct *queue,
2949 NT_PRINTER_INFO_LEVEL *printer,
2950 TALLOC_CTX *mem_ctx)
2952 data->data.string.string = NULL;
2953 data->data.string.size = 0;
2955 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2956 &data->data.string.string,
2957 &data->data.string.size);
2961 struct s_notify_info_data_table
2963 enum spoolss_NotifyType type;
2964 uint16_t field;
2965 const char *name;
2966 enum spoolss_NotifyTable variable_type;
2967 void (*fn) (int snum, struct spoolss_Notify *data,
2968 print_queue_struct *queue,
2969 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2972 /* A table describing the various print notification constants and
2973 whether the notification data is a pointer to a variable sized
2974 buffer, a one value uint32_t or a two value uint32_t. */
2976 static const struct s_notify_info_data_table notify_info_data_table[] =
2978 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2979 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2980 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2981 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2982 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2983 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2984 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2985 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2986 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2987 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2988 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
2999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3003 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3004 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3005 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3006 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3007 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3008 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3009 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3010 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3011 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3012 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3013 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3014 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3015 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3016 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3017 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3018 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3019 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3020 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3021 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3022 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3023 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3024 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3025 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3026 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3029 /*******************************************************************
3030 Return the variable_type of info_data structure.
3031 ********************************************************************/
3033 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3034 uint16_t field)
3036 int i=0;
3038 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3039 if ( (notify_info_data_table[i].type == type) &&
3040 (notify_info_data_table[i].field == field) ) {
3041 return notify_info_data_table[i].variable_type;
3045 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3047 return 0;
3050 /****************************************************************************
3051 ****************************************************************************/
3053 static bool search_notify(enum spoolss_NotifyType type,
3054 uint16_t field,
3055 int *value)
3057 int i;
3059 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3060 if (notify_info_data_table[i].type == type &&
3061 notify_info_data_table[i].field == field &&
3062 notify_info_data_table[i].fn != NULL) {
3063 *value = i;
3064 return true;
3068 return false;
3071 /****************************************************************************
3072 ****************************************************************************/
3074 void construct_info_data(struct spoolss_Notify *info_data,
3075 enum spoolss_NotifyType type,
3076 uint16_t field,
3077 int id)
3079 info_data->type = type;
3080 info_data->field.field = field;
3081 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3082 info_data->job_id = id;
3085 /*******************************************************************
3087 * fill a notify_info struct with info asked
3089 ********************************************************************/
3091 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3092 struct spoolss_NotifyInfo *info,
3093 int snum,
3094 const struct spoolss_NotifyOptionType *option_type,
3095 uint32_t id,
3096 TALLOC_CTX *mem_ctx)
3098 int field_num,j;
3099 enum spoolss_NotifyType type;
3100 uint16_t field;
3102 struct spoolss_Notify *current_data;
3103 NT_PRINTER_INFO_LEVEL *printer = NULL;
3104 print_queue_struct *queue=NULL;
3106 type = option_type->type;
3108 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3109 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3110 option_type->count, lp_servicename(snum)));
3112 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3113 return false;
3115 for(field_num=0; field_num < option_type->count; field_num++) {
3116 field = option_type->fields[field_num].field;
3118 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3120 if (!search_notify(type, field, &j) )
3121 continue;
3123 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3124 struct spoolss_Notify,
3125 info->count + 1);
3126 if (info->notifies == NULL) {
3127 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3128 free_a_printer(&printer, 2);
3129 return false;
3132 current_data = &info->notifies[info->count];
3134 construct_info_data(current_data, type, field, id);
3136 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3137 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3139 notify_info_data_table[j].fn(snum, current_data, queue,
3140 printer, mem_ctx);
3142 info->count++;
3145 free_a_printer(&printer, 2);
3146 return true;
3149 /*******************************************************************
3151 * fill a notify_info struct with info asked
3153 ********************************************************************/
3155 static bool construct_notify_jobs_info(print_queue_struct *queue,
3156 struct spoolss_NotifyInfo *info,
3157 NT_PRINTER_INFO_LEVEL *printer,
3158 int snum,
3159 const struct spoolss_NotifyOptionType *option_type,
3160 uint32_t id,
3161 TALLOC_CTX *mem_ctx)
3163 int field_num,j;
3164 enum spoolss_NotifyType type;
3165 uint16_t field;
3166 struct spoolss_Notify *current_data;
3168 DEBUG(4,("construct_notify_jobs_info\n"));
3170 type = option_type->type;
3172 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3173 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3174 option_type->count));
3176 for(field_num=0; field_num<option_type->count; field_num++) {
3177 field = option_type->fields[field_num].field;
3179 if (!search_notify(type, field, &j) )
3180 continue;
3182 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3183 struct spoolss_Notify,
3184 info->count + 1);
3185 if (info->notifies == NULL) {
3186 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3187 return false;
3190 current_data=&(info->notifies[info->count]);
3192 construct_info_data(current_data, type, field, id);
3193 notify_info_data_table[j].fn(snum, current_data, queue,
3194 printer, mem_ctx);
3195 info->count++;
3198 return true;
3202 * JFM: The enumeration is not that simple, it's even non obvious.
3204 * let's take an example: I want to monitor the PRINTER SERVER for
3205 * the printer's name and the number of jobs currently queued.
3206 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3207 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3209 * I have 3 printers on the back of my server.
3211 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3212 * structures.
3213 * Number Data Id
3214 * 1 printer 1 name 1
3215 * 2 printer 1 cjob 1
3216 * 3 printer 2 name 2
3217 * 4 printer 2 cjob 2
3218 * 5 printer 3 name 3
3219 * 6 printer 3 name 3
3221 * that's the print server case, the printer case is even worse.
3224 /*******************************************************************
3226 * enumerate all printers on the printserver
3227 * fill a notify_info struct with info asked
3229 ********************************************************************/
3231 static WERROR printserver_notify_info(pipes_struct *p,
3232 struct policy_handle *hnd,
3233 struct spoolss_NotifyInfo *info,
3234 TALLOC_CTX *mem_ctx)
3236 int snum;
3237 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3238 int n_services=lp_numservices();
3239 int i;
3240 struct spoolss_NotifyOption *option;
3241 struct spoolss_NotifyOptionType option_type;
3243 DEBUG(4,("printserver_notify_info\n"));
3245 if (!Printer)
3246 return WERR_BADFID;
3248 option = Printer->notify.option;
3250 info->version = 2;
3251 info->notifies = NULL;
3252 info->count = 0;
3254 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3255 sending a ffpcn() request first */
3257 if ( !option )
3258 return WERR_BADFID;
3260 for (i=0; i<option->count; i++) {
3261 option_type = option->types[i];
3263 if (option_type.type != PRINTER_NOTIFY_TYPE)
3264 continue;
3266 for (snum=0; snum<n_services; snum++)
3268 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3269 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3273 #if 0
3275 * Debugging information, don't delete.
3278 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3279 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3280 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3282 for (i=0; i<info->count; i++) {
3283 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3284 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3285 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3287 #endif
3289 return WERR_OK;
3292 /*******************************************************************
3294 * fill a notify_info struct with info asked
3296 ********************************************************************/
3298 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3299 struct spoolss_NotifyInfo *info,
3300 TALLOC_CTX *mem_ctx)
3302 int snum;
3303 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3304 int i;
3305 uint32_t id;
3306 struct spoolss_NotifyOption *option;
3307 struct spoolss_NotifyOptionType option_type;
3308 int count,j;
3309 print_queue_struct *queue=NULL;
3310 print_status_struct status;
3312 DEBUG(4,("printer_notify_info\n"));
3314 if (!Printer)
3315 return WERR_BADFID;
3317 option = Printer->notify.option;
3318 id = 0x0;
3320 info->version = 2;
3321 info->notifies = NULL;
3322 info->count = 0;
3324 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3325 sending a ffpcn() request first */
3327 if ( !option )
3328 return WERR_BADFID;
3330 get_printer_snum(p, hnd, &snum, NULL);
3332 for (i=0; i<option->count; i++) {
3333 option_type = option->types[i];
3335 switch (option_type.type) {
3336 case PRINTER_NOTIFY_TYPE:
3337 if(construct_notify_printer_info(Printer, info, snum,
3338 &option_type, id,
3339 mem_ctx))
3340 id--;
3341 break;
3343 case JOB_NOTIFY_TYPE: {
3344 NT_PRINTER_INFO_LEVEL *printer = NULL;
3346 count = print_queue_status(snum, &queue, &status);
3348 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3349 goto done;
3351 for (j=0; j<count; j++) {
3352 construct_notify_jobs_info(&queue[j], info,
3353 printer, snum,
3354 &option_type,
3355 queue[j].job,
3356 mem_ctx);
3359 free_a_printer(&printer, 2);
3361 done:
3362 SAFE_FREE(queue);
3363 break;
3369 * Debugging information, don't delete.
3372 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3373 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3374 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3376 for (i=0; i<info->count; i++) {
3377 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3378 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3379 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3382 return WERR_OK;
3385 /****************************************************************
3386 _spoolss_RouterRefreshPrinterChangeNotify
3387 ****************************************************************/
3389 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3390 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3392 struct spoolss_NotifyInfo *info;
3394 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3395 WERROR result = WERR_BADFID;
3397 /* we always have a spoolss_NotifyInfo struct */
3398 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3399 if (!info) {
3400 result = WERR_NOMEM;
3401 goto done;
3404 *r->out.info = info;
3406 if (!Printer) {
3407 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3408 "Invalid handle (%s:%u:%u).\n",
3409 OUR_HANDLE(r->in.handle)));
3410 goto done;
3413 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3416 * We are now using the change value, and
3417 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3418 * I don't have a global notification system, I'm sending back all the
3419 * informations even when _NOTHING_ has changed.
3422 /* We need to keep track of the change value to send back in
3423 RRPCN replies otherwise our updates are ignored. */
3425 Printer->notify.fnpcn = true;
3427 if (Printer->notify.client_connected) {
3428 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3429 "Saving change value in request [%x]\n",
3430 r->in.change_low));
3431 Printer->notify.change = r->in.change_low;
3434 /* just ignore the spoolss_NotifyOption */
3436 switch (Printer->printer_type) {
3437 case SPLHND_SERVER:
3438 result = printserver_notify_info(p, r->in.handle,
3439 info, p->mem_ctx);
3440 break;
3442 case SPLHND_PRINTER:
3443 result = printer_notify_info(p, r->in.handle,
3444 info, p->mem_ctx);
3445 break;
3448 Printer->notify.fnpcn = false;
3450 done:
3451 return result;
3454 /********************************************************************
3455 * construct_printer_info_0
3456 * fill a printer_info_0 struct
3457 ********************************************************************/
3459 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3460 const NT_PRINTER_INFO_LEVEL *ntprinter,
3461 struct spoolss_PrinterInfo0 *r,
3462 int snum)
3464 int count;
3465 counter_printer_0 *session_counter;
3466 time_t setuptime;
3467 print_status_struct status;
3469 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3470 W_ERROR_HAVE_NO_MEMORY(r->printername);
3472 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3473 W_ERROR_HAVE_NO_MEMORY(r->servername);
3475 count = print_queue_length(snum, &status);
3477 /* check if we already have a counter for this printer */
3478 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3479 if (session_counter->snum == snum)
3480 break;
3483 /* it's the first time, add it to the list */
3484 if (session_counter == NULL) {
3485 session_counter = SMB_MALLOC_P(counter_printer_0);
3486 W_ERROR_HAVE_NO_MEMORY(session_counter);
3487 ZERO_STRUCTP(session_counter);
3488 session_counter->snum = snum;
3489 session_counter->counter = 0;
3490 DLIST_ADD(counter_list, session_counter);
3493 /* increment it */
3494 session_counter->counter++;
3496 r->cjobs = count;
3497 r->total_jobs = 0;
3498 r->total_bytes = 0;
3500 setuptime = (time_t)ntprinter->info_2->setuptime;
3502 init_systemtime(&r->time, gmtime(&setuptime));
3504 /* JFM:
3505 * the global_counter should be stored in a TDB as it's common to all the clients
3506 * and should be zeroed on samba startup
3508 r->global_counter = session_counter->counter;
3509 r->total_pages = 0;
3510 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3511 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3512 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3513 r->free_build = SPOOLSS_RELEASE_BUILD;
3514 r->spooling = 0;
3515 r->max_spooling = 0;
3516 r->session_counter = session_counter->counter;
3517 r->num_error_out_of_paper = 0x0;
3518 r->num_error_not_ready = 0x0; /* number of print failure */
3519 r->job_error = 0x0;
3520 r->number_of_processors = 0x1;
3521 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3522 r->high_part_total_bytes = 0x0;
3523 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3524 r->last_error = WERR_OK;
3525 r->status = nt_printq_status(status.status);
3526 r->enumerate_network_printers = 0x0;
3527 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3528 r->processor_architecture = 0x0;
3529 r->processor_level = 0x6; /* 6 ???*/
3530 r->ref_ic = 0;
3531 r->reserved2 = 0;
3532 r->reserved3 = 0;
3534 return WERR_OK;
3537 /****************************************************************************
3538 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3539 should be valid upon entry
3540 ****************************************************************************/
3542 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3543 struct spoolss_DeviceMode *r,
3544 const NT_DEVICEMODE *ntdevmode)
3546 if (!r || !ntdevmode) {
3547 return WERR_INVALID_PARAM;
3550 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3551 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3553 r->specversion = ntdevmode->specversion;
3554 r->driverversion = ntdevmode->driverversion;
3555 r->size = ntdevmode->size;
3556 r->__driverextra_length = ntdevmode->driverextra;
3557 r->fields = ntdevmode->fields;
3559 r->orientation = ntdevmode->orientation;
3560 r->papersize = ntdevmode->papersize;
3561 r->paperlength = ntdevmode->paperlength;
3562 r->paperwidth = ntdevmode->paperwidth;
3563 r->scale = ntdevmode->scale;
3564 r->copies = ntdevmode->copies;
3565 r->defaultsource = ntdevmode->defaultsource;
3566 r->printquality = ntdevmode->printquality;
3567 r->color = ntdevmode->color;
3568 r->duplex = ntdevmode->duplex;
3569 r->yresolution = ntdevmode->yresolution;
3570 r->ttoption = ntdevmode->ttoption;
3571 r->collate = ntdevmode->collate;
3573 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3574 W_ERROR_HAVE_NO_MEMORY(r->formname);
3576 r->logpixels = ntdevmode->logpixels;
3577 r->bitsperpel = ntdevmode->bitsperpel;
3578 r->pelswidth = ntdevmode->pelswidth;
3579 r->pelsheight = ntdevmode->pelsheight;
3580 r->displayflags = ntdevmode->displayflags;
3581 r->displayfrequency = ntdevmode->displayfrequency;
3582 r->icmmethod = ntdevmode->icmmethod;
3583 r->icmintent = ntdevmode->icmintent;
3584 r->mediatype = ntdevmode->mediatype;
3585 r->dithertype = ntdevmode->dithertype;
3586 r->reserved1 = ntdevmode->reserved1;
3587 r->reserved2 = ntdevmode->reserved2;
3588 r->panningwidth = ntdevmode->panningwidth;
3589 r->panningheight = ntdevmode->panningheight;
3591 if (ntdevmode->nt_dev_private != NULL) {
3592 r->driverextra_data = data_blob_talloc(mem_ctx,
3593 ntdevmode->nt_dev_private,
3594 ntdevmode->driverextra);
3595 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3598 return WERR_OK;
3602 /****************************************************************************
3603 Create a spoolss_DeviceMode struct. Returns talloced memory.
3604 ****************************************************************************/
3606 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3607 const char *servicename)
3609 WERROR result;
3610 NT_PRINTER_INFO_LEVEL *printer = NULL;
3611 struct spoolss_DeviceMode *devmode = NULL;
3613 DEBUG(7,("construct_dev_mode\n"));
3615 DEBUGADD(8,("getting printer characteristics\n"));
3617 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3618 return NULL;
3620 if (!printer->info_2->devmode) {
3621 DEBUG(5, ("BONG! There was no device mode!\n"));
3622 goto done;
3625 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3626 if (!devmode) {
3627 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3628 goto done;
3631 DEBUGADD(8,("loading DEVICEMODE\n"));
3633 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3634 if (!W_ERROR_IS_OK(result)) {
3635 TALLOC_FREE(devmode);
3638 done:
3639 free_a_printer(&printer,2);
3641 return devmode;
3644 /********************************************************************
3645 * construct_printer_info1
3646 * fill a spoolss_PrinterInfo1 struct
3647 ********************************************************************/
3649 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3650 const NT_PRINTER_INFO_LEVEL *ntprinter,
3651 uint32_t flags,
3652 struct spoolss_PrinterInfo1 *r,
3653 int snum)
3655 r->flags = flags;
3657 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3658 ntprinter->info_2->printername,
3659 ntprinter->info_2->drivername,
3660 ntprinter->info_2->location);
3661 W_ERROR_HAVE_NO_MEMORY(r->description);
3663 if (*ntprinter->info_2->comment == '\0') {
3664 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3665 } else {
3666 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3668 W_ERROR_HAVE_NO_MEMORY(r->comment);
3670 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3671 W_ERROR_HAVE_NO_MEMORY(r->name);
3673 return WERR_OK;
3676 /********************************************************************
3677 * construct_printer_info2
3678 * fill a spoolss_PrinterInfo2 struct
3679 ********************************************************************/
3681 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3682 const NT_PRINTER_INFO_LEVEL *ntprinter,
3683 struct spoolss_PrinterInfo2 *r,
3684 int snum)
3686 int count;
3688 print_status_struct status;
3690 count = print_queue_length(snum, &status);
3692 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3693 W_ERROR_HAVE_NO_MEMORY(r->servername);
3694 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3695 W_ERROR_HAVE_NO_MEMORY(r->printername);
3696 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3697 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3698 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3699 W_ERROR_HAVE_NO_MEMORY(r->portname);
3700 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3701 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3703 if (*ntprinter->info_2->comment == '\0') {
3704 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3705 } else {
3706 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3708 W_ERROR_HAVE_NO_MEMORY(r->comment);
3710 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3711 W_ERROR_HAVE_NO_MEMORY(r->location);
3712 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3713 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3714 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3715 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3716 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3717 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3718 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3719 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3721 r->attributes = ntprinter->info_2->attributes;
3723 r->priority = ntprinter->info_2->priority;
3724 r->defaultpriority = ntprinter->info_2->default_priority;
3725 r->starttime = ntprinter->info_2->starttime;
3726 r->untiltime = ntprinter->info_2->untiltime;
3727 r->status = nt_printq_status(status.status);
3728 r->cjobs = count;
3729 r->averageppm = ntprinter->info_2->averageppm;
3731 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3732 if (!r->devmode) {
3733 DEBUG(8,("Returning NULL Devicemode!\n"));
3736 r->secdesc = NULL;
3738 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3739 /* don't use talloc_steal() here unless you do a deep steal of all
3740 the SEC_DESC members */
3742 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3745 return WERR_OK;
3748 /********************************************************************
3749 * construct_printer_info3
3750 * fill a spoolss_PrinterInfo3 struct
3751 ********************************************************************/
3753 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3754 const NT_PRINTER_INFO_LEVEL *ntprinter,
3755 struct spoolss_PrinterInfo3 *r,
3756 int snum)
3758 /* These are the components of the SD we are returning. */
3760 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3761 /* don't use talloc_steal() here unless you do a deep steal of all
3762 the SEC_DESC members */
3764 r->secdesc = dup_sec_desc(mem_ctx,
3765 ntprinter->info_2->secdesc_buf->sd);
3766 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3769 return WERR_OK;
3772 /********************************************************************
3773 * construct_printer_info4
3774 * fill a spoolss_PrinterInfo4 struct
3775 ********************************************************************/
3777 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3778 const NT_PRINTER_INFO_LEVEL *ntprinter,
3779 struct spoolss_PrinterInfo4 *r,
3780 int snum)
3782 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3783 W_ERROR_HAVE_NO_MEMORY(r->printername);
3784 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3785 W_ERROR_HAVE_NO_MEMORY(r->servername);
3787 r->attributes = ntprinter->info_2->attributes;
3789 return WERR_OK;
3792 /********************************************************************
3793 * construct_printer_info5
3794 * fill a spoolss_PrinterInfo5 struct
3795 ********************************************************************/
3797 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3798 const NT_PRINTER_INFO_LEVEL *ntprinter,
3799 struct spoolss_PrinterInfo5 *r,
3800 int snum)
3802 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3803 W_ERROR_HAVE_NO_MEMORY(r->printername);
3804 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3805 W_ERROR_HAVE_NO_MEMORY(r->portname);
3807 r->attributes = ntprinter->info_2->attributes;
3809 /* these two are not used by NT+ according to MSDN */
3811 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3812 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3814 return WERR_OK;
3817 /********************************************************************
3818 * construct_printer_info_6
3819 * fill a spoolss_PrinterInfo6 struct
3820 ********************************************************************/
3822 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3823 const NT_PRINTER_INFO_LEVEL *ntprinter,
3824 struct spoolss_PrinterInfo6 *r,
3825 int snum)
3827 int count;
3828 print_status_struct status;
3830 count = print_queue_length(snum, &status);
3832 r->status = nt_printq_status(status.status);
3834 return WERR_OK;
3837 /********************************************************************
3838 * construct_printer_info7
3839 * fill a spoolss_PrinterInfo7 struct
3840 ********************************************************************/
3842 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3843 Printer_entry *print_hnd,
3844 struct spoolss_PrinterInfo7 *r,
3845 int snum)
3847 struct GUID guid;
3849 if (is_printer_published(print_hnd, snum, &guid)) {
3850 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3851 r->action = DSPRINT_PUBLISH;
3852 } else {
3853 r->guid = talloc_strdup(mem_ctx, "");
3854 r->action = DSPRINT_UNPUBLISH;
3856 W_ERROR_HAVE_NO_MEMORY(r->guid);
3858 return WERR_OK;
3861 /********************************************************************
3862 * construct_printer_info8
3863 * fill a spoolss_PrinterInfo8 struct
3864 ********************************************************************/
3866 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3867 const NT_PRINTER_INFO_LEVEL *ntprinter,
3868 struct spoolss_DeviceModeInfo *r,
3869 int snum)
3871 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3872 if (!r->devmode) {
3873 DEBUG(8,("Returning NULL Devicemode!\n"));
3876 return WERR_OK;
3880 /********************************************************************
3881 ********************************************************************/
3883 static bool snum_is_shared_printer(int snum)
3885 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3888 /********************************************************************
3889 Spoolss_enumprinters.
3890 ********************************************************************/
3892 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3893 uint32_t level,
3894 uint32_t flags,
3895 union spoolss_PrinterInfo **info_p,
3896 uint32_t *count_p)
3898 int snum;
3899 int n_services = lp_numservices();
3900 union spoolss_PrinterInfo *info = NULL;
3901 uint32_t count = 0;
3902 WERROR result = WERR_OK;
3904 *count_p = 0;
3905 *info_p = NULL;
3907 for (snum = 0; snum < n_services; snum++) {
3909 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3911 if (!snum_is_shared_printer(snum)) {
3912 continue;
3915 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3916 lp_servicename(snum), snum));
3918 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3919 union spoolss_PrinterInfo,
3920 count + 1);
3921 if (!info) {
3922 result = WERR_NOMEM;
3923 goto out;
3926 result = get_a_printer(NULL, &ntprinter, 2,
3927 lp_const_servicename(snum));
3928 if (!W_ERROR_IS_OK(result)) {
3929 goto out;
3932 switch (level) {
3933 case 0:
3934 result = construct_printer_info0(info, ntprinter,
3935 &info[count].info0, snum);
3936 break;
3937 case 1:
3938 result = construct_printer_info1(info, ntprinter, flags,
3939 &info[count].info1, snum);
3940 break;
3941 case 2:
3942 result = construct_printer_info2(info, ntprinter,
3943 &info[count].info2, snum);
3944 break;
3945 case 4:
3946 result = construct_printer_info4(info, ntprinter,
3947 &info[count].info4, snum);
3948 break;
3949 case 5:
3950 result = construct_printer_info5(info, ntprinter,
3951 &info[count].info5, snum);
3952 break;
3954 default:
3955 result = WERR_UNKNOWN_LEVEL;
3956 free_a_printer(&ntprinter, 2);
3957 goto out;
3960 free_a_printer(&ntprinter, 2);
3961 if (!W_ERROR_IS_OK(result)) {
3962 goto out;
3965 count++;
3968 *count_p = count;
3969 *info_p = info;
3971 out:
3972 if (!W_ERROR_IS_OK(result)) {
3973 TALLOC_FREE(info);
3974 return result;
3977 *info_p = info;
3979 return WERR_OK;
3982 /********************************************************************
3983 * handle enumeration of printers at level 0
3984 ********************************************************************/
3986 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3987 uint32_t flags,
3988 const char *servername,
3989 union spoolss_PrinterInfo **info,
3990 uint32_t *count)
3992 DEBUG(4,("enum_all_printers_info_0\n"));
3994 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
3998 /********************************************************************
3999 ********************************************************************/
4001 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4002 uint32_t flags,
4003 union spoolss_PrinterInfo **info,
4004 uint32_t *count)
4006 DEBUG(4,("enum_all_printers_info_1\n"));
4008 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4011 /********************************************************************
4012 enum_all_printers_info_1_local.
4013 *********************************************************************/
4015 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4016 union spoolss_PrinterInfo **info,
4017 uint32_t *count)
4019 DEBUG(4,("enum_all_printers_info_1_local\n"));
4021 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4024 /********************************************************************
4025 enum_all_printers_info_1_name.
4026 *********************************************************************/
4028 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4029 const char *name,
4030 union spoolss_PrinterInfo **info,
4031 uint32_t *count)
4033 const char *s = name;
4035 DEBUG(4,("enum_all_printers_info_1_name\n"));
4037 if ((name[0] == '\\') && (name[1] == '\\')) {
4038 s = name + 2;
4041 if (!is_myname_or_ipaddr(s)) {
4042 return WERR_INVALID_NAME;
4045 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4048 /********************************************************************
4049 enum_all_printers_info_1_network.
4050 *********************************************************************/
4052 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4053 const char *name,
4054 union spoolss_PrinterInfo **info,
4055 uint32_t *count)
4057 const char *s = name;
4059 DEBUG(4,("enum_all_printers_info_1_network\n"));
4061 /* If we respond to a enum_printers level 1 on our name with flags
4062 set to PRINTER_ENUM_REMOTE with a list of printers then these
4063 printers incorrectly appear in the APW browse list.
4064 Specifically the printers for the server appear at the workgroup
4065 level where all the other servers in the domain are
4066 listed. Windows responds to this call with a
4067 WERR_CAN_NOT_COMPLETE so we should do the same. */
4069 if (name[0] == '\\' && name[1] == '\\') {
4070 s = name + 2;
4073 if (is_myname_or_ipaddr(s)) {
4074 return WERR_CAN_NOT_COMPLETE;
4077 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4080 /********************************************************************
4081 * api_spoolss_enumprinters
4083 * called from api_spoolss_enumprinters (see this to understand)
4084 ********************************************************************/
4086 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4087 union spoolss_PrinterInfo **info,
4088 uint32_t *count)
4090 DEBUG(4,("enum_all_printers_info_2\n"));
4092 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4095 /********************************************************************
4096 * handle enumeration of printers at level 1
4097 ********************************************************************/
4099 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4100 uint32_t flags,
4101 const char *name,
4102 union spoolss_PrinterInfo **info,
4103 uint32_t *count)
4105 /* Not all the flags are equals */
4107 if (flags & PRINTER_ENUM_LOCAL) {
4108 return enum_all_printers_info_1_local(mem_ctx, info, count);
4111 if (flags & PRINTER_ENUM_NAME) {
4112 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4115 if (flags & PRINTER_ENUM_NETWORK) {
4116 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4119 return WERR_OK; /* NT4sp5 does that */
4122 /********************************************************************
4123 * handle enumeration of printers at level 2
4124 ********************************************************************/
4126 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4127 uint32_t flags,
4128 const char *servername,
4129 union spoolss_PrinterInfo **info,
4130 uint32_t *count)
4132 if (flags & PRINTER_ENUM_LOCAL) {
4133 return enum_all_printers_info_2(mem_ctx, info, count);
4136 if (flags & PRINTER_ENUM_NAME) {
4137 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4138 return WERR_INVALID_NAME;
4141 return enum_all_printers_info_2(mem_ctx, info, count);
4144 if (flags & PRINTER_ENUM_REMOTE) {
4145 return WERR_UNKNOWN_LEVEL;
4148 return WERR_OK;
4151 /********************************************************************
4152 * handle enumeration of printers at level 4
4153 ********************************************************************/
4155 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4156 uint32_t flags,
4157 const char *servername,
4158 union spoolss_PrinterInfo **info,
4159 uint32_t *count)
4161 DEBUG(4,("enum_all_printers_info_4\n"));
4163 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4167 /********************************************************************
4168 * handle enumeration of printers at level 5
4169 ********************************************************************/
4171 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4172 uint32_t flags,
4173 const char *servername,
4174 union spoolss_PrinterInfo **info,
4175 uint32_t *count)
4177 DEBUG(4,("enum_all_printers_info_5\n"));
4179 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4182 /****************************************************************
4183 _spoolss_EnumPrinters
4184 ****************************************************************/
4186 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4187 struct spoolss_EnumPrinters *r)
4189 const char *name = NULL;
4190 WERROR result;
4192 /* that's an [in out] buffer */
4194 if (!r->in.buffer && (r->in.offered != 0)) {
4195 return WERR_INVALID_PARAM;
4198 DEBUG(4,("_spoolss_EnumPrinters\n"));
4200 *r->out.needed = 0;
4201 *r->out.count = 0;
4202 *r->out.info = NULL;
4205 * Level 1:
4206 * flags==PRINTER_ENUM_NAME
4207 * if name=="" then enumerates all printers
4208 * if name!="" then enumerate the printer
4209 * flags==PRINTER_ENUM_REMOTE
4210 * name is NULL, enumerate printers
4211 * Level 2: name!="" enumerates printers, name can't be NULL
4212 * Level 3: doesn't exist
4213 * Level 4: does a local registry lookup
4214 * Level 5: same as Level 2
4217 if (r->in.server) {
4218 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4219 W_ERROR_HAVE_NO_MEMORY(name);
4222 switch (r->in.level) {
4223 case 0:
4224 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4225 r->out.info, r->out.count);
4226 break;
4227 case 1:
4228 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4229 r->out.info, r->out.count);
4230 break;
4231 case 2:
4232 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4233 r->out.info, r->out.count);
4234 break;
4235 case 4:
4236 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4237 r->out.info, r->out.count);
4238 break;
4239 case 5:
4240 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4241 r->out.info, r->out.count);
4242 break;
4243 default:
4244 return WERR_UNKNOWN_LEVEL;
4247 if (!W_ERROR_IS_OK(result)) {
4248 return result;
4251 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4252 spoolss_EnumPrinters,
4253 *r->out.info, r->in.level,
4254 *r->out.count);
4255 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4256 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4258 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4261 /****************************************************************
4262 _spoolss_GetPrinter
4263 ****************************************************************/
4265 WERROR _spoolss_GetPrinter(pipes_struct *p,
4266 struct spoolss_GetPrinter *r)
4268 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4269 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4270 WERROR result = WERR_OK;
4272 int snum;
4274 /* that's an [in out] buffer */
4276 if (!r->in.buffer && (r->in.offered != 0)) {
4277 return WERR_INVALID_PARAM;
4280 *r->out.needed = 0;
4282 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4283 return WERR_BADFID;
4286 result = get_a_printer(Printer, &ntprinter, 2,
4287 lp_const_servicename(snum));
4288 if (!W_ERROR_IS_OK(result)) {
4289 return result;
4292 switch (r->in.level) {
4293 case 0:
4294 result = construct_printer_info0(p->mem_ctx, ntprinter,
4295 &r->out.info->info0, snum);
4296 break;
4297 case 1:
4298 result = construct_printer_info1(p->mem_ctx, ntprinter,
4299 PRINTER_ENUM_ICON8,
4300 &r->out.info->info1, snum);
4301 break;
4302 case 2:
4303 result = construct_printer_info2(p->mem_ctx, ntprinter,
4304 &r->out.info->info2, snum);
4305 break;
4306 case 3:
4307 result = construct_printer_info3(p->mem_ctx, ntprinter,
4308 &r->out.info->info3, snum);
4309 break;
4310 case 4:
4311 result = construct_printer_info4(p->mem_ctx, ntprinter,
4312 &r->out.info->info4, snum);
4313 break;
4314 case 5:
4315 result = construct_printer_info5(p->mem_ctx, ntprinter,
4316 &r->out.info->info5, snum);
4317 break;
4318 case 6:
4319 result = construct_printer_info6(p->mem_ctx, ntprinter,
4320 &r->out.info->info6, snum);
4321 break;
4322 case 7:
4323 result = construct_printer_info7(p->mem_ctx, Printer,
4324 &r->out.info->info7, snum);
4325 break;
4326 case 8:
4327 result = construct_printer_info8(p->mem_ctx, ntprinter,
4328 &r->out.info->info8, snum);
4329 break;
4330 default:
4331 result = WERR_UNKNOWN_LEVEL;
4332 break;
4335 free_a_printer(&ntprinter, 2);
4337 if (!W_ERROR_IS_OK(result)) {
4338 TALLOC_FREE(r->out.info);
4339 return result;
4342 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4343 r->out.info, r->in.level);
4344 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4346 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4349 /********************************************************************
4350 ********************************************************************/
4352 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4353 const char **string_array,
4354 const char *cservername)
4356 int i, num_strings = 0;
4357 const char **array = NULL;
4359 if (!string_array) {
4360 return NULL;
4363 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4365 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4366 cservername, string_array[i]);
4367 if (!str) {
4368 TALLOC_FREE(array);
4369 return NULL;
4373 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4374 TALLOC_FREE(array);
4375 return NULL;
4379 if (i > 0) {
4380 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4381 &array, &num_strings);
4384 return array;
4387 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4388 do { \
4389 if (in && strlen(in)) { \
4390 out = talloc_strdup(mem_ctx, in); \
4391 W_ERROR_HAVE_NO_MEMORY(out); \
4392 } else { \
4393 out = NULL; \
4395 } while (0);
4397 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4398 do { \
4399 if (in && strlen(in)) { \
4400 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4401 } else { \
4402 out = talloc_strdup(mem_ctx, ""); \
4404 W_ERROR_HAVE_NO_MEMORY(out); \
4405 } while (0);
4407 /********************************************************************
4408 * fill a spoolss_DriverInfo1 struct
4409 ********************************************************************/
4411 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4412 struct spoolss_DriverInfo1 *r,
4413 const struct spoolss_DriverInfo8 *driver,
4414 const char *servername)
4416 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4417 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4419 return WERR_OK;
4422 /********************************************************************
4423 * fill a spoolss_DriverInfo2 struct
4424 ********************************************************************/
4426 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4427 struct spoolss_DriverInfo2 *r,
4428 const struct spoolss_DriverInfo8 *driver,
4429 const char *servername)
4432 const char *cservername = canon_servername(servername);
4434 r->version = driver->version;
4436 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4437 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4438 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4439 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4441 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4442 driver->driver_path,
4443 r->driver_path);
4445 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4446 driver->data_file,
4447 r->data_file);
4449 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4450 driver->config_file,
4451 r->config_file);
4453 return WERR_OK;
4456 /********************************************************************
4457 * fill a spoolss_DriverInfo3 struct
4458 ********************************************************************/
4460 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4461 struct spoolss_DriverInfo3 *r,
4462 const struct spoolss_DriverInfo8 *driver,
4463 const char *servername)
4465 const char *cservername = canon_servername(servername);
4467 r->version = driver->version;
4469 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4470 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4471 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4472 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4474 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4475 driver->driver_path,
4476 r->driver_path);
4478 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4479 driver->data_file,
4480 r->data_file);
4482 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4483 driver->config_file,
4484 r->config_file);
4486 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4487 driver->help_file,
4488 r->help_file);
4490 FILL_DRIVER_STRING(mem_ctx,
4491 driver->monitor_name,
4492 r->monitor_name);
4494 FILL_DRIVER_STRING(mem_ctx,
4495 driver->default_datatype,
4496 r->default_datatype);
4498 r->dependent_files = string_array_from_driver_info(mem_ctx,
4499 driver->dependent_files,
4500 cservername);
4501 return WERR_OK;
4504 /********************************************************************
4505 * fill a spoolss_DriverInfo4 struct
4506 ********************************************************************/
4508 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4509 struct spoolss_DriverInfo4 *r,
4510 const struct spoolss_DriverInfo8 *driver,
4511 const char *servername)
4513 const char *cservername = canon_servername(servername);
4515 r->version = driver->version;
4517 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4518 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4519 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4520 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4522 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4523 driver->driver_path,
4524 r->driver_path);
4526 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4527 driver->data_file,
4528 r->data_file);
4530 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4531 driver->config_file,
4532 r->config_file);
4534 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4535 driver->help_file,
4536 r->help_file);
4538 r->dependent_files = string_array_from_driver_info(mem_ctx,
4539 driver->dependent_files,
4540 cservername);
4542 FILL_DRIVER_STRING(mem_ctx,
4543 driver->monitor_name,
4544 r->monitor_name);
4546 FILL_DRIVER_STRING(mem_ctx,
4547 driver->default_datatype,
4548 r->default_datatype);
4550 r->previous_names = string_array_from_driver_info(mem_ctx,
4551 driver->previous_names,
4552 cservername);
4554 return WERR_OK;
4557 /********************************************************************
4558 * fill a spoolss_DriverInfo5 struct
4559 ********************************************************************/
4561 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4562 struct spoolss_DriverInfo5 *r,
4563 const struct spoolss_DriverInfo8 *driver,
4564 const char *servername)
4566 const char *cservername = canon_servername(servername);
4568 r->version = driver->version;
4570 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4571 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4572 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4573 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4575 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4576 driver->driver_path,
4577 r->driver_path);
4579 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4580 driver->data_file,
4581 r->data_file);
4583 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4584 driver->config_file,
4585 r->config_file);
4587 r->driver_attributes = 0;
4588 r->config_version = 0;
4589 r->driver_version = 0;
4591 return WERR_OK;
4593 /********************************************************************
4594 * fill a spoolss_DriverInfo6 struct
4595 ********************************************************************/
4597 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4598 struct spoolss_DriverInfo6 *r,
4599 const struct spoolss_DriverInfo8 *driver,
4600 const char *servername)
4602 const char *cservername = canon_servername(servername);
4604 r->version = driver->version;
4606 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4607 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4608 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4609 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4611 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4612 driver->driver_path,
4613 r->driver_path);
4615 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4616 driver->data_file,
4617 r->data_file);
4619 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4620 driver->config_file,
4621 r->config_file);
4623 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4624 driver->help_file,
4625 r->help_file);
4627 FILL_DRIVER_STRING(mem_ctx,
4628 driver->monitor_name,
4629 r->monitor_name);
4631 FILL_DRIVER_STRING(mem_ctx,
4632 driver->default_datatype,
4633 r->default_datatype);
4635 r->dependent_files = string_array_from_driver_info(mem_ctx,
4636 driver->dependent_files,
4637 cservername);
4638 r->previous_names = string_array_from_driver_info(mem_ctx,
4639 driver->previous_names,
4640 cservername);
4642 r->driver_date = driver->driver_date;
4643 r->driver_version = driver->driver_version;
4645 FILL_DRIVER_STRING(mem_ctx,
4646 driver->manufacturer_name,
4647 r->manufacturer_name);
4648 FILL_DRIVER_STRING(mem_ctx,
4649 driver->manufacturer_url,
4650 r->manufacturer_url);
4651 FILL_DRIVER_STRING(mem_ctx,
4652 driver->hardware_id,
4653 r->hardware_id);
4654 FILL_DRIVER_STRING(mem_ctx,
4655 driver->provider,
4656 r->provider);
4658 return WERR_OK;
4661 /********************************************************************
4662 * fill a spoolss_DriverInfo8 struct
4663 ********************************************************************/
4665 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4666 struct spoolss_DriverInfo8 *r,
4667 const struct spoolss_DriverInfo8 *driver,
4668 const char *servername)
4670 const char *cservername = canon_servername(servername);
4672 r->version = driver->version;
4674 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4675 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4676 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4677 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4679 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4680 driver->driver_path,
4681 r->driver_path);
4683 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4684 driver->data_file,
4685 r->data_file);
4687 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4688 driver->config_file,
4689 r->config_file);
4691 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4692 driver->help_file,
4693 r->help_file);
4695 FILL_DRIVER_STRING(mem_ctx,
4696 driver->monitor_name,
4697 r->monitor_name);
4699 FILL_DRIVER_STRING(mem_ctx,
4700 driver->default_datatype,
4701 r->default_datatype);
4703 r->dependent_files = string_array_from_driver_info(mem_ctx,
4704 driver->dependent_files,
4705 cservername);
4706 r->previous_names = string_array_from_driver_info(mem_ctx,
4707 driver->previous_names,
4708 cservername);
4710 r->driver_date = driver->driver_date;
4711 r->driver_version = driver->driver_version;
4713 FILL_DRIVER_STRING(mem_ctx,
4714 driver->manufacturer_name,
4715 r->manufacturer_name);
4716 FILL_DRIVER_STRING(mem_ctx,
4717 driver->manufacturer_url,
4718 r->manufacturer_url);
4719 FILL_DRIVER_STRING(mem_ctx,
4720 driver->hardware_id,
4721 r->hardware_id);
4722 FILL_DRIVER_STRING(mem_ctx,
4723 driver->provider,
4724 r->provider);
4726 FILL_DRIVER_STRING(mem_ctx,
4727 driver->print_processor,
4728 r->print_processor);
4729 FILL_DRIVER_STRING(mem_ctx,
4730 driver->vendor_setup,
4731 r->vendor_setup);
4733 r->color_profiles = string_array_from_driver_info(mem_ctx,
4734 driver->color_profiles,
4735 cservername);
4737 FILL_DRIVER_STRING(mem_ctx,
4738 driver->inf_path,
4739 r->inf_path);
4741 r->printer_driver_attributes = driver->printer_driver_attributes;
4743 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4744 driver->core_driver_dependencies,
4745 cservername);
4747 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4748 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4750 return WERR_OK;
4753 #if 0 /* disabled until marshalling issues are resolved - gd */
4754 /********************************************************************
4755 ********************************************************************/
4757 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4758 struct spoolss_DriverFileInfo *r,
4759 const char *cservername,
4760 const char *file_name,
4761 enum spoolss_DriverFileType file_type,
4762 uint32_t file_version)
4764 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4765 cservername, file_name);
4766 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4767 r->file_type = file_type;
4768 r->file_version = file_version;
4770 return WERR_OK;
4773 /********************************************************************
4774 ********************************************************************/
4776 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4777 const struct spoolss_DriverInfo8 *driver,
4778 const char *cservername,
4779 struct spoolss_DriverFileInfo **info_p,
4780 uint32_t *count_p)
4782 struct spoolss_DriverFileInfo *info = NULL;
4783 uint32_t count = 0;
4784 WERROR result;
4785 uint32_t i;
4787 *info_p = NULL;
4788 *count_p = 0;
4790 if (strlen(driver->driver_path)) {
4791 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4792 struct spoolss_DriverFileInfo,
4793 count + 1);
4794 W_ERROR_HAVE_NO_MEMORY(info);
4795 result = fill_spoolss_DriverFileInfo(info,
4796 &info[count],
4797 cservername,
4798 driver->driver_path,
4799 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4801 W_ERROR_NOT_OK_RETURN(result);
4802 count++;
4805 if (strlen(driver->config_file)) {
4806 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4807 struct spoolss_DriverFileInfo,
4808 count + 1);
4809 W_ERROR_HAVE_NO_MEMORY(info);
4810 result = fill_spoolss_DriverFileInfo(info,
4811 &info[count],
4812 cservername,
4813 driver->config_file,
4814 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4816 W_ERROR_NOT_OK_RETURN(result);
4817 count++;
4820 if (strlen(driver->data_file)) {
4821 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4822 struct spoolss_DriverFileInfo,
4823 count + 1);
4824 W_ERROR_HAVE_NO_MEMORY(info);
4825 result = fill_spoolss_DriverFileInfo(info,
4826 &info[count],
4827 cservername,
4828 driver->data_file,
4829 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4831 W_ERROR_NOT_OK_RETURN(result);
4832 count++;
4835 if (strlen(driver->help_file)) {
4836 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4837 struct spoolss_DriverFileInfo,
4838 count + 1);
4839 W_ERROR_HAVE_NO_MEMORY(info);
4840 result = fill_spoolss_DriverFileInfo(info,
4841 &info[count],
4842 cservername,
4843 driver->help_file,
4844 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4846 W_ERROR_NOT_OK_RETURN(result);
4847 count++;
4850 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4851 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4852 struct spoolss_DriverFileInfo,
4853 count + 1);
4854 W_ERROR_HAVE_NO_MEMORY(info);
4855 result = fill_spoolss_DriverFileInfo(info,
4856 &info[count],
4857 cservername,
4858 driver->dependent_files[i],
4859 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4861 W_ERROR_NOT_OK_RETURN(result);
4862 count++;
4865 *info_p = info;
4866 *count_p = count;
4868 return WERR_OK;
4871 /********************************************************************
4872 * fill a spoolss_DriverInfo101 struct
4873 ********************************************************************/
4875 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4876 struct spoolss_DriverInfo101 *r,
4877 const struct spoolss_DriverInfo8 *driver,
4878 const char *servername)
4880 const char *cservername = canon_servername(servername);
4881 WERROR result;
4883 r->version = driver->version;
4885 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4886 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4887 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4888 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4890 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4891 cservername,
4892 &r->file_info,
4893 &r->file_count);
4894 if (!W_ERROR_IS_OK(result)) {
4895 return result;
4898 FILL_DRIVER_STRING(mem_ctx,
4899 driver->monitor_name,
4900 r->monitor_name);
4902 FILL_DRIVER_STRING(mem_ctx,
4903 driver->default_datatype,
4904 r->default_datatype);
4906 r->previous_names = string_array_from_driver_info(mem_ctx,
4907 driver->previous_names,
4908 cservername);
4909 r->driver_date = driver->driver_date;
4910 r->driver_version = driver->driver_version;
4912 FILL_DRIVER_STRING(mem_ctx,
4913 driver->manufacturer_name,
4914 r->manufacturer_name);
4915 FILL_DRIVER_STRING(mem_ctx,
4916 driver->manufacturer_url,
4917 r->manufacturer_url);
4918 FILL_DRIVER_STRING(mem_ctx,
4919 driver->hardware_id,
4920 r->hardware_id);
4921 FILL_DRIVER_STRING(mem_ctx,
4922 driver->provider,
4923 r->provider);
4925 return WERR_OK;
4927 #endif
4928 /********************************************************************
4929 ********************************************************************/
4931 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4932 uint32_t level,
4933 union spoolss_DriverInfo *r,
4934 int snum,
4935 const char *servername,
4936 const char *architecture,
4937 uint32_t version)
4939 NT_PRINTER_INFO_LEVEL *printer = NULL;
4940 struct spoolss_DriverInfo8 *driver;
4941 WERROR result;
4943 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4945 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4946 win_errstr(result)));
4948 if (!W_ERROR_IS_OK(result)) {
4949 return WERR_INVALID_PRINTER_NAME;
4952 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4953 architecture, version);
4955 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4956 win_errstr(result)));
4958 if (!W_ERROR_IS_OK(result)) {
4960 * Is this a W2k client ?
4963 if (version < 3) {
4964 free_a_printer(&printer, 2);
4965 return WERR_UNKNOWN_PRINTER_DRIVER;
4968 /* Yes - try again with a WinNT driver. */
4969 version = 2;
4970 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4971 architecture, version);
4972 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4973 win_errstr(result)));
4974 if (!W_ERROR_IS_OK(result)) {
4975 free_a_printer(&printer, 2);
4976 return WERR_UNKNOWN_PRINTER_DRIVER;
4980 switch (level) {
4981 case 1:
4982 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4983 break;
4984 case 2:
4985 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4986 break;
4987 case 3:
4988 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4989 break;
4990 case 4:
4991 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4992 break;
4993 case 5:
4994 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4995 break;
4996 case 6:
4997 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4998 break;
4999 case 8:
5000 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5001 break;
5002 #if 0 /* disabled until marshalling issues are resolved - gd */
5003 case 101:
5004 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5005 break;
5006 #endif
5007 default:
5008 result = WERR_UNKNOWN_LEVEL;
5009 break;
5012 free_a_printer(&printer, 2);
5013 free_a_printer_driver(driver);
5015 return result;
5018 /****************************************************************
5019 _spoolss_GetPrinterDriver2
5020 ****************************************************************/
5022 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5023 struct spoolss_GetPrinterDriver2 *r)
5025 Printer_entry *printer;
5026 WERROR result;
5028 const char *servername;
5029 int snum;
5031 /* that's an [in out] buffer */
5033 if (!r->in.buffer && (r->in.offered != 0)) {
5034 return WERR_INVALID_PARAM;
5037 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5039 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5040 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5041 return WERR_INVALID_PRINTER_NAME;
5044 *r->out.needed = 0;
5045 *r->out.server_major_version = 0;
5046 *r->out.server_minor_version = 0;
5048 servername = get_server_name(printer);
5050 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5051 return WERR_BADFID;
5054 result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5055 r->out.info, snum,
5056 servername,
5057 r->in.architecture,
5058 r->in.client_major_version);
5059 if (!W_ERROR_IS_OK(result)) {
5060 TALLOC_FREE(r->out.info);
5061 return result;
5064 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5065 r->out.info, r->in.level);
5066 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5068 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5072 /****************************************************************
5073 _spoolss_StartPagePrinter
5074 ****************************************************************/
5076 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5077 struct spoolss_StartPagePrinter *r)
5079 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5081 if (!Printer) {
5082 DEBUG(3,("_spoolss_StartPagePrinter: "
5083 "Error in startpageprinter printer handle\n"));
5084 return WERR_BADFID;
5087 Printer->page_started = true;
5088 return WERR_OK;
5091 /****************************************************************
5092 _spoolss_EndPagePrinter
5093 ****************************************************************/
5095 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5096 struct spoolss_EndPagePrinter *r)
5098 int snum;
5100 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5102 if (!Printer) {
5103 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5104 OUR_HANDLE(r->in.handle)));
5105 return WERR_BADFID;
5108 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5109 return WERR_BADFID;
5111 Printer->page_started = false;
5112 print_job_endpage(snum, Printer->jobid);
5114 return WERR_OK;
5117 /****************************************************************
5118 _spoolss_StartDocPrinter
5119 ****************************************************************/
5121 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5122 struct spoolss_StartDocPrinter *r)
5124 struct spoolss_DocumentInfo1 *info_1;
5125 int snum;
5126 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5128 if (!Printer) {
5129 DEBUG(2,("_spoolss_StartDocPrinter: "
5130 "Invalid handle (%s:%u:%u)\n",
5131 OUR_HANDLE(r->in.handle)));
5132 return WERR_BADFID;
5135 if (r->in.level != 1) {
5136 return WERR_UNKNOWN_LEVEL;
5139 info_1 = r->in.info.info1;
5142 * a nice thing with NT is it doesn't listen to what you tell it.
5143 * when asked to send _only_ RAW datas, it tries to send datas
5144 * in EMF format.
5146 * So I add checks like in NT Server ...
5149 if (info_1->datatype) {
5150 if (strcmp(info_1->datatype, "RAW") != 0) {
5151 *r->out.job_id = 0;
5152 return WERR_INVALID_DATATYPE;
5156 /* get the share number of the printer */
5157 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5158 return WERR_BADFID;
5161 Printer->jobid = print_job_start(p->server_info, snum,
5162 info_1->document_name,
5163 Printer->nt_devmode);
5165 /* An error occured in print_job_start() so return an appropriate
5166 NT error code. */
5168 if (Printer->jobid == -1) {
5169 return map_werror_from_unix(errno);
5172 Printer->document_started = true;
5173 *r->out.job_id = Printer->jobid;
5175 return WERR_OK;
5178 /****************************************************************
5179 _spoolss_EndDocPrinter
5180 ****************************************************************/
5182 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5183 struct spoolss_EndDocPrinter *r)
5185 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5186 int snum;
5188 if (!Printer) {
5189 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5190 OUR_HANDLE(r->in.handle)));
5191 return WERR_BADFID;
5194 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5195 return WERR_BADFID;
5198 Printer->document_started = false;
5199 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5200 /* error codes unhandled so far ... */
5202 return WERR_OK;
5205 /****************************************************************
5206 _spoolss_WritePrinter
5207 ****************************************************************/
5209 WERROR _spoolss_WritePrinter(pipes_struct *p,
5210 struct spoolss_WritePrinter *r)
5212 ssize_t buffer_written;
5213 int snum;
5214 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5216 if (!Printer) {
5217 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5218 OUR_HANDLE(r->in.handle)));
5219 *r->out.num_written = r->in._data_size;
5220 return WERR_BADFID;
5223 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5224 return WERR_BADFID;
5226 buffer_written = print_job_write(snum, Printer->jobid,
5227 (const char *)r->in.data.data,
5228 (SMB_OFF_T)-1,
5229 (size_t)r->in._data_size);
5230 if (buffer_written == (ssize_t)-1) {
5231 *r->out.num_written = 0;
5232 if (errno == ENOSPC)
5233 return WERR_NO_SPOOL_SPACE;
5234 else
5235 return WERR_ACCESS_DENIED;
5238 *r->out.num_written = r->in._data_size;
5240 return WERR_OK;
5243 /********************************************************************
5244 * api_spoolss_getprinter
5245 * called from the spoolss dispatcher
5247 ********************************************************************/
5249 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5250 pipes_struct *p)
5252 int snum;
5253 WERROR errcode = WERR_BADFUNC;
5254 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5256 if (!Printer) {
5257 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5258 OUR_HANDLE(handle)));
5259 return WERR_BADFID;
5262 if (!get_printer_snum(p, handle, &snum, NULL))
5263 return WERR_BADFID;
5265 switch (command) {
5266 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5267 errcode = print_queue_pause(p->server_info, snum);
5268 break;
5269 case SPOOLSS_PRINTER_CONTROL_RESUME:
5270 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5271 errcode = print_queue_resume(p->server_info, snum);
5272 break;
5273 case SPOOLSS_PRINTER_CONTROL_PURGE:
5274 errcode = print_queue_purge(p->server_info, snum);
5275 break;
5276 default:
5277 return WERR_UNKNOWN_LEVEL;
5280 return errcode;
5284 /****************************************************************
5285 _spoolss_AbortPrinter
5286 * From MSDN: "Deletes printer's spool file if printer is configured
5287 * for spooling"
5288 ****************************************************************/
5290 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5291 struct spoolss_AbortPrinter *r)
5293 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5294 int snum;
5295 WERROR errcode = WERR_OK;
5297 if (!Printer) {
5298 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5299 OUR_HANDLE(r->in.handle)));
5300 return WERR_BADFID;
5303 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5304 return WERR_BADFID;
5306 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5308 return errcode;
5311 /********************************************************************
5312 * called by spoolss_api_setprinter
5313 * when updating a printer description
5314 ********************************************************************/
5316 static WERROR update_printer_sec(struct policy_handle *handle,
5317 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5319 struct sec_desc_buf *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5320 WERROR result;
5321 int snum;
5323 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5325 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5326 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5327 OUR_HANDLE(handle)));
5329 result = WERR_BADFID;
5330 goto done;
5333 if (!secdesc_ctr) {
5334 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5335 result = WERR_INVALID_PARAM;
5336 goto done;
5339 /* Check the user has permissions to change the security
5340 descriptor. By experimentation with two NT machines, the user
5341 requires Full Access to the printer to change security
5342 information. */
5344 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5345 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5346 result = WERR_ACCESS_DENIED;
5347 goto done;
5350 /* NT seems to like setting the security descriptor even though
5351 nothing may have actually changed. */
5353 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5354 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5355 result = WERR_BADFID;
5356 goto done;
5359 if (DEBUGLEVEL >= 10) {
5360 struct security_acl *the_acl;
5361 int i;
5363 the_acl = old_secdesc_ctr->sd->dacl;
5364 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5365 PRINTERNAME(snum), the_acl->num_aces));
5367 for (i = 0; i < the_acl->num_aces; i++) {
5368 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5369 &the_acl->aces[i].trustee),
5370 the_acl->aces[i].access_mask));
5373 the_acl = secdesc_ctr->sd->dacl;
5375 if (the_acl) {
5376 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5377 PRINTERNAME(snum), the_acl->num_aces));
5379 for (i = 0; i < the_acl->num_aces; i++) {
5380 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5381 &the_acl->aces[i].trustee),
5382 the_acl->aces[i].access_mask));
5384 } else {
5385 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5389 new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5390 if (!new_secdesc_ctr) {
5391 result = WERR_NOMEM;
5392 goto done;
5395 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5396 result = WERR_OK;
5397 goto done;
5400 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5402 done:
5404 return result;
5407 /********************************************************************
5408 Canonicalize printer info from a client
5410 ATTN: It does not matter what we set the servername to hear
5411 since we do the necessary work in get_a_printer() to set it to
5412 the correct value based on what the client sent in the
5413 _spoolss_open_printer_ex().
5414 ********************************************************************/
5416 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5418 fstring printername;
5419 const char *p;
5421 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5422 "portname=%s drivername=%s comment=%s location=%s\n",
5423 info->servername, info->printername, info->sharename,
5424 info->portname, info->drivername, info->comment, info->location));
5426 /* we force some elements to "correct" values */
5427 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5428 fstrcpy(info->sharename, lp_servicename(snum));
5430 /* check to see if we allow printername != sharename */
5432 if ( lp_force_printername(snum) ) {
5433 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5434 global_myname(), info->sharename );
5435 } else {
5437 /* make sure printername is in \\server\printername format */
5439 fstrcpy( printername, info->printername );
5440 p = printername;
5441 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5442 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5443 p++;
5446 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5447 global_myname(), p );
5450 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5451 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5455 return true;
5458 /****************************************************************************
5459 ****************************************************************************/
5461 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5463 char *cmd = lp_addport_cmd();
5464 char *command = NULL;
5465 int ret;
5466 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5467 bool is_print_op = false;
5469 if ( !*cmd ) {
5470 return WERR_ACCESS_DENIED;
5473 command = talloc_asprintf(ctx,
5474 "%s \"%s\" \"%s\"", cmd, portname, uri );
5475 if (!command) {
5476 return WERR_NOMEM;
5479 if ( token )
5480 is_print_op = user_has_privileges( token, &se_printop );
5482 DEBUG(10,("Running [%s]\n", command));
5484 /********* BEGIN SePrintOperatorPrivilege **********/
5486 if ( is_print_op )
5487 become_root();
5489 ret = smbrun(command, NULL);
5491 if ( is_print_op )
5492 unbecome_root();
5494 /********* END SePrintOperatorPrivilege **********/
5496 DEBUGADD(10,("returned [%d]\n", ret));
5498 TALLOC_FREE(command);
5500 if ( ret != 0 ) {
5501 return WERR_ACCESS_DENIED;
5504 return WERR_OK;
5507 /****************************************************************************
5508 ****************************************************************************/
5510 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5512 char *cmd = lp_addprinter_cmd();
5513 char **qlines;
5514 char *command = NULL;
5515 int numlines;
5516 int ret;
5517 int fd;
5518 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5519 bool is_print_op = false;
5520 char *remote_machine = talloc_strdup(ctx, "%m");
5522 if (!remote_machine) {
5523 return false;
5525 remote_machine = talloc_sub_basic(ctx,
5526 current_user_info.smb_name,
5527 current_user_info.domain,
5528 remote_machine);
5529 if (!remote_machine) {
5530 return false;
5533 command = talloc_asprintf(ctx,
5534 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5535 cmd, printer->info_2->printername, printer->info_2->sharename,
5536 printer->info_2->portname, printer->info_2->drivername,
5537 printer->info_2->location, printer->info_2->comment, remote_machine);
5538 if (!command) {
5539 return false;
5542 if ( token )
5543 is_print_op = user_has_privileges( token, &se_printop );
5545 DEBUG(10,("Running [%s]\n", command));
5547 /********* BEGIN SePrintOperatorPrivilege **********/
5549 if ( is_print_op )
5550 become_root();
5552 if ( (ret = smbrun(command, &fd)) == 0 ) {
5553 /* Tell everyone we updated smb.conf. */
5554 message_send_all(smbd_messaging_context(),
5555 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5558 if ( is_print_op )
5559 unbecome_root();
5561 /********* END SePrintOperatorPrivilege **********/
5563 DEBUGADD(10,("returned [%d]\n", ret));
5565 TALLOC_FREE(command);
5566 TALLOC_FREE(remote_machine);
5568 if ( ret != 0 ) {
5569 if (fd != -1)
5570 close(fd);
5571 return false;
5574 /* reload our services immediately */
5575 become_root();
5576 reload_services(false);
5577 unbecome_root();
5579 numlines = 0;
5580 /* Get lines and convert them back to dos-codepage */
5581 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5582 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5583 close(fd);
5585 /* Set the portname to what the script says the portname should be. */
5586 /* but don't require anything to be return from the script exit a good error code */
5588 if (numlines) {
5589 /* Set the portname to what the script says the portname should be. */
5590 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5591 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5594 TALLOC_FREE(qlines);
5595 return true;
5599 /********************************************************************
5600 * Called by spoolss_api_setprinter
5601 * when updating a printer description.
5602 ********************************************************************/
5604 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5605 struct spoolss_SetPrinterInfoCtr *info_ctr,
5606 struct spoolss_DeviceMode *devmode)
5608 int snum;
5609 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5610 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5611 WERROR result;
5612 DATA_BLOB buffer;
5613 fstring asc_buffer;
5615 DEBUG(8,("update_printer\n"));
5617 result = WERR_OK;
5619 if (!Printer) {
5620 result = WERR_BADFID;
5621 goto done;
5624 if (!get_printer_snum(p, handle, &snum, NULL)) {
5625 result = WERR_BADFID;
5626 goto done;
5629 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5630 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5631 result = WERR_BADFID;
5632 goto done;
5635 DEBUGADD(8,("Converting info_2 struct\n"));
5638 * convert_printer_info converts the incoming
5639 * info from the client and overwrites the info
5640 * just read from the tdb in the pointer 'printer'.
5643 if (!convert_printer_info(info_ctr, printer)) {
5644 result = WERR_NOMEM;
5645 goto done;
5648 if (devmode) {
5649 /* we have a valid devmode
5650 convert it and link it*/
5652 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5653 if (!convert_devicemode(printer->info_2->printername, devmode,
5654 &printer->info_2->devmode)) {
5655 result = WERR_NOMEM;
5656 goto done;
5660 /* Do sanity check on the requested changes for Samba */
5662 if (!check_printer_ok(printer->info_2, snum)) {
5663 result = WERR_INVALID_PARAM;
5664 goto done;
5667 /* FIXME!!! If the driver has changed we really should verify that
5668 it is installed before doing much else --jerry */
5670 /* Check calling user has permission to update printer description */
5672 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5673 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5674 result = WERR_ACCESS_DENIED;
5675 goto done;
5678 /* Call addprinter hook */
5679 /* Check changes to see if this is really needed */
5681 if ( *lp_addprinter_cmd()
5682 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5683 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5684 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5685 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5687 /* add_printer_hook() will call reload_services() */
5689 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5690 printer) ) {
5691 result = WERR_ACCESS_DENIED;
5692 goto done;
5697 * When a *new* driver is bound to a printer, the drivername is used to
5698 * lookup previously saved driver initialization info, which is then
5699 * bound to the printer, simulating what happens in the Windows arch.
5701 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5703 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5704 printer->info_2->drivername));
5706 notify_printer_driver(snum, printer->info_2->drivername);
5710 * flag which changes actually occured. This is a small subset of
5711 * all the possible changes. We also have to update things in the
5712 * DsSpooler key.
5715 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5716 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5717 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5718 REG_SZ, buffer.data, buffer.length);
5720 notify_printer_comment(snum, printer->info_2->comment);
5723 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5724 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5725 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5726 REG_SZ, buffer.data, buffer.length);
5728 notify_printer_sharename(snum, printer->info_2->sharename);
5731 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5732 char *pname;
5734 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5735 pname++;
5736 else
5737 pname = printer->info_2->printername;
5740 push_reg_sz(talloc_tos(), &buffer, pname);
5741 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5742 REG_SZ, buffer.data, buffer.length);
5744 notify_printer_printername( snum, pname );
5747 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5748 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5749 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5750 REG_SZ, buffer.data, buffer.length);
5752 notify_printer_port(snum, printer->info_2->portname);
5755 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5756 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5757 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5758 REG_SZ, buffer.data, buffer.length);
5760 notify_printer_location(snum, printer->info_2->location);
5763 /* here we need to update some more DsSpooler keys */
5764 /* uNCName, serverName, shortServerName */
5766 push_reg_sz(talloc_tos(), &buffer, global_myname());
5767 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5768 REG_SZ, buffer.data, buffer.length);
5769 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5770 REG_SZ, buffer.data, buffer.length);
5772 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5773 global_myname(), printer->info_2->sharename );
5774 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5775 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5776 REG_SZ, buffer.data, buffer.length);
5778 /* Update printer info */
5779 result = mod_a_printer(printer, 2);
5781 done:
5782 free_a_printer(&printer, 2);
5783 free_a_printer(&old_printer, 2);
5786 return result;
5789 /****************************************************************************
5790 ****************************************************************************/
5791 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5792 struct policy_handle *handle,
5793 struct spoolss_SetPrinterInfo7 *info7)
5795 #ifdef HAVE_ADS
5796 int snum;
5797 Printer_entry *Printer;
5799 if ( lp_security() != SEC_ADS ) {
5800 return WERR_UNKNOWN_LEVEL;
5803 Printer = find_printer_index_by_hnd(p, handle);
5805 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5807 if (!Printer)
5808 return WERR_BADFID;
5810 if (!get_printer_snum(p, handle, &snum, NULL))
5811 return WERR_BADFID;
5813 nt_printer_publish(Printer, snum, info7->action);
5815 return WERR_OK;
5816 #else
5817 return WERR_UNKNOWN_LEVEL;
5818 #endif
5821 /********************************************************************
5822 ********************************************************************/
5824 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5825 struct spoolss_DeviceMode *devmode)
5827 int snum;
5828 NT_PRINTER_INFO_LEVEL *printer = NULL;
5829 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5830 WERROR result;
5832 DEBUG(8,("update_printer_devmode\n"));
5834 result = WERR_OK;
5836 if (!Printer) {
5837 result = WERR_BADFID;
5838 goto done;
5841 if (!get_printer_snum(p, handle, &snum, NULL)) {
5842 result = WERR_BADFID;
5843 goto done;
5846 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5847 result = WERR_BADFID;
5848 goto done;
5851 if (devmode) {
5852 /* we have a valid devmode
5853 convert it and link it*/
5855 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5856 if (!convert_devicemode(printer->info_2->printername, devmode,
5857 &printer->info_2->devmode)) {
5858 result = WERR_NOMEM;
5859 goto done;
5863 /* Check calling user has permission to update printer description */
5865 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5866 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5867 result = WERR_ACCESS_DENIED;
5868 goto done;
5872 /* Update printer info */
5873 result = mod_a_printer(printer, 2);
5875 done:
5876 free_a_printer(&printer, 2);
5878 return result;
5882 /****************************************************************
5883 _spoolss_SetPrinter
5884 ****************************************************************/
5886 WERROR _spoolss_SetPrinter(pipes_struct *p,
5887 struct spoolss_SetPrinter *r)
5889 WERROR result;
5891 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5893 if (!Printer) {
5894 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5895 OUR_HANDLE(r->in.handle)));
5896 return WERR_BADFID;
5899 /* check the level */
5900 switch (r->in.info_ctr->level) {
5901 case 0:
5902 return control_printer(r->in.handle, r->in.command, p);
5903 case 2:
5904 result = update_printer(p, r->in.handle,
5905 r->in.info_ctr,
5906 r->in.devmode_ctr->devmode);
5907 if (!W_ERROR_IS_OK(result))
5908 return result;
5909 if (r->in.secdesc_ctr->sd)
5910 result = update_printer_sec(r->in.handle, p,
5911 r->in.secdesc_ctr);
5912 return result;
5913 case 3:
5914 return update_printer_sec(r->in.handle, p,
5915 r->in.secdesc_ctr);
5916 case 7:
5917 return publish_or_unpublish_printer(p, r->in.handle,
5918 r->in.info_ctr->info.info7);
5919 case 8:
5920 return update_printer_devmode(p, r->in.handle,
5921 r->in.devmode_ctr->devmode);
5922 default:
5923 return WERR_UNKNOWN_LEVEL;
5927 /****************************************************************
5928 _spoolss_FindClosePrinterNotify
5929 ****************************************************************/
5931 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5932 struct spoolss_FindClosePrinterNotify *r)
5934 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5936 if (!Printer) {
5937 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5938 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5939 return WERR_BADFID;
5942 if (Printer->notify.client_connected == true) {
5943 int snum = -1;
5945 if ( Printer->printer_type == SPLHND_SERVER)
5946 snum = -1;
5947 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5948 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5949 return WERR_BADFID;
5951 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5954 Printer->notify.flags=0;
5955 Printer->notify.options=0;
5956 Printer->notify.localmachine[0]='\0';
5957 Printer->notify.printerlocal=0;
5958 TALLOC_FREE(Printer->notify.option);
5959 Printer->notify.client_connected = false;
5961 return WERR_OK;
5964 /****************************************************************
5965 _spoolss_AddJob
5966 ****************************************************************/
5968 WERROR _spoolss_AddJob(pipes_struct *p,
5969 struct spoolss_AddJob *r)
5971 if (!r->in.buffer && (r->in.offered != 0)) {
5972 return WERR_INVALID_PARAM;
5975 /* this is what a NT server returns for AddJob. AddJob must fail on
5976 * non-local printers */
5978 if (r->in.level != 1) {
5979 return WERR_UNKNOWN_LEVEL;
5982 return WERR_INVALID_PARAM;
5985 /****************************************************************************
5986 fill_job_info1
5987 ****************************************************************************/
5989 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5990 struct spoolss_JobInfo1 *r,
5991 const print_queue_struct *queue,
5992 int position, int snum,
5993 const NT_PRINTER_INFO_LEVEL *ntprinter)
5995 struct tm *t;
5997 t = gmtime(&queue->time);
5999 r->job_id = queue->job;
6001 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6002 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6003 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6004 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6005 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6006 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6007 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6008 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6009 r->data_type = talloc_strdup(mem_ctx, "RAW");
6010 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6011 r->text_status = talloc_strdup(mem_ctx, "");
6012 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6014 r->status = nt_printj_status(queue->status);
6015 r->priority = queue->priority;
6016 r->position = position;
6017 r->total_pages = queue->page_count;
6018 r->pages_printed = 0; /* ??? */
6020 init_systemtime(&r->submitted, t);
6022 return WERR_OK;
6025 /****************************************************************************
6026 fill_job_info2
6027 ****************************************************************************/
6029 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6030 struct spoolss_JobInfo2 *r,
6031 const print_queue_struct *queue,
6032 int position, int snum,
6033 const NT_PRINTER_INFO_LEVEL *ntprinter,
6034 struct spoolss_DeviceMode *devmode)
6036 struct tm *t;
6038 t = gmtime(&queue->time);
6040 r->job_id = queue->job;
6042 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6043 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6044 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6045 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6046 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6047 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6048 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6049 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6050 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6051 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6052 r->data_type = talloc_strdup(mem_ctx, "RAW");
6053 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6054 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6055 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6056 r->parameters = talloc_strdup(mem_ctx, "");
6057 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6058 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6059 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6061 r->devmode = devmode;
6063 r->text_status = talloc_strdup(mem_ctx, "");
6064 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6066 r->secdesc = NULL;
6068 r->status = nt_printj_status(queue->status);
6069 r->priority = queue->priority;
6070 r->position = position;
6071 r->start_time = 0;
6072 r->until_time = 0;
6073 r->total_pages = queue->page_count;
6074 r->size = queue->size;
6075 init_systemtime(&r->submitted, t);
6076 r->time = 0;
6077 r->pages_printed = 0; /* ??? */
6079 return WERR_OK;
6082 /****************************************************************************
6083 fill_job_info3
6084 ****************************************************************************/
6086 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6087 struct spoolss_JobInfo3 *r,
6088 const print_queue_struct *queue,
6089 const print_queue_struct *next_queue,
6090 int position, int snum,
6091 const NT_PRINTER_INFO_LEVEL *ntprinter)
6093 r->job_id = queue->job;
6094 r->next_job_id = 0;
6095 if (next_queue) {
6096 r->next_job_id = next_queue->job;
6098 r->reserved = 0;
6100 return WERR_OK;
6103 /****************************************************************************
6104 Enumjobs at level 1.
6105 ****************************************************************************/
6107 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6108 const print_queue_struct *queue,
6109 uint32_t num_queues, int snum,
6110 const NT_PRINTER_INFO_LEVEL *ntprinter,
6111 union spoolss_JobInfo **info_p,
6112 uint32_t *count)
6114 union spoolss_JobInfo *info;
6115 int i;
6116 WERROR result = WERR_OK;
6118 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6119 W_ERROR_HAVE_NO_MEMORY(info);
6121 *count = num_queues;
6123 for (i=0; i<*count; i++) {
6124 result = fill_job_info1(info,
6125 &info[i].info1,
6126 &queue[i],
6128 snum,
6129 ntprinter);
6130 if (!W_ERROR_IS_OK(result)) {
6131 goto out;
6135 out:
6136 if (!W_ERROR_IS_OK(result)) {
6137 TALLOC_FREE(info);
6138 *count = 0;
6139 return result;
6142 *info_p = info;
6144 return WERR_OK;
6147 /****************************************************************************
6148 Enumjobs at level 2.
6149 ****************************************************************************/
6151 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6152 const print_queue_struct *queue,
6153 uint32_t num_queues, int snum,
6154 const NT_PRINTER_INFO_LEVEL *ntprinter,
6155 union spoolss_JobInfo **info_p,
6156 uint32_t *count)
6158 union spoolss_JobInfo *info;
6159 int i;
6160 WERROR result = WERR_OK;
6162 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6163 W_ERROR_HAVE_NO_MEMORY(info);
6165 *count = num_queues;
6167 for (i=0; i<*count; i++) {
6169 struct spoolss_DeviceMode *devmode;
6171 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6172 if (!devmode) {
6173 result = WERR_NOMEM;
6174 goto out;
6177 result = fill_job_info2(info,
6178 &info[i].info2,
6179 &queue[i],
6181 snum,
6182 ntprinter,
6183 devmode);
6184 if (!W_ERROR_IS_OK(result)) {
6185 goto out;
6189 out:
6190 if (!W_ERROR_IS_OK(result)) {
6191 TALLOC_FREE(info);
6192 *count = 0;
6193 return result;
6196 *info_p = info;
6198 return WERR_OK;
6201 /****************************************************************************
6202 Enumjobs at level 3.
6203 ****************************************************************************/
6205 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6206 const print_queue_struct *queue,
6207 uint32_t num_queues, int snum,
6208 const NT_PRINTER_INFO_LEVEL *ntprinter,
6209 union spoolss_JobInfo **info_p,
6210 uint32_t *count)
6212 union spoolss_JobInfo *info;
6213 int i;
6214 WERROR result = WERR_OK;
6216 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6217 W_ERROR_HAVE_NO_MEMORY(info);
6219 *count = num_queues;
6221 for (i=0; i<*count; i++) {
6222 const print_queue_struct *next_queue = NULL;
6224 if (i+1 < *count) {
6225 next_queue = &queue[i+1];
6228 result = fill_job_info3(info,
6229 &info[i].info3,
6230 &queue[i],
6231 next_queue,
6233 snum,
6234 ntprinter);
6235 if (!W_ERROR_IS_OK(result)) {
6236 goto out;
6240 out:
6241 if (!W_ERROR_IS_OK(result)) {
6242 TALLOC_FREE(info);
6243 *count = 0;
6244 return result;
6247 *info_p = info;
6249 return WERR_OK;
6252 /****************************************************************
6253 _spoolss_EnumJobs
6254 ****************************************************************/
6256 WERROR _spoolss_EnumJobs(pipes_struct *p,
6257 struct spoolss_EnumJobs *r)
6259 WERROR result;
6260 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6261 int snum;
6262 print_status_struct prt_status;
6263 print_queue_struct *queue = NULL;
6264 uint32_t count;
6266 /* that's an [in out] buffer */
6268 if (!r->in.buffer && (r->in.offered != 0)) {
6269 return WERR_INVALID_PARAM;
6272 DEBUG(4,("_spoolss_EnumJobs\n"));
6274 *r->out.needed = 0;
6275 *r->out.count = 0;
6276 *r->out.info = NULL;
6278 /* lookup the printer snum and tdb entry */
6280 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6281 return WERR_BADFID;
6284 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6285 if (!W_ERROR_IS_OK(result)) {
6286 return result;
6289 count = print_queue_status(snum, &queue, &prt_status);
6290 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6291 count, prt_status.status, prt_status.message));
6293 if (count == 0) {
6294 SAFE_FREE(queue);
6295 free_a_printer(&ntprinter, 2);
6296 return WERR_OK;
6299 switch (r->in.level) {
6300 case 1:
6301 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6302 ntprinter, r->out.info, r->out.count);
6303 break;
6304 case 2:
6305 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6306 ntprinter, r->out.info, r->out.count);
6307 break;
6308 case 3:
6309 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6310 ntprinter, r->out.info, r->out.count);
6311 break;
6312 default:
6313 result = WERR_UNKNOWN_LEVEL;
6314 break;
6317 SAFE_FREE(queue);
6318 free_a_printer(&ntprinter, 2);
6320 if (!W_ERROR_IS_OK(result)) {
6321 return result;
6324 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6325 spoolss_EnumJobs,
6326 *r->out.info, r->in.level,
6327 *r->out.count);
6328 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6329 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6331 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6334 /****************************************************************
6335 _spoolss_ScheduleJob
6336 ****************************************************************/
6338 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6339 struct spoolss_ScheduleJob *r)
6341 return WERR_OK;
6344 /****************************************************************
6345 ****************************************************************/
6347 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6348 const char *printer_name,
6349 uint32_t job_id,
6350 struct spoolss_SetJobInfo1 *r)
6352 char *old_doc_name;
6354 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6355 return WERR_BADFID;
6358 if (strequal(old_doc_name, r->document_name)) {
6359 return WERR_OK;
6362 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6363 return WERR_BADFID;
6366 return WERR_OK;
6369 /****************************************************************
6370 _spoolss_SetJob
6371 ****************************************************************/
6373 WERROR _spoolss_SetJob(pipes_struct *p,
6374 struct spoolss_SetJob *r)
6376 int snum;
6377 WERROR errcode = WERR_BADFUNC;
6379 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6380 return WERR_BADFID;
6383 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6384 return WERR_INVALID_PRINTER_NAME;
6387 switch (r->in.command) {
6388 case SPOOLSS_JOB_CONTROL_CANCEL:
6389 case SPOOLSS_JOB_CONTROL_DELETE:
6390 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6391 errcode = WERR_OK;
6393 break;
6394 case SPOOLSS_JOB_CONTROL_PAUSE:
6395 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6396 errcode = WERR_OK;
6398 break;
6399 case SPOOLSS_JOB_CONTROL_RESTART:
6400 case SPOOLSS_JOB_CONTROL_RESUME:
6401 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6402 errcode = WERR_OK;
6404 break;
6405 case 0:
6406 errcode = WERR_OK;
6407 break;
6408 default:
6409 return WERR_UNKNOWN_LEVEL;
6412 if (!W_ERROR_IS_OK(errcode)) {
6413 return errcode;
6416 if (r->in.ctr == NULL) {
6417 return errcode;
6420 switch (r->in.ctr->level) {
6421 case 1:
6422 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6423 r->in.job_id,
6424 r->in.ctr->info.info1);
6425 break;
6426 case 2:
6427 case 3:
6428 case 4:
6429 default:
6430 return WERR_UNKNOWN_LEVEL;
6433 return errcode;
6436 /****************************************************************************
6437 Enumerates all printer drivers by level and architecture.
6438 ****************************************************************************/
6440 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6441 const char *servername,
6442 const char *architecture,
6443 uint32_t level,
6444 union spoolss_DriverInfo **info_p,
6445 uint32_t *count_p)
6447 int i;
6448 int ndrivers;
6449 uint32_t version;
6450 fstring *list = NULL;
6451 struct spoolss_DriverInfo8 *driver;
6452 union spoolss_DriverInfo *info = NULL;
6453 uint32_t count = 0;
6454 WERROR result = WERR_OK;
6456 *count_p = 0;
6457 *info_p = NULL;
6459 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6460 list = NULL;
6461 ndrivers = get_ntdrivers(&list, architecture, version);
6462 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6463 ndrivers, architecture, version));
6465 if (ndrivers == -1) {
6466 result = WERR_NOMEM;
6467 goto out;
6470 if (ndrivers != 0) {
6471 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6472 union spoolss_DriverInfo,
6473 count + ndrivers);
6474 if (!info) {
6475 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6476 "failed to enlarge driver info buffer!\n"));
6477 result = WERR_NOMEM;
6478 goto out;
6482 for (i=0; i<ndrivers; i++) {
6483 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6484 ZERO_STRUCT(driver);
6485 result = get_a_printer_driver(mem_ctx, &driver, list[i],
6486 architecture, version);
6487 if (!W_ERROR_IS_OK(result)) {
6488 goto out;
6491 switch (level) {
6492 case 1:
6493 result = fill_printer_driver_info1(info, &info[count+i].info1,
6494 driver, servername);
6495 break;
6496 case 2:
6497 result = fill_printer_driver_info2(info, &info[count+i].info2,
6498 driver, servername);
6499 break;
6500 case 3:
6501 result = fill_printer_driver_info3(info, &info[count+i].info3,
6502 driver, servername);
6503 break;
6504 case 4:
6505 result = fill_printer_driver_info4(info, &info[count+i].info4,
6506 driver, servername);
6507 break;
6508 case 5:
6509 result = fill_printer_driver_info5(info, &info[count+i].info5,
6510 driver, servername);
6511 break;
6512 case 6:
6513 result = fill_printer_driver_info6(info, &info[count+i].info6,
6514 driver, servername);
6515 break;
6516 case 8:
6517 result = fill_printer_driver_info8(info, &info[count+i].info8,
6518 driver, servername);
6519 break;
6520 default:
6521 result = WERR_UNKNOWN_LEVEL;
6522 break;
6525 free_a_printer_driver(driver);
6527 if (!W_ERROR_IS_OK(result)) {
6528 goto out;
6532 count += ndrivers;
6533 SAFE_FREE(list);
6536 out:
6537 SAFE_FREE(list);
6539 if (!W_ERROR_IS_OK(result)) {
6540 TALLOC_FREE(info);
6541 return result;
6544 *info_p = info;
6545 *count_p = count;
6547 return WERR_OK;
6550 /****************************************************************************
6551 Enumerates all printer drivers by level.
6552 ****************************************************************************/
6554 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6555 const char *servername,
6556 const char *architecture,
6557 uint32_t level,
6558 union spoolss_DriverInfo **info_p,
6559 uint32_t *count_p)
6561 uint32_t a,i;
6562 WERROR result = WERR_OK;
6564 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6566 for (a=0; archi_table[a].long_archi != NULL; a++) {
6568 union spoolss_DriverInfo *info = NULL;
6569 uint32_t count = 0;
6571 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6572 servername,
6573 archi_table[a].long_archi,
6574 level,
6575 &info,
6576 &count);
6577 if (!W_ERROR_IS_OK(result)) {
6578 continue;
6581 for (i=0; i < count; i++) {
6582 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6583 info[i], info_p, count_p);
6587 return result;
6590 return enumprinterdrivers_level_by_architecture(mem_ctx,
6591 servername,
6592 architecture,
6593 level,
6594 info_p,
6595 count_p);
6598 /****************************************************************
6599 _spoolss_EnumPrinterDrivers
6600 ****************************************************************/
6602 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6603 struct spoolss_EnumPrinterDrivers *r)
6605 const char *cservername;
6606 WERROR result;
6608 /* that's an [in out] buffer */
6610 if (!r->in.buffer && (r->in.offered != 0)) {
6611 return WERR_INVALID_PARAM;
6614 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6616 *r->out.needed = 0;
6617 *r->out.count = 0;
6618 *r->out.info = NULL;
6620 cservername = canon_servername(r->in.server);
6622 if (!is_myname_or_ipaddr(cservername)) {
6623 return WERR_UNKNOWN_PRINTER_DRIVER;
6626 result = enumprinterdrivers_level(p->mem_ctx, cservername,
6627 r->in.environment,
6628 r->in.level,
6629 r->out.info,
6630 r->out.count);
6631 if (!W_ERROR_IS_OK(result)) {
6632 return result;
6635 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6636 spoolss_EnumPrinterDrivers,
6637 *r->out.info, r->in.level,
6638 *r->out.count);
6639 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6640 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6642 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6645 /****************************************************************************
6646 ****************************************************************************/
6648 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6649 struct spoolss_FormInfo1 *r,
6650 const nt_forms_struct *form)
6652 r->form_name = talloc_strdup(mem_ctx, form->name);
6653 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6655 r->flags = form->flag;
6656 r->size.width = form->width;
6657 r->size.height = form->length;
6658 r->area.left = form->left;
6659 r->area.top = form->top;
6660 r->area.right = form->right;
6661 r->area.bottom = form->bottom;
6663 return WERR_OK;
6666 /****************************************************************
6667 spoolss_enumforms_level1
6668 ****************************************************************/
6670 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6671 const nt_forms_struct *builtin_forms,
6672 uint32_t num_builtin_forms,
6673 const nt_forms_struct *user_forms,
6674 uint32_t num_user_forms,
6675 union spoolss_FormInfo **info_p,
6676 uint32_t *count)
6678 union spoolss_FormInfo *info;
6679 WERROR result = WERR_OK;
6680 int i;
6682 *count = num_builtin_forms + num_user_forms;
6684 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6685 W_ERROR_HAVE_NO_MEMORY(info);
6687 /* construct the list of form structures */
6688 for (i=0; i<num_builtin_forms; i++) {
6689 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6690 result = fill_form_info_1(info, &info[i].info1,
6691 &builtin_forms[i]);
6692 if (!W_ERROR_IS_OK(result)) {
6693 goto out;
6697 for (i=0; i<num_user_forms; i++) {
6698 DEBUGADD(6,("Filling user form number [%d]\n",i));
6699 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6700 &user_forms[i]);
6701 if (!W_ERROR_IS_OK(result)) {
6702 goto out;
6706 out:
6707 if (!W_ERROR_IS_OK(result)) {
6708 TALLOC_FREE(info);
6709 *count = 0;
6710 return result;
6713 *info_p = info;
6715 return WERR_OK;
6718 /****************************************************************
6719 _spoolss_EnumForms
6720 ****************************************************************/
6722 WERROR _spoolss_EnumForms(pipes_struct *p,
6723 struct spoolss_EnumForms *r)
6725 WERROR result;
6726 nt_forms_struct *user_forms = NULL;
6727 nt_forms_struct *builtin_forms = NULL;
6728 uint32_t num_user_forms;
6729 uint32_t num_builtin_forms;
6731 *r->out.count = 0;
6732 *r->out.needed = 0;
6733 *r->out.info = NULL;
6735 /* that's an [in out] buffer */
6737 if (!r->in.buffer && (r->in.offered != 0) ) {
6738 return WERR_INVALID_PARAM;
6741 DEBUG(4,("_spoolss_EnumForms\n"));
6742 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6743 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6745 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6746 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6747 num_user_forms = get_ntforms(&user_forms);
6748 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6750 if (num_user_forms + num_builtin_forms == 0) {
6751 SAFE_FREE(builtin_forms);
6752 SAFE_FREE(user_forms);
6753 return WERR_NO_MORE_ITEMS;
6756 switch (r->in.level) {
6757 case 1:
6758 result = spoolss_enumforms_level1(p->mem_ctx,
6759 builtin_forms,
6760 num_builtin_forms,
6761 user_forms,
6762 num_user_forms,
6763 r->out.info,
6764 r->out.count);
6765 break;
6766 default:
6767 result = WERR_UNKNOWN_LEVEL;
6768 break;
6771 SAFE_FREE(user_forms);
6772 SAFE_FREE(builtin_forms);
6774 if (!W_ERROR_IS_OK(result)) {
6775 return result;
6778 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6779 spoolss_EnumForms,
6780 *r->out.info, r->in.level,
6781 *r->out.count);
6782 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6783 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6785 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6788 /****************************************************************
6789 ****************************************************************/
6791 static WERROR find_form_byname(const char *name,
6792 nt_forms_struct *form)
6794 nt_forms_struct *list = NULL;
6795 int num_forms = 0, i = 0;
6797 if (get_a_builtin_ntform_by_string(name, form)) {
6798 return WERR_OK;
6801 num_forms = get_ntforms(&list);
6802 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6804 if (num_forms == 0) {
6805 return WERR_BADFID;
6808 /* Check if the requested name is in the list of form structures */
6809 for (i = 0; i < num_forms; i++) {
6811 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6813 if (strequal(name, list[i].name)) {
6814 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6815 *form = list[i];
6816 SAFE_FREE(list);
6817 return WERR_OK;
6821 SAFE_FREE(list);
6823 return WERR_BADFID;
6826 /****************************************************************
6827 _spoolss_GetForm
6828 ****************************************************************/
6830 WERROR _spoolss_GetForm(pipes_struct *p,
6831 struct spoolss_GetForm *r)
6833 WERROR result;
6834 nt_forms_struct form;
6836 /* that's an [in out] buffer */
6838 if (!r->in.buffer && (r->in.offered != 0)) {
6839 return WERR_INVALID_PARAM;
6842 DEBUG(4,("_spoolss_GetForm\n"));
6843 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6844 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6846 result = find_form_byname(r->in.form_name, &form);
6847 if (!W_ERROR_IS_OK(result)) {
6848 TALLOC_FREE(r->out.info);
6849 return result;
6852 switch (r->in.level) {
6853 case 1:
6854 result = fill_form_info_1(p->mem_ctx,
6855 &r->out.info->info1,
6856 &form);
6857 break;
6859 default:
6860 result = WERR_UNKNOWN_LEVEL;
6861 break;
6864 if (!W_ERROR_IS_OK(result)) {
6865 TALLOC_FREE(r->out.info);
6866 return result;
6869 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6870 r->out.info, r->in.level);
6871 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6873 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6876 /****************************************************************************
6877 ****************************************************************************/
6879 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6880 struct spoolss_PortInfo1 *r,
6881 const char *name)
6883 r->port_name = talloc_strdup(mem_ctx, name);
6884 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6886 return WERR_OK;
6889 /****************************************************************************
6890 TODO: This probably needs distinguish between TCP/IP and Local ports
6891 somehow.
6892 ****************************************************************************/
6894 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6895 struct spoolss_PortInfo2 *r,
6896 const char *name)
6898 r->port_name = talloc_strdup(mem_ctx, name);
6899 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6901 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6902 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6904 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6905 W_ERROR_HAVE_NO_MEMORY(r->description);
6907 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6908 r->reserved = 0;
6910 return WERR_OK;
6914 /****************************************************************************
6915 wrapper around the enumer ports command
6916 ****************************************************************************/
6918 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6920 char *cmd = lp_enumports_cmd();
6921 char **qlines = NULL;
6922 char *command = NULL;
6923 int numlines;
6924 int ret;
6925 int fd;
6927 *count = 0;
6928 *lines = NULL;
6930 /* if no hook then just fill in the default port */
6932 if ( !*cmd ) {
6933 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6934 return WERR_NOMEM;
6936 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6937 TALLOC_FREE(qlines);
6938 return WERR_NOMEM;
6940 qlines[1] = NULL;
6941 numlines = 1;
6943 else {
6944 /* we have a valid enumport command */
6946 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6947 if (!command) {
6948 return WERR_NOMEM;
6951 DEBUG(10,("Running [%s]\n", command));
6952 ret = smbrun(command, &fd);
6953 DEBUG(10,("Returned [%d]\n", ret));
6954 TALLOC_FREE(command);
6955 if (ret != 0) {
6956 if (fd != -1) {
6957 close(fd);
6959 return WERR_ACCESS_DENIED;
6962 numlines = 0;
6963 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6964 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6965 close(fd);
6968 *count = numlines;
6969 *lines = qlines;
6971 return WERR_OK;
6974 /****************************************************************************
6975 enumports level 1.
6976 ****************************************************************************/
6978 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6979 union spoolss_PortInfo **info_p,
6980 uint32_t *count)
6982 union spoolss_PortInfo *info = NULL;
6983 int i=0;
6984 WERROR result = WERR_OK;
6985 char **qlines = NULL;
6986 int numlines = 0;
6988 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6989 if (!W_ERROR_IS_OK(result)) {
6990 goto out;
6993 if (numlines) {
6994 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6995 if (!info) {
6996 DEBUG(10,("Returning WERR_NOMEM\n"));
6997 result = WERR_NOMEM;
6998 goto out;
7001 for (i=0; i<numlines; i++) {
7002 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7003 result = fill_port_1(info, &info[i].info1, qlines[i]);
7004 if (!W_ERROR_IS_OK(result)) {
7005 goto out;
7009 TALLOC_FREE(qlines);
7011 out:
7012 if (!W_ERROR_IS_OK(result)) {
7013 TALLOC_FREE(info);
7014 TALLOC_FREE(qlines);
7015 *count = 0;
7016 *info_p = NULL;
7017 return result;
7020 *info_p = info;
7021 *count = numlines;
7023 return WERR_OK;
7026 /****************************************************************************
7027 enumports level 2.
7028 ****************************************************************************/
7030 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7031 union spoolss_PortInfo **info_p,
7032 uint32_t *count)
7034 union spoolss_PortInfo *info = NULL;
7035 int i=0;
7036 WERROR result = WERR_OK;
7037 char **qlines = NULL;
7038 int numlines = 0;
7040 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7041 if (!W_ERROR_IS_OK(result)) {
7042 goto out;
7045 if (numlines) {
7046 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7047 if (!info) {
7048 DEBUG(10,("Returning WERR_NOMEM\n"));
7049 result = WERR_NOMEM;
7050 goto out;
7053 for (i=0; i<numlines; i++) {
7054 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7055 result = fill_port_2(info, &info[i].info2, qlines[i]);
7056 if (!W_ERROR_IS_OK(result)) {
7057 goto out;
7061 TALLOC_FREE(qlines);
7063 out:
7064 if (!W_ERROR_IS_OK(result)) {
7065 TALLOC_FREE(info);
7066 TALLOC_FREE(qlines);
7067 *count = 0;
7068 *info_p = NULL;
7069 return result;
7072 *info_p = info;
7073 *count = numlines;
7075 return WERR_OK;
7078 /****************************************************************
7079 _spoolss_EnumPorts
7080 ****************************************************************/
7082 WERROR _spoolss_EnumPorts(pipes_struct *p,
7083 struct spoolss_EnumPorts *r)
7085 WERROR result;
7087 /* that's an [in out] buffer */
7089 if (!r->in.buffer && (r->in.offered != 0)) {
7090 return WERR_INVALID_PARAM;
7093 DEBUG(4,("_spoolss_EnumPorts\n"));
7095 *r->out.count = 0;
7096 *r->out.needed = 0;
7097 *r->out.info = NULL;
7099 switch (r->in.level) {
7100 case 1:
7101 result = enumports_level_1(p->mem_ctx, r->out.info,
7102 r->out.count);
7103 break;
7104 case 2:
7105 result = enumports_level_2(p->mem_ctx, r->out.info,
7106 r->out.count);
7107 break;
7108 default:
7109 return WERR_UNKNOWN_LEVEL;
7112 if (!W_ERROR_IS_OK(result)) {
7113 return result;
7116 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7117 spoolss_EnumPorts,
7118 *r->out.info, r->in.level,
7119 *r->out.count);
7120 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7121 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7123 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7126 /****************************************************************************
7127 ****************************************************************************/
7129 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7130 const char *server,
7131 struct spoolss_SetPrinterInfoCtr *info_ctr,
7132 struct spoolss_DeviceMode *devmode,
7133 struct security_descriptor *sec_desc,
7134 struct spoolss_UserLevelCtr *user_ctr,
7135 struct policy_handle *handle)
7137 NT_PRINTER_INFO_LEVEL *printer = NULL;
7138 fstring name;
7139 int snum;
7140 WERROR err = WERR_OK;
7142 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7143 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7144 return WERR_NOMEM;
7147 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7148 if (!convert_printer_info(info_ctr, printer)) {
7149 free_a_printer(&printer, 2);
7150 return WERR_NOMEM;
7153 /* samba does not have a concept of local, non-shared printers yet, so
7154 * make sure we always setup sharename - gd */
7155 if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7156 DEBUG(5, ("spoolss_addprinterex_level_2: "
7157 "no sharename has been set, setting printername %s as sharename\n",
7158 printer->info_2->printername));
7159 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7162 /* check to see if the printer already exists */
7164 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7165 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7166 printer->info_2->sharename));
7167 free_a_printer(&printer, 2);
7168 return WERR_PRINTER_ALREADY_EXISTS;
7171 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7172 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7173 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7174 printer->info_2->printername));
7175 free_a_printer(&printer, 2);
7176 return WERR_PRINTER_ALREADY_EXISTS;
7180 /* validate printer info struct */
7181 if (!info_ctr->info.info2->printername ||
7182 strlen(info_ctr->info.info2->printername) == 0) {
7183 free_a_printer(&printer,2);
7184 return WERR_INVALID_PRINTER_NAME;
7186 if (!info_ctr->info.info2->portname ||
7187 strlen(info_ctr->info.info2->portname) == 0) {
7188 free_a_printer(&printer,2);
7189 return WERR_UNKNOWN_PORT;
7191 if (!info_ctr->info.info2->drivername ||
7192 strlen(info_ctr->info.info2->drivername) == 0) {
7193 free_a_printer(&printer,2);
7194 return WERR_UNKNOWN_PRINTER_DRIVER;
7196 if (!info_ctr->info.info2->printprocessor ||
7197 strlen(info_ctr->info.info2->printprocessor) == 0) {
7198 free_a_printer(&printer,2);
7199 return WERR_UNKNOWN_PRINTPROCESSOR;
7202 /* FIXME!!! smbd should check to see if the driver is installed before
7203 trying to add a printer like this --jerry */
7205 if (*lp_addprinter_cmd() ) {
7206 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7207 printer) ) {
7208 free_a_printer(&printer,2);
7209 return WERR_ACCESS_DENIED;
7211 } else {
7212 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7213 "smb.conf parameter \"addprinter command\" is defined. This"
7214 "parameter must exist for this call to succeed\n",
7215 printer->info_2->sharename ));
7218 /* use our primary netbios name since get_a_printer() will convert
7219 it to what the client expects on a case by case basis */
7221 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7222 printer->info_2->sharename);
7225 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7226 free_a_printer(&printer,2);
7227 return WERR_ACCESS_DENIED;
7230 /* you must be a printer admin to add a new printer */
7231 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7232 free_a_printer(&printer,2);
7233 return WERR_ACCESS_DENIED;
7237 * Do sanity check on the requested changes for Samba.
7240 if (!check_printer_ok(printer->info_2, snum)) {
7241 free_a_printer(&printer,2);
7242 return WERR_INVALID_PARAM;
7246 * When a printer is created, the drivername bound to the printer is used
7247 * to lookup previously saved driver initialization info, which is then
7248 * bound to the new printer, simulating what happens in the Windows arch.
7251 if (devmode)
7253 /* A valid devmode was included, convert and link it
7255 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7257 if (!convert_devicemode(printer->info_2->printername, devmode,
7258 &printer->info_2->devmode)) {
7259 return WERR_NOMEM;
7263 /* write the ASCII on disk */
7264 err = mod_a_printer(printer, 2);
7265 if (!W_ERROR_IS_OK(err)) {
7266 free_a_printer(&printer,2);
7267 return err;
7270 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7271 /* Handle open failed - remove addition. */
7272 del_a_printer(printer->info_2->sharename);
7273 free_a_printer(&printer,2);
7274 ZERO_STRUCTP(handle);
7275 return WERR_ACCESS_DENIED;
7278 update_c_setprinter(false);
7279 free_a_printer(&printer,2);
7281 return WERR_OK;
7284 /****************************************************************
7285 _spoolss_AddPrinterEx
7286 ****************************************************************/
7288 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7289 struct spoolss_AddPrinterEx *r)
7291 switch (r->in.info_ctr->level) {
7292 case 1:
7293 /* we don't handle yet */
7294 /* but I know what to do ... */
7295 return WERR_UNKNOWN_LEVEL;
7296 case 2:
7297 return spoolss_addprinterex_level_2(p, r->in.server,
7298 r->in.info_ctr,
7299 r->in.devmode_ctr->devmode,
7300 r->in.secdesc_ctr->sd,
7301 r->in.userlevel_ctr,
7302 r->out.handle);
7303 default:
7304 return WERR_UNKNOWN_LEVEL;
7308 /****************************************************************
7309 _spoolss_AddPrinter
7310 ****************************************************************/
7312 WERROR _spoolss_AddPrinter(pipes_struct *p,
7313 struct spoolss_AddPrinter *r)
7315 struct spoolss_AddPrinterEx a;
7316 struct spoolss_UserLevelCtr userlevel_ctr;
7318 ZERO_STRUCT(userlevel_ctr);
7320 userlevel_ctr.level = 1;
7322 a.in.server = r->in.server;
7323 a.in.info_ctr = r->in.info_ctr;
7324 a.in.devmode_ctr = r->in.devmode_ctr;
7325 a.in.secdesc_ctr = r->in.secdesc_ctr;
7326 a.in.userlevel_ctr = &userlevel_ctr;
7327 a.out.handle = r->out.handle;
7329 return _spoolss_AddPrinterEx(p, &a);
7332 /****************************************************************
7333 _spoolss_AddPrinterDriverEx
7334 ****************************************************************/
7336 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7337 struct spoolss_AddPrinterDriverEx *r)
7339 WERROR err = WERR_OK;
7340 char *driver_name = NULL;
7341 uint32_t version;
7342 const char *fn;
7344 switch (p->hdr_req.opnum) {
7345 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7346 fn = "_spoolss_AddPrinterDriver";
7347 break;
7348 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7349 fn = "_spoolss_AddPrinterDriverEx";
7350 break;
7351 default:
7352 return WERR_INVALID_PARAM;
7356 * we only support the semantics of AddPrinterDriver()
7357 * i.e. only copy files that are newer than existing ones
7360 if (r->in.flags == 0) {
7361 return WERR_INVALID_PARAM;
7364 if (r->in.flags != APD_COPY_NEW_FILES) {
7365 return WERR_ACCESS_DENIED;
7368 /* FIXME */
7369 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7370 /* Clever hack from Martin Zielinski <mz@seh.de>
7371 * to allow downgrade from level 8 (Vista).
7373 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7374 r->in.info_ctr->level));
7375 return WERR_UNKNOWN_LEVEL;
7378 DEBUG(5,("Cleaning driver's information\n"));
7379 err = clean_up_driver_struct(p, r->in.info_ctr);
7380 if (!W_ERROR_IS_OK(err))
7381 goto done;
7383 DEBUG(5,("Moving driver to final destination\n"));
7384 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7385 &err)) ) {
7386 goto done;
7389 if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7390 err = WERR_ACCESS_DENIED;
7391 goto done;
7395 * I think this is where he DrvUpgradePrinter() hook would be
7396 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7397 * server. Right now, we just need to send ourselves a message
7398 * to update each printer bound to this driver. --jerry
7401 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7402 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7403 fn, driver_name));
7406 done:
7407 return err;
7410 /****************************************************************
7411 _spoolss_AddPrinterDriver
7412 ****************************************************************/
7414 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7415 struct spoolss_AddPrinterDriver *r)
7417 struct spoolss_AddPrinterDriverEx a;
7419 switch (r->in.info_ctr->level) {
7420 case 2:
7421 case 3:
7422 case 4:
7423 case 5:
7424 break;
7425 default:
7426 return WERR_UNKNOWN_LEVEL;
7429 a.in.servername = r->in.servername;
7430 a.in.info_ctr = r->in.info_ctr;
7431 a.in.flags = APD_COPY_NEW_FILES;
7433 return _spoolss_AddPrinterDriverEx(p, &a);
7436 /****************************************************************************
7437 ****************************************************************************/
7439 struct _spoolss_paths {
7440 int type;
7441 const char *share;
7442 const char *dir;
7445 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7447 static const struct _spoolss_paths spoolss_paths[]= {
7448 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7449 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7452 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7453 const char *servername,
7454 const char *environment,
7455 int component,
7456 char **path)
7458 const char *pservername = NULL;
7459 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7460 const char *short_archi;
7462 *path = NULL;
7464 /* environment may be empty */
7465 if (environment && strlen(environment)) {
7466 long_archi = environment;
7469 /* servername may be empty */
7470 if (servername && strlen(servername)) {
7471 pservername = canon_servername(servername);
7473 if (!is_myname_or_ipaddr(pservername)) {
7474 return WERR_INVALID_PARAM;
7478 if (!(short_archi = get_short_archi(long_archi))) {
7479 return WERR_INVALID_ENVIRONMENT;
7482 switch (component) {
7483 case SPOOLSS_PRTPROCS_PATH:
7484 case SPOOLSS_DRIVER_PATH:
7485 if (pservername) {
7486 *path = talloc_asprintf(mem_ctx,
7487 "\\\\%s\\%s\\%s",
7488 pservername,
7489 spoolss_paths[component].share,
7490 short_archi);
7491 } else {
7492 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7493 SPOOLSS_DEFAULT_SERVER_PATH,
7494 spoolss_paths[component].dir,
7495 short_archi);
7497 break;
7498 default:
7499 return WERR_INVALID_PARAM;
7502 if (!*path) {
7503 return WERR_NOMEM;
7506 return WERR_OK;
7509 /****************************************************************************
7510 ****************************************************************************/
7512 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7513 const char *servername,
7514 const char *environment,
7515 struct spoolss_DriverDirectoryInfo1 *r)
7517 WERROR werr;
7518 char *path = NULL;
7520 werr = compose_spoolss_server_path(mem_ctx,
7521 servername,
7522 environment,
7523 SPOOLSS_DRIVER_PATH,
7524 &path);
7525 if (!W_ERROR_IS_OK(werr)) {
7526 return werr;
7529 DEBUG(4,("printer driver directory: [%s]\n", path));
7531 r->directory_name = path;
7533 return WERR_OK;
7536 /****************************************************************
7537 _spoolss_GetPrinterDriverDirectory
7538 ****************************************************************/
7540 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7541 struct spoolss_GetPrinterDriverDirectory *r)
7543 WERROR werror;
7545 /* that's an [in out] buffer */
7547 if (!r->in.buffer && (r->in.offered != 0)) {
7548 return WERR_INVALID_PARAM;
7551 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7552 r->in.level));
7554 *r->out.needed = 0;
7556 /* r->in.level is ignored */
7558 werror = getprinterdriverdir_level_1(p->mem_ctx,
7559 r->in.server,
7560 r->in.environment,
7561 &r->out.info->info1);
7562 if (!W_ERROR_IS_OK(werror)) {
7563 TALLOC_FREE(r->out.info);
7564 return werror;
7567 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7568 r->out.info, r->in.level);
7569 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7571 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7574 /****************************************************************
7575 _spoolss_EnumPrinterData
7576 ****************************************************************/
7578 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7579 struct spoolss_EnumPrinterData *r)
7581 WERROR result;
7582 struct spoolss_EnumPrinterDataEx r2;
7583 uint32_t count;
7584 struct spoolss_PrinterEnumValues *info, *val = NULL;
7585 uint32_t needed;
7587 r2.in.handle = r->in.handle;
7588 r2.in.key_name = "PrinterDriverData";
7589 r2.in.offered = 0;
7590 r2.out.count = &count;
7591 r2.out.info = &info;
7592 r2.out.needed = &needed;
7594 result = _spoolss_EnumPrinterDataEx(p, &r2);
7595 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7596 r2.in.offered = needed;
7597 result = _spoolss_EnumPrinterDataEx(p, &r2);
7599 if (!W_ERROR_IS_OK(result)) {
7600 return result;
7604 * The NT machine wants to know the biggest size of value and data
7606 * cf: MSDN EnumPrinterData remark section
7609 if (!r->in.value_offered && !r->in.data_offered) {
7610 uint32_t biggest_valuesize = 0;
7611 uint32_t biggest_datasize = 0;
7612 int i, name_length;
7614 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7616 for (i=0; i<count; i++) {
7618 name_length = strlen(info[i].value_name);
7619 if (strlen(info[i].value_name) > biggest_valuesize) {
7620 biggest_valuesize = name_length;
7623 if (info[i].data_length > biggest_datasize) {
7624 biggest_datasize = info[i].data_length;
7627 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7628 biggest_datasize));
7631 /* the value is an UNICODE string but real_value_size is the length
7632 in bytes including the trailing 0 */
7634 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7635 *r->out.data_needed = biggest_datasize;
7637 DEBUG(6,("final values: [%d], [%d]\n",
7638 *r->out.value_needed, *r->out.data_needed));
7640 return WERR_OK;
7643 if (r->in.enum_index < count) {
7644 val = &info[r->in.enum_index];
7647 if (val == NULL) {
7648 /* out_value should default to "" or else NT4 has
7649 problems unmarshalling the response */
7651 if (r->in.value_offered) {
7652 *r->out.value_needed = 1;
7653 r->out.value_name = talloc_strdup(r, "");
7654 if (!r->out.value_name) {
7655 return WERR_NOMEM;
7657 } else {
7658 r->out.value_name = NULL;
7659 *r->out.value_needed = 0;
7662 /* the data is counted in bytes */
7664 *r->out.data_needed = r->in.data_offered;
7666 result = WERR_NO_MORE_ITEMS;
7667 } else {
7669 * the value is:
7670 * - counted in bytes in the request
7671 * - counted in UNICODE chars in the max reply
7672 * - counted in bytes in the real size
7674 * take a pause *before* coding not *during* coding
7677 /* name */
7678 if (r->in.value_offered) {
7679 r->out.value_name = talloc_strdup(r, val->value_name);
7680 if (!r->out.value_name) {
7681 return WERR_NOMEM;
7683 *r->out.value_needed = val->value_name_len;
7684 } else {
7685 r->out.value_name = NULL;
7686 *r->out.value_needed = 0;
7689 /* type */
7691 *r->out.type = val->type;
7693 /* data - counted in bytes */
7696 * See the section "Dynamically Typed Query Parameters"
7697 * in MS-RPRN.
7700 if (r->out.data && val->data && val->data->data &&
7701 val->data_length && r->in.data_offered) {
7702 memcpy(r->out.data, val->data->data,
7703 MIN(val->data_length,r->in.data_offered));
7706 *r->out.data_needed = val->data_length;
7708 result = WERR_OK;
7711 return result;
7714 /****************************************************************
7715 _spoolss_SetPrinterData
7716 ****************************************************************/
7718 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7719 struct spoolss_SetPrinterData *r)
7721 struct spoolss_SetPrinterDataEx r2;
7723 r2.in.handle = r->in.handle;
7724 r2.in.key_name = "PrinterDriverData";
7725 r2.in.value_name = r->in.value_name;
7726 r2.in.type = r->in.type;
7727 r2.in.data = r->in.data;
7728 r2.in.offered = r->in.offered;
7730 return _spoolss_SetPrinterDataEx(p, &r2);
7733 /****************************************************************
7734 _spoolss_ResetPrinter
7735 ****************************************************************/
7737 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7738 struct spoolss_ResetPrinter *r)
7740 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7741 int snum;
7743 DEBUG(5,("_spoolss_ResetPrinter\n"));
7746 * All we do is to check to see if the handle and queue is valid.
7747 * This call really doesn't mean anything to us because we only
7748 * support RAW printing. --jerry
7751 if (!Printer) {
7752 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7753 OUR_HANDLE(r->in.handle)));
7754 return WERR_BADFID;
7757 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7758 return WERR_BADFID;
7761 /* blindly return success */
7762 return WERR_OK;
7765 /****************************************************************
7766 _spoolss_DeletePrinterData
7767 ****************************************************************/
7769 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7770 struct spoolss_DeletePrinterData *r)
7772 struct spoolss_DeletePrinterDataEx r2;
7774 r2.in.handle = r->in.handle;
7775 r2.in.key_name = "PrinterDriverData";
7776 r2.in.value_name = r->in.value_name;
7778 return _spoolss_DeletePrinterDataEx(p, &r2);
7781 /****************************************************************
7782 _spoolss_AddForm
7783 ****************************************************************/
7785 WERROR _spoolss_AddForm(pipes_struct *p,
7786 struct spoolss_AddForm *r)
7788 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7789 nt_forms_struct tmpForm;
7790 int snum = -1;
7791 WERROR status = WERR_OK;
7792 NT_PRINTER_INFO_LEVEL *printer = NULL;
7793 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7795 int count=0;
7796 nt_forms_struct *list=NULL;
7797 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7798 int i;
7800 DEBUG(5,("_spoolss_AddForm\n"));
7802 if (!Printer) {
7803 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7804 OUR_HANDLE(r->in.handle)));
7805 return WERR_BADFID;
7809 /* forms can be added on printer or on the print server handle */
7811 if ( Printer->printer_type == SPLHND_PRINTER )
7813 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7814 return WERR_BADFID;
7816 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7817 if (!W_ERROR_IS_OK(status))
7818 goto done;
7821 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7822 and not a printer admin, then fail */
7824 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7825 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7826 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7827 NULL, NULL,
7828 p->server_info->ptok,
7829 lp_printer_admin(snum))) {
7830 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7831 status = WERR_ACCESS_DENIED;
7832 goto done;
7835 switch (form->flags) {
7836 case SPOOLSS_FORM_USER:
7837 case SPOOLSS_FORM_BUILTIN:
7838 case SPOOLSS_FORM_PRINTER:
7839 break;
7840 default:
7841 status = WERR_INVALID_PARAM;
7842 goto done;
7845 /* can't add if builtin */
7847 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7848 status = WERR_FILE_EXISTS;
7849 goto done;
7852 count = get_ntforms(&list);
7854 for (i=0; i < count; i++) {
7855 if (strequal(form->form_name, list[i].name)) {
7856 status = WERR_FILE_EXISTS;
7857 goto done;
7861 if(!add_a_form(&list, form, &count)) {
7862 status = WERR_NOMEM;
7863 goto done;
7866 become_root();
7867 write_ntforms(&list, count);
7868 unbecome_root();
7871 * ChangeID must always be set if this is a printer
7874 if ( Printer->printer_type == SPLHND_PRINTER )
7875 status = mod_a_printer(printer, 2);
7877 done:
7878 if ( printer )
7879 free_a_printer(&printer, 2);
7880 SAFE_FREE(list);
7882 return status;
7885 /****************************************************************
7886 _spoolss_DeleteForm
7887 ****************************************************************/
7889 WERROR _spoolss_DeleteForm(pipes_struct *p,
7890 struct spoolss_DeleteForm *r)
7892 const char *form_name = r->in.form_name;
7893 nt_forms_struct tmpForm;
7894 int count=0;
7895 nt_forms_struct *list=NULL;
7896 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7897 int snum = -1;
7898 WERROR status = WERR_OK;
7899 NT_PRINTER_INFO_LEVEL *printer = NULL;
7900 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7901 bool ret = false;
7903 DEBUG(5,("_spoolss_DeleteForm\n"));
7905 if (!Printer) {
7906 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7907 OUR_HANDLE(r->in.handle)));
7908 return WERR_BADFID;
7911 /* forms can be deleted on printer of on the print server handle */
7913 if ( Printer->printer_type == SPLHND_PRINTER )
7915 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7916 return WERR_BADFID;
7918 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7919 if (!W_ERROR_IS_OK(status))
7920 goto done;
7923 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7924 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7925 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7926 NULL, NULL,
7927 p->server_info->ptok,
7928 lp_printer_admin(snum))) {
7929 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7930 return WERR_ACCESS_DENIED;
7934 /* can't delete if builtin */
7936 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7937 status = WERR_INVALID_PARAM;
7938 goto done;
7941 count = get_ntforms(&list);
7943 become_root();
7944 ret = delete_a_form(&list, form_name, &count, &status);
7945 unbecome_root();
7946 if (ret == false) {
7947 goto done;
7951 * ChangeID must always be set if this is a printer
7954 if ( Printer->printer_type == SPLHND_PRINTER )
7955 status = mod_a_printer(printer, 2);
7957 done:
7958 if ( printer )
7959 free_a_printer(&printer, 2);
7960 SAFE_FREE(list);
7962 return status;
7965 /****************************************************************
7966 _spoolss_SetForm
7967 ****************************************************************/
7969 WERROR _spoolss_SetForm(pipes_struct *p,
7970 struct spoolss_SetForm *r)
7972 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7973 nt_forms_struct tmpForm;
7974 int snum = -1;
7975 WERROR status = WERR_OK;
7976 NT_PRINTER_INFO_LEVEL *printer = NULL;
7977 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7979 int count=0;
7980 nt_forms_struct *list=NULL;
7981 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7983 DEBUG(5,("_spoolss_SetForm\n"));
7985 if (!Printer) {
7986 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7987 OUR_HANDLE(r->in.handle)));
7988 return WERR_BADFID;
7991 /* forms can be modified on printer of on the print server handle */
7993 if ( Printer->printer_type == SPLHND_PRINTER )
7995 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7996 return WERR_BADFID;
7998 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7999 if (!W_ERROR_IS_OK(status))
8000 goto done;
8003 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8004 and not a printer admin, then fail */
8006 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8007 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8008 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8009 NULL, NULL,
8010 p->server_info->ptok,
8011 lp_printer_admin(snum))) {
8012 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8013 status = WERR_ACCESS_DENIED;
8014 goto done;
8017 /* can't set if builtin */
8018 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8019 status = WERR_INVALID_PARAM;
8020 goto done;
8023 count = get_ntforms(&list);
8024 update_a_form(&list, form, count);
8025 become_root();
8026 write_ntforms(&list, count);
8027 unbecome_root();
8030 * ChangeID must always be set if this is a printer
8033 if ( Printer->printer_type == SPLHND_PRINTER )
8034 status = mod_a_printer(printer, 2);
8037 done:
8038 if ( printer )
8039 free_a_printer(&printer, 2);
8040 SAFE_FREE(list);
8042 return status;
8045 /****************************************************************************
8046 fill_print_processor1
8047 ****************************************************************************/
8049 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8050 struct spoolss_PrintProcessorInfo1 *r,
8051 const char *print_processor_name)
8053 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8054 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8056 return WERR_OK;
8059 /****************************************************************************
8060 enumprintprocessors level 1.
8061 ****************************************************************************/
8063 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8064 union spoolss_PrintProcessorInfo **info_p,
8065 uint32_t *count)
8067 union spoolss_PrintProcessorInfo *info;
8068 WERROR result;
8070 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8071 W_ERROR_HAVE_NO_MEMORY(info);
8073 *count = 1;
8075 result = fill_print_processor1(info, &info[0].info1, "winprint");
8076 if (!W_ERROR_IS_OK(result)) {
8077 goto out;
8080 out:
8081 if (!W_ERROR_IS_OK(result)) {
8082 TALLOC_FREE(info);
8083 *count = 0;
8084 return result;
8087 *info_p = info;
8089 return WERR_OK;
8092 /****************************************************************
8093 _spoolss_EnumPrintProcessors
8094 ****************************************************************/
8096 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8097 struct spoolss_EnumPrintProcessors *r)
8099 WERROR result;
8101 /* that's an [in out] buffer */
8103 if (!r->in.buffer && (r->in.offered != 0)) {
8104 return WERR_INVALID_PARAM;
8107 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8110 * Enumerate the print processors ...
8112 * Just reply with "winprint", to keep NT happy
8113 * and I can use my nice printer checker.
8116 *r->out.count = 0;
8117 *r->out.needed = 0;
8118 *r->out.info = NULL;
8120 switch (r->in.level) {
8121 case 1:
8122 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8123 r->out.count);
8124 break;
8125 default:
8126 return WERR_UNKNOWN_LEVEL;
8129 if (!W_ERROR_IS_OK(result)) {
8130 return result;
8133 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8134 spoolss_EnumPrintProcessors,
8135 *r->out.info, r->in.level,
8136 *r->out.count);
8137 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8138 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8140 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8143 /****************************************************************************
8144 fill_printprocdatatype1
8145 ****************************************************************************/
8147 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8148 struct spoolss_PrintProcDataTypesInfo1 *r,
8149 const char *name_array)
8151 r->name_array = talloc_strdup(mem_ctx, name_array);
8152 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8154 return WERR_OK;
8157 /****************************************************************************
8158 enumprintprocdatatypes level 1.
8159 ****************************************************************************/
8161 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8162 union spoolss_PrintProcDataTypesInfo **info_p,
8163 uint32_t *count)
8165 WERROR result;
8166 union spoolss_PrintProcDataTypesInfo *info;
8168 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8169 W_ERROR_HAVE_NO_MEMORY(info);
8171 *count = 1;
8173 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8174 if (!W_ERROR_IS_OK(result)) {
8175 goto out;
8178 out:
8179 if (!W_ERROR_IS_OK(result)) {
8180 TALLOC_FREE(info);
8181 *count = 0;
8182 return result;
8185 *info_p = info;
8187 return WERR_OK;
8190 /****************************************************************
8191 _spoolss_EnumPrintProcDataTypes
8192 ****************************************************************/
8194 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8195 struct spoolss_EnumPrintProcDataTypes *r)
8197 WERROR result;
8199 /* that's an [in out] buffer */
8201 if (!r->in.buffer && (r->in.offered != 0)) {
8202 return WERR_INVALID_PARAM;
8205 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8207 *r->out.count = 0;
8208 *r->out.needed = 0;
8209 *r->out.info = NULL;
8211 switch (r->in.level) {
8212 case 1:
8213 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8214 r->out.count);
8215 break;
8216 default:
8217 return WERR_UNKNOWN_LEVEL;
8220 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8221 spoolss_EnumPrintProcDataTypes,
8222 *r->out.info, r->in.level,
8223 *r->out.count);
8224 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8225 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8227 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8230 /****************************************************************************
8231 fill_monitor_1
8232 ****************************************************************************/
8234 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8235 struct spoolss_MonitorInfo1 *r,
8236 const char *monitor_name)
8238 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8239 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8241 return WERR_OK;
8244 /****************************************************************************
8245 fill_monitor_2
8246 ****************************************************************************/
8248 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8249 struct spoolss_MonitorInfo2 *r,
8250 const char *monitor_name,
8251 const char *environment,
8252 const char *dll_name)
8254 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8255 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8256 r->environment = talloc_strdup(mem_ctx, environment);
8257 W_ERROR_HAVE_NO_MEMORY(r->environment);
8258 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8259 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8261 return WERR_OK;
8264 /****************************************************************************
8265 enumprintmonitors level 1.
8266 ****************************************************************************/
8268 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8269 union spoolss_MonitorInfo **info_p,
8270 uint32_t *count)
8272 union spoolss_MonitorInfo *info;
8273 WERROR result = WERR_OK;
8275 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8276 W_ERROR_HAVE_NO_MEMORY(info);
8278 *count = 2;
8280 result = fill_monitor_1(info, &info[0].info1,
8281 SPL_LOCAL_PORT);
8282 if (!W_ERROR_IS_OK(result)) {
8283 goto out;
8286 result = fill_monitor_1(info, &info[1].info1,
8287 SPL_TCPIP_PORT);
8288 if (!W_ERROR_IS_OK(result)) {
8289 goto out;
8292 out:
8293 if (!W_ERROR_IS_OK(result)) {
8294 TALLOC_FREE(info);
8295 *count = 0;
8296 return result;
8299 *info_p = info;
8301 return WERR_OK;
8304 /****************************************************************************
8305 enumprintmonitors level 2.
8306 ****************************************************************************/
8308 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8309 union spoolss_MonitorInfo **info_p,
8310 uint32_t *count)
8312 union spoolss_MonitorInfo *info;
8313 WERROR result = WERR_OK;
8315 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8316 W_ERROR_HAVE_NO_MEMORY(info);
8318 *count = 2;
8320 result = fill_monitor_2(info, &info[0].info2,
8321 SPL_LOCAL_PORT,
8322 "Windows NT X86", /* FIXME */
8323 "localmon.dll");
8324 if (!W_ERROR_IS_OK(result)) {
8325 goto out;
8328 result = fill_monitor_2(info, &info[1].info2,
8329 SPL_TCPIP_PORT,
8330 "Windows NT X86", /* FIXME */
8331 "tcpmon.dll");
8332 if (!W_ERROR_IS_OK(result)) {
8333 goto out;
8336 out:
8337 if (!W_ERROR_IS_OK(result)) {
8338 TALLOC_FREE(info);
8339 *count = 0;
8340 return result;
8343 *info_p = info;
8345 return WERR_OK;
8348 /****************************************************************
8349 _spoolss_EnumMonitors
8350 ****************************************************************/
8352 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8353 struct spoolss_EnumMonitors *r)
8355 WERROR result;
8357 /* that's an [in out] buffer */
8359 if (!r->in.buffer && (r->in.offered != 0)) {
8360 return WERR_INVALID_PARAM;
8363 DEBUG(5,("_spoolss_EnumMonitors\n"));
8366 * Enumerate the print monitors ...
8368 * Just reply with "Local Port", to keep NT happy
8369 * and I can use my nice printer checker.
8372 *r->out.count = 0;
8373 *r->out.needed = 0;
8374 *r->out.info = NULL;
8376 switch (r->in.level) {
8377 case 1:
8378 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8379 r->out.count);
8380 break;
8381 case 2:
8382 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8383 r->out.count);
8384 break;
8385 default:
8386 return WERR_UNKNOWN_LEVEL;
8389 if (!W_ERROR_IS_OK(result)) {
8390 return result;
8393 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8394 spoolss_EnumMonitors,
8395 *r->out.info, r->in.level,
8396 *r->out.count);
8397 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8398 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8400 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8403 /****************************************************************************
8404 ****************************************************************************/
8406 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8407 const print_queue_struct *queue,
8408 int count, int snum,
8409 const NT_PRINTER_INFO_LEVEL *ntprinter,
8410 uint32_t jobid,
8411 struct spoolss_JobInfo1 *r)
8413 int i = 0;
8414 bool found = false;
8416 for (i=0; i<count; i++) {
8417 if (queue[i].job == (int)jobid) {
8418 found = true;
8419 break;
8423 if (found == false) {
8424 /* NT treats not found as bad param... yet another bad choice */
8425 return WERR_INVALID_PARAM;
8428 return fill_job_info1(mem_ctx,
8430 &queue[i],
8432 snum,
8433 ntprinter);
8436 /****************************************************************************
8437 ****************************************************************************/
8439 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8440 const print_queue_struct *queue,
8441 int count, int snum,
8442 const NT_PRINTER_INFO_LEVEL *ntprinter,
8443 uint32_t jobid,
8444 struct spoolss_JobInfo2 *r)
8446 int i = 0;
8447 bool found = false;
8448 struct spoolss_DeviceMode *devmode;
8449 NT_DEVICEMODE *nt_devmode;
8450 WERROR result;
8452 for (i=0; i<count; i++) {
8453 if (queue[i].job == (int)jobid) {
8454 found = true;
8455 break;
8459 if (found == false) {
8460 /* NT treats not found as bad param... yet another bad
8461 choice */
8462 return WERR_INVALID_PARAM;
8466 * if the print job does not have a DEVMODE associated with it,
8467 * just use the one for the printer. A NULL devicemode is not
8468 * a failure condition
8471 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8472 if (nt_devmode) {
8473 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8474 W_ERROR_HAVE_NO_MEMORY(devmode);
8475 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8476 if (!W_ERROR_IS_OK(result)) {
8477 return result;
8479 } else {
8480 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8481 W_ERROR_HAVE_NO_MEMORY(devmode);
8484 return fill_job_info2(mem_ctx,
8486 &queue[i],
8488 snum,
8489 ntprinter,
8490 devmode);
8493 /****************************************************************
8494 _spoolss_GetJob
8495 ****************************************************************/
8497 WERROR _spoolss_GetJob(pipes_struct *p,
8498 struct spoolss_GetJob *r)
8500 WERROR result = WERR_OK;
8501 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8502 int snum;
8503 int count;
8504 print_queue_struct *queue = NULL;
8505 print_status_struct prt_status;
8507 /* that's an [in out] buffer */
8509 if (!r->in.buffer && (r->in.offered != 0)) {
8510 return WERR_INVALID_PARAM;
8513 DEBUG(5,("_spoolss_GetJob\n"));
8515 *r->out.needed = 0;
8517 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8518 return WERR_BADFID;
8521 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8522 if (!W_ERROR_IS_OK(result)) {
8523 return result;
8526 count = print_queue_status(snum, &queue, &prt_status);
8528 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8529 count, prt_status.status, prt_status.message));
8531 switch (r->in.level) {
8532 case 1:
8533 result = getjob_level_1(p->mem_ctx,
8534 queue, count, snum, ntprinter,
8535 r->in.job_id, &r->out.info->info1);
8536 break;
8537 case 2:
8538 result = getjob_level_2(p->mem_ctx,
8539 queue, count, snum, ntprinter,
8540 r->in.job_id, &r->out.info->info2);
8541 break;
8542 default:
8543 result = WERR_UNKNOWN_LEVEL;
8544 break;
8547 SAFE_FREE(queue);
8548 free_a_printer(&ntprinter, 2);
8550 if (!W_ERROR_IS_OK(result)) {
8551 TALLOC_FREE(r->out.info);
8552 return result;
8555 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8556 r->in.level);
8557 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8559 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8562 /****************************************************************
8563 _spoolss_GetPrinterDataEx
8564 ****************************************************************/
8566 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8567 struct spoolss_GetPrinterDataEx *r)
8570 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8571 struct regval_blob *val = NULL;
8572 NT_PRINTER_INFO_LEVEL *printer = NULL;
8573 int snum = 0;
8574 WERROR result = WERR_OK;
8575 DATA_BLOB blob;
8577 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8579 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8580 r->in.key_name, r->in.value_name));
8582 /* in case of problem, return some default values */
8584 *r->out.needed = 0;
8585 *r->out.type = REG_NONE;
8587 if (!Printer) {
8588 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8589 OUR_HANDLE(r->in.handle)));
8590 result = WERR_BADFID;
8591 goto done;
8594 /* Is the handle to a printer or to the server? */
8596 if (Printer->printer_type == SPLHND_SERVER) {
8598 union spoolss_PrinterData data;
8600 result = getprinterdata_printer_server(p->mem_ctx,
8601 r->in.value_name,
8602 r->out.type,
8603 &data);
8604 if (!W_ERROR_IS_OK(result)) {
8605 goto done;
8608 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8609 *r->out.type, &data);
8610 if (!W_ERROR_IS_OK(result)) {
8611 goto done;
8614 *r->out.needed = blob.length;
8616 if (r->in.offered >= *r->out.needed) {
8617 memcpy(r->out.data, blob.data, blob.length);
8620 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8623 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8624 result = WERR_BADFID;
8625 goto done;
8628 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8629 if (!W_ERROR_IS_OK(result)) {
8630 goto done;
8633 /* check to see if the keyname is valid */
8634 if (!strlen(r->in.key_name)) {
8635 result = WERR_INVALID_PARAM;
8636 goto done;
8639 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8641 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8642 strequal(r->in.value_name, "ChangeId")) {
8643 *r->out.type = REG_DWORD;
8644 *r->out.needed = 4;
8645 if (r->in.offered >= *r->out.needed) {
8646 SIVAL(r->out.data, 0, printer->info_2->changeid);
8647 result = WERR_OK;
8649 goto done;
8652 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8653 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8654 "Invalid keyname [%s]\n", r->in.key_name ));
8655 result = WERR_BADFILE;
8656 goto done;
8659 val = get_printer_data(printer->info_2,
8660 r->in.key_name, r->in.value_name);
8661 if (!val) {
8662 result = WERR_BADFILE;
8663 goto done;
8666 *r->out.needed = regval_size(val);
8667 *r->out.type = regval_type(val);
8669 if (r->in.offered >= *r->out.needed) {
8670 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8672 done:
8673 if (printer) {
8674 free_a_printer(&printer, 2);
8677 if (!W_ERROR_IS_OK(result)) {
8678 return result;
8681 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8682 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8684 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8687 /****************************************************************
8688 _spoolss_SetPrinterDataEx
8689 ****************************************************************/
8691 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8692 struct spoolss_SetPrinterDataEx *r)
8694 NT_PRINTER_INFO_LEVEL *printer = NULL;
8695 int snum = 0;
8696 WERROR result = WERR_OK;
8697 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8698 char *oid_string;
8700 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8702 /* From MSDN documentation of SetPrinterDataEx: pass request to
8703 SetPrinterData if key is "PrinterDriverData" */
8705 if (!Printer) {
8706 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8707 OUR_HANDLE(r->in.handle)));
8708 return WERR_BADFID;
8711 if (Printer->printer_type == SPLHND_SERVER) {
8712 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8713 "Not implemented for server handles yet\n"));
8714 return WERR_INVALID_PARAM;
8717 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8718 return WERR_BADFID;
8722 * Access check : NT returns "access denied" if you make a
8723 * SetPrinterData call without the necessary privildge.
8724 * we were originally returning OK if nothing changed
8725 * which made Win2k issue **a lot** of SetPrinterData
8726 * when connecting to a printer --jerry
8729 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8730 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8731 "change denied by handle access permissions\n"));
8732 return WERR_ACCESS_DENIED;
8735 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8736 if (!W_ERROR_IS_OK(result)) {
8737 return result;
8740 /* check for OID in valuename */
8742 oid_string = strchr(r->in.value_name, ',');
8743 if (oid_string) {
8744 *oid_string = '\0';
8745 oid_string++;
8748 /* save the registry data */
8750 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8751 r->in.type, r->in.data, r->in.offered);
8753 if (W_ERROR_IS_OK(result)) {
8754 /* save the OID if one was specified */
8755 if (oid_string) {
8756 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8757 r->in.key_name, SPOOL_OID_KEY);
8758 if (!str) {
8759 result = WERR_NOMEM;
8760 goto done;
8764 * I'm not checking the status here on purpose. Don't know
8765 * if this is right, but I'm returning the status from the
8766 * previous set_printer_dataex() call. I have no idea if
8767 * this is right. --jerry
8770 set_printer_dataex(printer, str, r->in.value_name,
8771 REG_SZ, (uint8_t *)oid_string,
8772 strlen(oid_string)+1);
8775 result = mod_a_printer(printer, 2);
8778 done:
8779 free_a_printer(&printer, 2);
8781 return result;
8784 /****************************************************************
8785 _spoolss_DeletePrinterDataEx
8786 ****************************************************************/
8788 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8789 struct spoolss_DeletePrinterDataEx *r)
8791 NT_PRINTER_INFO_LEVEL *printer = NULL;
8792 int snum=0;
8793 WERROR status = WERR_OK;
8794 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8796 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8798 if (!Printer) {
8799 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8800 "Invalid handle (%s:%u:%u).\n",
8801 OUR_HANDLE(r->in.handle)));
8802 return WERR_BADFID;
8805 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8806 return WERR_BADFID;
8808 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8809 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8810 "printer properties change denied by handle\n"));
8811 return WERR_ACCESS_DENIED;
8814 if (!r->in.value_name || !r->in.key_name) {
8815 return WERR_NOMEM;
8818 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8819 if (!W_ERROR_IS_OK(status))
8820 return status;
8822 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8824 if ( W_ERROR_IS_OK(status) )
8825 mod_a_printer( printer, 2 );
8827 free_a_printer(&printer, 2);
8829 return status;
8832 /****************************************************************
8833 _spoolss_EnumPrinterKey
8834 ****************************************************************/
8836 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8837 struct spoolss_EnumPrinterKey *r)
8839 fstring *keynames = NULL;
8840 int num_keys;
8841 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8842 NT_PRINTER_DATA *data;
8843 NT_PRINTER_INFO_LEVEL *printer = NULL;
8844 int snum = 0;
8845 WERROR result = WERR_BADFILE;
8846 int i;
8847 const char **array = NULL;
8848 DATA_BLOB blob;
8850 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8852 if (!Printer) {
8853 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8854 OUR_HANDLE(r->in.handle)));
8855 return WERR_BADFID;
8858 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8859 return WERR_BADFID;
8862 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8863 if (!W_ERROR_IS_OK(result)) {
8864 return result;
8867 /* get the list of subkey names */
8869 data = printer->info_2->data;
8871 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8872 if (num_keys == -1) {
8873 result = WERR_BADFILE;
8874 goto done;
8877 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8878 if (!array) {
8879 result = WERR_NOMEM;
8880 goto done;
8883 if (!num_keys) {
8884 array[0] = talloc_strdup(array, "");
8885 if (!array[0]) {
8886 result = WERR_NOMEM;
8887 goto done;
8891 for (i=0; i < num_keys; i++) {
8893 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8894 keynames[i]));
8896 array[i] = talloc_strdup(array, keynames[i]);
8897 if (!array[i]) {
8898 result = WERR_NOMEM;
8899 goto done;
8903 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8904 result = WERR_NOMEM;
8905 goto done;
8908 *r->out._ndr_size = r->in.offered / 2;
8909 *r->out.needed = blob.length;
8911 if (r->in.offered < *r->out.needed) {
8912 result = WERR_MORE_DATA;
8913 } else {
8914 result = WERR_OK;
8915 r->out.key_buffer->string_array = array;
8918 done:
8919 if (!W_ERROR_IS_OK(result)) {
8920 TALLOC_FREE(array);
8921 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8922 *r->out.needed = 0;
8926 free_a_printer(&printer, 2);
8927 SAFE_FREE(keynames);
8929 return result;
8932 /****************************************************************
8933 _spoolss_DeletePrinterKey
8934 ****************************************************************/
8936 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8937 struct spoolss_DeletePrinterKey *r)
8939 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8940 NT_PRINTER_INFO_LEVEL *printer = NULL;
8941 int snum=0;
8942 WERROR status;
8944 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8946 if (!Printer) {
8947 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8948 OUR_HANDLE(r->in.handle)));
8949 return WERR_BADFID;
8952 /* if keyname == NULL, return error */
8954 if ( !r->in.key_name )
8955 return WERR_INVALID_PARAM;
8957 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8958 return WERR_BADFID;
8960 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8961 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8962 "printer properties change denied by handle\n"));
8963 return WERR_ACCESS_DENIED;
8966 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8967 if (!W_ERROR_IS_OK(status))
8968 return status;
8970 /* delete the key and all subneys */
8972 status = delete_all_printer_data( printer->info_2, r->in.key_name );
8974 if ( W_ERROR_IS_OK(status) )
8975 status = mod_a_printer(printer, 2);
8977 free_a_printer( &printer, 2 );
8979 return status;
8982 /****************************************************************
8983 ****************************************************************/
8985 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8986 struct regval_blob *v,
8987 struct spoolss_PrinterEnumValues *r)
8989 r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
8990 W_ERROR_HAVE_NO_MEMORY(r->data);
8992 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
8993 W_ERROR_HAVE_NO_MEMORY(r->value_name);
8995 r->value_name_len = strlen_m_term(regval_name(v)) * 2;
8997 r->type = regval_type(v);
8998 r->data_length = regval_size(v);
9000 if (r->data_length) {
9001 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9004 return WERR_OK;
9007 /****************************************************************
9008 _spoolss_EnumPrinterDataEx
9009 ****************************************************************/
9011 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9012 struct spoolss_EnumPrinterDataEx *r)
9014 uint32_t count = 0;
9015 NT_PRINTER_INFO_LEVEL *printer = NULL;
9016 struct spoolss_PrinterEnumValues *info = NULL;
9017 NT_PRINTER_DATA *p_data;
9018 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9019 int snum;
9020 WERROR result;
9021 int key_index;
9022 int i;
9024 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9026 *r->out.count = 0;
9027 *r->out.needed = 0;
9028 *r->out.info = NULL;
9030 if (!Printer) {
9031 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9032 OUR_HANDLE(r->in.handle)));
9033 return WERR_BADFID;
9037 * first check for a keyname of NULL or "". Win2k seems to send
9038 * this a lot and we should send back WERR_INVALID_PARAM
9039 * no need to spend time looking up the printer in this case.
9040 * --jerry
9043 if (!strlen(r->in.key_name)) {
9044 result = WERR_INVALID_PARAM;
9045 goto done;
9048 /* get the printer off of disk */
9050 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9051 return WERR_BADFID;
9054 ZERO_STRUCT(printer);
9055 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9056 if (!W_ERROR_IS_OK(result)) {
9057 return result;
9060 /* now look for a match on the key name */
9062 p_data = printer->info_2->data;
9064 key_index = lookup_printerkey(p_data, r->in.key_name);
9065 if (key_index == -1) {
9066 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9067 r->in.key_name));
9068 result = WERR_INVALID_PARAM;
9069 goto done;
9072 /* allocate the memory for the array of pointers -- if necessary */
9074 count = regval_ctr_numvals(p_data->keys[key_index].values);
9075 if (!count) {
9076 result = WERR_OK; /* ??? */
9077 goto done;
9080 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9081 struct spoolss_PrinterEnumValues,
9082 count);
9083 if (!info) {
9084 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9085 result = WERR_NOMEM;
9086 goto done;
9090 * loop through all params and build the array to pass
9091 * back to the client
9094 for (i=0; i < count; i++) {
9096 struct regval_blob *val;
9098 /* lookup the registry value */
9100 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9102 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9104 /* copy the data */
9106 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9107 if (!W_ERROR_IS_OK(result)) {
9108 goto done;
9112 #if 0 /* FIXME - gd */
9113 /* housekeeping information in the reply */
9115 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9116 * the hand marshalled container size is a multiple
9117 * of 4 bytes for RPC alignment.
9120 if (needed % 4) {
9121 needed += 4-(needed % 4);
9123 #endif
9124 *r->out.count = count;
9125 *r->out.info = info;
9127 done:
9129 if (printer) {
9130 free_a_printer(&printer, 2);
9133 if (!W_ERROR_IS_OK(result)) {
9134 return result;
9137 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9138 spoolss_EnumPrinterDataEx,
9139 *r->out.info,
9140 *r->out.count);
9141 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9142 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9144 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9147 /****************************************************************************
9148 ****************************************************************************/
9150 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9151 const char *servername,
9152 const char *environment,
9153 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9155 WERROR werr;
9156 char *path = NULL;
9158 werr = compose_spoolss_server_path(mem_ctx,
9159 servername,
9160 environment,
9161 SPOOLSS_PRTPROCS_PATH,
9162 &path);
9163 if (!W_ERROR_IS_OK(werr)) {
9164 return werr;
9167 DEBUG(4,("print processor directory: [%s]\n", path));
9169 r->directory_name = path;
9171 return WERR_OK;
9174 /****************************************************************
9175 _spoolss_GetPrintProcessorDirectory
9176 ****************************************************************/
9178 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9179 struct spoolss_GetPrintProcessorDirectory *r)
9181 WERROR result;
9183 /* that's an [in out] buffer */
9185 if (!r->in.buffer && (r->in.offered != 0)) {
9186 return WERR_INVALID_PARAM;
9189 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9190 r->in.level));
9192 *r->out.needed = 0;
9194 /* r->in.level is ignored */
9196 /* We always should reply with a local print processor directory so that
9197 * users are not forced to have a [prnproc$] share on the Samba spoolss
9198 * server - Guenther */
9200 result = getprintprocessordirectory_level_1(p->mem_ctx,
9201 NULL, /* r->in.server */
9202 r->in.environment,
9203 &r->out.info->info1);
9204 if (!W_ERROR_IS_OK(result)) {
9205 TALLOC_FREE(r->out.info);
9206 return result;
9209 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9210 r->out.info, r->in.level);
9211 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9213 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9216 /*******************************************************************
9217 ********************************************************************/
9219 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9220 const char *dllname)
9222 enum ndr_err_code ndr_err;
9223 struct spoolss_MonitorUi ui;
9225 ui.dll_name = dllname;
9227 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9228 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9229 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9230 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9232 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9235 /*******************************************************************
9236 Streams the monitor UI DLL name in UNICODE
9237 *******************************************************************/
9239 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9240 NT_USER_TOKEN *token, DATA_BLOB *in,
9241 DATA_BLOB *out, uint32_t *needed)
9243 const char *dllname = "tcpmonui.dll";
9245 *needed = (strlen(dllname)+1) * 2;
9247 if (out->length < *needed) {
9248 return WERR_INSUFFICIENT_BUFFER;
9251 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9252 return WERR_NOMEM;
9255 return WERR_OK;
9258 /*******************************************************************
9259 ********************************************************************/
9261 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9262 struct spoolss_PortData1 *port1,
9263 const DATA_BLOB *buf)
9265 enum ndr_err_code ndr_err;
9266 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9267 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9268 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9269 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9271 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9274 /*******************************************************************
9275 ********************************************************************/
9277 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9278 struct spoolss_PortData2 *port2,
9279 const DATA_BLOB *buf)
9281 enum ndr_err_code ndr_err;
9282 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9283 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9284 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9285 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9287 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9290 /*******************************************************************
9291 Create a new TCP/IP port
9292 *******************************************************************/
9294 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9295 NT_USER_TOKEN *token, DATA_BLOB *in,
9296 DATA_BLOB *out, uint32_t *needed)
9298 struct spoolss_PortData1 port1;
9299 struct spoolss_PortData2 port2;
9300 char *device_uri = NULL;
9301 uint32_t version;
9303 const char *portname;
9304 const char *hostaddress;
9305 const char *queue;
9306 uint32_t port_number;
9307 uint32_t protocol;
9309 /* peek for spoolss_PortData version */
9311 if (!in || (in->length < (128 + 4))) {
9312 return WERR_GENERAL_FAILURE;
9315 version = IVAL(in->data, 128);
9317 switch (version) {
9318 case 1:
9319 ZERO_STRUCT(port1);
9321 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9322 return WERR_NOMEM;
9325 portname = port1.portname;
9326 hostaddress = port1.hostaddress;
9327 queue = port1.queue;
9328 protocol = port1.protocol;
9329 port_number = port1.port_number;
9331 break;
9332 case 2:
9333 ZERO_STRUCT(port2);
9335 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9336 return WERR_NOMEM;
9339 portname = port2.portname;
9340 hostaddress = port2.hostaddress;
9341 queue = port2.queue;
9342 protocol = port2.protocol;
9343 port_number = port2.port_number;
9345 break;
9346 default:
9347 DEBUG(1,("xcvtcp_addport: "
9348 "unknown version of port_data: %d\n", version));
9349 return WERR_UNKNOWN_PORT;
9352 /* create the device URI and call the add_port_hook() */
9354 switch (protocol) {
9355 case PROTOCOL_RAWTCP_TYPE:
9356 device_uri = talloc_asprintf(mem_ctx,
9357 "socket://%s:%d/", hostaddress,
9358 port_number);
9359 break;
9361 case PROTOCOL_LPR_TYPE:
9362 device_uri = talloc_asprintf(mem_ctx,
9363 "lpr://%s/%s", hostaddress, queue );
9364 break;
9366 default:
9367 return WERR_UNKNOWN_PORT;
9370 if (!device_uri) {
9371 return WERR_NOMEM;
9374 return add_port_hook(mem_ctx, token, portname, device_uri);
9377 /*******************************************************************
9378 *******************************************************************/
9380 struct xcv_api_table xcvtcp_cmds[] = {
9381 { "MonitorUI", xcvtcp_monitorui },
9382 { "AddPort", xcvtcp_addport},
9383 { NULL, NULL }
9386 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9387 NT_USER_TOKEN *token, const char *command,
9388 DATA_BLOB *inbuf,
9389 DATA_BLOB *outbuf,
9390 uint32_t *needed )
9392 int i;
9394 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9396 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9397 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9398 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9401 return WERR_BADFUNC;
9404 /*******************************************************************
9405 *******************************************************************/
9406 #if 0 /* don't support management using the "Local Port" monitor */
9408 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9409 NT_USER_TOKEN *token, DATA_BLOB *in,
9410 DATA_BLOB *out, uint32_t *needed)
9412 const char *dllname = "localui.dll";
9414 *needed = (strlen(dllname)+1) * 2;
9416 if (out->length < *needed) {
9417 return WERR_INSUFFICIENT_BUFFER;
9420 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9421 return WERR_NOMEM;
9424 return WERR_OK;
9427 /*******************************************************************
9428 *******************************************************************/
9430 struct xcv_api_table xcvlocal_cmds[] = {
9431 { "MonitorUI", xcvlocal_monitorui },
9432 { NULL, NULL }
9434 #else
9435 struct xcv_api_table xcvlocal_cmds[] = {
9436 { NULL, NULL }
9438 #endif
9442 /*******************************************************************
9443 *******************************************************************/
9445 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9446 NT_USER_TOKEN *token, const char *command,
9447 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9448 uint32_t *needed)
9450 int i;
9452 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9454 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9455 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9456 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9458 return WERR_BADFUNC;
9461 /****************************************************************
9462 _spoolss_XcvData
9463 ****************************************************************/
9465 WERROR _spoolss_XcvData(pipes_struct *p,
9466 struct spoolss_XcvData *r)
9468 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9469 DATA_BLOB out_data = data_blob_null;
9470 WERROR werror;
9472 if (!Printer) {
9473 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9474 OUR_HANDLE(r->in.handle)));
9475 return WERR_BADFID;
9478 /* Has to be a handle to the TCP/IP port monitor */
9480 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9481 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9482 return WERR_BADFID;
9485 /* requires administrative access to the server */
9487 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9488 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9489 return WERR_ACCESS_DENIED;
9492 /* Allocate the outgoing buffer */
9494 if (r->in.out_data_size) {
9495 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9496 if (out_data.data == NULL) {
9497 return WERR_NOMEM;
9501 switch ( Printer->printer_type ) {
9502 case SPLHND_PORTMON_TCP:
9503 werror = process_xcvtcp_command(p->mem_ctx,
9504 p->server_info->ptok,
9505 r->in.function_name,
9506 &r->in.in_data, &out_data,
9507 r->out.needed);
9508 break;
9509 case SPLHND_PORTMON_LOCAL:
9510 werror = process_xcvlocal_command(p->mem_ctx,
9511 p->server_info->ptok,
9512 r->in.function_name,
9513 &r->in.in_data, &out_data,
9514 r->out.needed);
9515 break;
9516 default:
9517 werror = WERR_INVALID_PRINT_MONITOR;
9520 if (!W_ERROR_IS_OK(werror)) {
9521 return werror;
9524 *r->out.status_code = 0;
9526 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9527 memcpy(r->out.out_data, out_data.data,
9528 MIN(r->in.out_data_size, out_data.length));
9531 return WERR_OK;
9534 /****************************************************************
9535 _spoolss_AddPrintProcessor
9536 ****************************************************************/
9538 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9539 struct spoolss_AddPrintProcessor *r)
9541 /* for now, just indicate success and ignore the add. We'll
9542 automatically set the winprint processor for printer
9543 entries later. Used to debug the LexMark Optra S 1855 PCL
9544 driver --jerry */
9546 return WERR_OK;
9549 /****************************************************************
9550 _spoolss_AddPort
9551 ****************************************************************/
9553 WERROR _spoolss_AddPort(pipes_struct *p,
9554 struct spoolss_AddPort *r)
9556 /* do what w2k3 does */
9558 return WERR_NOT_SUPPORTED;
9561 /****************************************************************
9562 _spoolss_GetPrinterDriver
9563 ****************************************************************/
9565 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9566 struct spoolss_GetPrinterDriver *r)
9568 p->rng_fault_state = true;
9569 return WERR_NOT_SUPPORTED;
9572 /****************************************************************
9573 _spoolss_ReadPrinter
9574 ****************************************************************/
9576 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9577 struct spoolss_ReadPrinter *r)
9579 p->rng_fault_state = true;
9580 return WERR_NOT_SUPPORTED;
9583 /****************************************************************
9584 _spoolss_WaitForPrinterChange
9585 ****************************************************************/
9587 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9588 struct spoolss_WaitForPrinterChange *r)
9590 p->rng_fault_state = true;
9591 return WERR_NOT_SUPPORTED;
9594 /****************************************************************
9595 _spoolss_ConfigurePort
9596 ****************************************************************/
9598 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9599 struct spoolss_ConfigurePort *r)
9601 p->rng_fault_state = true;
9602 return WERR_NOT_SUPPORTED;
9605 /****************************************************************
9606 _spoolss_DeletePort
9607 ****************************************************************/
9609 WERROR _spoolss_DeletePort(pipes_struct *p,
9610 struct spoolss_DeletePort *r)
9612 p->rng_fault_state = true;
9613 return WERR_NOT_SUPPORTED;
9616 /****************************************************************
9617 _spoolss_CreatePrinterIC
9618 ****************************************************************/
9620 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9621 struct spoolss_CreatePrinterIC *r)
9623 p->rng_fault_state = true;
9624 return WERR_NOT_SUPPORTED;
9627 /****************************************************************
9628 _spoolss_PlayGDIScriptOnPrinterIC
9629 ****************************************************************/
9631 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9632 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9634 p->rng_fault_state = true;
9635 return WERR_NOT_SUPPORTED;
9638 /****************************************************************
9639 _spoolss_DeletePrinterIC
9640 ****************************************************************/
9642 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9643 struct spoolss_DeletePrinterIC *r)
9645 p->rng_fault_state = true;
9646 return WERR_NOT_SUPPORTED;
9649 /****************************************************************
9650 _spoolss_AddPrinterConnection
9651 ****************************************************************/
9653 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9654 struct spoolss_AddPrinterConnection *r)
9656 p->rng_fault_state = true;
9657 return WERR_NOT_SUPPORTED;
9660 /****************************************************************
9661 _spoolss_DeletePrinterConnection
9662 ****************************************************************/
9664 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9665 struct spoolss_DeletePrinterConnection *r)
9667 p->rng_fault_state = true;
9668 return WERR_NOT_SUPPORTED;
9671 /****************************************************************
9672 _spoolss_PrinterMessageBox
9673 ****************************************************************/
9675 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9676 struct spoolss_PrinterMessageBox *r)
9678 p->rng_fault_state = true;
9679 return WERR_NOT_SUPPORTED;
9682 /****************************************************************
9683 _spoolss_AddMonitor
9684 ****************************************************************/
9686 WERROR _spoolss_AddMonitor(pipes_struct *p,
9687 struct spoolss_AddMonitor *r)
9689 p->rng_fault_state = true;
9690 return WERR_NOT_SUPPORTED;
9693 /****************************************************************
9694 _spoolss_DeleteMonitor
9695 ****************************************************************/
9697 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9698 struct spoolss_DeleteMonitor *r)
9700 p->rng_fault_state = true;
9701 return WERR_NOT_SUPPORTED;
9704 /****************************************************************
9705 _spoolss_DeletePrintProcessor
9706 ****************************************************************/
9708 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9709 struct spoolss_DeletePrintProcessor *r)
9711 p->rng_fault_state = true;
9712 return WERR_NOT_SUPPORTED;
9715 /****************************************************************
9716 _spoolss_AddPrintProvidor
9717 ****************************************************************/
9719 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9720 struct spoolss_AddPrintProvidor *r)
9722 p->rng_fault_state = true;
9723 return WERR_NOT_SUPPORTED;
9726 /****************************************************************
9727 _spoolss_DeletePrintProvidor
9728 ****************************************************************/
9730 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9731 struct spoolss_DeletePrintProvidor *r)
9733 p->rng_fault_state = true;
9734 return WERR_NOT_SUPPORTED;
9737 /****************************************************************
9738 _spoolss_FindFirstPrinterChangeNotification
9739 ****************************************************************/
9741 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9742 struct spoolss_FindFirstPrinterChangeNotification *r)
9744 p->rng_fault_state = true;
9745 return WERR_NOT_SUPPORTED;
9748 /****************************************************************
9749 _spoolss_FindNextPrinterChangeNotification
9750 ****************************************************************/
9752 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9753 struct spoolss_FindNextPrinterChangeNotification *r)
9755 p->rng_fault_state = true;
9756 return WERR_NOT_SUPPORTED;
9759 /****************************************************************
9760 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9761 ****************************************************************/
9763 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9764 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9766 p->rng_fault_state = true;
9767 return WERR_NOT_SUPPORTED;
9770 /****************************************************************
9771 _spoolss_ReplyOpenPrinter
9772 ****************************************************************/
9774 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9775 struct spoolss_ReplyOpenPrinter *r)
9777 p->rng_fault_state = true;
9778 return WERR_NOT_SUPPORTED;
9781 /****************************************************************
9782 _spoolss_RouterReplyPrinter
9783 ****************************************************************/
9785 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9786 struct spoolss_RouterReplyPrinter *r)
9788 p->rng_fault_state = true;
9789 return WERR_NOT_SUPPORTED;
9792 /****************************************************************
9793 _spoolss_ReplyClosePrinter
9794 ****************************************************************/
9796 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9797 struct spoolss_ReplyClosePrinter *r)
9799 p->rng_fault_state = true;
9800 return WERR_NOT_SUPPORTED;
9803 /****************************************************************
9804 _spoolss_AddPortEx
9805 ****************************************************************/
9807 WERROR _spoolss_AddPortEx(pipes_struct *p,
9808 struct spoolss_AddPortEx *r)
9810 p->rng_fault_state = true;
9811 return WERR_NOT_SUPPORTED;
9814 /****************************************************************
9815 _spoolss_RouterFindFirstPrinterChangeNotification
9816 ****************************************************************/
9818 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9819 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9821 p->rng_fault_state = true;
9822 return WERR_NOT_SUPPORTED;
9825 /****************************************************************
9826 _spoolss_SpoolerInit
9827 ****************************************************************/
9829 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9830 struct spoolss_SpoolerInit *r)
9832 p->rng_fault_state = true;
9833 return WERR_NOT_SUPPORTED;
9836 /****************************************************************
9837 _spoolss_ResetPrinterEx
9838 ****************************************************************/
9840 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9841 struct spoolss_ResetPrinterEx *r)
9843 p->rng_fault_state = true;
9844 return WERR_NOT_SUPPORTED;
9847 /****************************************************************
9848 _spoolss_RouterReplyPrinterEx
9849 ****************************************************************/
9851 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9852 struct spoolss_RouterReplyPrinterEx *r)
9854 p->rng_fault_state = true;
9855 return WERR_NOT_SUPPORTED;
9858 /****************************************************************
9859 _spoolss_44
9860 ****************************************************************/
9862 WERROR _spoolss_44(pipes_struct *p,
9863 struct spoolss_44 *r)
9865 p->rng_fault_state = true;
9866 return WERR_NOT_SUPPORTED;
9869 /****************************************************************
9870 _spoolss_47
9871 ****************************************************************/
9873 WERROR _spoolss_47(pipes_struct *p,
9874 struct spoolss_47 *r)
9876 p->rng_fault_state = true;
9877 return WERR_NOT_SUPPORTED;
9880 /****************************************************************
9881 _spoolss_4a
9882 ****************************************************************/
9884 WERROR _spoolss_4a(pipes_struct *p,
9885 struct spoolss_4a *r)
9887 p->rng_fault_state = true;
9888 return WERR_NOT_SUPPORTED;
9891 /****************************************************************
9892 _spoolss_4b
9893 ****************************************************************/
9895 WERROR _spoolss_4b(pipes_struct *p,
9896 struct spoolss_4b *r)
9898 p->rng_fault_state = true;
9899 return WERR_NOT_SUPPORTED;
9902 /****************************************************************
9903 _spoolss_4c
9904 ****************************************************************/
9906 WERROR _spoolss_4c(pipes_struct *p,
9907 struct spoolss_4c *r)
9909 p->rng_fault_state = true;
9910 return WERR_NOT_SUPPORTED;
9913 /****************************************************************
9914 _spoolss_53
9915 ****************************************************************/
9917 WERROR _spoolss_53(pipes_struct *p,
9918 struct spoolss_53 *r)
9920 p->rng_fault_state = true;
9921 return WERR_NOT_SUPPORTED;
9924 /****************************************************************
9925 _spoolss_55
9926 ****************************************************************/
9928 WERROR _spoolss_55(pipes_struct *p,
9929 struct spoolss_55 *r)
9931 p->rng_fault_state = true;
9932 return WERR_NOT_SUPPORTED;
9935 /****************************************************************
9936 _spoolss_56
9937 ****************************************************************/
9939 WERROR _spoolss_56(pipes_struct *p,
9940 struct spoolss_56 *r)
9942 p->rng_fault_state = true;
9943 return WERR_NOT_SUPPORTED;
9946 /****************************************************************
9947 _spoolss_57
9948 ****************************************************************/
9950 WERROR _spoolss_57(pipes_struct *p,
9951 struct spoolss_57 *r)
9953 p->rng_fault_state = true;
9954 return WERR_NOT_SUPPORTED;
9957 /****************************************************************
9958 _spoolss_5a
9959 ****************************************************************/
9961 WERROR _spoolss_5a(pipes_struct *p,
9962 struct spoolss_5a *r)
9964 p->rng_fault_state = true;
9965 return WERR_NOT_SUPPORTED;
9968 /****************************************************************
9969 _spoolss_5b
9970 ****************************************************************/
9972 WERROR _spoolss_5b(pipes_struct *p,
9973 struct spoolss_5b *r)
9975 p->rng_fault_state = true;
9976 return WERR_NOT_SUPPORTED;
9979 /****************************************************************
9980 _spoolss_5c
9981 ****************************************************************/
9983 WERROR _spoolss_5c(pipes_struct *p,
9984 struct spoolss_5c *r)
9986 p->rng_fault_state = true;
9987 return WERR_NOT_SUPPORTED;
9990 /****************************************************************
9991 _spoolss_5d
9992 ****************************************************************/
9994 WERROR _spoolss_5d(pipes_struct *p,
9995 struct spoolss_5d *r)
9997 p->rng_fault_state = true;
9998 return WERR_NOT_SUPPORTED;
10001 /****************************************************************
10002 _spoolss_5e
10003 ****************************************************************/
10005 WERROR _spoolss_5e(pipes_struct *p,
10006 struct spoolss_5e *r)
10008 p->rng_fault_state = true;
10009 return WERR_NOT_SUPPORTED;
10012 /****************************************************************
10013 _spoolss_5f
10014 ****************************************************************/
10016 WERROR _spoolss_5f(pipes_struct *p,
10017 struct spoolss_5f *r)
10019 p->rng_fault_state = true;
10020 return WERR_NOT_SUPPORTED;
10023 /****************************************************************
10024 _spoolss_60
10025 ****************************************************************/
10027 WERROR _spoolss_60(pipes_struct *p,
10028 struct spoolss_60 *r)
10030 p->rng_fault_state = true;
10031 return WERR_NOT_SUPPORTED;
10034 /****************************************************************
10035 _spoolss_61
10036 ****************************************************************/
10038 WERROR _spoolss_61(pipes_struct *p,
10039 struct spoolss_61 *r)
10041 p->rng_fault_state = true;
10042 return WERR_NOT_SUPPORTED;
10045 /****************************************************************
10046 _spoolss_62
10047 ****************************************************************/
10049 WERROR _spoolss_62(pipes_struct *p,
10050 struct spoolss_62 *r)
10052 p->rng_fault_state = true;
10053 return WERR_NOT_SUPPORTED;
10056 /****************************************************************
10057 _spoolss_63
10058 ****************************************************************/
10060 WERROR _spoolss_63(pipes_struct *p,
10061 struct spoolss_63 *r)
10063 p->rng_fault_state = true;
10064 return WERR_NOT_SUPPORTED;
10067 /****************************************************************
10068 _spoolss_64
10069 ****************************************************************/
10071 WERROR _spoolss_64(pipes_struct *p,
10072 struct spoolss_64 *r)
10074 p->rng_fault_state = true;
10075 return WERR_NOT_SUPPORTED;
10078 /****************************************************************
10079 _spoolss_65
10080 ****************************************************************/
10082 WERROR _spoolss_65(pipes_struct *p,
10083 struct spoolss_65 *r)
10085 p->rng_fault_state = true;
10086 return WERR_NOT_SUPPORTED;
10089 /****************************************************************
10090 _spoolss_GetCorePrinterDrivers
10091 ****************************************************************/
10093 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10094 struct spoolss_GetCorePrinterDrivers *r)
10096 p->rng_fault_state = true;
10097 return WERR_NOT_SUPPORTED;
10100 /****************************************************************
10101 _spoolss_67
10102 ****************************************************************/
10104 WERROR _spoolss_67(pipes_struct *p,
10105 struct spoolss_67 *r)
10107 p->rng_fault_state = true;
10108 return WERR_NOT_SUPPORTED;
10111 /****************************************************************
10112 _spoolss_GetPrinterDriverPackagePath
10113 ****************************************************************/
10115 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10116 struct spoolss_GetPrinterDriverPackagePath *r)
10118 p->rng_fault_state = true;
10119 return WERR_NOT_SUPPORTED;
10122 /****************************************************************
10123 _spoolss_69
10124 ****************************************************************/
10126 WERROR _spoolss_69(pipes_struct *p,
10127 struct spoolss_69 *r)
10129 p->rng_fault_state = true;
10130 return WERR_NOT_SUPPORTED;
10133 /****************************************************************
10134 _spoolss_6a
10135 ****************************************************************/
10137 WERROR _spoolss_6a(pipes_struct *p,
10138 struct spoolss_6a *r)
10140 p->rng_fault_state = true;
10141 return WERR_NOT_SUPPORTED;
10144 /****************************************************************
10145 _spoolss_6b
10146 ****************************************************************/
10148 WERROR _spoolss_6b(pipes_struct *p,
10149 struct spoolss_6b *r)
10151 p->rng_fault_state = true;
10152 return WERR_NOT_SUPPORTED;
10155 /****************************************************************
10156 _spoolss_6c
10157 ****************************************************************/
10159 WERROR _spoolss_6c(pipes_struct *p,
10160 struct spoolss_6c *r)
10162 p->rng_fault_state = true;
10163 return WERR_NOT_SUPPORTED;
10166 /****************************************************************
10167 _spoolss_6d
10168 ****************************************************************/
10170 WERROR _spoolss_6d(pipes_struct *p,
10171 struct spoolss_6d *r)
10173 p->rng_fault_state = true;
10174 return WERR_NOT_SUPPORTED;