s3-spoolss: add registry_value_to_printer_enum_value.
[Samba.git] / source3 / rpc_server / srv_spoolss_nt.c
blob97223c90ff290e461a5d54cfdd2a929ab02dbfa7
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 /* macros stolen from s4 spoolss server */
31 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
32 ((info)?ndr_size_##fn(info, level, ic, 0):0)
34 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
35 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
37 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
38 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
40 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
43 extern userdom_struct current_user_info;
45 #undef DBGC_CLASS
46 #define DBGC_CLASS DBGC_RPC_SRV
48 #ifndef MAX_OPEN_PRINTER_EXS
49 #define MAX_OPEN_PRINTER_EXS 50
50 #endif
52 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
53 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
55 struct table_node {
56 const char *long_archi;
57 const char *short_archi;
58 int version;
61 static Printer_entry *printers_list;
63 typedef struct _counter_printer_0 {
64 struct _counter_printer_0 *next;
65 struct _counter_printer_0 *prev;
67 int snum;
68 uint32 counter;
69 } counter_printer_0;
71 static counter_printer_0 *counter_list;
73 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
74 static uint32 smb_connections=0;
77 /* in printing/nt_printing.c */
79 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
81 /* API table for Xcv Monitor functions */
83 struct xcv_api_table {
84 const char *name;
85 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
88 /********************************************************************
89 * Canonicalize servername.
90 ********************************************************************/
92 static const char *canon_servername(const char *servername)
94 const char *pservername = servername;
95 while (*pservername == '\\') {
96 pservername++;
98 return pservername;
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v)
104 switch (v) {
105 case LPQ_QUEUED:
106 return 0;
107 case LPQ_PAUSED:
108 return JOB_STATUS_PAUSED;
109 case LPQ_SPOOLING:
110 return JOB_STATUS_SPOOLING;
111 case LPQ_PRINTING:
112 return JOB_STATUS_PRINTING;
113 case LPQ_ERROR:
114 return JOB_STATUS_ERROR;
115 case LPQ_DELETING:
116 return JOB_STATUS_DELETING;
117 case LPQ_OFFLINE:
118 return JOB_STATUS_OFFLINE;
119 case LPQ_PAPEROUT:
120 return JOB_STATUS_PAPEROUT;
121 case LPQ_PRINTED:
122 return JOB_STATUS_PRINTED;
123 case LPQ_DELETED:
124 return JOB_STATUS_DELETED;
125 case LPQ_BLOCKED:
126 return JOB_STATUS_BLOCKED_DEVQ;
127 case LPQ_USER_INTERVENTION:
128 return JOB_STATUS_USER_INTERVENTION;
130 return 0;
133 static int nt_printq_status(int v)
135 switch (v) {
136 case LPQ_PAUSED:
137 return PRINTER_STATUS_PAUSED;
138 case LPQ_QUEUED:
139 case LPQ_SPOOLING:
140 case LPQ_PRINTING:
141 return 0;
143 return 0;
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
152 WERROR result;
153 NTSTATUS status;
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 return;
169 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
170 handle,
171 &result);
172 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 win_errstr(result)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2, NULL);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
191 smb_connections--;
194 /****************************************************************************
195 Functions to free a printer entry datastruct.
196 ****************************************************************************/
198 static int printer_entry_destructor(Printer_entry *Printer)
200 if (Printer->notify.client_connected==True) {
201 int snum = -1;
203 if ( Printer->printer_type == SPLHND_SERVER) {
204 snum = -1;
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == SPLHND_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
208 if (snum != -1)
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 TALLOC_FREE(Printer->notify.option);
219 Printer->notify.client_connected=False;
221 free_nt_devicemode( &Printer->nt_devmode );
222 free_a_printer( &Printer->printer_info, 2 );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
226 return 0;
229 /****************************************************************************
230 find printer index by handle
231 ****************************************************************************/
233 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *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, POLICY_HND *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", OUR_HANDLE(hnd)));
255 return False;
258 close_policy_hnd(p, hnd);
260 return True;
263 /****************************************************************************
264 Delete a printer given a handle.
265 ****************************************************************************/
267 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
269 char *cmd = lp_deleteprinter_cmd();
270 char *command = NULL;
271 int ret;
272 SE_PRIV se_printop = SE_PRINT_OPERATOR;
273 bool is_print_op = False;
275 /* can't fail if we don't try */
277 if ( !*cmd )
278 return WERR_OK;
280 command = talloc_asprintf(ctx,
281 "%s \"%s\"",
282 cmd, sharename);
283 if (!command) {
284 return WERR_NOMEM;
286 if ( token )
287 is_print_op = user_has_privileges( token, &se_printop );
289 DEBUG(10,("Running [%s]\n", command));
291 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
293 if ( is_print_op )
294 become_root();
296 if ( (ret = smbrun(command, NULL)) == 0 ) {
297 /* Tell everyone we updated smb.conf. */
298 message_send_all(smbd_messaging_context(),
299 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
302 if ( is_print_op )
303 unbecome_root();
305 /********** END SePrintOperatorPrivlege BLOCK **********/
307 DEBUGADD(10,("returned [%d]\n", ret));
309 TALLOC_FREE(command);
311 if (ret != 0)
312 return WERR_BADFID; /* What to return here? */
314 /* go ahead and re-read the services immediately */
315 reload_services( False );
317 if ( lp_servicenumber( sharename ) < 0 )
318 return WERR_ACCESS_DENIED;
320 return WERR_OK;
323 /****************************************************************************
324 Delete a printer given a handle.
325 ****************************************************************************/
327 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
329 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331 if (!Printer) {
332 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
333 return WERR_BADFID;
337 * It turns out that Windows allows delete printer on a handle
338 * opened by an admin user, then used on a pipe handle created
339 * by an anonymous user..... but they're working on security.... riiight !
340 * JRA.
343 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
344 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
345 return WERR_ACCESS_DENIED;
348 /* this does not need a become root since the access check has been
349 done on the handle already */
351 if (del_a_printer( Printer->sharename ) != 0) {
352 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
353 return WERR_BADFID;
356 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
357 Printer->sharename );
360 /****************************************************************************
361 Return the snum of a printer corresponding to an handle.
362 ****************************************************************************/
364 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
365 struct share_params **params)
367 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
369 if (!Printer) {
370 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
371 return False;
374 switch (Printer->printer_type) {
375 case SPLHND_PRINTER:
376 DEBUG(4,("short name:%s\n", Printer->sharename));
377 *number = print_queue_snum(Printer->sharename);
378 return (*number != -1);
379 case SPLHND_SERVER:
380 return False;
381 default:
382 return False;
386 /****************************************************************************
387 Set printer handle type.
388 Check if it's \\server or \\server\printer
389 ****************************************************************************/
391 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
393 DEBUG(3,("Setting printer type=%s\n", handlename));
395 if ( strlen(handlename) < 3 ) {
396 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
397 return False;
400 /* it's a print server */
401 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
402 DEBUGADD(4,("Printer is a print server\n"));
403 Printer->printer_type = SPLHND_SERVER;
405 /* it's a printer (set_printer_hnd_name() will handle port monitors */
406 else {
407 DEBUGADD(4,("Printer is a printer\n"));
408 Printer->printer_type = SPLHND_PRINTER;
411 return True;
414 /****************************************************************************
415 Set printer handle name.. Accept names like \\server, \\server\printer,
416 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
417 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
418 XcvDataPort() interface.
419 ****************************************************************************/
421 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
423 int snum;
424 int n_services=lp_numservices();
425 char *aprinter, *printername;
426 const char *servername;
427 fstring sname;
428 bool found=False;
429 NT_PRINTER_INFO_LEVEL *printer = NULL;
430 WERROR result;
432 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
434 aprinter = handlename;
435 if ( *handlename == '\\' ) {
436 servername = canon_servername(handlename);
437 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
438 *aprinter = '\0';
439 aprinter++;
441 } else {
442 servername = "";
445 /* save the servername to fill in replies on this handle */
447 if ( !is_myname_or_ipaddr( servername ) )
448 return False;
450 fstrcpy( Printer->servername, servername );
452 if ( Printer->printer_type == SPLHND_SERVER )
453 return True;
455 if ( Printer->printer_type != SPLHND_PRINTER )
456 return False;
458 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
460 /* check for the Port Monitor Interface */
462 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
463 Printer->printer_type = SPLHND_PORTMON_TCP;
464 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
465 found = True;
467 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
468 Printer->printer_type = SPLHND_PORTMON_LOCAL;
469 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
470 found = True;
473 /* Search all sharenames first as this is easier than pulling
474 the printer_info_2 off of disk. Don't use find_service() since
475 that calls out to map_username() */
477 /* do another loop to look for printernames */
479 for (snum=0; !found && snum<n_services; snum++) {
481 /* no point going on if this is not a printer */
483 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
484 continue;
486 fstrcpy(sname, lp_servicename(snum));
487 if ( strequal( aprinter, sname ) ) {
488 found = True;
489 break;
492 /* no point looking up the printer object if
493 we aren't allowing printername != sharename */
495 if ( lp_force_printername(snum) )
496 continue;
498 fstrcpy(sname, lp_servicename(snum));
500 printer = NULL;
502 /* This call doesn't fill in the location or comment from
503 * a CUPS server for efficiency with large numbers of printers.
504 * JRA.
507 result = get_a_printer_search( NULL, &printer, 2, sname );
508 if ( !W_ERROR_IS_OK(result) ) {
509 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
510 sname, win_errstr(result)));
511 continue;
514 /* printername is always returned as \\server\printername */
515 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
516 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
517 printer->info_2->printername));
518 free_a_printer( &printer, 2);
519 continue;
522 printername++;
524 if ( strequal(printername, aprinter) ) {
525 free_a_printer( &printer, 2);
526 found = True;
527 break;
530 DEBUGADD(10, ("printername: %s\n", printername));
532 free_a_printer( &printer, 2);
535 free_a_printer( &printer, 2);
537 if ( !found ) {
538 DEBUGADD(4,("Printer not found\n"));
539 return False;
542 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
544 fstrcpy(Printer->sharename, sname);
546 return True;
549 /****************************************************************************
550 Find first available printer slot. creates a printer handle for you.
551 ****************************************************************************/
553 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
555 Printer_entry *new_printer;
557 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
559 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
560 if (new_printer == NULL) {
561 return false;
563 talloc_set_destructor(new_printer, printer_entry_destructor);
565 if (!create_policy_hnd(p, hnd, new_printer)) {
566 TALLOC_FREE(new_printer);
567 return False;
570 /* Add to the internal list. */
571 DLIST_ADD(printers_list, new_printer);
573 new_printer->notify.option=NULL;
575 if (!set_printer_hnd_printertype(new_printer, name)) {
576 close_printer_handle(p, hnd);
577 return False;
580 if (!set_printer_hnd_name(new_printer, name)) {
581 close_printer_handle(p, hnd);
582 return False;
585 new_printer->access_granted = access_granted;
587 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
589 return True;
592 /***************************************************************************
593 check to see if the client motify handle is monitoring the notification
594 given by (notify_type, notify_field).
595 **************************************************************************/
597 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
598 uint16 notify_field)
600 return True;
603 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
604 uint16 notify_field)
606 struct spoolss_NotifyOption *option = p->notify.option;
607 uint32 i, j;
610 * Flags should always be zero when the change notify
611 * is registered by the client's spooler. A user Win32 app
612 * might use the flags though instead of the NOTIFY_OPTION_INFO
613 * --jerry
616 if (!option) {
617 return False;
620 if (p->notify.flags)
621 return is_monitoring_event_flags(
622 p->notify.flags, notify_type, notify_field);
624 for (i = 0; i < option->count; i++) {
626 /* Check match for notify_type */
628 if (option->types[i].type != notify_type)
629 continue;
631 /* Check match for field */
633 for (j = 0; j < option->types[i].count; j++) {
634 if (option->types[i].fields[j] == notify_field) {
635 return True;
640 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
641 p->servername, p->sharename, notify_type, notify_field));
643 return False;
646 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
647 _data->data.integer[0] = _integer; \
648 _data->data.integer[1] = 0;
651 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
652 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
653 if (!_data->data.string.string) {\
654 _data->data.string.size = 0; \
656 _data->data.string.size = strlen_m_term(_p) * 2;
658 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
659 _data->data.devmode.devmode = _devmode;
661 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
662 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
663 if (!_data->data.sd.sd) { \
664 _data->data.sd.sd_size = 0; \
666 _data->data.sd.sd_size = _size;
668 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
669 struct tm *t,
670 const char **pp,
671 uint32_t *plen)
673 struct spoolss_Time st;
674 uint32_t len = 16;
675 char *p;
677 if (!init_systemtime(&st, t)) {
678 return;
681 p = talloc_array(mem_ctx, char, len);
682 if (!p) {
683 return;
687 * Systemtime must be linearized as a set of UINT16's.
688 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
691 SSVAL(p, 0, st.year);
692 SSVAL(p, 2, st.month);
693 SSVAL(p, 4, st.day_of_week);
694 SSVAL(p, 6, st.day);
695 SSVAL(p, 8, st.hour);
696 SSVAL(p, 10, st.minute);
697 SSVAL(p, 12, st.second);
698 SSVAL(p, 14, st.millisecond);
700 *pp = p;
701 *plen = len;
704 /* Convert a notification message to a struct spoolss_Notify */
706 static void notify_one_value(struct spoolss_notify_msg *msg,
707 struct spoolss_Notify *data,
708 TALLOC_CTX *mem_ctx)
710 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
713 static void notify_string(struct spoolss_notify_msg *msg,
714 struct spoolss_Notify *data,
715 TALLOC_CTX *mem_ctx)
717 /* The length of the message includes the trailing \0 */
719 data->data.string.size = msg->len * 2;
720 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
721 if (!data->data.string.string) {
722 data->data.string.size = 0;
723 return;
727 static void notify_system_time(struct spoolss_notify_msg *msg,
728 struct spoolss_Notify *data,
729 TALLOC_CTX *mem_ctx)
731 data->data.string.string = NULL;
732 data->data.string.size = 0;
734 if (msg->len != sizeof(time_t)) {
735 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
736 msg->len));
737 return;
740 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
741 &data->data.string.string,
742 &data->data.string.size);
745 struct notify2_message_table {
746 const char *name;
747 void (*fn)(struct spoolss_notify_msg *msg,
748 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
751 static struct notify2_message_table printer_notify_table[] = {
752 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
753 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
754 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
755 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
756 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
757 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
758 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
759 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
760 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
761 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
762 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
763 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
764 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
765 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
766 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
767 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
768 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
769 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
770 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
773 static struct notify2_message_table job_notify_table[] = {
774 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
775 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
776 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
777 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
778 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
779 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
780 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
781 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
782 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
783 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
784 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
785 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
786 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
787 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
788 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
789 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
790 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
791 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
792 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
793 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
794 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
795 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
796 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
797 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
801 /***********************************************************************
802 Allocate talloc context for container object
803 **********************************************************************/
805 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
807 if ( !ctr )
808 return;
810 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
812 return;
815 /***********************************************************************
816 release all allocated memory and zero out structure
817 **********************************************************************/
819 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
821 if ( !ctr )
822 return;
824 if ( ctr->ctx )
825 talloc_destroy(ctr->ctx);
827 ZERO_STRUCTP(ctr);
829 return;
832 /***********************************************************************
833 **********************************************************************/
835 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
837 if ( !ctr )
838 return NULL;
840 return ctr->ctx;
843 /***********************************************************************
844 **********************************************************************/
846 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
848 if ( !ctr || !ctr->msg_groups )
849 return NULL;
851 if ( idx >= ctr->num_groups )
852 return NULL;
854 return &ctr->msg_groups[idx];
858 /***********************************************************************
859 How many groups of change messages do we have ?
860 **********************************************************************/
862 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
864 if ( !ctr )
865 return 0;
867 return ctr->num_groups;
870 /***********************************************************************
871 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
872 **********************************************************************/
874 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
876 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
877 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
878 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
879 int i, new_slot;
881 if ( !ctr || !msg )
882 return 0;
884 /* loop over all groups looking for a matching printer name */
886 for ( i=0; i<ctr->num_groups; i++ ) {
887 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
888 break;
891 /* add a new group? */
893 if ( i == ctr->num_groups ) {
894 ctr->num_groups++;
896 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
897 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
898 return 0;
900 ctr->msg_groups = groups;
902 /* clear the new entry and set the printer name */
904 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
905 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
908 /* add the change messages; 'i' is the correct index now regardless */
910 msg_grp = &ctr->msg_groups[i];
912 msg_grp->num_msgs++;
914 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
915 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
916 return 0;
918 msg_grp->msgs = msg_list;
920 new_slot = msg_grp->num_msgs-1;
921 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
923 /* need to allocate own copy of data */
925 if ( msg->len != 0 )
926 msg_grp->msgs[new_slot].notify.data = (char *)
927 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
929 return ctr->num_groups;
932 /***********************************************************************
933 Send a change notication message on all handles which have a call
934 back registered
935 **********************************************************************/
937 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
939 Printer_entry *p;
940 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
941 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
942 SPOOLSS_NOTIFY_MSG *messages;
943 int sending_msg_count;
945 if ( !msg_group ) {
946 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
947 return;
950 messages = msg_group->msgs;
952 if ( !messages ) {
953 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
954 return;
957 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
959 /* loop over all printers */
961 for (p = printers_list; p; p = p->next) {
962 struct spoolss_Notify *notifies;
963 uint32_t count = 0;
964 uint32_t id;
965 int i;
967 /* Is there notification on this handle? */
969 if ( !p->notify.client_connected )
970 continue;
972 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
974 /* For this printer? Print servers always receive
975 notifications. */
977 if ( ( p->printer_type == SPLHND_PRINTER ) &&
978 ( !strequal(msg_group->printername, p->sharename) ) )
979 continue;
981 DEBUG(10,("Our printer\n"));
983 /* allocate the max entries possible */
985 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
986 if (!notifies) {
987 return;
990 /* build the array of change notifications */
992 sending_msg_count = 0;
994 for ( i=0; i<msg_group->num_msgs; i++ ) {
995 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
997 /* Are we monitoring this event? */
999 if (!is_monitoring_event(p, msg->type, msg->field))
1000 continue;
1002 sending_msg_count++;
1005 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1006 msg->type, msg->field, p->sharename));
1009 * if the is a printer notification handle and not a job notification
1010 * type, then set the id to 0. Other wise just use what was specified
1011 * in the message.
1013 * When registering change notification on a print server handle
1014 * we always need to send back the id (snum) matching the printer
1015 * for which the change took place. For change notify registered
1016 * on a printer handle, this does not matter and the id should be 0.
1018 * --jerry
1021 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1022 id = 0;
1023 else
1024 id = msg->id;
1027 /* Convert unix jobid to smb jobid */
1029 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1030 id = sysjob_to_jobid(msg->id);
1032 if (id == -1) {
1033 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1034 goto done;
1038 construct_info_data( &notifies[count], msg->type, msg->field, id );
1040 switch(msg->type) {
1041 case PRINTER_NOTIFY_TYPE:
1042 if ( printer_notify_table[msg->field].fn )
1043 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1044 break;
1046 case JOB_NOTIFY_TYPE:
1047 if ( job_notify_table[msg->field].fn )
1048 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1049 break;
1051 default:
1052 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1053 goto done;
1056 count++;
1059 if ( sending_msg_count ) {
1060 NTSTATUS status;
1061 WERROR werr;
1062 union spoolss_ReplyPrinterInfo info;
1063 struct spoolss_NotifyInfo info0;
1064 uint32_t reply_result;
1066 info0.version = 0x2;
1067 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1068 info0.count = count;
1069 info0.notifies = notifies;
1071 info.info0 = &info0;
1073 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1074 &p->notify.client_hnd,
1075 p->notify.change, /* color */
1076 p->notify.flags,
1077 &reply_result,
1078 0, /* reply_type, must be 0 */
1079 info,
1080 &werr);
1081 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1082 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1083 notify_cli_pipe->srv_name_slash,
1084 win_errstr(werr)));
1086 switch (reply_result) {
1087 case 0:
1088 break;
1089 case PRINTER_NOTIFY_INFO_DISCARDED:
1090 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1091 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1092 break;
1093 default:
1094 break;
1099 done:
1100 DEBUG(8,("send_notify2_changes: Exit...\n"));
1101 return;
1104 /***********************************************************************
1105 **********************************************************************/
1107 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1110 uint32 tv_sec, tv_usec;
1111 size_t offset = 0;
1113 /* Unpack message */
1115 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1116 msg->printer);
1118 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1119 &tv_sec, &tv_usec,
1120 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1122 if (msg->len == 0)
1123 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1124 &msg->notify.value[0], &msg->notify.value[1]);
1125 else
1126 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1127 &msg->len, &msg->notify.data);
1129 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1130 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1132 tv->tv_sec = tv_sec;
1133 tv->tv_usec = tv_usec;
1135 if (msg->len == 0)
1136 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1137 msg->notify.value[1]));
1138 else
1139 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1141 return True;
1144 /********************************************************************
1145 Receive a notify2 message list
1146 ********************************************************************/
1148 static void receive_notify2_message_list(struct messaging_context *msg,
1149 void *private_data,
1150 uint32_t msg_type,
1151 struct server_id server_id,
1152 DATA_BLOB *data)
1154 size_t msg_count, i;
1155 char *buf = (char *)data->data;
1156 char *msg_ptr;
1157 size_t msg_len;
1158 SPOOLSS_NOTIFY_MSG notify;
1159 SPOOLSS_NOTIFY_MSG_CTR messages;
1160 int num_groups;
1162 if (data->length < 4) {
1163 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1164 return;
1167 msg_count = IVAL(buf, 0);
1168 msg_ptr = buf + 4;
1170 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1172 if (msg_count == 0) {
1173 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1174 return;
1177 /* initialize the container */
1179 ZERO_STRUCT( messages );
1180 notify_msg_ctr_init( &messages );
1183 * build message groups for each printer identified
1184 * in a change_notify msg. Remember that a PCN message
1185 * includes the handle returned for the srv_spoolss_replyopenprinter()
1186 * call. Therefore messages are grouped according to printer handle.
1189 for ( i=0; i<msg_count; i++ ) {
1190 struct timeval msg_tv;
1192 if (msg_ptr + 4 - buf > data->length) {
1193 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1194 return;
1197 msg_len = IVAL(msg_ptr,0);
1198 msg_ptr += 4;
1200 if (msg_ptr + msg_len - buf > data->length) {
1201 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1202 return;
1205 /* unpack messages */
1207 ZERO_STRUCT( notify );
1208 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1209 msg_ptr += msg_len;
1211 /* add to correct list in container */
1213 notify_msg_ctr_addmsg( &messages, &notify );
1215 /* free memory that might have been allocated by notify2_unpack_msg() */
1217 if ( notify.len != 0 )
1218 SAFE_FREE( notify.notify.data );
1221 /* process each group of messages */
1223 num_groups = notify_msg_ctr_numgroups( &messages );
1224 for ( i=0; i<num_groups; i++ )
1225 send_notify2_changes( &messages, i );
1228 /* cleanup */
1230 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1232 notify_msg_ctr_destroy( &messages );
1234 return;
1237 /********************************************************************
1238 Send a message to ourself about new driver being installed
1239 so we can upgrade the information for each printer bound to this
1240 driver
1241 ********************************************************************/
1243 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1245 int len = strlen(drivername);
1247 if (!len)
1248 return False;
1250 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1251 drivername));
1253 messaging_send_buf(smbd_messaging_context(), procid_self(),
1254 MSG_PRINTER_DRVUPGRADE,
1255 (uint8 *)drivername, len+1);
1257 return True;
1260 /**********************************************************************
1261 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1262 over all printers, upgrading ones as necessary
1263 **********************************************************************/
1265 void do_drv_upgrade_printer(struct messaging_context *msg,
1266 void *private_data,
1267 uint32_t msg_type,
1268 struct server_id server_id,
1269 DATA_BLOB *data)
1271 fstring drivername;
1272 int snum;
1273 int n_services = lp_numservices();
1274 size_t len;
1276 len = MIN(data->length,sizeof(drivername)-1);
1277 strncpy(drivername, (const char *)data->data, len);
1279 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1281 /* Iterate the printer list */
1283 for (snum=0; snum<n_services; snum++)
1285 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1287 WERROR result;
1288 NT_PRINTER_INFO_LEVEL *printer = NULL;
1290 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1291 if (!W_ERROR_IS_OK(result))
1292 continue;
1294 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1296 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1298 /* all we care about currently is the change_id */
1300 result = mod_a_printer(printer, 2);
1301 if (!W_ERROR_IS_OK(result)) {
1302 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1303 win_errstr(result)));
1307 free_a_printer(&printer, 2);
1311 /* all done */
1314 /********************************************************************
1315 Update the cache for all printq's with a registered client
1316 connection
1317 ********************************************************************/
1319 void update_monitored_printq_cache( void )
1321 Printer_entry *printer = printers_list;
1322 int snum;
1324 /* loop through all printers and update the cache where
1325 client_connected == True */
1326 while ( printer )
1328 if ( (printer->printer_type == SPLHND_PRINTER)
1329 && printer->notify.client_connected )
1331 snum = print_queue_snum(printer->sharename);
1332 print_queue_status( snum, NULL, NULL );
1335 printer = printer->next;
1338 return;
1340 /********************************************************************
1341 Send a message to ourself about new driver being installed
1342 so we can upgrade the information for each printer bound to this
1343 driver
1344 ********************************************************************/
1346 static bool srv_spoolss_reset_printerdata(char* drivername)
1348 int len = strlen(drivername);
1350 if (!len)
1351 return False;
1353 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1354 drivername));
1356 messaging_send_buf(smbd_messaging_context(), procid_self(),
1357 MSG_PRINTERDATA_INIT_RESET,
1358 (uint8 *)drivername, len+1);
1360 return True;
1363 /**********************************************************************
1364 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1365 over all printers, resetting printer data as neessary
1366 **********************************************************************/
1368 void reset_all_printerdata(struct messaging_context *msg,
1369 void *private_data,
1370 uint32_t msg_type,
1371 struct server_id server_id,
1372 DATA_BLOB *data)
1374 fstring drivername;
1375 int snum;
1376 int n_services = lp_numservices();
1377 size_t len;
1379 len = MIN( data->length, sizeof(drivername)-1 );
1380 strncpy( drivername, (const char *)data->data, len );
1382 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1384 /* Iterate the printer list */
1386 for ( snum=0; snum<n_services; snum++ )
1388 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1390 WERROR result;
1391 NT_PRINTER_INFO_LEVEL *printer = NULL;
1393 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1394 if ( !W_ERROR_IS_OK(result) )
1395 continue;
1398 * if the printer is bound to the driver,
1399 * then reset to the new driver initdata
1402 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1404 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1406 if ( !set_driver_init(printer, 2) ) {
1407 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1408 printer->info_2->printername, printer->info_2->drivername));
1411 result = mod_a_printer( printer, 2 );
1412 if ( !W_ERROR_IS_OK(result) ) {
1413 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1414 get_dos_error_msg(result)));
1418 free_a_printer( &printer, 2 );
1422 /* all done */
1424 return;
1427 /****************************************************************
1428 _spoolss_OpenPrinter
1429 ****************************************************************/
1431 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1432 struct spoolss_OpenPrinter *r)
1434 struct spoolss_OpenPrinterEx e;
1435 WERROR werr;
1437 ZERO_STRUCT(e.in.userlevel);
1439 e.in.printername = r->in.printername;
1440 e.in.datatype = r->in.datatype;
1441 e.in.devmode_ctr = r->in.devmode_ctr;
1442 e.in.access_mask = r->in.access_mask;
1443 e.in.level = 0;
1445 e.out.handle = r->out.handle;
1447 werr = _spoolss_OpenPrinterEx(p, &e);
1449 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1450 /* OpenPrinterEx returns this for a bad
1451 * printer name. We must return WERR_INVALID_PRINTER_NAME
1452 * instead.
1454 werr = WERR_INVALID_PRINTER_NAME;
1457 return werr;
1460 /********************************************************************
1461 ********************************************************************/
1463 bool convert_devicemode(const char *printername,
1464 const struct spoolss_DeviceMode *devmode,
1465 NT_DEVICEMODE **pp_nt_devmode)
1467 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1470 * Ensure nt_devmode is a valid pointer
1471 * as we will be overwriting it.
1474 if (nt_devmode == NULL) {
1475 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1476 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1477 return false;
1480 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1481 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1483 nt_devmode->specversion = devmode->specversion;
1484 nt_devmode->driverversion = devmode->driverversion;
1485 nt_devmode->size = devmode->size;
1486 nt_devmode->fields = devmode->fields;
1487 nt_devmode->orientation = devmode->orientation;
1488 nt_devmode->papersize = devmode->papersize;
1489 nt_devmode->paperlength = devmode->paperlength;
1490 nt_devmode->paperwidth = devmode->paperwidth;
1491 nt_devmode->scale = devmode->scale;
1492 nt_devmode->copies = devmode->copies;
1493 nt_devmode->defaultsource = devmode->defaultsource;
1494 nt_devmode->printquality = devmode->printquality;
1495 nt_devmode->color = devmode->color;
1496 nt_devmode->duplex = devmode->duplex;
1497 nt_devmode->yresolution = devmode->yresolution;
1498 nt_devmode->ttoption = devmode->ttoption;
1499 nt_devmode->collate = devmode->collate;
1501 nt_devmode->logpixels = devmode->logpixels;
1502 nt_devmode->bitsperpel = devmode->bitsperpel;
1503 nt_devmode->pelswidth = devmode->pelswidth;
1504 nt_devmode->pelsheight = devmode->pelsheight;
1505 nt_devmode->displayflags = devmode->displayflags;
1506 nt_devmode->displayfrequency = devmode->displayfrequency;
1507 nt_devmode->icmmethod = devmode->icmmethod;
1508 nt_devmode->icmintent = devmode->icmintent;
1509 nt_devmode->mediatype = devmode->mediatype;
1510 nt_devmode->dithertype = devmode->dithertype;
1511 nt_devmode->reserved1 = devmode->reserved1;
1512 nt_devmode->reserved2 = devmode->reserved2;
1513 nt_devmode->panningwidth = devmode->panningwidth;
1514 nt_devmode->panningheight = devmode->panningheight;
1517 * Only change private and driverextra if the incoming devmode
1518 * has a new one. JRA.
1521 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1522 SAFE_FREE(nt_devmode->nt_dev_private);
1523 nt_devmode->driverextra = devmode->__driverextra_length;
1524 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1525 return false;
1526 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1529 *pp_nt_devmode = nt_devmode;
1531 return true;
1534 /****************************************************************
1535 _spoolss_OpenPrinterEx
1536 ****************************************************************/
1538 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1539 struct spoolss_OpenPrinterEx *r)
1541 POLICY_HND *handle = r->out.handle;
1542 char *name = CONST_DISCARD(char *, r->in.printername);
1543 int snum;
1544 Printer_entry *Printer=NULL;
1546 if (!name) {
1547 return WERR_INVALID_PARAM;
1550 /* some sanity check because you can open a printer or a print server */
1551 /* aka: \\server\printer or \\server */
1553 DEBUGADD(3,("checking name: %s\n",name));
1555 if (!open_printer_hnd(p, handle, name, 0)) {
1556 ZERO_STRUCTP(r->out.handle);
1557 return WERR_INVALID_PARAM;
1560 Printer=find_printer_index_by_hnd(p, handle);
1561 if ( !Printer ) {
1562 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1563 "handle we created for printer %s\n", name ));
1564 close_printer_handle(p,handle);
1565 ZERO_STRUCTP(r->out.handle);
1566 return WERR_INVALID_PARAM;
1570 * First case: the user is opening the print server:
1572 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1573 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1575 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1576 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1577 * or if the user is listed in the smb.conf printer admin parameter.
1579 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1580 * client view printer folder, but does not show the MSAPW.
1582 * Note: this test needs code to check access rights here too. Jeremy
1583 * could you look at this?
1585 * Second case: the user is opening a printer:
1586 * NT doesn't let us connect to a printer if the connecting user
1587 * doesn't have print permission.
1589 * Third case: user is opening a Port Monitor
1590 * access checks same as opening a handle to the print server.
1593 switch (Printer->printer_type )
1595 case SPLHND_SERVER:
1596 case SPLHND_PORTMON_TCP:
1597 case SPLHND_PORTMON_LOCAL:
1598 /* Printserver handles use global struct... */
1600 snum = -1;
1602 /* Map standard access rights to object specific access rights */
1604 se_map_standard(&r->in.access_mask,
1605 &printserver_std_mapping);
1607 /* Deny any object specific bits that don't apply to print
1608 servers (i.e printer and job specific bits) */
1610 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1612 if (r->in.access_mask &
1613 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1614 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1615 close_printer_handle(p, handle);
1616 ZERO_STRUCTP(r->out.handle);
1617 return WERR_ACCESS_DENIED;
1620 /* Allow admin access */
1622 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1624 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1626 if (!lp_ms_add_printer_wizard()) {
1627 close_printer_handle(p, handle);
1628 ZERO_STRUCTP(r->out.handle);
1629 return WERR_ACCESS_DENIED;
1632 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1633 and not a printer admin, then fail */
1635 if ((p->server_info->utok.uid != 0) &&
1636 !user_has_privileges(p->server_info->ptok,
1637 &se_printop ) &&
1638 !token_contains_name_in_list(
1639 uidtoname(p->server_info->utok.uid),
1640 NULL, NULL,
1641 p->server_info->ptok,
1642 lp_printer_admin(snum))) {
1643 close_printer_handle(p, handle);
1644 ZERO_STRUCTP(r->out.handle);
1645 return WERR_ACCESS_DENIED;
1648 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1650 else
1652 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1655 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1656 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1658 /* We fall through to return WERR_OK */
1659 break;
1661 case SPLHND_PRINTER:
1662 /* NT doesn't let us connect to a printer if the connecting user
1663 doesn't have print permission. */
1665 if (!get_printer_snum(p, handle, &snum, NULL)) {
1666 close_printer_handle(p, handle);
1667 ZERO_STRUCTP(r->out.handle);
1668 return WERR_BADFID;
1671 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1673 /* map an empty access mask to the minimum access mask */
1674 if (r->in.access_mask == 0x0)
1675 r->in.access_mask = PRINTER_ACCESS_USE;
1678 * If we are not serving the printer driver for this printer,
1679 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1680 * will keep NT clients happy --jerry
1683 if (lp_use_client_driver(snum)
1684 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1686 r->in.access_mask = PRINTER_ACCESS_USE;
1689 /* check smb.conf parameters and the the sec_desc */
1691 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1692 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1693 ZERO_STRUCTP(r->out.handle);
1694 return WERR_ACCESS_DENIED;
1697 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1698 p->server_info->ptok, snum) ||
1699 !print_access_check(p->server_info, snum,
1700 r->in.access_mask)) {
1701 DEBUG(3, ("access DENIED for printer open\n"));
1702 close_printer_handle(p, handle);
1703 ZERO_STRUCTP(r->out.handle);
1704 return WERR_ACCESS_DENIED;
1707 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1708 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1709 close_printer_handle(p, handle);
1710 ZERO_STRUCTP(r->out.handle);
1711 return WERR_ACCESS_DENIED;
1714 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1715 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1716 else
1717 r->in.access_mask = PRINTER_ACCESS_USE;
1719 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1720 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1722 break;
1724 default:
1725 /* sanity check to prevent programmer error */
1726 ZERO_STRUCTP(r->out.handle);
1727 return WERR_BADFID;
1730 Printer->access_granted = r->in.access_mask;
1733 * If the client sent a devmode in the OpenPrinter() call, then
1734 * save it here in case we get a job submission on this handle
1737 if ((Printer->printer_type != SPLHND_SERVER) &&
1738 r->in.devmode_ctr.devmode) {
1739 convert_devicemode(Printer->sharename,
1740 r->in.devmode_ctr.devmode,
1741 &Printer->nt_devmode);
1744 #if 0 /* JERRY -- I'm doubtful this is really effective */
1745 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1746 optimization in Windows 2000 clients --jerry */
1748 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1749 && (RA_WIN2K == get_remote_arch()) )
1751 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1752 sys_usleep( 500000 );
1754 #endif
1756 return WERR_OK;
1759 /****************************************************************************
1760 ****************************************************************************/
1762 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1763 NT_PRINTER_INFO_LEVEL_2 *d)
1765 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1767 if (!r || !d) {
1768 return false;
1771 d->attributes = r->attributes;
1772 d->priority = r->priority;
1773 d->default_priority = r->defaultpriority;
1774 d->starttime = r->starttime;
1775 d->untiltime = r->untiltime;
1776 d->status = r->status;
1777 d->cjobs = r->cjobs;
1779 fstrcpy(d->servername, r->servername);
1780 fstrcpy(d->printername, r->printername);
1781 fstrcpy(d->sharename, r->sharename);
1782 fstrcpy(d->portname, r->portname);
1783 fstrcpy(d->drivername, r->drivername);
1784 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1785 fstrcpy(d->location, r->location);
1786 fstrcpy(d->sepfile, r->sepfile);
1787 fstrcpy(d->printprocessor, r->printprocessor);
1788 fstrcpy(d->datatype, r->datatype);
1789 fstrcpy(d->parameters, r->parameters);
1791 return true;
1794 /****************************************************************************
1795 ****************************************************************************/
1797 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1798 NT_PRINTER_INFO_LEVEL *printer)
1800 bool ret;
1802 switch (info_ctr->level) {
1803 case 2:
1804 /* allocate memory if needed. Messy because
1805 convert_printer_info is used to update an existing
1806 printer or build a new one */
1808 if (!printer->info_2) {
1809 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1810 if (!printer->info_2) {
1811 DEBUG(0,("convert_printer_info: "
1812 "talloc() failed!\n"));
1813 return false;
1817 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1818 printer->info_2);
1819 printer->info_2->setuptime = time(NULL);
1820 return ret;
1823 return false;
1826 /*******************************************************************
1827 ********************************************************************/
1829 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1831 int i;
1833 if (!sarray) {
1834 *farray = NULL;
1835 return true;
1838 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1839 if (!*farray) {
1840 return false;
1843 for (i=0; sarray[i] != NULL; i++) {
1844 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1845 if (!*farray) {
1846 return false;
1848 fstrcpy((*farray)[i], sarray[i]);
1851 fstrcpy((*farray)[i], "");
1853 return true;
1856 /*******************************************************************
1857 ********************************************************************/
1859 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1860 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1862 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1864 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1866 if (*p == NULL) {
1867 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1868 if (*p == NULL) {
1869 return false;
1871 ZERO_STRUCTP(*p);
1874 d = *p;
1876 d->cversion = r->version;
1878 fstrcpy(d->name, r->driver_name);
1879 fstrcpy(d->environment, r->architecture);
1880 fstrcpy(d->driverpath, r->driver_path);
1881 fstrcpy(d->datafile, r->data_file);
1882 fstrcpy(d->configfile, r->config_file);
1883 fstrcpy(d->helpfile, r->help_file);
1884 fstrcpy(d->monitorname, r->monitor_name);
1885 fstrcpy(d->defaultdatatype, r->default_datatype);
1887 DEBUGADD(8,( "version: %d\n", d->cversion));
1888 DEBUGADD(8,( "name: %s\n", d->name));
1889 DEBUGADD(8,( "environment: %s\n", d->environment));
1890 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1891 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1892 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1893 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1894 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1895 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1897 if (r->dependent_files) {
1898 if (!string_array_to_fstring_array(r->dependent_files->string,
1899 &d->dependentfiles)) {
1900 SAFE_FREE(*p);
1901 return false;
1905 return true;
1908 /*******************************************************************
1909 ********************************************************************/
1911 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1912 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1914 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1916 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1918 if (*p == NULL) {
1919 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1920 if (*p == NULL) {
1921 return false;
1923 ZERO_STRUCTP(*p);
1926 d = *p;
1928 d->version = r->version;
1930 fstrcpy(d->name, r->driver_name);
1931 fstrcpy(d->environment, r->architecture);
1932 fstrcpy(d->driverpath, r->driver_path);
1933 fstrcpy(d->datafile, r->data_file);
1934 fstrcpy(d->configfile, r->config_file);
1935 fstrcpy(d->helpfile, r->help_file);
1936 fstrcpy(d->monitorname, r->monitor_name);
1937 fstrcpy(d->defaultdatatype, r->default_datatype);
1939 DEBUGADD(8,( "version: %d\n", d->version));
1940 DEBUGADD(8,( "name: %s\n", d->name));
1941 DEBUGADD(8,( "environment: %s\n", d->environment));
1942 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1943 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1944 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1945 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1946 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1947 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1949 if (r->dependent_files) {
1950 if (!string_array_to_fstring_array(r->dependent_files->string,
1951 &d->dependentfiles)) {
1952 goto error;
1956 if (r->previous_names) {
1957 if (!string_array_to_fstring_array(r->previous_names->string,
1958 &d->previousnames)) {
1959 goto error;
1963 return true;
1965 error:
1966 SAFE_FREE(*p);
1967 return false;
1970 /********************************************************************
1971 ********************************************************************/
1973 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1974 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1975 uint32_t level)
1977 switch (level) {
1978 case 3:
1979 printer->info_3 = NULL;
1980 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1981 return false;
1983 break;
1984 case 6:
1985 printer->info_6 = NULL;
1986 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1987 return false;
1989 break;
1990 default:
1991 return false;
1994 return true;
1997 /********************************************************************
1998 * _spoolss_enddocprinter_internal.
1999 ********************************************************************/
2001 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2003 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2004 int snum;
2006 if (!Printer) {
2007 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2008 return WERR_BADFID;
2011 if (!get_printer_snum(p, handle, &snum, NULL))
2012 return WERR_BADFID;
2014 Printer->document_started=False;
2015 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2016 /* error codes unhandled so far ... */
2018 return WERR_OK;
2021 /****************************************************************
2022 _spoolss_ClosePrinter
2023 ****************************************************************/
2025 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2026 struct spoolss_ClosePrinter *r)
2028 POLICY_HND *handle = r->in.handle;
2030 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2032 if (Printer && Printer->document_started)
2033 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
2035 if (!close_printer_handle(p, handle))
2036 return WERR_BADFID;
2038 /* clear the returned printer handle. Observed behavior
2039 from Win2k server. Don't think this really matters.
2040 Previous code just copied the value of the closed
2041 handle. --jerry */
2043 ZERO_STRUCTP(r->out.handle);
2045 return WERR_OK;
2048 /****************************************************************
2049 _spoolss_DeletePrinter
2050 ****************************************************************/
2052 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2053 struct spoolss_DeletePrinter *r)
2055 POLICY_HND *handle = r->in.handle;
2056 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2057 WERROR result;
2059 if (Printer && Printer->document_started)
2060 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
2062 result = delete_printer_handle(p, handle);
2064 update_c_setprinter(False);
2066 return result;
2069 /*******************************************************************
2070 * static function to lookup the version id corresponding to an
2071 * long architecture string
2072 ******************************************************************/
2074 static int get_version_id (char * arch)
2076 int i;
2077 struct table_node archi_table[]= {
2079 {"Windows 4.0", "WIN40", 0 },
2080 {"Windows NT x86", "W32X86", 2 },
2081 {"Windows NT R4000", "W32MIPS", 2 },
2082 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2083 {"Windows NT PowerPC", "W32PPC", 2 },
2084 {"Windows IA64", "IA64", 3 },
2085 {"Windows x64", "x64", 3 },
2086 {NULL, "", -1 }
2089 for (i=0; archi_table[i].long_archi != NULL; i++)
2091 if (strcmp(arch, archi_table[i].long_archi) == 0)
2092 return (archi_table[i].version);
2095 return -1;
2098 /****************************************************************
2099 _spoolss_DeletePrinterDriver
2100 ****************************************************************/
2102 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2103 struct spoolss_DeletePrinterDriver *r)
2105 char *driver;
2106 char *arch;
2107 NT_PRINTER_DRIVER_INFO_LEVEL info;
2108 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2109 int version;
2110 WERROR status;
2111 WERROR status_win2k = WERR_ACCESS_DENIED;
2112 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2114 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2115 and not a printer admin, then fail */
2117 if ( (p->server_info->utok.uid != 0)
2118 && !user_has_privileges(p->server_info->ptok, &se_printop )
2119 && !token_contains_name_in_list(
2120 uidtoname(p->server_info->utok.uid), NULL,
2121 NULL, p->server_info->ptok,
2122 lp_printer_admin(-1)) )
2124 return WERR_ACCESS_DENIED;
2127 driver = CONST_DISCARD(char *, r->in.driver);
2128 arch = CONST_DISCARD(char *, r->in.architecture);
2130 /* check that we have a valid driver name first */
2132 if ((version=get_version_id(arch)) == -1)
2133 return WERR_INVALID_ENVIRONMENT;
2135 ZERO_STRUCT(info);
2136 ZERO_STRUCT(info_win2k);
2138 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2140 /* try for Win2k driver if "Windows NT x86" */
2142 if ( version == 2 ) {
2143 version = 3;
2144 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2145 status = WERR_UNKNOWN_PRINTER_DRIVER;
2146 goto done;
2149 /* otherwise it was a failure */
2150 else {
2151 status = WERR_UNKNOWN_PRINTER_DRIVER;
2152 goto done;
2157 if (printer_driver_in_use(info.info_3)) {
2158 status = WERR_PRINTER_DRIVER_IN_USE;
2159 goto done;
2162 if ( version == 2 )
2164 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2166 /* if we get to here, we now have 2 driver info structures to remove */
2167 /* remove the Win2k driver first*/
2169 status_win2k = delete_printer_driver(
2170 p, info_win2k.info_3, 3, False );
2171 free_a_printer_driver( info_win2k, 3 );
2173 /* this should not have failed---if it did, report to client */
2174 if ( !W_ERROR_IS_OK(status_win2k) )
2176 status = status_win2k;
2177 goto done;
2182 status = delete_printer_driver(p, info.info_3, version, False);
2184 /* if at least one of the deletes succeeded return OK */
2186 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2187 status = WERR_OK;
2189 done:
2190 free_a_printer_driver( info, 3 );
2192 return status;
2195 /****************************************************************
2196 _spoolss_DeletePrinterDriverEx
2197 ****************************************************************/
2199 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2200 struct spoolss_DeletePrinterDriverEx *r)
2202 char *driver;
2203 char *arch;
2204 NT_PRINTER_DRIVER_INFO_LEVEL info;
2205 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2206 int version;
2207 uint32_t flags = r->in.delete_flags;
2208 bool delete_files;
2209 WERROR status;
2210 WERROR status_win2k = WERR_ACCESS_DENIED;
2211 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2213 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2214 and not a printer admin, then fail */
2216 if ( (p->server_info->utok.uid != 0)
2217 && !user_has_privileges(p->server_info->ptok, &se_printop )
2218 && !token_contains_name_in_list(
2219 uidtoname(p->server_info->utok.uid), NULL, NULL,
2220 p->server_info->ptok, lp_printer_admin(-1)) )
2222 return WERR_ACCESS_DENIED;
2225 driver = CONST_DISCARD(char *, r->in.driver);
2226 arch = CONST_DISCARD(char *, r->in.architecture);
2228 /* check that we have a valid driver name first */
2229 if ((version=get_version_id(arch)) == -1) {
2230 /* this is what NT returns */
2231 return WERR_INVALID_ENVIRONMENT;
2234 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2235 version = r->in.version;
2237 ZERO_STRUCT(info);
2238 ZERO_STRUCT(info_win2k);
2240 status = get_a_printer_driver(&info, 3, driver, arch, version);
2242 if ( !W_ERROR_IS_OK(status) )
2245 * if the client asked for a specific version,
2246 * or this is something other than Windows NT x86,
2247 * then we've failed
2250 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2251 goto done;
2253 /* try for Win2k driver if "Windows NT x86" */
2255 version = 3;
2256 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2257 status = WERR_UNKNOWN_PRINTER_DRIVER;
2258 goto done;
2262 if ( printer_driver_in_use(info.info_3) ) {
2263 status = WERR_PRINTER_DRIVER_IN_USE;
2264 goto done;
2268 * we have a couple of cases to consider.
2269 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2270 * then the delete should fail if **any** files overlap with
2271 * other drivers
2272 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2273 * non-overlapping files
2274 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2275 * is set, the do not delete any files
2276 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2279 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2281 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2283 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2284 /* no idea of the correct error here */
2285 status = WERR_ACCESS_DENIED;
2286 goto done;
2290 /* also check for W32X86/3 if necessary; maybe we already have? */
2292 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2293 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2296 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2297 /* no idea of the correct error here */
2298 free_a_printer_driver( info_win2k, 3 );
2299 status = WERR_ACCESS_DENIED;
2300 goto done;
2303 /* if we get to here, we now have 2 driver info structures to remove */
2304 /* remove the Win2k driver first*/
2306 status_win2k = delete_printer_driver(
2307 p, info_win2k.info_3, 3, delete_files);
2308 free_a_printer_driver( info_win2k, 3 );
2310 /* this should not have failed---if it did, report to client */
2312 if ( !W_ERROR_IS_OK(status_win2k) )
2313 goto done;
2317 status = delete_printer_driver(p, info.info_3, version, delete_files);
2319 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2320 status = WERR_OK;
2321 done:
2322 free_a_printer_driver( info, 3 );
2324 return status;
2328 /****************************************************************************
2329 Internal routine for removing printerdata
2330 ***************************************************************************/
2332 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2334 return delete_printer_data( printer->info_2, key, value );
2337 /****************************************************************************
2338 Internal routine for storing printerdata
2339 ***************************************************************************/
2341 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2342 uint32 type, uint8 *data, int real_len )
2344 /* the registry objects enforce uniqueness based on value name */
2346 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2349 /********************************************************************
2350 GetPrinterData on a printer server Handle.
2351 ********************************************************************/
2353 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2354 const char *value,
2355 enum winreg_Type *type,
2356 union spoolss_PrinterData *data)
2358 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2360 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2361 *type = REG_DWORD;
2362 data->value = 0x00;
2363 return WERR_OK;
2366 if (!StrCaseCmp(value, "BeepEnabled")) {
2367 *type = REG_DWORD;
2368 data->value = 0x00;
2369 return WERR_OK;
2372 if (!StrCaseCmp(value, "EventLog")) {
2373 *type = REG_DWORD;
2374 /* formally was 0x1b */
2375 data->value = 0x00;
2376 return WERR_OK;
2379 if (!StrCaseCmp(value, "NetPopup")) {
2380 *type = REG_DWORD;
2381 data->value = 0x00;
2382 return WERR_OK;
2385 if (!StrCaseCmp(value, "MajorVersion")) {
2386 *type = REG_DWORD;
2388 /* Windows NT 4.0 seems to not allow uploading of drivers
2389 to a server that reports 0x3 as the MajorVersion.
2390 need to investigate more how Win2k gets around this .
2391 -- jerry */
2393 if (RA_WINNT == get_remote_arch()) {
2394 data->value = 0x02;
2395 } else {
2396 data->value = 0x03;
2399 return WERR_OK;
2402 if (!StrCaseCmp(value, "MinorVersion")) {
2403 *type = REG_DWORD;
2404 data->value = 0x00;
2405 return WERR_OK;
2408 /* REG_BINARY
2409 * uint32 size = 0x114
2410 * uint32 major = 5
2411 * uint32 minor = [0|1]
2412 * uint32 build = [2195|2600]
2413 * extra unicode string = e.g. "Service Pack 3"
2415 if (!StrCaseCmp(value, "OSVersion")) {
2416 DATA_BLOB blob;
2417 enum ndr_err_code ndr_err;
2418 struct spoolss_OSVersion os;
2420 os.major = 5; /* Windows 2000 == 5.0 */
2421 os.minor = 0;
2422 os.build = 2195; /* build */
2423 os.extra_string = ""; /* leave extra string empty */
2425 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2426 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2427 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2428 return WERR_GENERAL_FAILURE;
2431 *type = REG_BINARY;
2432 data->binary = blob;
2434 return WERR_OK;
2438 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2439 *type = REG_SZ;
2441 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2442 W_ERROR_HAVE_NO_MEMORY(data->string);
2444 return WERR_OK;
2447 if (!StrCaseCmp(value, "Architecture")) {
2448 *type = REG_SZ;
2450 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2451 W_ERROR_HAVE_NO_MEMORY(data->string);
2453 return WERR_OK;
2456 if (!StrCaseCmp(value, "DsPresent")) {
2457 *type = REG_DWORD;
2459 /* only show the publish check box if we are a
2460 member of a AD domain */
2462 if (lp_security() == SEC_ADS) {
2463 data->value = 0x01;
2464 } else {
2465 data->value = 0x00;
2467 return WERR_OK;
2470 if (!StrCaseCmp(value, "DNSMachineName")) {
2471 const char *hostname = get_mydnsfullname();
2473 if (!hostname) {
2474 return WERR_BADFILE;
2477 *type = REG_SZ;
2478 data->string = talloc_strdup(mem_ctx, hostname);
2479 W_ERROR_HAVE_NO_MEMORY(data->string);
2481 return WERR_OK;
2484 return WERR_BADFILE;
2487 /****************************************************************
2488 _spoolss_GetPrinterData
2489 ****************************************************************/
2491 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2492 struct spoolss_GetPrinterData *r)
2494 WERROR result;
2495 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2496 NT_PRINTER_INFO_LEVEL *printer = NULL;
2497 int snum = 0;
2500 * Reminder: when it's a string, the length is in BYTES
2501 * even if UNICODE is negociated.
2503 * JFM, 4/19/1999
2506 /* in case of problem, return some default values */
2508 *r->out.needed = 0;
2509 *r->out.type = 0;
2511 DEBUG(4,("_spoolss_GetPrinterData\n"));
2513 if (!Printer) {
2514 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2515 OUR_HANDLE(r->in.handle)));
2516 result = WERR_BADFID;
2517 goto done;
2520 if (Printer->printer_type == SPLHND_SERVER) {
2521 result = getprinterdata_printer_server(p->mem_ctx,
2522 r->in.value_name,
2523 r->out.type,
2524 r->out.data);
2525 } else {
2526 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2527 result = WERR_BADFID;
2528 goto done;
2531 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2532 if (!W_ERROR_IS_OK(result)) {
2533 goto done;
2536 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2538 if (strequal(r->in.value_name, "ChangeId")) {
2539 *r->out.type = REG_DWORD;
2540 r->out.data->value = printer->info_2->changeid;
2541 result = WERR_OK;
2542 } else {
2543 REGISTRY_VALUE *v;
2544 DATA_BLOB blob;
2546 v = get_printer_data(printer->info_2,
2547 SPOOL_PRINTERDATA_KEY,
2548 r->in.value_name);
2549 if (!v) {
2550 result = WERR_BADFILE;
2551 goto done;
2554 *r->out.type = v->type;
2556 blob = data_blob_const(v->data_p, v->size);
2558 result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2559 r->out.data,
2560 *r->out.type);
2564 done:
2565 /* cleanup & exit */
2567 if (printer) {
2568 free_a_printer(&printer, 2);
2571 if (!W_ERROR_IS_OK(result)) {
2572 return result;
2575 *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2576 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2577 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2579 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2582 /*********************************************************
2583 Connect to the client machine.
2584 **********************************************************/
2586 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2587 struct sockaddr_storage *client_ss, const char *remote_machine)
2589 NTSTATUS ret;
2590 struct cli_state *the_cli;
2591 struct sockaddr_storage rm_addr;
2593 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2594 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2595 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2596 return False;
2599 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2600 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2601 return False;
2603 } else {
2604 char addr[INET6_ADDRSTRLEN];
2605 rm_addr = *client_ss;
2606 print_sockaddr(addr, sizeof(addr), &rm_addr);
2607 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2608 addr));
2611 /* setup the connection */
2613 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2614 &rm_addr, 0, "IPC$", "IPC",
2615 "", /* username */
2616 "", /* domain */
2617 "", /* password */
2618 0, lp_client_signing(), NULL );
2620 if ( !NT_STATUS_IS_OK( ret ) ) {
2621 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2622 remote_machine ));
2623 return False;
2626 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2627 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2628 cli_shutdown(the_cli);
2629 return False;
2633 * Ok - we have an anonymous connection to the IPC$ share.
2634 * Now start the NT Domain stuff :-).
2637 ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2638 if (!NT_STATUS_IS_OK(ret)) {
2639 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2640 remote_machine, nt_errstr(ret)));
2641 cli_shutdown(the_cli);
2642 return False;
2645 return True;
2648 /***************************************************************************
2649 Connect to the client.
2650 ****************************************************************************/
2652 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2653 uint32 localprinter, uint32 type,
2654 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2656 WERROR result;
2657 NTSTATUS status;
2660 * If it's the first connection, contact the client
2661 * and connect to the IPC$ share anonymously
2663 if (smb_connections==0) {
2664 fstring unix_printer;
2666 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2668 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2669 return False;
2671 messaging_register(smbd_messaging_context(), NULL,
2672 MSG_PRINTER_NOTIFY2,
2673 receive_notify2_message_list);
2674 /* Tell the connections db we're now interested in printer
2675 * notify messages. */
2676 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2680 * Tell the specific printing tdb we want messages for this printer
2681 * by registering our PID.
2684 if (!print_notify_register_pid(snum))
2685 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2687 smb_connections++;
2689 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2690 printer,
2691 localprinter,
2692 type,
2694 NULL,
2695 handle,
2696 &result);
2697 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2698 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2699 win_errstr(result)));
2701 return (W_ERROR_IS_OK(result));
2704 /****************************************************************
2705 ****************************************************************/
2707 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2708 const struct spoolss_NotifyOption *r)
2710 struct spoolss_NotifyOption *option;
2711 uint32_t i,k;
2713 if (!r) {
2714 return NULL;
2717 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2718 if (!option) {
2719 return NULL;
2722 *option = *r;
2724 if (!option->count) {
2725 return option;
2728 option->types = talloc_zero_array(option,
2729 struct spoolss_NotifyOptionType, option->count);
2730 if (!option->types) {
2731 talloc_free(option);
2732 return NULL;
2735 for (i=0; i < option->count; i++) {
2736 option->types[i] = r->types[i];
2738 if (option->types[i].count) {
2739 option->types[i].fields = talloc_zero_array(option,
2740 enum spoolss_Field, option->types[i].count);
2741 if (!option->types[i].fields) {
2742 talloc_free(option);
2743 return NULL;
2745 for (k=0; k<option->types[i].count; k++) {
2746 option->types[i].fields[k] =
2747 r->types[i].fields[k];
2752 return option;
2755 /****************************************************************
2756 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2758 * before replying OK: status=0 a rpc call is made to the workstation
2759 * asking ReplyOpenPrinter
2761 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2762 * called from api_spoolss_rffpcnex
2763 ****************************************************************/
2765 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2766 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2768 POLICY_HND *handle = r->in.handle;
2769 int snum = -1;
2770 struct spoolss_NotifyOption *option = r->in.notify_options;
2771 struct sockaddr_storage client_ss;
2773 /* store the notify value in the printer struct */
2775 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2777 if (!Printer) {
2778 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2779 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2780 return WERR_BADFID;
2783 Printer->notify.flags = r->in.flags;
2784 Printer->notify.options = r->in.options;
2785 Printer->notify.printerlocal = r->in.printer_local;
2787 TALLOC_FREE(Printer->notify.option);
2788 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2790 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2792 /* Connect to the client machine and send a ReplyOpenPrinter */
2794 if ( Printer->printer_type == SPLHND_SERVER)
2795 snum = -1;
2796 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2797 !get_printer_snum(p, handle, &snum, NULL) )
2798 return WERR_BADFID;
2800 if (!interpret_string_addr(&client_ss, p->client_address,
2801 AI_NUMERICHOST)) {
2802 return WERR_SERVER_UNAVAILABLE;
2805 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2806 Printer->notify.printerlocal, 1,
2807 &Printer->notify.client_hnd, &client_ss))
2808 return WERR_SERVER_UNAVAILABLE;
2810 Printer->notify.client_connected=True;
2812 return WERR_OK;
2815 /*******************************************************************
2816 * fill a notify_info_data with the servername
2817 ********************************************************************/
2819 void spoolss_notify_server_name(int snum,
2820 struct spoolss_Notify *data,
2821 print_queue_struct *queue,
2822 NT_PRINTER_INFO_LEVEL *printer,
2823 TALLOC_CTX *mem_ctx)
2825 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2828 /*******************************************************************
2829 * fill a notify_info_data with the printername (not including the servername).
2830 ********************************************************************/
2832 void spoolss_notify_printer_name(int snum,
2833 struct spoolss_Notify *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2838 /* the notify name should not contain the \\server\ part */
2839 char *p = strrchr(printer->info_2->printername, '\\');
2841 if (!p) {
2842 p = printer->info_2->printername;
2843 } else {
2844 p++;
2847 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2850 /*******************************************************************
2851 * fill a notify_info_data with the servicename
2852 ********************************************************************/
2854 void spoolss_notify_share_name(int snum,
2855 struct spoolss_Notify *data,
2856 print_queue_struct *queue,
2857 NT_PRINTER_INFO_LEVEL *printer,
2858 TALLOC_CTX *mem_ctx)
2860 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2863 /*******************************************************************
2864 * fill a notify_info_data with the port name
2865 ********************************************************************/
2867 void spoolss_notify_port_name(int snum,
2868 struct spoolss_Notify *data,
2869 print_queue_struct *queue,
2870 NT_PRINTER_INFO_LEVEL *printer,
2871 TALLOC_CTX *mem_ctx)
2873 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2876 /*******************************************************************
2877 * fill a notify_info_data with the printername
2878 * but it doesn't exist, have to see what to do
2879 ********************************************************************/
2881 void spoolss_notify_driver_name(int snum,
2882 struct spoolss_Notify *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2887 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2890 /*******************************************************************
2891 * fill a notify_info_data with the comment
2892 ********************************************************************/
2894 void spoolss_notify_comment(int snum,
2895 struct spoolss_Notify *data,
2896 print_queue_struct *queue,
2897 NT_PRINTER_INFO_LEVEL *printer,
2898 TALLOC_CTX *mem_ctx)
2900 char *p;
2902 if (*printer->info_2->comment == '\0') {
2903 p = lp_comment(snum);
2904 } else {
2905 p = printer->info_2->comment;
2908 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2911 /*******************************************************************
2912 * fill a notify_info_data with the comment
2913 * location = "Room 1, floor 2, building 3"
2914 ********************************************************************/
2916 void spoolss_notify_location(int snum,
2917 struct spoolss_Notify *data,
2918 print_queue_struct *queue,
2919 NT_PRINTER_INFO_LEVEL *printer,
2920 TALLOC_CTX *mem_ctx)
2922 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2925 /*******************************************************************
2926 * fill a notify_info_data with the device mode
2927 * jfm:xxxx don't to it for know but that's a real problem !!!
2928 ********************************************************************/
2930 static void spoolss_notify_devmode(int snum,
2931 struct spoolss_Notify *data,
2932 print_queue_struct *queue,
2933 NT_PRINTER_INFO_LEVEL *printer,
2934 TALLOC_CTX *mem_ctx)
2936 /* for a dummy implementation we have to zero the fields */
2937 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2940 /*******************************************************************
2941 * fill a notify_info_data with the separator file name
2942 ********************************************************************/
2944 void spoolss_notify_sepfile(int snum,
2945 struct spoolss_Notify *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2950 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2953 /*******************************************************************
2954 * fill a notify_info_data with the print processor
2955 * jfm:xxxx return always winprint to indicate we don't do anything to it
2956 ********************************************************************/
2958 void spoolss_notify_print_processor(int snum,
2959 struct spoolss_Notify *data,
2960 print_queue_struct *queue,
2961 NT_PRINTER_INFO_LEVEL *printer,
2962 TALLOC_CTX *mem_ctx)
2964 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2967 /*******************************************************************
2968 * fill a notify_info_data with the print processor options
2969 * jfm:xxxx send an empty string
2970 ********************************************************************/
2972 void spoolss_notify_parameters(int snum,
2973 struct spoolss_Notify *data,
2974 print_queue_struct *queue,
2975 NT_PRINTER_INFO_LEVEL *printer,
2976 TALLOC_CTX *mem_ctx)
2978 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2981 /*******************************************************************
2982 * fill a notify_info_data with the data type
2983 * jfm:xxxx always send RAW as data type
2984 ********************************************************************/
2986 void spoolss_notify_datatype(int snum,
2987 struct spoolss_Notify *data,
2988 print_queue_struct *queue,
2989 NT_PRINTER_INFO_LEVEL *printer,
2990 TALLOC_CTX *mem_ctx)
2992 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2995 /*******************************************************************
2996 * fill a notify_info_data with the security descriptor
2997 * jfm:xxxx send an null pointer to say no security desc
2998 * have to implement security before !
2999 ********************************************************************/
3001 static void spoolss_notify_security_desc(int snum,
3002 struct spoolss_Notify *data,
3003 print_queue_struct *queue,
3004 NT_PRINTER_INFO_LEVEL *printer,
3005 TALLOC_CTX *mem_ctx)
3007 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3008 printer->info_2->secdesc_buf->sd_size,
3009 printer->info_2->secdesc_buf->sd);
3012 /*******************************************************************
3013 * fill a notify_info_data with the attributes
3014 * jfm:xxxx a samba printer is always shared
3015 ********************************************************************/
3017 void spoolss_notify_attributes(int snum,
3018 struct spoolss_Notify *data,
3019 print_queue_struct *queue,
3020 NT_PRINTER_INFO_LEVEL *printer,
3021 TALLOC_CTX *mem_ctx)
3023 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3026 /*******************************************************************
3027 * fill a notify_info_data with the priority
3028 ********************************************************************/
3030 static void spoolss_notify_priority(int snum,
3031 struct spoolss_Notify *data,
3032 print_queue_struct *queue,
3033 NT_PRINTER_INFO_LEVEL *printer,
3034 TALLOC_CTX *mem_ctx)
3036 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3039 /*******************************************************************
3040 * fill a notify_info_data with the default priority
3041 ********************************************************************/
3043 static void spoolss_notify_default_priority(int snum,
3044 struct spoolss_Notify *data,
3045 print_queue_struct *queue,
3046 NT_PRINTER_INFO_LEVEL *printer,
3047 TALLOC_CTX *mem_ctx)
3049 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3052 /*******************************************************************
3053 * fill a notify_info_data with the start time
3054 ********************************************************************/
3056 static void spoolss_notify_start_time(int snum,
3057 struct spoolss_Notify *data,
3058 print_queue_struct *queue,
3059 NT_PRINTER_INFO_LEVEL *printer,
3060 TALLOC_CTX *mem_ctx)
3062 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3065 /*******************************************************************
3066 * fill a notify_info_data with the until time
3067 ********************************************************************/
3069 static void spoolss_notify_until_time(int snum,
3070 struct spoolss_Notify *data,
3071 print_queue_struct *queue,
3072 NT_PRINTER_INFO_LEVEL *printer,
3073 TALLOC_CTX *mem_ctx)
3075 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3078 /*******************************************************************
3079 * fill a notify_info_data with the status
3080 ********************************************************************/
3082 static void spoolss_notify_status(int snum,
3083 struct spoolss_Notify *data,
3084 print_queue_struct *queue,
3085 NT_PRINTER_INFO_LEVEL *printer,
3086 TALLOC_CTX *mem_ctx)
3088 print_status_struct status;
3090 print_queue_length(snum, &status);
3091 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3094 /*******************************************************************
3095 * fill a notify_info_data with the number of jobs queued
3096 ********************************************************************/
3098 void spoolss_notify_cjobs(int snum,
3099 struct spoolss_Notify *data,
3100 print_queue_struct *queue,
3101 NT_PRINTER_INFO_LEVEL *printer,
3102 TALLOC_CTX *mem_ctx)
3104 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3107 /*******************************************************************
3108 * fill a notify_info_data with the average ppm
3109 ********************************************************************/
3111 static void spoolss_notify_average_ppm(int snum,
3112 struct spoolss_Notify *data,
3113 print_queue_struct *queue,
3114 NT_PRINTER_INFO_LEVEL *printer,
3115 TALLOC_CTX *mem_ctx)
3117 /* always respond 8 pages per minutes */
3118 /* a little hard ! */
3119 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3122 /*******************************************************************
3123 * fill a notify_info_data with username
3124 ********************************************************************/
3126 static void spoolss_notify_username(int snum,
3127 struct spoolss_Notify *data,
3128 print_queue_struct *queue,
3129 NT_PRINTER_INFO_LEVEL *printer,
3130 TALLOC_CTX *mem_ctx)
3132 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3135 /*******************************************************************
3136 * fill a notify_info_data with job status
3137 ********************************************************************/
3139 static void spoolss_notify_job_status(int snum,
3140 struct spoolss_Notify *data,
3141 print_queue_struct *queue,
3142 NT_PRINTER_INFO_LEVEL *printer,
3143 TALLOC_CTX *mem_ctx)
3145 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3148 /*******************************************************************
3149 * fill a notify_info_data with job name
3150 ********************************************************************/
3152 static void spoolss_notify_job_name(int snum,
3153 struct spoolss_Notify *data,
3154 print_queue_struct *queue,
3155 NT_PRINTER_INFO_LEVEL *printer,
3156 TALLOC_CTX *mem_ctx)
3158 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3161 /*******************************************************************
3162 * fill a notify_info_data with job status
3163 ********************************************************************/
3165 static void spoolss_notify_job_status_string(int snum,
3166 struct spoolss_Notify *data,
3167 print_queue_struct *queue,
3168 NT_PRINTER_INFO_LEVEL *printer,
3169 TALLOC_CTX *mem_ctx)
3172 * Now we're returning job status codes we just return a "" here. JRA.
3175 const char *p = "";
3177 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3178 p = "unknown";
3180 switch (queue->status) {
3181 case LPQ_QUEUED:
3182 p = "Queued";
3183 break;
3184 case LPQ_PAUSED:
3185 p = ""; /* NT provides the paused string */
3186 break;
3187 case LPQ_SPOOLING:
3188 p = "Spooling";
3189 break;
3190 case LPQ_PRINTING:
3191 p = "Printing";
3192 break;
3194 #endif /* NO LONGER NEEDED. */
3196 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3199 /*******************************************************************
3200 * fill a notify_info_data with job time
3201 ********************************************************************/
3203 static void spoolss_notify_job_time(int snum,
3204 struct spoolss_Notify *data,
3205 print_queue_struct *queue,
3206 NT_PRINTER_INFO_LEVEL *printer,
3207 TALLOC_CTX *mem_ctx)
3209 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3212 /*******************************************************************
3213 * fill a notify_info_data with job size
3214 ********************************************************************/
3216 static void spoolss_notify_job_size(int snum,
3217 struct spoolss_Notify *data,
3218 print_queue_struct *queue,
3219 NT_PRINTER_INFO_LEVEL *printer,
3220 TALLOC_CTX *mem_ctx)
3222 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3225 /*******************************************************************
3226 * fill a notify_info_data with page info
3227 ********************************************************************/
3228 static void spoolss_notify_total_pages(int snum,
3229 struct spoolss_Notify *data,
3230 print_queue_struct *queue,
3231 NT_PRINTER_INFO_LEVEL *printer,
3232 TALLOC_CTX *mem_ctx)
3234 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3237 /*******************************************************************
3238 * fill a notify_info_data with pages printed info.
3239 ********************************************************************/
3240 static void spoolss_notify_pages_printed(int snum,
3241 struct spoolss_Notify *data,
3242 print_queue_struct *queue,
3243 NT_PRINTER_INFO_LEVEL *printer,
3244 TALLOC_CTX *mem_ctx)
3246 /* Add code when back-end tracks this */
3247 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3250 /*******************************************************************
3251 Fill a notify_info_data with job position.
3252 ********************************************************************/
3254 static void spoolss_notify_job_position(int snum,
3255 struct spoolss_Notify *data,
3256 print_queue_struct *queue,
3257 NT_PRINTER_INFO_LEVEL *printer,
3258 TALLOC_CTX *mem_ctx)
3260 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3263 /*******************************************************************
3264 Fill a notify_info_data with submitted time.
3265 ********************************************************************/
3267 static void spoolss_notify_submitted_time(int snum,
3268 struct spoolss_Notify *data,
3269 print_queue_struct *queue,
3270 NT_PRINTER_INFO_LEVEL *printer,
3271 TALLOC_CTX *mem_ctx)
3273 data->data.string.string = NULL;
3274 data->data.string.size = 0;
3276 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3277 &data->data.string.string,
3278 &data->data.string.size);
3282 struct s_notify_info_data_table
3284 enum spoolss_NotifyType type;
3285 enum spoolss_Field field;
3286 const char *name;
3287 enum spoolss_NotifyTable variable_type;
3288 void (*fn) (int snum, struct spoolss_Notify *data,
3289 print_queue_struct *queue,
3290 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3293 /* A table describing the various print notification constants and
3294 whether the notification data is a pointer to a variable sized
3295 buffer, a one value uint32 or a two value uint32. */
3297 static const struct s_notify_info_data_table notify_info_data_table[] =
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3350 /*******************************************************************
3351 Return the variable_type of info_data structure.
3352 ********************************************************************/
3354 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3355 enum spoolss_Field field)
3357 int i=0;
3359 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3360 if ( (notify_info_data_table[i].type == type) &&
3361 (notify_info_data_table[i].field == field) ) {
3362 return notify_info_data_table[i].variable_type;
3366 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3368 return 0;
3371 /****************************************************************************
3372 ****************************************************************************/
3374 static bool search_notify(enum spoolss_NotifyType type,
3375 enum spoolss_Field field,
3376 int *value)
3378 int i;
3380 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3381 if (notify_info_data_table[i].type == type &&
3382 notify_info_data_table[i].field == field &&
3383 notify_info_data_table[i].fn != NULL) {
3384 *value = i;
3385 return True;
3389 return False;
3392 /****************************************************************************
3393 ****************************************************************************/
3395 void construct_info_data(struct spoolss_Notify *info_data,
3396 enum spoolss_NotifyType type,
3397 enum spoolss_Field field,
3398 int id)
3400 info_data->type = type;
3401 info_data->field = field;
3402 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3403 info_data->job_id = id;
3406 /*******************************************************************
3408 * fill a notify_info struct with info asked
3410 ********************************************************************/
3412 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3413 struct spoolss_NotifyInfo *info,
3414 int snum,
3415 const struct spoolss_NotifyOptionType *option_type,
3416 uint32_t id,
3417 TALLOC_CTX *mem_ctx)
3419 int field_num,j;
3420 enum spoolss_NotifyType type;
3421 enum spoolss_Field field;
3423 struct spoolss_Notify *current_data;
3424 NT_PRINTER_INFO_LEVEL *printer = NULL;
3425 print_queue_struct *queue=NULL;
3427 type = option_type->type;
3429 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3430 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3431 option_type->count, lp_servicename(snum)));
3433 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3434 return False;
3436 for(field_num=0; field_num < option_type->count; field_num++) {
3437 field = option_type->fields[field_num];
3439 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3441 if (!search_notify(type, field, &j) )
3442 continue;
3444 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3445 struct spoolss_Notify,
3446 info->count + 1);
3447 if (info->notifies == NULL) {
3448 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3449 free_a_printer(&printer, 2);
3450 return False;
3453 current_data = &info->notifies[info->count];
3455 construct_info_data(current_data, type, field, id);
3457 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3458 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3460 notify_info_data_table[j].fn(snum, current_data, queue,
3461 printer, mem_ctx);
3463 info->count++;
3466 free_a_printer(&printer, 2);
3467 return True;
3470 /*******************************************************************
3472 * fill a notify_info struct with info asked
3474 ********************************************************************/
3476 static bool construct_notify_jobs_info(print_queue_struct *queue,
3477 struct spoolss_NotifyInfo *info,
3478 NT_PRINTER_INFO_LEVEL *printer,
3479 int snum,
3480 const struct spoolss_NotifyOptionType *option_type,
3481 uint32_t id,
3482 TALLOC_CTX *mem_ctx)
3484 int field_num,j;
3485 enum spoolss_NotifyType type;
3486 enum spoolss_Field field;
3487 struct spoolss_Notify *current_data;
3489 DEBUG(4,("construct_notify_jobs_info\n"));
3491 type = option_type->type;
3493 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3494 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3495 option_type->count));
3497 for(field_num=0; field_num<option_type->count; field_num++) {
3498 field = option_type->fields[field_num];
3500 if (!search_notify(type, field, &j) )
3501 continue;
3503 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3504 struct spoolss_Notify,
3505 info->count + 1);
3506 if (info->notifies == NULL) {
3507 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3508 return False;
3511 current_data=&(info->notifies[info->count]);
3513 construct_info_data(current_data, type, field, id);
3514 notify_info_data_table[j].fn(snum, current_data, queue,
3515 printer, mem_ctx);
3516 info->count++;
3519 return True;
3523 * JFM: The enumeration is not that simple, it's even non obvious.
3525 * let's take an example: I want to monitor the PRINTER SERVER for
3526 * the printer's name and the number of jobs currently queued.
3527 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3528 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3530 * I have 3 printers on the back of my server.
3532 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3533 * structures.
3534 * Number Data Id
3535 * 1 printer 1 name 1
3536 * 2 printer 1 cjob 1
3537 * 3 printer 2 name 2
3538 * 4 printer 2 cjob 2
3539 * 5 printer 3 name 3
3540 * 6 printer 3 name 3
3542 * that's the print server case, the printer case is even worse.
3545 /*******************************************************************
3547 * enumerate all printers on the printserver
3548 * fill a notify_info struct with info asked
3550 ********************************************************************/
3552 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3553 struct spoolss_NotifyInfo *info,
3554 TALLOC_CTX *mem_ctx)
3556 int snum;
3557 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3558 int n_services=lp_numservices();
3559 int i;
3560 struct spoolss_NotifyOption *option;
3561 struct spoolss_NotifyOptionType option_type;
3563 DEBUG(4,("printserver_notify_info\n"));
3565 if (!Printer)
3566 return WERR_BADFID;
3568 option = Printer->notify.option;
3570 info->version = 2;
3571 info->notifies = NULL;
3572 info->count = 0;
3574 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3575 sending a ffpcn() request first */
3577 if ( !option )
3578 return WERR_BADFID;
3580 for (i=0; i<option->count; i++) {
3581 option_type = option->types[i];
3583 if (option_type.type != PRINTER_NOTIFY_TYPE)
3584 continue;
3586 for (snum=0; snum<n_services; snum++)
3588 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3589 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3593 #if 0
3595 * Debugging information, don't delete.
3598 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3599 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3600 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3602 for (i=0; i<info->count; i++) {
3603 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3604 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3605 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3607 #endif
3609 return WERR_OK;
3612 /*******************************************************************
3614 * fill a notify_info struct with info asked
3616 ********************************************************************/
3618 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3619 TALLOC_CTX *mem_ctx)
3621 int snum;
3622 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3623 int i;
3624 uint32 id;
3625 struct spoolss_NotifyOption *option;
3626 struct spoolss_NotifyOptionType option_type;
3627 int count,j;
3628 print_queue_struct *queue=NULL;
3629 print_status_struct status;
3631 DEBUG(4,("printer_notify_info\n"));
3633 if (!Printer)
3634 return WERR_BADFID;
3636 option = Printer->notify.option;
3637 id = 0x0;
3639 info->version = 2;
3640 info->notifies = NULL;
3641 info->count = 0;
3643 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3644 sending a ffpcn() request first */
3646 if ( !option )
3647 return WERR_BADFID;
3649 get_printer_snum(p, hnd, &snum, NULL);
3651 for (i=0; i<option->count; i++) {
3652 option_type = option->types[i];
3654 switch (option_type.type) {
3655 case PRINTER_NOTIFY_TYPE:
3656 if(construct_notify_printer_info(Printer, info, snum,
3657 &option_type, id,
3658 mem_ctx))
3659 id--;
3660 break;
3662 case JOB_NOTIFY_TYPE: {
3663 NT_PRINTER_INFO_LEVEL *printer = NULL;
3665 count = print_queue_status(snum, &queue, &status);
3667 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3668 goto done;
3670 for (j=0; j<count; j++) {
3671 construct_notify_jobs_info(&queue[j], info,
3672 printer, snum,
3673 &option_type,
3674 queue[j].job,
3675 mem_ctx);
3678 free_a_printer(&printer, 2);
3680 done:
3681 SAFE_FREE(queue);
3682 break;
3688 * Debugging information, don't delete.
3691 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3692 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3693 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3695 for (i=0; i<info->count; i++) {
3696 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3697 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3698 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3701 return WERR_OK;
3704 /****************************************************************
3705 _spoolss_RouterRefreshPrinterChangeNotify
3706 ****************************************************************/
3708 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3709 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3711 POLICY_HND *handle = r->in.handle;
3712 struct spoolss_NotifyInfo *info;
3714 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3715 WERROR result = WERR_BADFID;
3717 /* we always have a spoolss_NotifyInfo struct */
3718 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3719 if (!info) {
3720 result = WERR_NOMEM;
3721 goto done;
3724 *r->out.info = info;
3726 if (!Printer) {
3727 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3728 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3729 goto done;
3732 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3735 * We are now using the change value, and
3736 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3737 * I don't have a global notification system, I'm sending back all the
3738 * informations even when _NOTHING_ has changed.
3741 /* We need to keep track of the change value to send back in
3742 RRPCN replies otherwise our updates are ignored. */
3744 Printer->notify.fnpcn = True;
3746 if (Printer->notify.client_connected) {
3747 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3748 "Saving change value in request [%x]\n",
3749 r->in.change_low));
3750 Printer->notify.change = r->in.change_low;
3753 /* just ignore the spoolss_NotifyOption */
3755 switch (Printer->printer_type) {
3756 case SPLHND_SERVER:
3757 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3758 break;
3760 case SPLHND_PRINTER:
3761 result = printer_notify_info(p, handle, info, p->mem_ctx);
3762 break;
3765 Printer->notify.fnpcn = False;
3767 done:
3768 return result;
3771 /********************************************************************
3772 * construct_printer_info_0
3773 * fill a printer_info_0 struct
3774 ********************************************************************/
3776 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3777 const NT_PRINTER_INFO_LEVEL *ntprinter,
3778 struct spoolss_PrinterInfo0 *r,
3779 int snum)
3781 int count;
3782 counter_printer_0 *session_counter;
3783 time_t setuptime;
3784 print_status_struct status;
3786 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3787 W_ERROR_HAVE_NO_MEMORY(r->printername);
3789 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3790 W_ERROR_HAVE_NO_MEMORY(r->servername);
3792 count = print_queue_length(snum, &status);
3794 /* check if we already have a counter for this printer */
3795 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3796 if (session_counter->snum == snum)
3797 break;
3800 /* it's the first time, add it to the list */
3801 if (session_counter == NULL) {
3802 session_counter = SMB_MALLOC_P(counter_printer_0);
3803 W_ERROR_HAVE_NO_MEMORY(session_counter);
3804 ZERO_STRUCTP(session_counter);
3805 session_counter->snum = snum;
3806 session_counter->counter = 0;
3807 DLIST_ADD(counter_list, session_counter);
3810 /* increment it */
3811 session_counter->counter++;
3813 r->cjobs = count;
3814 r->total_jobs = 0;
3815 r->total_bytes = 0;
3817 setuptime = (time_t)ntprinter->info_2->setuptime;
3819 init_systemtime(&r->time, gmtime(&setuptime));
3821 /* JFM:
3822 * the global_counter should be stored in a TDB as it's common to all the clients
3823 * and should be zeroed on samba startup
3825 r->global_counter = session_counter->counter;
3826 r->total_pages = 0;
3827 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3828 r->version = 0x0005; /* NT 5 */
3829 r->free_build = 0x0893; /* build 2195 */
3830 r->spooling = 0;
3831 r->max_spooling = 0;
3832 r->session_counter = session_counter->counter;
3833 r->num_error_out_of_paper = 0x0;
3834 r->num_error_not_ready = 0x0; /* number of print failure */
3835 r->job_error = 0x0;
3836 r->number_of_processors = 0x1;
3837 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3838 r->high_part_total_bytes = 0x0;
3839 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3840 r->last_error = WERR_OK;
3841 r->status = nt_printq_status(status.status);
3842 r->enumerate_network_printers = 0x0;
3843 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3844 r->processor_architecture = 0x0;
3845 r->processor_level = 0x6; /* 6 ???*/
3846 r->ref_ic = 0;
3847 r->reserved2 = 0;
3848 r->reserved3 = 0;
3850 return WERR_OK;
3853 /****************************************************************************
3854 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3855 should be valid upon entry
3856 ****************************************************************************/
3858 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3859 struct spoolss_DeviceMode *r,
3860 const NT_DEVICEMODE *ntdevmode)
3862 if (!r || !ntdevmode) {
3863 return WERR_INVALID_PARAM;
3866 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3867 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3869 r->specversion = ntdevmode->specversion;
3870 r->driverversion = ntdevmode->driverversion;
3871 r->size = ntdevmode->size;
3872 r->__driverextra_length = ntdevmode->driverextra;
3873 r->fields = ntdevmode->fields;
3875 r->orientation = ntdevmode->orientation;
3876 r->papersize = ntdevmode->papersize;
3877 r->paperlength = ntdevmode->paperlength;
3878 r->paperwidth = ntdevmode->paperwidth;
3879 r->scale = ntdevmode->scale;
3880 r->copies = ntdevmode->copies;
3881 r->defaultsource = ntdevmode->defaultsource;
3882 r->printquality = ntdevmode->printquality;
3883 r->color = ntdevmode->color;
3884 r->duplex = ntdevmode->duplex;
3885 r->yresolution = ntdevmode->yresolution;
3886 r->ttoption = ntdevmode->ttoption;
3887 r->collate = ntdevmode->collate;
3889 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3890 W_ERROR_HAVE_NO_MEMORY(r->formname);
3892 /* all 0 below are values that have not been set in the old parsing/copy
3893 * function, maybe they should... - gd */
3895 r->logpixels = 0;
3896 r->bitsperpel = 0;
3897 r->pelswidth = 0;
3898 r->pelsheight = 0;
3899 r->displayflags = 0;
3900 r->displayfrequency = 0;
3901 r->icmmethod = ntdevmode->icmmethod;
3902 r->icmintent = ntdevmode->icmintent;
3903 r->mediatype = ntdevmode->mediatype;
3904 r->dithertype = ntdevmode->dithertype;
3905 r->reserved1 = 0;
3906 r->reserved2 = 0;
3907 r->panningwidth = 0;
3908 r->panningheight = 0;
3910 if (ntdevmode->nt_dev_private != NULL) {
3911 r->driverextra_data = data_blob_talloc(mem_ctx,
3912 ntdevmode->nt_dev_private,
3913 ntdevmode->driverextra);
3914 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3917 return WERR_OK;
3921 /****************************************************************************
3922 Create a spoolss_DeviceMode struct. Returns talloced memory.
3923 ****************************************************************************/
3925 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3926 const char *servicename)
3928 WERROR result;
3929 NT_PRINTER_INFO_LEVEL *printer = NULL;
3930 struct spoolss_DeviceMode *devmode = NULL;
3932 DEBUG(7,("construct_dev_mode\n"));
3934 DEBUGADD(8,("getting printer characteristics\n"));
3936 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3937 return NULL;
3939 if (!printer->info_2->devmode) {
3940 DEBUG(5, ("BONG! There was no device mode!\n"));
3941 goto done;
3944 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3945 if (!devmode) {
3946 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3947 goto done;
3950 DEBUGADD(8,("loading DEVICEMODE\n"));
3952 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3953 if (!W_ERROR_IS_OK(result)) {
3954 TALLOC_FREE(devmode);
3957 done:
3958 free_a_printer(&printer,2);
3960 return devmode;
3963 /********************************************************************
3964 * construct_printer_info3
3965 * fill a spoolss_PrinterInfo3 struct
3966 ********************************************************************/
3968 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3969 const NT_PRINTER_INFO_LEVEL *ntprinter,
3970 struct spoolss_PrinterInfo3 *r,
3971 int snum)
3973 /* These are the components of the SD we are returning. */
3975 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3976 /* don't use talloc_steal() here unless you do a deep steal of all
3977 the SEC_DESC members */
3979 r->secdesc = dup_sec_desc(mem_ctx,
3980 ntprinter->info_2->secdesc_buf->sd);
3981 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3984 return WERR_OK;
3987 /********************************************************************
3988 * construct_printer_info4
3989 * fill a spoolss_PrinterInfo4 struct
3990 ********************************************************************/
3992 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3993 const NT_PRINTER_INFO_LEVEL *ntprinter,
3994 struct spoolss_PrinterInfo4 *r,
3995 int snum)
3997 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3998 W_ERROR_HAVE_NO_MEMORY(r->printername);
3999 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4000 W_ERROR_HAVE_NO_MEMORY(r->servername);
4002 r->attributes = ntprinter->info_2->attributes;
4004 return WERR_OK;
4007 /********************************************************************
4008 * construct_printer_info5
4009 * fill a spoolss_PrinterInfo5 struct
4010 ********************************************************************/
4012 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4013 const NT_PRINTER_INFO_LEVEL *ntprinter,
4014 struct spoolss_PrinterInfo5 *r,
4015 int snum)
4017 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4018 W_ERROR_HAVE_NO_MEMORY(r->printername);
4019 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4020 W_ERROR_HAVE_NO_MEMORY(r->portname);
4022 r->attributes = ntprinter->info_2->attributes;
4024 /* these two are not used by NT+ according to MSDN */
4026 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4027 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4029 return WERR_OK;
4032 /********************************************************************
4033 * construct_printer_info_6
4034 * fill a spoolss_PrinterInfo6 struct
4035 ********************************************************************/
4037 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4038 const NT_PRINTER_INFO_LEVEL *ntprinter,
4039 struct spoolss_PrinterInfo6 *r,
4040 int snum)
4042 int count;
4043 print_status_struct status;
4045 count = print_queue_length(snum, &status);
4047 r->status = nt_printq_status(status.status);
4049 return WERR_OK;
4052 /********************************************************************
4053 * construct_printer_info7
4054 * fill a spoolss_PrinterInfo7 struct
4055 ********************************************************************/
4057 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4058 Printer_entry *print_hnd,
4059 struct spoolss_PrinterInfo7 *r,
4060 int snum)
4062 struct GUID guid;
4064 if (is_printer_published(print_hnd, snum, &guid)) {
4065 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4066 r->action = DSPRINT_PUBLISH;
4067 } else {
4068 r->guid = talloc_strdup(mem_ctx, "");
4069 r->action = DSPRINT_UNPUBLISH;
4071 W_ERROR_HAVE_NO_MEMORY(r->guid);
4073 return WERR_OK;
4076 /********************************************************************
4077 * construct_printer_info1
4078 * fill a spoolss_PrinterInfo1 struct
4079 ********************************************************************/
4081 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4082 const NT_PRINTER_INFO_LEVEL *ntprinter,
4083 uint32_t flags,
4084 struct spoolss_PrinterInfo1 *r,
4085 int snum)
4087 char *chaine = NULL;
4088 r->flags = flags;
4090 if (*ntprinter->info_2->comment == '\0') {
4091 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4092 chaine = talloc_asprintf(mem_ctx,
4093 "%s,%s,%s", ntprinter->info_2->printername,
4094 ntprinter->info_2->drivername, lp_comment(snum));
4095 } else {
4096 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4097 chaine = talloc_asprintf(mem_ctx,
4098 "%s,%s,%s", ntprinter->info_2->printername,
4099 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4101 W_ERROR_HAVE_NO_MEMORY(chaine);
4102 W_ERROR_HAVE_NO_MEMORY(r->comment);
4104 r->description = talloc_strdup(mem_ctx, chaine);
4105 W_ERROR_HAVE_NO_MEMORY(r->description);
4106 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4107 W_ERROR_HAVE_NO_MEMORY(r->name);
4109 return WERR_OK;
4112 /********************************************************************
4113 * construct_printer_info2
4114 * fill a spoolss_PrinterInfo2 struct
4115 ********************************************************************/
4117 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4118 const NT_PRINTER_INFO_LEVEL *ntprinter,
4119 struct spoolss_PrinterInfo2 *r,
4120 int snum)
4122 int count;
4124 print_status_struct status;
4126 count = print_queue_length(snum, &status);
4128 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4129 W_ERROR_HAVE_NO_MEMORY(r->servername);
4130 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4131 W_ERROR_HAVE_NO_MEMORY(r->printername);
4132 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4133 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4134 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4135 W_ERROR_HAVE_NO_MEMORY(r->portname);
4136 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4137 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4139 if (*ntprinter->info_2->comment == '\0') {
4140 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4141 } else {
4142 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4144 W_ERROR_HAVE_NO_MEMORY(r->comment);
4146 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4147 W_ERROR_HAVE_NO_MEMORY(r->location);
4148 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4149 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4150 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4151 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4152 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4153 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4154 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4155 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4157 r->attributes = ntprinter->info_2->attributes;
4159 r->priority = ntprinter->info_2->priority;
4160 r->defaultpriority = ntprinter->info_2->default_priority;
4161 r->starttime = ntprinter->info_2->starttime;
4162 r->untiltime = ntprinter->info_2->untiltime;
4163 r->status = nt_printq_status(status.status);
4164 r->cjobs = count;
4165 r->averageppm = ntprinter->info_2->averageppm;
4167 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4168 if (!r->devmode) {
4169 DEBUG(8,("Returning NULL Devicemode!\n"));
4172 r->secdesc = NULL;
4174 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4175 /* don't use talloc_steal() here unless you do a deep steal of all
4176 the SEC_DESC members */
4178 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4181 return WERR_OK;
4184 /********************************************************************
4185 ********************************************************************/
4187 static bool snum_is_shared_printer(int snum)
4189 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4192 /********************************************************************
4193 Spoolss_enumprinters.
4194 ********************************************************************/
4196 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4197 uint32_t flags,
4198 union spoolss_PrinterInfo **info_p,
4199 uint32_t *count)
4201 int snum;
4202 int n_services = lp_numservices();
4203 union spoolss_PrinterInfo *info = NULL;
4204 WERROR result = WERR_OK;
4206 DEBUG(4,("enum_all_printers_info_1\n"));
4208 *count = 0;
4210 for (snum=0; snum<n_services; snum++) {
4212 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4213 struct spoolss_PrinterInfo1 info1;
4215 if (!snum_is_shared_printer(snum)) {
4216 continue;
4219 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4221 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4222 if (!W_ERROR_IS_OK(result)) {
4223 continue;
4226 result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
4227 free_a_printer(&ntprinter,2);
4228 if (!W_ERROR_IS_OK(result)) {
4229 continue;
4232 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4233 union spoolss_PrinterInfo,
4234 *count + 1);
4235 if (!info) {
4236 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4237 result = WERR_NOMEM;
4238 goto out;
4241 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
4243 info[*count].info1 = info1;
4244 (*count)++;
4247 out:
4248 if (!W_ERROR_IS_OK(result)) {
4249 TALLOC_FREE(info);
4250 *count = 0;
4251 return result;
4254 *info_p = info;
4256 return WERR_OK;
4259 /********************************************************************
4260 enum_all_printers_info_1_local.
4261 *********************************************************************/
4263 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4264 union spoolss_PrinterInfo **info,
4265 uint32_t *count)
4267 DEBUG(4,("enum_all_printers_info_1_local\n"));
4269 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4272 /********************************************************************
4273 enum_all_printers_info_1_name.
4274 *********************************************************************/
4276 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4277 const char *name,
4278 union spoolss_PrinterInfo **info,
4279 uint32_t *count)
4281 const char *s = name;
4283 DEBUG(4,("enum_all_printers_info_1_name\n"));
4285 if ((name[0] == '\\') && (name[1] == '\\')) {
4286 s = name + 2;
4289 if (!is_myname_or_ipaddr(s)) {
4290 return WERR_INVALID_NAME;
4293 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4296 /********************************************************************
4297 enum_all_printers_info_1_network.
4298 *********************************************************************/
4300 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4301 const char *name,
4302 union spoolss_PrinterInfo **info,
4303 uint32_t *count)
4305 const char *s = name;
4307 DEBUG(4,("enum_all_printers_info_1_network\n"));
4309 /* If we respond to a enum_printers level 1 on our name with flags
4310 set to PRINTER_ENUM_REMOTE with a list of printers then these
4311 printers incorrectly appear in the APW browse list.
4312 Specifically the printers for the server appear at the workgroup
4313 level where all the other servers in the domain are
4314 listed. Windows responds to this call with a
4315 WERR_CAN_NOT_COMPLETE so we should do the same. */
4317 if (name[0] == '\\' && name[1] == '\\') {
4318 s = name + 2;
4321 if (is_myname_or_ipaddr(s)) {
4322 return WERR_CAN_NOT_COMPLETE;
4325 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4328 /********************************************************************
4329 * api_spoolss_enumprinters
4331 * called from api_spoolss_enumprinters (see this to understand)
4332 ********************************************************************/
4334 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4335 union spoolss_PrinterInfo **info_p,
4336 uint32_t *count)
4338 int snum;
4339 int n_services = lp_numservices();
4340 union spoolss_PrinterInfo *info = NULL;
4341 WERROR result = WERR_OK;
4343 *count = 0;
4345 for (snum=0; snum<n_services; snum++) {
4347 struct spoolss_PrinterInfo2 info2;
4348 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4350 if (!snum_is_shared_printer(snum)) {
4351 continue;
4354 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4356 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4357 if (!W_ERROR_IS_OK(result)) {
4358 continue;
4361 result = construct_printer_info2(info, ntprinter, &info2, snum);
4362 free_a_printer(&ntprinter, 2);
4363 if (!W_ERROR_IS_OK(result)) {
4364 continue;
4367 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4368 union spoolss_PrinterInfo,
4369 *count + 1);
4370 if (!info) {
4371 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4372 result = WERR_NOMEM;
4373 goto out;
4376 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
4378 info[*count].info2 = info2;
4380 (*count)++;
4383 out:
4384 if (!W_ERROR_IS_OK(result)) {
4385 TALLOC_FREE(info);
4386 *count = 0;
4387 return result;
4390 *info_p = info;
4392 return WERR_OK;
4395 /********************************************************************
4396 * handle enumeration of printers at level 1
4397 ********************************************************************/
4399 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4400 uint32_t flags,
4401 const char *name,
4402 union spoolss_PrinterInfo **info,
4403 uint32_t *count)
4405 /* Not all the flags are equals */
4407 if (flags & PRINTER_ENUM_LOCAL) {
4408 return enum_all_printers_info_1_local(mem_ctx, info, count);
4411 if (flags & PRINTER_ENUM_NAME) {
4412 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4415 if (flags & PRINTER_ENUM_NETWORK) {
4416 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4419 return WERR_OK; /* NT4sp5 does that */
4422 /********************************************************************
4423 * handle enumeration of printers at level 2
4424 ********************************************************************/
4426 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4427 uint32_t flags,
4428 const char *servername,
4429 union spoolss_PrinterInfo **info,
4430 uint32_t *count)
4432 if (flags & PRINTER_ENUM_LOCAL) {
4433 return enum_all_printers_info_2(mem_ctx, info, count);
4436 if (flags & PRINTER_ENUM_NAME) {
4437 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4438 return WERR_INVALID_NAME;
4441 return enum_all_printers_info_2(mem_ctx, info, count);
4444 if (flags & PRINTER_ENUM_REMOTE) {
4445 return WERR_UNKNOWN_LEVEL;
4448 return WERR_OK;
4451 /********************************************************************
4452 * handle enumeration of printers at level 5
4453 ********************************************************************/
4455 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4456 uint32_t flags,
4457 const char *servername,
4458 union spoolss_PrinterInfo **info,
4459 uint32_t *count)
4461 /* return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
4462 return WERR_OK;
4465 /****************************************************************
4466 _spoolss_EnumPrinters
4467 ****************************************************************/
4469 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4470 struct spoolss_EnumPrinters *r)
4472 const char *name;
4473 WERROR result;
4475 /* that's an [in out] buffer */
4477 if (!r->in.buffer && (r->in.offered != 0)) {
4478 return WERR_INVALID_PARAM;
4481 DEBUG(4,("_spoolss_EnumPrinters\n"));
4483 *r->out.needed = 0;
4484 *r->out.count = 0;
4485 *r->out.info = NULL;
4488 * Level 1:
4489 * flags==PRINTER_ENUM_NAME
4490 * if name=="" then enumerates all printers
4491 * if name!="" then enumerate the printer
4492 * flags==PRINTER_ENUM_REMOTE
4493 * name is NULL, enumerate printers
4494 * Level 2: name!="" enumerates printers, name can't be NULL
4495 * Level 3: doesn't exist
4496 * Level 4: does a local registry lookup
4497 * Level 5: same as Level 2
4500 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4501 W_ERROR_HAVE_NO_MEMORY(name);
4503 switch (r->in.level) {
4504 case 1:
4505 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4506 r->out.info, r->out.count);
4507 break;
4508 case 2:
4509 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4510 r->out.info, r->out.count);
4511 break;
4512 case 5:
4513 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4514 r->out.info, r->out.count);
4515 break;
4516 case 3:
4517 case 4:
4518 result = WERR_OK; /* ??? */
4519 break;
4520 default:
4521 return WERR_UNKNOWN_LEVEL;
4524 if (!W_ERROR_IS_OK(result)) {
4525 return result;
4528 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4529 spoolss_EnumPrinters, NULL,
4530 *r->out.info, r->in.level,
4531 *r->out.count);
4532 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4533 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4535 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4538 /****************************************************************
4539 _spoolss_GetPrinter
4540 ****************************************************************/
4542 WERROR _spoolss_GetPrinter(pipes_struct *p,
4543 struct spoolss_GetPrinter *r)
4545 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4546 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4547 WERROR result = WERR_OK;
4549 int snum;
4551 /* that's an [in out] buffer */
4553 if (!r->in.buffer && (r->in.offered != 0)) {
4554 return WERR_INVALID_PARAM;
4557 *r->out.needed = 0;
4559 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4560 return WERR_BADFID;
4563 result = get_a_printer(Printer, &ntprinter, 2,
4564 lp_const_servicename(snum));
4565 if (!W_ERROR_IS_OK(result)) {
4566 return result;
4569 switch (r->in.level) {
4570 case 0:
4571 result = construct_printer_info0(p->mem_ctx, ntprinter,
4572 &r->out.info->info0, snum);
4573 break;
4574 case 1:
4575 result = construct_printer_info1(p->mem_ctx, ntprinter,
4576 PRINTER_ENUM_ICON8,
4577 &r->out.info->info1, snum);
4578 break;
4579 case 2:
4580 result = construct_printer_info2(p->mem_ctx, ntprinter,
4581 &r->out.info->info2, snum);
4582 break;
4583 case 3:
4584 result = construct_printer_info3(p->mem_ctx, ntprinter,
4585 &r->out.info->info3, snum);
4586 break;
4587 case 4:
4588 result = construct_printer_info4(p->mem_ctx, ntprinter,
4589 &r->out.info->info4, snum);
4590 break;
4591 case 5:
4592 result = construct_printer_info5(p->mem_ctx, ntprinter,
4593 &r->out.info->info5, snum);
4594 break;
4595 case 6:
4596 result = construct_printer_info6(p->mem_ctx, ntprinter,
4597 &r->out.info->info6, snum);
4598 break;
4599 case 7:
4600 result = construct_printer_info7(p->mem_ctx, Printer,
4601 &r->out.info->info7, snum);
4602 break;
4603 default:
4604 result = WERR_UNKNOWN_LEVEL;
4605 break;
4608 free_a_printer(&ntprinter, 2);
4610 if (!W_ERROR_IS_OK(result)) {
4611 TALLOC_FREE(r->out.info);
4612 return result;
4615 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4616 r->out.info, r->in.level);
4617 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4619 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4622 /********************************************************************
4623 ********************************************************************/
4625 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4626 fstring *fstring_array,
4627 const char *cservername)
4629 int i, num_strings = 0;
4630 const char **array = NULL;
4632 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4634 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4635 cservername, fstring_array[i]);
4636 if (!str) {
4637 TALLOC_FREE(array);
4638 return NULL;
4642 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4643 TALLOC_FREE(array);
4644 return NULL;
4648 if (i > 0) {
4649 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4650 &array, &num_strings);
4653 return array;
4656 /********************************************************************
4657 * fill a spoolss_DriverInfo1 struct
4658 ********************************************************************/
4660 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4661 struct spoolss_DriverInfo1 *r,
4662 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4663 const char *servername,
4664 const char *architecture)
4666 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4667 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4669 return WERR_OK;
4672 /********************************************************************
4673 * fill a spoolss_DriverInfo2 struct
4674 ********************************************************************/
4676 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4677 struct spoolss_DriverInfo2 *r,
4678 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4679 const char *servername)
4682 const char *cservername = canon_servername(servername);
4684 r->version = driver->info_3->cversion;
4686 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4687 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4688 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4689 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4691 if (strlen(driver->info_3->driverpath)) {
4692 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4693 cservername, driver->info_3->driverpath);
4694 } else {
4695 r->driver_path = talloc_strdup(mem_ctx, "");
4697 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4699 if (strlen(driver->info_3->datafile)) {
4700 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4701 cservername, driver->info_3->datafile);
4702 } else {
4703 r->data_file = talloc_strdup(mem_ctx, "");
4705 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4707 if (strlen(driver->info_3->configfile)) {
4708 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4709 cservername, driver->info_3->configfile);
4710 } else {
4711 r->config_file = talloc_strdup(mem_ctx, "");
4713 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4715 return WERR_OK;
4718 /********************************************************************
4719 * fill a spoolss_DriverInfo3 struct
4720 ********************************************************************/
4722 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4723 struct spoolss_DriverInfo3 *r,
4724 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4725 const char *servername)
4727 const char *cservername = canon_servername(servername);
4729 r->version = driver->info_3->cversion;
4731 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4732 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4733 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4734 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4736 if (strlen(driver->info_3->driverpath)) {
4737 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4738 cservername, driver->info_3->driverpath);
4739 } else {
4740 r->driver_path = talloc_strdup(mem_ctx, "");
4742 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4744 if (strlen(driver->info_3->datafile)) {
4745 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4746 cservername, driver->info_3->datafile);
4747 } else {
4748 r->data_file = talloc_strdup(mem_ctx, "");
4750 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4752 if (strlen(driver->info_3->configfile)) {
4753 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4754 cservername, driver->info_3->configfile);
4755 } else {
4756 r->config_file = talloc_strdup(mem_ctx, "");
4758 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4760 if (strlen(driver->info_3->helpfile)) {
4761 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4762 cservername, driver->info_3->helpfile);
4763 } else {
4764 r->help_file = talloc_strdup(mem_ctx, "");
4766 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4768 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4769 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4770 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4771 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4773 r->dependent_files = string_array_from_driver_info(mem_ctx,
4774 driver->info_3->dependentfiles,
4775 cservername);
4776 return WERR_OK;
4779 /********************************************************************
4780 * fill a spoolss_DriverInfo6 struct
4781 ********************************************************************/
4783 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4784 struct spoolss_DriverInfo6 *r,
4785 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4786 const char *servername)
4788 const char *cservername = canon_servername(servername);
4790 r->version = driver->info_3->cversion;
4792 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4793 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4794 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4795 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4797 if (strlen(driver->info_3->driverpath)) {
4798 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4799 cservername, driver->info_3->driverpath);
4800 } else {
4801 r->driver_path = talloc_strdup(mem_ctx, "");
4803 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4805 if (strlen(driver->info_3->datafile)) {
4806 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4807 cservername, driver->info_3->datafile);
4808 } else {
4809 r->data_file = talloc_strdup(mem_ctx, "");
4811 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4813 if (strlen(driver->info_3->configfile)) {
4814 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4815 cservername, driver->info_3->configfile);
4816 } else {
4817 r->config_file = talloc_strdup(mem_ctx, "");
4819 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4821 if (strlen(driver->info_3->helpfile)) {
4822 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4823 cservername, driver->info_3->helpfile);
4824 } else {
4825 r->help_file = talloc_strdup(mem_ctx, "");
4827 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4829 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4830 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4831 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4832 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4834 r->dependent_files = string_array_from_driver_info(mem_ctx,
4835 driver->info_3->dependentfiles,
4836 cservername);
4837 r->previous_names = string_array_from_driver_info(mem_ctx,
4838 NULL,
4839 cservername);
4841 r->driver_date = 0;
4842 r->driver_version = 0;
4844 r->manufacturer_name = talloc_strdup(mem_ctx, "");
4845 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
4846 r->manufacturer_url = talloc_strdup(mem_ctx, "");
4847 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
4848 r->hardware_id = talloc_strdup(mem_ctx, "");
4849 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
4850 r->provider = talloc_strdup(mem_ctx, "");
4851 W_ERROR_HAVE_NO_MEMORY(r->provider);
4853 return WERR_OK;
4856 /********************************************************************
4857 * construct_printer_driver_info_1
4858 ********************************************************************/
4860 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
4861 struct spoolss_DriverInfo1 *r,
4862 int snum,
4863 const char *servername,
4864 const char *architecture,
4865 uint32_t version)
4867 NT_PRINTER_INFO_LEVEL *printer = NULL;
4868 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4869 WERROR result;
4871 ZERO_STRUCT(driver);
4873 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4874 return WERR_INVALID_PRINTER_NAME;
4876 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4877 free_a_printer(&printer, 2);
4878 return WERR_UNKNOWN_PRINTER_DRIVER;
4881 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
4883 free_a_printer(&printer,2);
4885 return result;
4888 /********************************************************************
4889 * construct_printer_driver_info_2
4890 * fill a printer_info_2 struct
4891 ********************************************************************/
4893 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
4894 struct spoolss_DriverInfo2 *r,
4895 int snum,
4896 const char *servername,
4897 const char *architecture,
4898 uint32_t version)
4900 NT_PRINTER_INFO_LEVEL *printer = NULL;
4901 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4902 WERROR result;
4904 ZERO_STRUCT(printer);
4905 ZERO_STRUCT(driver);
4907 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4908 return WERR_INVALID_PRINTER_NAME;
4910 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4911 free_a_printer(&printer, 2);
4912 return WERR_UNKNOWN_PRINTER_DRIVER;
4915 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
4917 free_a_printer(&printer,2);
4919 return result;
4922 /********************************************************************
4923 * construct_printer_info_3
4924 * fill a printer_info_3 struct
4925 ********************************************************************/
4927 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
4928 struct spoolss_DriverInfo3 *r,
4929 int snum,
4930 const char *servername,
4931 const char *architecture,
4932 uint32_t version)
4934 NT_PRINTER_INFO_LEVEL *printer = NULL;
4935 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4936 WERROR status;
4937 ZERO_STRUCT(driver);
4939 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
4940 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4941 if (!W_ERROR_IS_OK(status))
4942 return WERR_INVALID_PRINTER_NAME;
4944 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4945 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4947 #if 0 /* JERRY */
4950 * I put this code in during testing. Helpful when commenting out the
4951 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4952 * as win2k always queries the driver using an infor level of 6.
4953 * I've left it in (but ifdef'd out) because I'll probably
4954 * use it in experimentation again in the future. --jerry 22/01/2002
4957 if (!W_ERROR_IS_OK(status)) {
4959 * Is this a W2k client ?
4961 if (version == 3) {
4962 /* Yes - try again with a WinNT driver. */
4963 version = 2;
4964 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4965 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4967 #endif
4969 if (!W_ERROR_IS_OK(status)) {
4970 free_a_printer(&printer,2);
4971 return WERR_UNKNOWN_PRINTER_DRIVER;
4974 #if 0 /* JERRY */
4976 #endif
4979 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
4981 free_a_printer(&printer,2);
4983 return status;
4986 /********************************************************************
4987 * construct_printer_info_6
4988 * fill a printer_info_6 struct
4989 ********************************************************************/
4991 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
4992 struct spoolss_DriverInfo6 *r,
4993 int snum,
4994 const char *servername,
4995 const char *architecture,
4996 uint32_t version)
4998 NT_PRINTER_INFO_LEVEL *printer = NULL;
4999 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5000 WERROR status;
5002 ZERO_STRUCT(driver);
5004 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5006 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5008 if (!W_ERROR_IS_OK(status))
5009 return WERR_INVALID_PRINTER_NAME;
5011 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5013 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5015 if (!W_ERROR_IS_OK(status))
5018 * Is this a W2k client ?
5021 if (version < 3) {
5022 free_a_printer(&printer,2);
5023 return WERR_UNKNOWN_PRINTER_DRIVER;
5026 /* Yes - try again with a WinNT driver. */
5027 version = 2;
5028 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5029 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5030 if (!W_ERROR_IS_OK(status)) {
5031 free_a_printer(&printer,2);
5032 return WERR_UNKNOWN_PRINTER_DRIVER;
5036 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5038 free_a_printer(&printer,2);
5039 free_a_printer_driver(driver, 3);
5041 return status;
5044 /****************************************************************
5045 _spoolss_GetPrinterDriver2
5046 ****************************************************************/
5048 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5049 struct spoolss_GetPrinterDriver2 *r)
5051 Printer_entry *printer;
5052 WERROR result;
5054 const char *servername;
5055 int snum;
5057 /* that's an [in out] buffer */
5059 if (!r->in.buffer && (r->in.offered != 0)) {
5060 return WERR_INVALID_PARAM;
5063 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5065 if (!(printer = find_printer_index_by_hnd( p, r->in.handle))) {
5066 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5067 return WERR_INVALID_PRINTER_NAME;
5070 *r->out.needed = 0;
5071 *r->out.server_major_version = 0;
5072 *r->out.server_minor_version = 0;
5074 servername = get_server_name(printer);
5076 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5077 return WERR_BADFID;
5080 switch (r->in.level) {
5081 case 1:
5082 result = construct_printer_driver_info_1(p->mem_ctx,
5083 &r->out.info->info1,
5084 snum,
5085 servername,
5086 r->in.architecture,
5087 r->in.client_major_version);
5088 break;
5089 case 2:
5090 result = construct_printer_driver_info_2(p->mem_ctx,
5091 &r->out.info->info2,
5092 snum,
5093 servername,
5094 r->in.architecture,
5095 r->in.client_major_version);
5096 break;
5097 case 3:
5098 result = construct_printer_driver_info_3(p->mem_ctx,
5099 &r->out.info->info3,
5100 snum,
5101 servername,
5102 r->in.architecture,
5103 r->in.client_major_version);
5104 break;
5105 case 6:
5106 result = construct_printer_driver_info_6(p->mem_ctx,
5107 &r->out.info->info6,
5108 snum,
5109 servername,
5110 r->in.architecture,
5111 r->in.client_major_version);
5112 break;
5113 default:
5114 #if 0 /* JERRY */
5115 case 101:
5116 /* apparently this call is the equivalent of
5117 EnumPrinterDataEx() for the DsDriver key */
5118 break;
5119 #endif
5120 result = WERR_UNKNOWN_LEVEL;
5121 break;
5124 if (!W_ERROR_IS_OK(result)) {
5125 TALLOC_FREE(r->out.info);
5126 return result;
5129 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5130 r->out.info, r->in.level);
5131 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5133 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5137 /****************************************************************
5138 _spoolss_StartPagePrinter
5139 ****************************************************************/
5141 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5142 struct spoolss_StartPagePrinter *r)
5144 POLICY_HND *handle = r->in.handle;
5146 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5148 if (!Printer) {
5149 DEBUG(3,("_spoolss_StartPagePrinter: "
5150 "Error in startpageprinter printer handle\n"));
5151 return WERR_BADFID;
5154 Printer->page_started=True;
5155 return WERR_OK;
5158 /****************************************************************
5159 _spoolss_EndPagePrinter
5160 ****************************************************************/
5162 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5163 struct spoolss_EndPagePrinter *r)
5165 POLICY_HND *handle = r->in.handle;
5166 int snum;
5168 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5170 if (!Printer) {
5171 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5172 OUR_HANDLE(handle)));
5173 return WERR_BADFID;
5176 if (!get_printer_snum(p, handle, &snum, NULL))
5177 return WERR_BADFID;
5179 Printer->page_started=False;
5180 print_job_endpage(snum, Printer->jobid);
5182 return WERR_OK;
5185 /****************************************************************
5186 _spoolss_StartDocPrinter
5187 ****************************************************************/
5189 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5190 struct spoolss_StartDocPrinter *r)
5192 POLICY_HND *handle = r->in.handle;
5193 uint32_t *jobid = r->out.job_id;
5194 struct spoolss_DocumentInfo1 *info_1;
5195 int snum;
5196 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5198 if (!Printer) {
5199 DEBUG(2,("_spoolss_StartDocPrinter: "
5200 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5201 return WERR_BADFID;
5204 if (r->in.level != 1) {
5205 return WERR_UNKNOWN_LEVEL;
5208 info_1 = r->in.info.info1;
5211 * a nice thing with NT is it doesn't listen to what you tell it.
5212 * when asked to send _only_ RAW datas, it tries to send datas
5213 * in EMF format.
5215 * So I add checks like in NT Server ...
5218 if (info_1->datatype) {
5219 if (strcmp(info_1->datatype, "RAW") != 0) {
5220 (*jobid)=0;
5221 return WERR_INVALID_DATATYPE;
5225 /* get the share number of the printer */
5226 if (!get_printer_snum(p, handle, &snum, NULL)) {
5227 return WERR_BADFID;
5230 Printer->jobid = print_job_start(p->server_info, snum,
5231 info_1->document_name,
5232 Printer->nt_devmode);
5234 /* An error occured in print_job_start() so return an appropriate
5235 NT error code. */
5237 if (Printer->jobid == -1) {
5238 return map_werror_from_unix(errno);
5241 Printer->document_started=True;
5242 (*jobid) = Printer->jobid;
5244 return WERR_OK;
5247 /****************************************************************
5248 _spoolss_EndDocPrinter
5249 ****************************************************************/
5251 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5252 struct spoolss_EndDocPrinter *r)
5254 POLICY_HND *handle = r->in.handle;
5256 return _spoolss_enddocprinter_internal(p, handle);
5259 /****************************************************************
5260 _spoolss_WritePrinter
5261 ****************************************************************/
5263 WERROR _spoolss_WritePrinter(pipes_struct *p,
5264 struct spoolss_WritePrinter *r)
5266 POLICY_HND *handle = r->in.handle;
5267 uint32 buffer_size = r->in._data_size;
5268 uint8 *buffer = r->in.data.data;
5269 uint32 *buffer_written = &r->in._data_size;
5270 int snum;
5271 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5273 if (!Printer) {
5274 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5275 OUR_HANDLE(handle)));
5276 *r->out.num_written = r->in._data_size;
5277 return WERR_BADFID;
5280 if (!get_printer_snum(p, handle, &snum, NULL))
5281 return WERR_BADFID;
5283 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5284 (SMB_OFF_T)-1, (size_t)buffer_size);
5285 if (*buffer_written == (uint32)-1) {
5286 *r->out.num_written = 0;
5287 if (errno == ENOSPC)
5288 return WERR_NO_SPOOL_SPACE;
5289 else
5290 return WERR_ACCESS_DENIED;
5293 *r->out.num_written = r->in._data_size;
5295 return WERR_OK;
5298 /********************************************************************
5299 * api_spoolss_getprinter
5300 * called from the spoolss dispatcher
5302 ********************************************************************/
5304 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5305 pipes_struct *p)
5307 int snum;
5308 WERROR errcode = WERR_BADFUNC;
5309 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5311 if (!Printer) {
5312 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5313 return WERR_BADFID;
5316 if (!get_printer_snum(p, handle, &snum, NULL))
5317 return WERR_BADFID;
5319 switch (command) {
5320 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5321 if (print_queue_pause(p->server_info, snum, &errcode)) {
5322 errcode = WERR_OK;
5324 break;
5325 case SPOOLSS_PRINTER_CONTROL_RESUME:
5326 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5327 if (print_queue_resume(p->server_info, snum, &errcode)) {
5328 errcode = WERR_OK;
5330 break;
5331 case SPOOLSS_PRINTER_CONTROL_PURGE:
5332 if (print_queue_purge(p->server_info, snum, &errcode)) {
5333 errcode = WERR_OK;
5335 break;
5336 default:
5337 return WERR_UNKNOWN_LEVEL;
5340 return errcode;
5344 /****************************************************************
5345 _spoolss_AbortPrinter
5346 * From MSDN: "Deletes printer's spool file if printer is configured
5347 * for spooling"
5348 ****************************************************************/
5350 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5351 struct spoolss_AbortPrinter *r)
5353 POLICY_HND *handle = r->in.handle;
5354 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5355 int snum;
5356 WERROR errcode = WERR_OK;
5358 if (!Printer) {
5359 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5360 OUR_HANDLE(handle)));
5361 return WERR_BADFID;
5364 if (!get_printer_snum(p, handle, &snum, NULL))
5365 return WERR_BADFID;
5367 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5369 return errcode;
5372 /********************************************************************
5373 * called by spoolss_api_setprinter
5374 * when updating a printer description
5375 ********************************************************************/
5377 static WERROR update_printer_sec(POLICY_HND *handle,
5378 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5380 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5381 WERROR result;
5382 int snum;
5384 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5386 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5387 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5388 OUR_HANDLE(handle)));
5390 result = WERR_BADFID;
5391 goto done;
5394 if (!secdesc_ctr) {
5395 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5396 result = WERR_INVALID_PARAM;
5397 goto done;
5400 /* Check the user has permissions to change the security
5401 descriptor. By experimentation with two NT machines, the user
5402 requires Full Access to the printer to change security
5403 information. */
5405 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5406 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5407 result = WERR_ACCESS_DENIED;
5408 goto done;
5411 /* NT seems to like setting the security descriptor even though
5412 nothing may have actually changed. */
5414 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5415 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5416 result = WERR_BADFID;
5417 goto done;
5420 if (DEBUGLEVEL >= 10) {
5421 SEC_ACL *the_acl;
5422 int i;
5424 the_acl = old_secdesc_ctr->sd->dacl;
5425 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5426 PRINTERNAME(snum), the_acl->num_aces));
5428 for (i = 0; i < the_acl->num_aces; i++) {
5429 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5430 &the_acl->aces[i].trustee),
5431 the_acl->aces[i].access_mask));
5434 the_acl = secdesc_ctr->sd->dacl;
5436 if (the_acl) {
5437 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5438 PRINTERNAME(snum), the_acl->num_aces));
5440 for (i = 0; i < the_acl->num_aces; i++) {
5441 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5442 &the_acl->aces[i].trustee),
5443 the_acl->aces[i].access_mask));
5445 } else {
5446 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5450 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5451 if (!new_secdesc_ctr) {
5452 result = WERR_NOMEM;
5453 goto done;
5456 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5457 result = WERR_OK;
5458 goto done;
5461 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5463 done:
5465 return result;
5468 /********************************************************************
5469 Canonicalize printer info from a client
5471 ATTN: It does not matter what we set the servername to hear
5472 since we do the necessary work in get_a_printer() to set it to
5473 the correct value based on what the client sent in the
5474 _spoolss_open_printer_ex().
5475 ********************************************************************/
5477 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5479 fstring printername;
5480 const char *p;
5482 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5483 "portname=%s drivername=%s comment=%s location=%s\n",
5484 info->servername, info->printername, info->sharename,
5485 info->portname, info->drivername, info->comment, info->location));
5487 /* we force some elements to "correct" values */
5488 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5489 fstrcpy(info->sharename, lp_servicename(snum));
5491 /* check to see if we allow printername != sharename */
5493 if ( lp_force_printername(snum) ) {
5494 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5495 global_myname(), info->sharename );
5496 } else {
5498 /* make sure printername is in \\server\printername format */
5500 fstrcpy( printername, info->printername );
5501 p = printername;
5502 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5503 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5504 p++;
5507 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5508 global_myname(), p );
5511 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5512 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5516 return True;
5519 /****************************************************************************
5520 ****************************************************************************/
5522 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5524 char *cmd = lp_addport_cmd();
5525 char *command = NULL;
5526 int ret;
5527 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5528 bool is_print_op = False;
5530 if ( !*cmd ) {
5531 return WERR_ACCESS_DENIED;
5534 command = talloc_asprintf(ctx,
5535 "%s \"%s\" \"%s\"", cmd, portname, uri );
5536 if (!command) {
5537 return WERR_NOMEM;
5540 if ( token )
5541 is_print_op = user_has_privileges( token, &se_printop );
5543 DEBUG(10,("Running [%s]\n", command));
5545 /********* BEGIN SePrintOperatorPrivilege **********/
5547 if ( is_print_op )
5548 become_root();
5550 ret = smbrun(command, NULL);
5552 if ( is_print_op )
5553 unbecome_root();
5555 /********* END SePrintOperatorPrivilege **********/
5557 DEBUGADD(10,("returned [%d]\n", ret));
5559 TALLOC_FREE(command);
5561 if ( ret != 0 ) {
5562 return WERR_ACCESS_DENIED;
5565 return WERR_OK;
5568 /****************************************************************************
5569 ****************************************************************************/
5571 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5573 char *cmd = lp_addprinter_cmd();
5574 char **qlines;
5575 char *command = NULL;
5576 int numlines;
5577 int ret;
5578 int fd;
5579 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5580 bool is_print_op = False;
5581 char *remote_machine = talloc_strdup(ctx, "%m");
5583 if (!remote_machine) {
5584 return false;
5586 remote_machine = talloc_sub_basic(ctx,
5587 current_user_info.smb_name,
5588 current_user_info.domain,
5589 remote_machine);
5590 if (!remote_machine) {
5591 return false;
5594 command = talloc_asprintf(ctx,
5595 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5596 cmd, printer->info_2->printername, printer->info_2->sharename,
5597 printer->info_2->portname, printer->info_2->drivername,
5598 printer->info_2->location, printer->info_2->comment, remote_machine);
5599 if (!command) {
5600 return false;
5603 if ( token )
5604 is_print_op = user_has_privileges( token, &se_printop );
5606 DEBUG(10,("Running [%s]\n", command));
5608 /********* BEGIN SePrintOperatorPrivilege **********/
5610 if ( is_print_op )
5611 become_root();
5613 if ( (ret = smbrun(command, &fd)) == 0 ) {
5614 /* Tell everyone we updated smb.conf. */
5615 message_send_all(smbd_messaging_context(),
5616 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5619 if ( is_print_op )
5620 unbecome_root();
5622 /********* END SePrintOperatorPrivilege **********/
5624 DEBUGADD(10,("returned [%d]\n", ret));
5626 TALLOC_FREE(command);
5627 TALLOC_FREE(remote_machine);
5629 if ( ret != 0 ) {
5630 if (fd != -1)
5631 close(fd);
5632 return False;
5635 /* reload our services immediately */
5636 reload_services( False );
5638 numlines = 0;
5639 /* Get lines and convert them back to dos-codepage */
5640 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5641 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5642 close(fd);
5644 /* Set the portname to what the script says the portname should be. */
5645 /* but don't require anything to be return from the script exit a good error code */
5647 if (numlines) {
5648 /* Set the portname to what the script says the portname should be. */
5649 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5650 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5653 TALLOC_FREE(qlines);
5654 return True;
5658 /********************************************************************
5659 * Called by spoolss_api_setprinter
5660 * when updating a printer description.
5661 ********************************************************************/
5663 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
5664 struct spoolss_SetPrinterInfoCtr *info_ctr,
5665 struct spoolss_DeviceMode *devmode)
5667 int snum;
5668 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5669 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5670 WERROR result;
5671 UNISTR2 buffer;
5672 fstring asc_buffer;
5674 DEBUG(8,("update_printer\n"));
5676 result = WERR_OK;
5678 if (!Printer) {
5679 result = WERR_BADFID;
5680 goto done;
5683 if (!get_printer_snum(p, handle, &snum, NULL)) {
5684 result = WERR_BADFID;
5685 goto done;
5688 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5689 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5690 result = WERR_BADFID;
5691 goto done;
5694 DEBUGADD(8,("Converting info_2 struct\n"));
5697 * convert_printer_info converts the incoming
5698 * info from the client and overwrites the info
5699 * just read from the tdb in the pointer 'printer'.
5702 if (!convert_printer_info(info_ctr, printer)) {
5703 result = WERR_NOMEM;
5704 goto done;
5707 if (devmode) {
5708 /* we have a valid devmode
5709 convert it and link it*/
5711 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5712 if (!convert_devicemode(printer->info_2->printername, devmode,
5713 &printer->info_2->devmode)) {
5714 result = WERR_NOMEM;
5715 goto done;
5719 /* Do sanity check on the requested changes for Samba */
5721 if (!check_printer_ok(printer->info_2, snum)) {
5722 result = WERR_INVALID_PARAM;
5723 goto done;
5726 /* FIXME!!! If the driver has changed we really should verify that
5727 it is installed before doing much else --jerry */
5729 /* Check calling user has permission to update printer description */
5731 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5732 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5733 result = WERR_ACCESS_DENIED;
5734 goto done;
5737 /* Call addprinter hook */
5738 /* Check changes to see if this is really needed */
5740 if ( *lp_addprinter_cmd()
5741 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5742 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5743 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5744 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5746 /* add_printer_hook() will call reload_services() */
5748 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5749 printer) ) {
5750 result = WERR_ACCESS_DENIED;
5751 goto done;
5756 * When a *new* driver is bound to a printer, the drivername is used to
5757 * lookup previously saved driver initialization info, which is then
5758 * bound to the printer, simulating what happens in the Windows arch.
5760 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5762 if (!set_driver_init(printer, 2))
5764 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5765 printer->info_2->drivername));
5768 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5769 printer->info_2->drivername));
5771 notify_printer_driver(snum, printer->info_2->drivername);
5775 * flag which changes actually occured. This is a small subset of
5776 * all the possible changes. We also have to update things in the
5777 * DsSpooler key.
5780 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5781 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
5782 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5783 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5785 notify_printer_comment(snum, printer->info_2->comment);
5788 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5789 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
5790 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5791 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5793 notify_printer_sharename(snum, printer->info_2->sharename);
5796 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5797 char *pname;
5799 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5800 pname++;
5801 else
5802 pname = printer->info_2->printername;
5805 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
5806 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5807 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5809 notify_printer_printername( snum, pname );
5812 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5813 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
5814 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5815 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5817 notify_printer_port(snum, printer->info_2->portname);
5820 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5821 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
5822 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5823 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5825 notify_printer_location(snum, printer->info_2->location);
5828 /* here we need to update some more DsSpooler keys */
5829 /* uNCName, serverName, shortServerName */
5831 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
5832 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5833 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5834 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5835 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5837 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5838 global_myname(), printer->info_2->sharename );
5839 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
5840 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5841 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5843 /* Update printer info */
5844 result = mod_a_printer(printer, 2);
5846 done:
5847 free_a_printer(&printer, 2);
5848 free_a_printer(&old_printer, 2);
5851 return result;
5854 /****************************************************************************
5855 ****************************************************************************/
5856 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
5857 struct spoolss_SetPrinterInfo7 *info7)
5859 #ifdef HAVE_ADS
5860 int snum;
5861 Printer_entry *Printer;
5863 if ( lp_security() != SEC_ADS ) {
5864 return WERR_UNKNOWN_LEVEL;
5867 Printer = find_printer_index_by_hnd(p, handle);
5869 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5871 if (!Printer)
5872 return WERR_BADFID;
5874 if (!get_printer_snum(p, handle, &snum, NULL))
5875 return WERR_BADFID;
5877 nt_printer_publish(Printer, snum, info7->action);
5879 return WERR_OK;
5880 #else
5881 return WERR_UNKNOWN_LEVEL;
5882 #endif
5885 /****************************************************************
5886 _spoolss_SetPrinter
5887 ****************************************************************/
5889 WERROR _spoolss_SetPrinter(pipes_struct *p,
5890 struct spoolss_SetPrinter *r)
5892 POLICY_HND *handle = r->in.handle;
5893 WERROR result;
5895 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5897 if (!Printer) {
5898 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5899 OUR_HANDLE(handle)));
5900 return WERR_BADFID;
5903 /* check the level */
5904 switch (r->in.info_ctr->level) {
5905 case 0:
5906 return control_printer(handle, r->in.command, p);
5907 case 2:
5908 result = update_printer(p, handle,
5909 r->in.info_ctr,
5910 r->in.devmode_ctr->devmode);
5911 if (!W_ERROR_IS_OK(result))
5912 return result;
5913 if (r->in.secdesc_ctr->sd)
5914 result = update_printer_sec(handle, p,
5915 r->in.secdesc_ctr);
5916 return result;
5917 case 3:
5918 return update_printer_sec(handle, p,
5919 r->in.secdesc_ctr);
5920 case 7:
5921 return publish_or_unpublish_printer(p, handle,
5922 r->in.info_ctr->info.info7);
5923 default:
5924 return WERR_UNKNOWN_LEVEL;
5928 /****************************************************************
5929 _spoolss_FindClosePrinterNotify
5930 ****************************************************************/
5932 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5933 struct spoolss_FindClosePrinterNotify *r)
5935 POLICY_HND *handle = r->in.handle;
5936 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5938 if (!Printer) {
5939 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5940 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5941 return WERR_BADFID;
5944 if (Printer->notify.client_connected==True) {
5945 int snum = -1;
5947 if ( Printer->printer_type == SPLHND_SERVER)
5948 snum = -1;
5949 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5950 !get_printer_snum(p, handle, &snum, NULL) )
5951 return WERR_BADFID;
5953 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5956 Printer->notify.flags=0;
5957 Printer->notify.options=0;
5958 Printer->notify.localmachine[0]='\0';
5959 Printer->notify.printerlocal=0;
5960 TALLOC_FREE(Printer->notify.option);
5961 Printer->notify.client_connected=False;
5963 return WERR_OK;
5966 /****************************************************************
5967 _spoolss_AddJob
5968 ****************************************************************/
5970 WERROR _spoolss_AddJob(pipes_struct *p,
5971 struct spoolss_AddJob *r)
5973 if (!r->in.buffer && (r->in.offered != 0)) {
5974 return WERR_INVALID_PARAM;
5977 /* this is what a NT server returns for AddJob. AddJob must fail on
5978 * non-local printers */
5980 if (r->in.level != 1) {
5981 return WERR_UNKNOWN_LEVEL;
5984 return WERR_INVALID_PARAM;
5987 /****************************************************************************
5988 fill_job_info1
5989 ****************************************************************************/
5991 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5992 struct spoolss_JobInfo1 *r,
5993 const print_queue_struct *queue,
5994 int position, int snum,
5995 const NT_PRINTER_INFO_LEVEL *ntprinter)
5997 struct tm *t;
5999 t = gmtime(&queue->time);
6001 r->job_id = queue->job;
6003 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6004 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6005 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6006 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6007 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6008 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6009 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6010 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6011 r->data_type = talloc_strdup(mem_ctx, "RAW");
6012 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6013 r->text_status = talloc_strdup(mem_ctx, "");
6014 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6016 r->status = nt_printj_status(queue->status);
6017 r->priority = queue->priority;
6018 r->position = position;
6019 r->total_pages = queue->page_count;
6020 r->pages_printed = 0; /* ??? */
6022 init_systemtime(&r->submitted, t);
6024 return WERR_OK;
6027 /****************************************************************************
6028 fill_job_info2
6029 ****************************************************************************/
6031 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6032 struct spoolss_JobInfo2 *r,
6033 const print_queue_struct *queue,
6034 int position, int snum,
6035 const NT_PRINTER_INFO_LEVEL *ntprinter,
6036 struct spoolss_DeviceMode *devmode)
6038 struct tm *t;
6040 t = gmtime(&queue->time);
6042 r->job_id = queue->job;
6044 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6045 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6046 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6047 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6048 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6049 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6050 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6051 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6052 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6053 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6054 r->data_type = talloc_strdup(mem_ctx, "RAW");
6055 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6056 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6057 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6058 r->parameters = talloc_strdup(mem_ctx, "");
6059 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6060 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6061 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6063 r->devmode = devmode;
6065 r->text_status = talloc_strdup(mem_ctx, "");
6066 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6068 r->secdesc = NULL;
6070 r->status = nt_printj_status(queue->status);
6071 r->priority = queue->priority;
6072 r->position = position;
6073 r->start_time = 0;
6074 r->until_time = 0;
6075 r->total_pages = queue->page_count;
6076 r->size = queue->size;
6077 init_systemtime(&r->submitted, t);
6078 r->time = 0;
6079 r->pages_printed = 0; /* ??? */
6081 return WERR_OK;
6084 /****************************************************************************
6085 Enumjobs at level 1.
6086 ****************************************************************************/
6088 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6089 const print_queue_struct *queue,
6090 uint32_t num_queues, int snum,
6091 const NT_PRINTER_INFO_LEVEL *ntprinter,
6092 union spoolss_JobInfo **info_p,
6093 uint32_t *count)
6095 union spoolss_JobInfo *info;
6096 int i;
6097 WERROR result = WERR_OK;
6099 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6100 W_ERROR_HAVE_NO_MEMORY(info);
6102 *count = num_queues;
6104 for (i=0; i<*count; i++) {
6105 result = fill_job_info1(info,
6106 &info[i].info1,
6107 &queue[i],
6109 snum,
6110 ntprinter);
6111 if (!W_ERROR_IS_OK(result)) {
6112 goto out;
6116 out:
6117 if (!W_ERROR_IS_OK(result)) {
6118 TALLOC_FREE(info);
6119 *count = 0;
6120 return result;
6123 *info_p = info;
6125 return WERR_OK;
6128 /****************************************************************************
6129 Enumjobs at level 2.
6130 ****************************************************************************/
6132 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6133 const print_queue_struct *queue,
6134 uint32_t num_queues, int snum,
6135 const NT_PRINTER_INFO_LEVEL *ntprinter,
6136 union spoolss_JobInfo **info_p,
6137 uint32_t *count)
6139 union spoolss_JobInfo *info;
6140 int i;
6141 WERROR result = WERR_OK;
6143 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6144 W_ERROR_HAVE_NO_MEMORY(info);
6146 *count = num_queues;
6148 for (i=0; i<*count; i++) {
6150 struct spoolss_DeviceMode *devmode;
6152 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6153 if (!devmode) {
6154 result = WERR_NOMEM;
6155 goto out;
6158 result = fill_job_info2(info,
6159 &info[i].info2,
6160 &queue[i],
6162 snum,
6163 ntprinter,
6164 devmode);
6165 if (!W_ERROR_IS_OK(result)) {
6166 goto out;
6170 out:
6171 if (!W_ERROR_IS_OK(result)) {
6172 TALLOC_FREE(info);
6173 *count = 0;
6174 return result;
6177 *info_p = info;
6179 return WERR_OK;
6182 /****************************************************************
6183 _spoolss_EnumJobs
6184 ****************************************************************/
6186 WERROR _spoolss_EnumJobs(pipes_struct *p,
6187 struct spoolss_EnumJobs *r)
6189 WERROR result;
6190 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6191 int snum;
6192 print_status_struct prt_status;
6193 print_queue_struct *queue = NULL;
6194 uint32_t count;
6196 /* that's an [in out] buffer */
6198 if (!r->in.buffer && (r->in.offered != 0)) {
6199 return WERR_INVALID_PARAM;
6202 DEBUG(4,("_spoolss_EnumJobs\n"));
6204 *r->out.needed = 0;
6205 *r->out.count = 0;
6206 *r->out.info = NULL;
6208 /* lookup the printer snum and tdb entry */
6210 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6211 return WERR_BADFID;
6214 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6215 if (!W_ERROR_IS_OK(result)) {
6216 return result;
6219 count = print_queue_status(snum, &queue, &prt_status);
6220 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6221 count, prt_status.status, prt_status.message));
6223 if (count == 0) {
6224 SAFE_FREE(queue);
6225 free_a_printer(&ntprinter, 2);
6226 return WERR_OK;
6229 switch (r->in.level) {
6230 case 1:
6231 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6232 ntprinter, r->out.info, r->out.count);
6233 break;
6234 case 2:
6235 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6236 ntprinter, r->out.info, r->out.count);
6237 break;
6238 default:
6239 result = WERR_UNKNOWN_LEVEL;
6240 break;
6243 SAFE_FREE(queue);
6244 free_a_printer(&ntprinter, 2);
6246 if (!W_ERROR_IS_OK(result)) {
6247 return result;
6250 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6251 spoolss_EnumJobs, NULL,
6252 *r->out.info, r->in.level,
6253 *r->out.count);
6254 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6255 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6257 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6260 /****************************************************************
6261 _spoolss_ScheduleJob
6262 ****************************************************************/
6264 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6265 struct spoolss_ScheduleJob *r)
6267 return WERR_OK;
6270 /****************************************************************
6271 _spoolss_SetJob
6272 ****************************************************************/
6274 WERROR _spoolss_SetJob(pipes_struct *p,
6275 struct spoolss_SetJob *r)
6277 POLICY_HND *handle = r->in.handle;
6278 uint32 jobid = r->in.job_id;
6279 uint32 command = r->in.command;
6281 int snum;
6282 WERROR errcode = WERR_BADFUNC;
6284 if (!get_printer_snum(p, handle, &snum, NULL)) {
6285 return WERR_BADFID;
6288 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6289 return WERR_INVALID_PRINTER_NAME;
6292 switch (command) {
6293 case SPOOLSS_JOB_CONTROL_CANCEL:
6294 case SPOOLSS_JOB_CONTROL_DELETE:
6295 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6296 errcode = WERR_OK;
6298 break;
6299 case SPOOLSS_JOB_CONTROL_PAUSE:
6300 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6301 errcode = WERR_OK;
6303 break;
6304 case SPOOLSS_JOB_CONTROL_RESTART:
6305 case SPOOLSS_JOB_CONTROL_RESUME:
6306 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6307 errcode = WERR_OK;
6309 break;
6310 default:
6311 return WERR_UNKNOWN_LEVEL;
6314 return errcode;
6317 /****************************************************************************
6318 Enumerates all printer drivers at level 1.
6319 ****************************************************************************/
6321 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6322 const char *servername,
6323 const char *architecture,
6324 union spoolss_DriverInfo **info_p,
6325 uint32_t *count)
6327 int i;
6328 int ndrivers;
6329 uint32_t version;
6330 fstring *list = NULL;
6331 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6332 union spoolss_DriverInfo *info = NULL;
6333 WERROR result = WERR_OK;
6335 *count = 0;
6337 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6338 list = NULL;
6339 ndrivers = get_ntdrivers(&list, architecture, version);
6340 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6341 ndrivers, architecture, version));
6343 if (ndrivers == -1) {
6344 result = WERR_NOMEM;
6345 goto out;
6348 if (ndrivers != 0) {
6349 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6350 union spoolss_DriverInfo,
6351 *count + ndrivers);
6352 if (!info) {
6353 DEBUG(0,("enumprinterdrivers_level1: "
6354 "failed to enlarge driver info buffer!\n"));
6355 result = WERR_NOMEM;
6356 goto out;
6360 for (i=0; i<ndrivers; i++) {
6361 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6362 ZERO_STRUCT(driver);
6363 result = get_a_printer_driver(&driver, 3, list[i],
6364 architecture, version);
6365 if (!W_ERROR_IS_OK(result)) {
6366 goto out;
6368 result = fill_printer_driver_info1(info, &info[*count+i].info1,
6369 &driver, servername,
6370 architecture);
6371 if (!W_ERROR_IS_OK(result)) {
6372 free_a_printer_driver(driver, 3);
6373 goto out;
6375 free_a_printer_driver(driver, 3);
6378 *count += ndrivers;
6379 SAFE_FREE(list);
6382 out:
6383 SAFE_FREE(list);
6385 if (!W_ERROR_IS_OK(result)) {
6386 TALLOC_FREE(info);
6387 *count = 0;
6388 return result;
6391 *info_p = info;
6393 return WERR_OK;
6396 /****************************************************************************
6397 Enumerates all printer drivers at level 2.
6398 ****************************************************************************/
6400 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6401 const char *servername,
6402 const char *architecture,
6403 union spoolss_DriverInfo **info_p,
6404 uint32_t *count)
6406 int i;
6407 int ndrivers;
6408 uint32_t version;
6409 fstring *list = NULL;
6410 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6411 union spoolss_DriverInfo *info = NULL;
6412 WERROR result = WERR_OK;
6414 *count = 0;
6416 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6417 list = NULL;
6418 ndrivers = get_ntdrivers(&list, architecture, version);
6419 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6420 ndrivers, architecture, version));
6422 if (ndrivers == -1) {
6423 result = WERR_NOMEM;
6424 goto out;
6427 if (ndrivers != 0) {
6428 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6429 union spoolss_DriverInfo,
6430 *count + ndrivers);
6431 if (!info) {
6432 DEBUG(0,("enumprinterdrivers_level2: "
6433 "failed to enlarge driver info buffer!\n"));
6434 result = WERR_NOMEM;
6435 goto out;
6439 for (i=0; i<ndrivers; i++) {
6440 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6441 ZERO_STRUCT(driver);
6442 result = get_a_printer_driver(&driver, 3, list[i],
6443 architecture, version);
6444 if (!W_ERROR_IS_OK(result)) {
6445 goto out;
6447 result = fill_printer_driver_info2(info, &info[*count+i].info2,
6448 &driver, servername);
6449 if (!W_ERROR_IS_OK(result)) {
6450 free_a_printer_driver(driver, 3);
6451 goto out;
6453 free_a_printer_driver(driver, 3);
6456 *count += ndrivers;
6457 SAFE_FREE(list);
6460 out:
6461 SAFE_FREE(list);
6463 if (!W_ERROR_IS_OK(result)) {
6464 TALLOC_FREE(info);
6465 *count = 0;
6466 return result;
6469 *info_p = info;
6471 return WERR_OK;
6474 /****************************************************************************
6475 Enumerates all printer drivers at level 3.
6476 ****************************************************************************/
6478 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6479 const char *servername,
6480 const char *architecture,
6481 union spoolss_DriverInfo **info_p,
6482 uint32_t *count)
6484 int i;
6485 int ndrivers;
6486 uint32_t version;
6487 fstring *list = NULL;
6488 union spoolss_DriverInfo *info = NULL;
6489 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6490 WERROR result = WERR_OK;
6492 *count = 0;
6494 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6495 list = NULL;
6496 ndrivers = get_ntdrivers(&list, architecture, version);
6497 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6498 ndrivers, architecture, version));
6500 if (ndrivers == -1) {
6501 result = WERR_NOMEM;
6502 goto out;
6505 if (ndrivers != 0) {
6506 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6507 union spoolss_DriverInfo,
6508 *count + ndrivers);
6509 if (!info) {
6510 DEBUG(0,("enumprinterdrivers_level3: "
6511 "failed to enlarge driver info buffer!\n"));
6512 result = WERR_NOMEM;
6513 goto out;
6517 for (i=0; i<ndrivers; i++) {
6518 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6519 ZERO_STRUCT(driver);
6520 result = get_a_printer_driver(&driver, 3, list[i],
6521 architecture, version);
6522 if (!W_ERROR_IS_OK(result)) {
6523 goto out;
6525 result = fill_printer_driver_info3(info, &info[*count+i].info3,
6526 &driver, servername);
6527 if (!W_ERROR_IS_OK(result)) {
6528 free_a_printer_driver(driver, 3);
6529 goto out;
6532 free_a_printer_driver(driver, 3);
6535 *count += ndrivers;
6536 SAFE_FREE(list);
6539 out:
6540 SAFE_FREE(list);
6542 if (!W_ERROR_IS_OK(result)) {
6543 TALLOC_FREE(info);
6544 *count = 0;
6545 return result;
6548 *info_p = info;
6550 return WERR_OK;
6553 /****************************************************************
6554 _spoolss_EnumPrinterDrivers
6555 ****************************************************************/
6557 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6558 struct spoolss_EnumPrinterDrivers *r)
6560 const char *cservername;
6561 WERROR result;
6563 /* that's an [in out] buffer */
6565 if (!r->in.buffer && (r->in.offered != 0)) {
6566 return WERR_INVALID_PARAM;
6569 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6571 *r->out.needed = 0;
6572 *r->out.count = 0;
6573 *r->out.info = NULL;
6575 cservername = canon_servername(r->in.server);
6577 if (!is_myname_or_ipaddr(cservername)) {
6578 return WERR_UNKNOWN_PRINTER_DRIVER;
6581 switch (r->in.level) {
6582 case 1:
6583 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6584 r->in.environment,
6585 r->out.info, r->out.count);
6586 break;
6587 case 2:
6588 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6589 r->in.environment,
6590 r->out.info, r->out.count);
6591 break;
6592 case 3:
6593 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6594 r->in.environment,
6595 r->out.info, r->out.count);
6596 break;
6597 default:
6598 return WERR_UNKNOWN_LEVEL;
6601 if (!W_ERROR_IS_OK(result)) {
6602 return result;
6605 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6606 spoolss_EnumPrinterDrivers, NULL,
6607 *r->out.info, r->in.level,
6608 *r->out.count);
6609 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6610 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6612 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6615 /****************************************************************************
6616 ****************************************************************************/
6618 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6619 struct spoolss_FormInfo1 *r,
6620 const nt_forms_struct *form)
6622 r->form_name = talloc_strdup(mem_ctx, form->name);
6623 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6625 r->flags = form->flag;
6626 r->size.width = form->width;
6627 r->size.height = form->length;
6628 r->area.left = form->left;
6629 r->area.top = form->top;
6630 r->area.right = form->right;
6631 r->area.bottom = form->bottom;
6633 return WERR_OK;
6636 /****************************************************************
6637 spoolss_enumforms_level1
6638 ****************************************************************/
6640 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6641 const nt_forms_struct *builtin_forms,
6642 uint32_t num_builtin_forms,
6643 const nt_forms_struct *user_forms,
6644 uint32_t num_user_forms,
6645 union spoolss_FormInfo **info_p,
6646 uint32_t *count)
6648 union spoolss_FormInfo *info;
6649 WERROR result = WERR_OK;
6650 int i;
6652 *count = num_builtin_forms + num_user_forms;
6654 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6655 W_ERROR_HAVE_NO_MEMORY(info);
6657 /* construct the list of form structures */
6658 for (i=0; i<num_builtin_forms; i++) {
6659 DEBUGADD(6,("Filling form number [%d]\n",i));
6660 result = fill_form_info_1(info, &info[i].info1,
6661 &builtin_forms[i]);
6662 if (!W_ERROR_IS_OK(result)) {
6663 goto out;
6667 for (; i<num_user_forms; i++) {
6668 DEBUGADD(6,("Filling form number [%d]\n",i));
6669 result = fill_form_info_1(info, &info[i].info1,
6670 &user_forms[i-num_builtin_forms]);
6671 if (!W_ERROR_IS_OK(result)) {
6672 goto out;
6676 out:
6677 if (!W_ERROR_IS_OK(result)) {
6678 TALLOC_FREE(info);
6679 *count = 0;
6680 return result;
6683 *info_p = info;
6685 return WERR_OK;
6688 /****************************************************************
6689 _spoolss_EnumForms
6690 ****************************************************************/
6692 WERROR _spoolss_EnumForms(pipes_struct *p,
6693 struct spoolss_EnumForms *r)
6695 WERROR result;
6696 nt_forms_struct *user_forms = NULL;
6697 nt_forms_struct *builtin_forms = NULL;
6698 uint32_t num_user_forms;
6699 uint32_t num_builtin_forms;
6701 *r->out.count = 0;
6702 *r->out.needed = 0;
6703 *r->out.info = NULL;
6705 /* that's an [in out] buffer */
6707 if (!r->in.buffer && (r->in.offered != 0) ) {
6708 return WERR_INVALID_PARAM;
6711 DEBUG(4,("_spoolss_EnumForms\n"));
6712 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6713 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6715 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6716 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6717 num_user_forms = get_ntforms(&user_forms);
6718 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6720 if (num_user_forms + num_builtin_forms == 0) {
6721 SAFE_FREE(builtin_forms);
6722 SAFE_FREE(user_forms);
6723 return WERR_NO_MORE_ITEMS;
6726 switch (r->in.level) {
6727 case 1:
6728 result = spoolss_enumforms_level1(p->mem_ctx,
6729 builtin_forms,
6730 num_builtin_forms,
6731 user_forms,
6732 num_user_forms,
6733 r->out.info,
6734 r->out.count);
6735 break;
6736 default:
6737 result = WERR_UNKNOWN_LEVEL;
6738 break;
6741 SAFE_FREE(user_forms);
6742 SAFE_FREE(builtin_forms);
6744 if (!W_ERROR_IS_OK(result)) {
6745 return result;
6748 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6749 spoolss_EnumForms, NULL,
6750 *r->out.info, r->in.level,
6751 *r->out.count);
6752 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6753 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6755 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6758 /****************************************************************
6759 ****************************************************************/
6761 static WERROR find_form_byname(const char *name,
6762 nt_forms_struct *form)
6764 nt_forms_struct *list = NULL;
6765 int num_forms = 0, i = 0;
6767 if (get_a_builtin_ntform_by_string(name, form)) {
6768 return WERR_OK;
6771 num_forms = get_ntforms(&list);
6772 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6774 if (num_forms == 0) {
6775 return WERR_BADFID;
6778 /* Check if the requested name is in the list of form structures */
6779 for (i = 0; i < num_forms; i++) {
6781 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6783 if (strequal(name, list[i].name)) {
6784 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6785 *form = list[i];
6786 SAFE_FREE(list);
6787 return WERR_OK;
6791 SAFE_FREE(list);
6793 return WERR_BADFID;
6796 /****************************************************************
6797 _spoolss_GetForm
6798 ****************************************************************/
6800 WERROR _spoolss_GetForm(pipes_struct *p,
6801 struct spoolss_GetForm *r)
6803 WERROR result;
6804 nt_forms_struct form;
6806 /* that's an [in out] buffer */
6808 if (!r->in.buffer && (r->in.offered != 0)) {
6809 return WERR_INVALID_PARAM;
6812 DEBUG(4,("_spoolss_GetForm\n"));
6813 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6814 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6816 result = find_form_byname(r->in.form_name, &form);
6817 if (!W_ERROR_IS_OK(result)) {
6818 TALLOC_FREE(r->out.info);
6819 return result;
6822 switch (r->in.level) {
6823 case 1:
6824 result = fill_form_info_1(p->mem_ctx,
6825 &r->out.info->info1,
6826 &form);
6827 break;
6829 default:
6830 result = WERR_UNKNOWN_LEVEL;
6831 break;
6834 if (!W_ERROR_IS_OK(result)) {
6835 TALLOC_FREE(r->out.info);
6836 return result;
6839 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6840 r->out.info, r->in.level);
6841 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6843 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6846 /****************************************************************************
6847 ****************************************************************************/
6849 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6850 struct spoolss_PortInfo1 *r,
6851 const char *name)
6853 r->port_name = talloc_strdup(mem_ctx, name);
6854 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6856 return WERR_OK;
6859 /****************************************************************************
6860 TODO: This probably needs distinguish between TCP/IP and Local ports
6861 somehow.
6862 ****************************************************************************/
6864 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6865 struct spoolss_PortInfo2 *r,
6866 const char *name)
6868 r->port_name = talloc_strdup(mem_ctx, name);
6869 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6871 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6872 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6874 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6875 W_ERROR_HAVE_NO_MEMORY(r->description);
6877 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6878 r->reserved = 0;
6880 return WERR_OK;
6884 /****************************************************************************
6885 wrapper around the enumer ports command
6886 ****************************************************************************/
6888 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
6890 char *cmd = lp_enumports_cmd();
6891 char **qlines = NULL;
6892 char *command = NULL;
6893 int numlines;
6894 int ret;
6895 int fd;
6897 *count = 0;
6898 *lines = NULL;
6900 /* if no hook then just fill in the default port */
6902 if ( !*cmd ) {
6903 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6904 return WERR_NOMEM;
6906 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6907 TALLOC_FREE(qlines);
6908 return WERR_NOMEM;
6910 qlines[1] = NULL;
6911 numlines = 1;
6913 else {
6914 /* we have a valid enumport command */
6916 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6917 if (!command) {
6918 return WERR_NOMEM;
6921 DEBUG(10,("Running [%s]\n", command));
6922 ret = smbrun(command, &fd);
6923 DEBUG(10,("Returned [%d]\n", ret));
6924 TALLOC_FREE(command);
6925 if (ret != 0) {
6926 if (fd != -1) {
6927 close(fd);
6929 return WERR_ACCESS_DENIED;
6932 numlines = 0;
6933 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6934 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6935 close(fd);
6938 *count = numlines;
6939 *lines = qlines;
6941 return WERR_OK;
6944 /****************************************************************************
6945 enumports level 1.
6946 ****************************************************************************/
6948 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6949 union spoolss_PortInfo **info_p,
6950 uint32_t *count)
6952 union spoolss_PortInfo *info = NULL;
6953 int i=0;
6954 WERROR result = WERR_OK;
6955 char **qlines = NULL;
6956 int numlines = 0;
6958 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6959 if (!W_ERROR_IS_OK(result)) {
6960 goto out;
6963 if (numlines) {
6964 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6965 if (!info) {
6966 DEBUG(10,("Returning WERR_NOMEM\n"));
6967 result = WERR_NOMEM;
6968 goto out;
6971 for (i=0; i<numlines; i++) {
6972 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6973 result = fill_port_1(info, &info[i].info1, qlines[i]);
6974 if (!W_ERROR_IS_OK(result)) {
6975 goto out;
6979 TALLOC_FREE(qlines);
6981 out:
6982 if (!W_ERROR_IS_OK(result)) {
6983 TALLOC_FREE(info);
6984 TALLOC_FREE(qlines);
6985 *count = 0;
6986 *info_p = NULL;
6987 return result;
6990 *info_p = info;
6991 *count = numlines;
6993 return WERR_OK;
6996 /****************************************************************************
6997 enumports level 2.
6998 ****************************************************************************/
7000 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7001 union spoolss_PortInfo **info_p,
7002 uint32_t *count)
7004 union spoolss_PortInfo *info = NULL;
7005 int i=0;
7006 WERROR result = WERR_OK;
7007 char **qlines = NULL;
7008 int numlines = 0;
7010 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7011 if (!W_ERROR_IS_OK(result)) {
7012 goto out;
7015 if (numlines) {
7016 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7017 if (!info) {
7018 DEBUG(10,("Returning WERR_NOMEM\n"));
7019 result = WERR_NOMEM;
7020 goto out;
7023 for (i=0; i<numlines; i++) {
7024 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7025 result = fill_port_2(info, &info[i].info2, qlines[i]);
7026 if (!W_ERROR_IS_OK(result)) {
7027 goto out;
7031 TALLOC_FREE(qlines);
7033 out:
7034 if (!W_ERROR_IS_OK(result)) {
7035 TALLOC_FREE(info);
7036 TALLOC_FREE(qlines);
7037 *count = 0;
7038 *info_p = NULL;
7039 return result;
7042 *info_p = info;
7043 *count = numlines;
7045 return WERR_OK;
7048 /****************************************************************
7049 _spoolss_EnumPorts
7050 ****************************************************************/
7052 WERROR _spoolss_EnumPorts(pipes_struct *p,
7053 struct spoolss_EnumPorts *r)
7055 WERROR result;
7057 /* that's an [in out] buffer */
7059 if (!r->in.buffer && (r->in.offered != 0)) {
7060 return WERR_INVALID_PARAM;
7063 DEBUG(4,("_spoolss_EnumPorts\n"));
7065 *r->out.count = 0;
7066 *r->out.needed = 0;
7067 *r->out.info = NULL;
7069 switch (r->in.level) {
7070 case 1:
7071 result = enumports_level_1(p->mem_ctx, r->out.info,
7072 r->out.count);
7073 break;
7074 case 2:
7075 result = enumports_level_2(p->mem_ctx, r->out.info,
7076 r->out.count);
7077 break;
7078 default:
7079 return WERR_UNKNOWN_LEVEL;
7082 if (!W_ERROR_IS_OK(result)) {
7083 return result;
7086 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7087 spoolss_EnumPorts, NULL,
7088 *r->out.info, r->in.level,
7089 *r->out.count);
7090 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7091 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7093 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7096 /****************************************************************************
7097 ****************************************************************************/
7099 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7100 const char *server,
7101 struct spoolss_SetPrinterInfoCtr *info_ctr,
7102 struct spoolss_DeviceMode *devmode,
7103 struct security_descriptor *sec_desc,
7104 struct spoolss_UserLevelCtr *user_ctr,
7105 POLICY_HND *handle)
7107 NT_PRINTER_INFO_LEVEL *printer = NULL;
7108 fstring name;
7109 int snum;
7110 WERROR err = WERR_OK;
7112 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7113 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7114 return WERR_NOMEM;
7117 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7118 if (!convert_printer_info(info_ctr, printer)) {
7119 free_a_printer(&printer, 2);
7120 return WERR_NOMEM;
7123 /* check to see if the printer already exists */
7125 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7126 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7127 printer->info_2->sharename));
7128 free_a_printer(&printer, 2);
7129 return WERR_PRINTER_ALREADY_EXISTS;
7132 /* FIXME!!! smbd should check to see if the driver is installed before
7133 trying to add a printer like this --jerry */
7135 if (*lp_addprinter_cmd() ) {
7136 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7137 printer) ) {
7138 free_a_printer(&printer,2);
7139 return WERR_ACCESS_DENIED;
7141 } else {
7142 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7143 "smb.conf parameter \"addprinter command\" is defined. This"
7144 "parameter must exist for this call to succeed\n",
7145 printer->info_2->sharename ));
7148 /* use our primary netbios name since get_a_printer() will convert
7149 it to what the client expects on a case by case basis */
7151 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7152 printer->info_2->sharename);
7155 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7156 free_a_printer(&printer,2);
7157 return WERR_ACCESS_DENIED;
7160 /* you must be a printer admin to add a new printer */
7161 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7162 free_a_printer(&printer,2);
7163 return WERR_ACCESS_DENIED;
7167 * Do sanity check on the requested changes for Samba.
7170 if (!check_printer_ok(printer->info_2, snum)) {
7171 free_a_printer(&printer,2);
7172 return WERR_INVALID_PARAM;
7176 * When a printer is created, the drivername bound to the printer is used
7177 * to lookup previously saved driver initialization info, which is then
7178 * bound to the new printer, simulating what happens in the Windows arch.
7181 if (!devmode)
7183 set_driver_init(printer, 2);
7185 else
7187 /* A valid devmode was included, convert and link it
7189 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7191 if (!convert_devicemode(printer->info_2->printername, devmode,
7192 &printer->info_2->devmode)) {
7193 return WERR_NOMEM;
7197 /* write the ASCII on disk */
7198 err = mod_a_printer(printer, 2);
7199 if (!W_ERROR_IS_OK(err)) {
7200 free_a_printer(&printer,2);
7201 return err;
7204 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7205 /* Handle open failed - remove addition. */
7206 del_a_printer(printer->info_2->sharename);
7207 free_a_printer(&printer,2);
7208 ZERO_STRUCTP(handle);
7209 return WERR_ACCESS_DENIED;
7212 update_c_setprinter(False);
7213 free_a_printer(&printer,2);
7215 return WERR_OK;
7218 /****************************************************************
7219 _spoolss_AddPrinterEx
7220 ****************************************************************/
7222 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7223 struct spoolss_AddPrinterEx *r)
7225 switch (r->in.info_ctr->level) {
7226 case 1:
7227 /* we don't handle yet */
7228 /* but I know what to do ... */
7229 return WERR_UNKNOWN_LEVEL;
7230 case 2:
7231 return spoolss_addprinterex_level_2(p, r->in.server,
7232 r->in.info_ctr,
7233 r->in.devmode_ctr->devmode,
7234 r->in.secdesc_ctr->sd,
7235 r->in.userlevel_ctr,
7236 r->out.handle);
7237 default:
7238 return WERR_UNKNOWN_LEVEL;
7242 /****************************************************************
7243 _spoolss_AddPrinterDriver
7244 ****************************************************************/
7246 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7247 struct spoolss_AddPrinterDriver *r)
7249 uint32_t level = r->in.info_ctr->level;
7250 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7251 WERROR err = WERR_OK;
7252 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7253 fstring driver_name;
7254 uint32 version;
7255 const char *fn;
7257 switch (p->hdr_req.opnum) {
7258 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7259 fn = "_spoolss_AddPrinterDriver";
7260 break;
7261 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7262 fn = "_spoolss_AddPrinterDriverEx";
7263 break;
7264 default:
7265 return WERR_INVALID_PARAM;
7269 /* FIXME */
7270 if (level != 3 && level != 6) {
7271 /* Clever hack from Martin Zielinski <mz@seh.de>
7272 * to allow downgrade from level 8 (Vista).
7274 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7275 return WERR_UNKNOWN_LEVEL;
7278 ZERO_STRUCT(driver);
7280 if (!convert_printer_driver_info(info, &driver, level)) {
7281 err = WERR_NOMEM;
7282 goto done;
7285 DEBUG(5,("Cleaning driver's information\n"));
7286 err = clean_up_driver_struct(p, driver, level);
7287 if (!W_ERROR_IS_OK(err))
7288 goto done;
7290 DEBUG(5,("Moving driver to final destination\n"));
7291 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7292 &err)) ) {
7293 goto done;
7296 if (add_a_printer_driver(driver, level)!=0) {
7297 err = WERR_ACCESS_DENIED;
7298 goto done;
7301 switch(level) {
7302 case 3:
7303 fstrcpy(driver_name,
7304 driver.info_3->name ? driver.info_3->name : "");
7305 break;
7306 case 6:
7307 fstrcpy(driver_name,
7308 driver.info_6->name ? driver.info_6->name : "");
7309 break;
7313 * I think this is where he DrvUpgradePrinter() hook would be
7314 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7315 * server. Right now, we just need to send ourselves a message
7316 * to update each printer bound to this driver. --jerry
7319 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7320 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7321 fn, driver_name));
7325 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7326 * decide if the driver init data should be deleted. The rules are:
7327 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7328 * 2) delete init data only if there is no 2k/Xp driver
7329 * 3) always delete init data
7330 * The generalized rule is always use init data from the highest order driver.
7331 * It is necessary to follow the driver install by an initialization step to
7332 * finish off this process.
7334 if (level == 3)
7335 version = driver.info_3->cversion;
7336 else if (level == 6)
7337 version = driver.info_6->version;
7338 else
7339 version = -1;
7340 switch (version) {
7342 * 9x printer driver - never delete init data
7344 case 0:
7345 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7346 fn, driver_name));
7347 break;
7350 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7351 * there is no 2k/Xp driver init data for this driver name.
7353 case 2:
7355 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7357 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7359 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7361 if (!del_driver_init(driver_name))
7362 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7363 fn, driver_name));
7364 } else {
7366 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7368 free_a_printer_driver(driver1,3);
7369 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7370 fn, driver_name));
7373 break;
7376 * 2k or Xp printer driver - always delete init data
7378 case 3:
7379 if (!del_driver_init(driver_name))
7380 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7381 fn, driver_name));
7382 break;
7384 default:
7385 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7386 break;
7390 done:
7391 free_a_printer_driver(driver, level);
7392 return err;
7395 /****************************************************************
7396 _spoolss_AddPrinterDriverEx
7397 ****************************************************************/
7399 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7400 struct spoolss_AddPrinterDriverEx *r)
7402 struct spoolss_AddPrinterDriver a;
7405 * we only support the semantics of AddPrinterDriver()
7406 * i.e. only copy files that are newer than existing ones
7409 if (r->in.flags != APD_COPY_NEW_FILES) {
7410 return WERR_ACCESS_DENIED;
7413 a.in.servername = r->in.servername;
7414 a.in.info_ctr = r->in.info_ctr;
7416 return _spoolss_AddPrinterDriver(p, &a);
7419 /****************************************************************************
7420 ****************************************************************************/
7422 struct _spoolss_paths {
7423 int type;
7424 const char *share;
7425 const char *dir;
7428 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7430 static const struct _spoolss_paths spoolss_paths[]= {
7431 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7432 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7435 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7436 const char *servername,
7437 const char *environment,
7438 int component,
7439 char **path)
7441 const char *pservername = NULL;
7442 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7443 const char *short_archi;
7445 *path = NULL;
7447 /* environment may be empty */
7448 if (environment && strlen(environment)) {
7449 long_archi = environment;
7452 /* servername may be empty */
7453 if (servername && strlen(servername)) {
7454 pservername = canon_servername(servername);
7456 if (!is_myname_or_ipaddr(pservername)) {
7457 return WERR_INVALID_PARAM;
7461 if (!(short_archi = get_short_archi(long_archi))) {
7462 return WERR_INVALID_ENVIRONMENT;
7465 switch (component) {
7466 case SPOOLSS_PRTPROCS_PATH:
7467 case SPOOLSS_DRIVER_PATH:
7468 if (pservername) {
7469 *path = talloc_asprintf(mem_ctx,
7470 "\\\\%s\\%s\\%s",
7471 pservername,
7472 spoolss_paths[component].share,
7473 short_archi);
7474 } else {
7475 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7476 SPOOLSS_DEFAULT_SERVER_PATH,
7477 spoolss_paths[component].dir,
7478 short_archi);
7480 break;
7481 default:
7482 return WERR_INVALID_PARAM;
7485 if (!*path) {
7486 return WERR_NOMEM;
7489 return WERR_OK;
7492 /****************************************************************************
7493 ****************************************************************************/
7495 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7496 const char *servername,
7497 const char *environment,
7498 struct spoolss_DriverDirectoryInfo1 *r)
7500 WERROR werr;
7501 char *path = NULL;
7503 werr = compose_spoolss_server_path(mem_ctx,
7504 servername,
7505 environment,
7506 SPOOLSS_DRIVER_PATH,
7507 &path);
7508 if (!W_ERROR_IS_OK(werr)) {
7509 return werr;
7512 DEBUG(4,("printer driver directory: [%s]\n", path));
7514 r->directory_name = path;
7516 return WERR_OK;
7519 /****************************************************************
7520 _spoolss_GetPrinterDriverDirectory
7521 ****************************************************************/
7523 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7524 struct spoolss_GetPrinterDriverDirectory *r)
7526 WERROR werror;
7528 /* that's an [in out] buffer */
7530 if (!r->in.buffer && (r->in.offered != 0)) {
7531 return WERR_INVALID_PARAM;
7534 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7535 r->in.level));
7537 *r->out.needed = 0;
7539 /* r->in.level is ignored */
7541 werror = getprinterdriverdir_level_1(p->mem_ctx,
7542 r->in.server,
7543 r->in.environment,
7544 &r->out.info->info1);
7545 if (!W_ERROR_IS_OK(werror)) {
7546 TALLOC_FREE(r->out.info);
7547 return werror;
7550 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7551 r->out.info, r->in.level);
7552 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7554 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7557 /****************************************************************
7558 _spoolss_EnumPrinterData
7559 ****************************************************************/
7561 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7562 struct spoolss_EnumPrinterData *r)
7564 NT_PRINTER_INFO_LEVEL *printer = NULL;
7565 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7566 int snum;
7567 WERROR result;
7568 REGISTRY_VALUE *val = NULL;
7569 NT_PRINTER_DATA *p_data;
7570 int i, key_index, num_values;
7571 int name_length;
7573 *r->out.value_needed = 0;
7574 *r->out.type = REG_NONE;
7575 *r->out.data_needed = 0;
7577 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7579 if (!Printer) {
7580 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7581 OUR_HANDLE(r->in.handle)));
7582 return WERR_BADFID;
7585 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7586 return WERR_BADFID;
7589 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7590 if (!W_ERROR_IS_OK(result)) {
7591 return result;
7594 p_data = printer->info_2->data;
7595 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7597 result = WERR_OK;
7600 * The NT machine wants to know the biggest size of value and data
7602 * cf: MSDN EnumPrinterData remark section
7605 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7607 uint32_t biggest_valuesize = 0;
7608 uint32_t biggest_datasize = 0;
7610 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7612 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7614 for ( i=0; i<num_values; i++ )
7616 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7618 name_length = strlen(val->valuename);
7619 if ( strlen(val->valuename) > biggest_valuesize )
7620 biggest_valuesize = name_length;
7622 if ( val->size > biggest_datasize )
7623 biggest_datasize = val->size;
7625 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7626 biggest_datasize));
7629 /* the value is an UNICODE string but real_value_size is the length
7630 in bytes including the trailing 0 */
7632 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7633 *r->out.data_needed = biggest_datasize;
7635 DEBUG(6,("final values: [%d], [%d]\n",
7636 *r->out.value_needed, *r->out.data_needed));
7638 goto done;
7642 * the value len is wrong in NT sp3
7643 * that's the number of bytes not the number of unicode chars
7646 if (key_index != -1) {
7647 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7648 r->in.enum_index);
7651 if (!val) {
7653 /* out_value should default to "" or else NT4 has
7654 problems unmarshalling the response */
7656 if (r->in.value_offered) {
7657 *r->out.value_needed = 1;
7658 r->out.value_name = talloc_strdup(r, "");
7659 if (!r->out.value_name) {
7660 result = WERR_NOMEM;
7661 goto done;
7663 } else {
7664 r->out.value_name = NULL;
7665 *r->out.value_needed = 0;
7668 /* the data is counted in bytes */
7670 *r->out.data_needed = r->in.data_offered;
7672 result = WERR_NO_MORE_ITEMS;
7673 } else {
7675 * the value is:
7676 * - counted in bytes in the request
7677 * - counted in UNICODE chars in the max reply
7678 * - counted in bytes in the real size
7680 * take a pause *before* coding not *during* coding
7683 /* name */
7684 if (r->in.value_offered) {
7685 r->out.value_name = talloc_strdup(r, regval_name(val));
7686 if (!r->out.value_name) {
7687 result = WERR_NOMEM;
7688 goto done;
7690 *r->out.value_needed = strlen_m(regval_name(val));
7691 } else {
7692 r->out.value_name = NULL;
7693 *r->out.value_needed = 0;
7696 /* type */
7698 *r->out.type = regval_type(val);
7700 /* data - counted in bytes */
7702 if (r->out.data && regval_size(val)) {
7703 memcpy(r->out.data, regval_data_p(val), regval_size(val));
7706 *r->out.data_needed = regval_size(val);
7709 done:
7710 free_a_printer(&printer, 2);
7711 return result;
7714 /****************************************************************
7715 _spoolss_SetPrinterData
7716 ****************************************************************/
7718 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7719 struct spoolss_SetPrinterData *r)
7721 NT_PRINTER_INFO_LEVEL *printer = NULL;
7722 int snum=0;
7723 WERROR result = WERR_OK;
7724 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7725 DATA_BLOB blob;
7727 DEBUG(5,("_spoolss_SetPrinterData\n"));
7729 if (!Printer) {
7730 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
7731 OUR_HANDLE(r->in.handle)));
7732 return WERR_BADFID;
7735 if (Printer->printer_type == SPLHND_SERVER) {
7736 DEBUG(10,("_spoolss_SetPrinterData: "
7737 "Not implemented for server handles yet\n"));
7738 return WERR_INVALID_PARAM;
7741 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7742 return WERR_BADFID;
7746 * Access check : NT returns "access denied" if you make a
7747 * SetPrinterData call without the necessary privildge.
7748 * we were originally returning OK if nothing changed
7749 * which made Win2k issue **a lot** of SetPrinterData
7750 * when connecting to a printer --jerry
7753 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7754 DEBUG(3,("_spoolss_SetPrinterData: "
7755 "change denied by handle access permissions\n"));
7756 result = WERR_ACCESS_DENIED;
7757 goto done;
7760 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7761 if (!W_ERROR_IS_OK(result)) {
7762 return result;
7765 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
7766 r->in.type, &r->in.data);
7767 if (!W_ERROR_IS_OK(result)) {
7768 goto done;
7772 * When client side code sets a magic printer data key, detect it and save
7773 * the current printer data and the magic key's data (its the DEVMODE) for
7774 * future printer/driver initializations.
7776 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
7777 /* Set devmode and printer initialization info */
7778 result = save_driver_init(printer, 2, blob.data, blob.length);
7780 srv_spoolss_reset_printerdata(printer->info_2->drivername);
7782 goto done;
7785 result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
7786 r->in.value_name, r->in.type,
7787 blob.data, blob.length);
7788 if (W_ERROR_IS_OK(result)) {
7789 result = mod_a_printer(printer, 2);
7792 done:
7793 free_a_printer(&printer, 2);
7795 return result;
7798 /****************************************************************
7799 _spoolss_ResetPrinter
7800 ****************************************************************/
7802 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7803 struct spoolss_ResetPrinter *r)
7805 POLICY_HND *handle = r->in.handle;
7806 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7807 int snum;
7809 DEBUG(5,("_spoolss_ResetPrinter\n"));
7812 * All we do is to check to see if the handle and queue is valid.
7813 * This call really doesn't mean anything to us because we only
7814 * support RAW printing. --jerry
7817 if (!Printer) {
7818 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7819 OUR_HANDLE(handle)));
7820 return WERR_BADFID;
7823 if (!get_printer_snum(p,handle, &snum, NULL))
7824 return WERR_BADFID;
7827 /* blindly return success */
7828 return WERR_OK;
7831 /****************************************************************
7832 _spoolss_DeletePrinterData
7833 ****************************************************************/
7835 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7836 struct spoolss_DeletePrinterData *r)
7838 POLICY_HND *handle = r->in.handle;
7839 NT_PRINTER_INFO_LEVEL *printer = NULL;
7840 int snum=0;
7841 WERROR status = WERR_OK;
7842 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7844 DEBUG(5,("_spoolss_DeletePrinterData\n"));
7846 if (!Printer) {
7847 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
7848 OUR_HANDLE(handle)));
7849 return WERR_BADFID;
7852 if (!get_printer_snum(p, handle, &snum, NULL))
7853 return WERR_BADFID;
7855 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7856 DEBUG(3, ("_spoolss_DeletePrinterData: "
7857 "printer properties change denied by handle\n"));
7858 return WERR_ACCESS_DENIED;
7861 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7862 if (!W_ERROR_IS_OK(status))
7863 return status;
7865 if (!r->in.value_name) {
7866 free_a_printer(&printer, 2);
7867 return WERR_NOMEM;
7870 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
7871 r->in.value_name );
7873 if ( W_ERROR_IS_OK(status) )
7874 mod_a_printer( printer, 2 );
7876 free_a_printer(&printer, 2);
7878 return status;
7881 /****************************************************************
7882 _spoolss_AddForm
7883 ****************************************************************/
7885 WERROR _spoolss_AddForm(pipes_struct *p,
7886 struct spoolss_AddForm *r)
7888 POLICY_HND *handle = r->in.handle;
7889 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7890 nt_forms_struct tmpForm;
7891 int snum;
7892 WERROR status = WERR_OK;
7893 NT_PRINTER_INFO_LEVEL *printer = NULL;
7895 int count=0;
7896 nt_forms_struct *list=NULL;
7897 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7899 DEBUG(5,("_spoolss_AddForm\n"));
7901 if (!Printer) {
7902 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7903 OUR_HANDLE(handle)));
7904 return WERR_BADFID;
7908 /* forms can be added on printer of on the print server handle */
7910 if ( Printer->printer_type == SPLHND_PRINTER )
7912 if (!get_printer_snum(p,handle, &snum, NULL))
7913 return WERR_BADFID;
7915 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7916 if (!W_ERROR_IS_OK(status))
7917 goto done;
7920 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7921 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7922 status = WERR_ACCESS_DENIED;
7923 goto done;
7926 /* can't add if builtin */
7928 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7929 status = WERR_FILE_EXISTS;
7930 goto done;
7933 count = get_ntforms(&list);
7935 if(!add_a_form(&list, form, &count)) {
7936 status = WERR_NOMEM;
7937 goto done;
7940 write_ntforms(&list, count);
7943 * ChangeID must always be set if this is a printer
7946 if ( Printer->printer_type == SPLHND_PRINTER )
7947 status = mod_a_printer(printer, 2);
7949 done:
7950 if ( printer )
7951 free_a_printer(&printer, 2);
7952 SAFE_FREE(list);
7954 return status;
7957 /****************************************************************
7958 _spoolss_DeleteForm
7959 ****************************************************************/
7961 WERROR _spoolss_DeleteForm(pipes_struct *p,
7962 struct spoolss_DeleteForm *r)
7964 POLICY_HND *handle = r->in.handle;
7965 const char *form_name = r->in.form_name;
7966 nt_forms_struct tmpForm;
7967 int count=0;
7968 nt_forms_struct *list=NULL;
7969 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7970 int snum;
7971 WERROR status = WERR_OK;
7972 NT_PRINTER_INFO_LEVEL *printer = NULL;
7974 DEBUG(5,("_spoolss_DeleteForm\n"));
7976 if (!Printer) {
7977 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7978 OUR_HANDLE(handle)));
7979 return WERR_BADFID;
7982 /* forms can be deleted on printer of on the print server handle */
7984 if ( Printer->printer_type == SPLHND_PRINTER )
7986 if (!get_printer_snum(p,handle, &snum, NULL))
7987 return WERR_BADFID;
7989 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7990 if (!W_ERROR_IS_OK(status))
7991 goto done;
7994 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7995 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
7996 status = WERR_ACCESS_DENIED;
7997 goto done;
8000 /* can't delete if builtin */
8002 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8003 status = WERR_INVALID_PARAM;
8004 goto done;
8007 count = get_ntforms(&list);
8009 if ( !delete_a_form(&list, form_name, &count, &status ))
8010 goto done;
8013 * ChangeID must always be set if this is a printer
8016 if ( Printer->printer_type == SPLHND_PRINTER )
8017 status = mod_a_printer(printer, 2);
8019 done:
8020 if ( printer )
8021 free_a_printer(&printer, 2);
8022 SAFE_FREE(list);
8024 return status;
8027 /****************************************************************
8028 _spoolss_SetForm
8029 ****************************************************************/
8031 WERROR _spoolss_SetForm(pipes_struct *p,
8032 struct spoolss_SetForm *r)
8034 POLICY_HND *handle = r->in.handle;
8035 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8036 nt_forms_struct tmpForm;
8037 int snum;
8038 WERROR status = WERR_OK;
8039 NT_PRINTER_INFO_LEVEL *printer = NULL;
8041 int count=0;
8042 nt_forms_struct *list=NULL;
8043 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8045 DEBUG(5,("_spoolss_SetForm\n"));
8047 if (!Printer) {
8048 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8049 OUR_HANDLE(handle)));
8050 return WERR_BADFID;
8053 /* forms can be modified on printer of on the print server handle */
8055 if ( Printer->printer_type == SPLHND_PRINTER )
8057 if (!get_printer_snum(p,handle, &snum, NULL))
8058 return WERR_BADFID;
8060 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8061 if (!W_ERROR_IS_OK(status))
8062 goto done;
8065 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8066 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8067 status = WERR_ACCESS_DENIED;
8068 goto done;
8071 /* can't set if builtin */
8072 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8073 status = WERR_INVALID_PARAM;
8074 goto done;
8077 count = get_ntforms(&list);
8078 update_a_form(&list, form, count);
8079 write_ntforms(&list, count);
8082 * ChangeID must always be set if this is a printer
8085 if ( Printer->printer_type == SPLHND_PRINTER )
8086 status = mod_a_printer(printer, 2);
8089 done:
8090 if ( printer )
8091 free_a_printer(&printer, 2);
8092 SAFE_FREE(list);
8094 return status;
8097 /****************************************************************************
8098 fill_print_processor1
8099 ****************************************************************************/
8101 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8102 struct spoolss_PrintProcessorInfo1 *r,
8103 const char *print_processor_name)
8105 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8106 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8108 return WERR_OK;
8111 /****************************************************************************
8112 enumprintprocessors level 1.
8113 ****************************************************************************/
8115 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8116 union spoolss_PrintProcessorInfo **info_p,
8117 uint32_t *count)
8119 union spoolss_PrintProcessorInfo *info;
8120 WERROR result;
8122 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8123 W_ERROR_HAVE_NO_MEMORY(info);
8125 *count = 1;
8127 result = fill_print_processor1(info, &info[0].info1, "winprint");
8128 if (!W_ERROR_IS_OK(result)) {
8129 goto out;
8132 out:
8133 if (!W_ERROR_IS_OK(result)) {
8134 TALLOC_FREE(info);
8135 *count = 0;
8136 return result;
8139 *info_p = info;
8141 return WERR_OK;
8144 /****************************************************************
8145 _spoolss_EnumPrintProcessors
8146 ****************************************************************/
8148 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8149 struct spoolss_EnumPrintProcessors *r)
8151 WERROR result;
8153 /* that's an [in out] buffer */
8155 if (!r->in.buffer && (r->in.offered != 0)) {
8156 return WERR_INVALID_PARAM;
8159 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8162 * Enumerate the print processors ...
8164 * Just reply with "winprint", to keep NT happy
8165 * and I can use my nice printer checker.
8168 *r->out.count = 0;
8169 *r->out.needed = 0;
8170 *r->out.info = NULL;
8172 switch (r->in.level) {
8173 case 1:
8174 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8175 r->out.count);
8176 break;
8177 default:
8178 return WERR_UNKNOWN_LEVEL;
8181 if (!W_ERROR_IS_OK(result)) {
8182 return result;
8185 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8186 spoolss_EnumPrintProcessors, NULL,
8187 *r->out.info, r->in.level,
8188 *r->out.count);
8189 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8190 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8192 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8195 /****************************************************************************
8196 fill_printprocdatatype1
8197 ****************************************************************************/
8199 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8200 struct spoolss_PrintProcDataTypesInfo1 *r,
8201 const char *name_array)
8203 r->name_array = talloc_strdup(mem_ctx, name_array);
8204 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8206 return WERR_OK;
8209 /****************************************************************************
8210 enumprintprocdatatypes level 1.
8211 ****************************************************************************/
8213 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8214 union spoolss_PrintProcDataTypesInfo **info_p,
8215 uint32_t *count)
8217 WERROR result;
8218 union spoolss_PrintProcDataTypesInfo *info;
8220 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8221 W_ERROR_HAVE_NO_MEMORY(info);
8223 *count = 1;
8225 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8226 if (!W_ERROR_IS_OK(result)) {
8227 goto out;
8230 out:
8231 if (!W_ERROR_IS_OK(result)) {
8232 TALLOC_FREE(info);
8233 *count = 0;
8234 return result;
8237 *info_p = info;
8239 return WERR_OK;
8242 /****************************************************************
8243 _spoolss_EnumPrintProcDataTypes
8244 ****************************************************************/
8246 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8247 struct spoolss_EnumPrintProcDataTypes *r)
8249 WERROR result;
8251 /* that's an [in out] buffer */
8253 if (!r->in.buffer && (r->in.offered != 0)) {
8254 return WERR_INVALID_PARAM;
8257 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8259 *r->out.count = 0;
8260 *r->out.needed = 0;
8261 *r->out.info = NULL;
8263 switch (r->in.level) {
8264 case 1:
8265 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8266 r->out.count);
8267 break;
8268 default:
8269 return WERR_UNKNOWN_LEVEL;
8272 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8273 spoolss_EnumPrintProcDataTypes, NULL,
8274 *r->out.info, r->in.level,
8275 *r->out.count);
8276 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8277 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8279 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8282 /****************************************************************************
8283 fill_monitor_1
8284 ****************************************************************************/
8286 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8287 struct spoolss_MonitorInfo1 *r,
8288 const char *monitor_name)
8290 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8291 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8293 return WERR_OK;
8296 /****************************************************************************
8297 fill_monitor_2
8298 ****************************************************************************/
8300 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8301 struct spoolss_MonitorInfo2 *r,
8302 const char *monitor_name,
8303 const char *environment,
8304 const char *dll_name)
8306 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8307 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8308 r->environment = talloc_strdup(mem_ctx, environment);
8309 W_ERROR_HAVE_NO_MEMORY(r->environment);
8310 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8311 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8313 return WERR_OK;
8316 /****************************************************************************
8317 enumprintmonitors level 1.
8318 ****************************************************************************/
8320 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8321 union spoolss_MonitorInfo **info_p,
8322 uint32_t *count)
8324 union spoolss_MonitorInfo *info;
8325 WERROR result = WERR_OK;
8327 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8328 W_ERROR_HAVE_NO_MEMORY(info);
8330 *count = 2;
8332 result = fill_monitor_1(info, &info[0].info1,
8333 SPL_LOCAL_PORT);
8334 if (!W_ERROR_IS_OK(result)) {
8335 goto out;
8338 result = fill_monitor_1(info, &info[1].info1,
8339 SPL_TCPIP_PORT);
8340 if (!W_ERROR_IS_OK(result)) {
8341 goto out;
8344 out:
8345 if (!W_ERROR_IS_OK(result)) {
8346 TALLOC_FREE(info);
8347 *count = 0;
8348 return result;
8351 *info_p = info;
8353 return WERR_OK;
8356 /****************************************************************************
8357 enumprintmonitors level 2.
8358 ****************************************************************************/
8360 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8361 union spoolss_MonitorInfo **info_p,
8362 uint32_t *count)
8364 union spoolss_MonitorInfo *info;
8365 WERROR result = WERR_OK;
8367 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8368 W_ERROR_HAVE_NO_MEMORY(info);
8370 *count = 2;
8372 result = fill_monitor_2(info, &info[0].info2,
8373 SPL_LOCAL_PORT,
8374 "Windows NT X86", /* FIXME */
8375 "localmon.dll");
8376 if (!W_ERROR_IS_OK(result)) {
8377 goto out;
8380 result = fill_monitor_2(info, &info[1].info2,
8381 SPL_TCPIP_PORT,
8382 "Windows NT X86", /* FIXME */
8383 "tcpmon.dll");
8384 if (!W_ERROR_IS_OK(result)) {
8385 goto out;
8388 out:
8389 if (!W_ERROR_IS_OK(result)) {
8390 TALLOC_FREE(info);
8391 *count = 0;
8392 return result;
8395 *info_p = info;
8397 return WERR_OK;
8400 /****************************************************************
8401 _spoolss_EnumMonitors
8402 ****************************************************************/
8404 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8405 struct spoolss_EnumMonitors *r)
8407 WERROR result;
8409 /* that's an [in out] buffer */
8411 if (!r->in.buffer && (r->in.offered != 0)) {
8412 return WERR_INVALID_PARAM;
8415 DEBUG(5,("_spoolss_EnumMonitors\n"));
8418 * Enumerate the print monitors ...
8420 * Just reply with "Local Port", to keep NT happy
8421 * and I can use my nice printer checker.
8424 *r->out.count = 0;
8425 *r->out.needed = 0;
8426 *r->out.info = NULL;
8428 switch (r->in.level) {
8429 case 1:
8430 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8431 r->out.count);
8432 break;
8433 case 2:
8434 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8435 r->out.count);
8436 break;
8437 default:
8438 return WERR_UNKNOWN_LEVEL;
8441 if (!W_ERROR_IS_OK(result)) {
8442 return result;
8445 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8446 spoolss_EnumMonitors, NULL,
8447 *r->out.info, r->in.level,
8448 *r->out.count);
8449 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8450 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8452 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8455 /****************************************************************************
8456 ****************************************************************************/
8458 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8459 const print_queue_struct *queue,
8460 int count, int snum,
8461 const NT_PRINTER_INFO_LEVEL *ntprinter,
8462 uint32_t jobid,
8463 struct spoolss_JobInfo1 *r)
8465 int i = 0;
8466 bool found = false;
8468 for (i=0; i<count && found == false; i++) {
8469 if (queue[i].job == (int)jobid) {
8470 found = true;
8474 if (found == false) {
8475 /* NT treats not found as bad param... yet another bad choice */
8476 return WERR_INVALID_PARAM;
8479 return fill_job_info1(mem_ctx,
8481 &queue[i-1],
8483 snum,
8484 ntprinter);
8487 /****************************************************************************
8488 ****************************************************************************/
8490 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8491 const print_queue_struct *queue,
8492 int count, int snum,
8493 const NT_PRINTER_INFO_LEVEL *ntprinter,
8494 uint32_t jobid,
8495 struct spoolss_JobInfo2 *r)
8497 int i = 0;
8498 bool found = false;
8499 struct spoolss_DeviceMode *devmode;
8500 NT_DEVICEMODE *nt_devmode;
8501 WERROR result;
8503 for (i=0; i<count && found == false; i++) {
8504 if (queue[i].job == (int)jobid) {
8505 found = true;
8509 if (found == false) {
8510 /* NT treats not found as bad param... yet another bad
8511 choice */
8512 return WERR_INVALID_PARAM;
8516 * if the print job does not have a DEVMODE associated with it,
8517 * just use the one for the printer. A NULL devicemode is not
8518 * a failure condition
8521 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8522 if (nt_devmode) {
8523 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8524 W_ERROR_HAVE_NO_MEMORY(devmode);
8525 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8526 if (!W_ERROR_IS_OK(result)) {
8527 return result;
8529 } else {
8530 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8531 W_ERROR_HAVE_NO_MEMORY(devmode);
8534 return fill_job_info2(mem_ctx,
8536 &queue[i-1],
8538 snum,
8539 ntprinter,
8540 devmode);
8543 /****************************************************************
8544 _spoolss_GetJob
8545 ****************************************************************/
8547 WERROR _spoolss_GetJob(pipes_struct *p,
8548 struct spoolss_GetJob *r)
8550 WERROR result = WERR_OK;
8551 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8552 int snum;
8553 int count;
8554 print_queue_struct *queue = NULL;
8555 print_status_struct prt_status;
8557 /* that's an [in out] buffer */
8559 if (!r->in.buffer && (r->in.offered != 0)) {
8560 return WERR_INVALID_PARAM;
8563 DEBUG(5,("_spoolss_GetJob\n"));
8565 *r->out.needed = 0;
8567 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8568 return WERR_BADFID;
8571 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8572 if (!W_ERROR_IS_OK(result)) {
8573 return result;
8576 count = print_queue_status(snum, &queue, &prt_status);
8578 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8579 count, prt_status.status, prt_status.message));
8581 switch (r->in.level) {
8582 case 1:
8583 result = getjob_level_1(p->mem_ctx,
8584 queue, count, snum, ntprinter,
8585 r->in.job_id, &r->out.info->info1);
8586 break;
8587 case 2:
8588 result = getjob_level_2(p->mem_ctx,
8589 queue, count, snum, ntprinter,
8590 r->in.job_id, &r->out.info->info2);
8591 break;
8592 default:
8593 result = WERR_UNKNOWN_LEVEL;
8594 break;
8597 SAFE_FREE(queue);
8598 free_a_printer(&ntprinter, 2);
8600 if (!W_ERROR_IS_OK(result)) {
8601 TALLOC_FREE(r->out.info);
8602 return result;
8605 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8606 r->out.info, r->in.level);
8607 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8609 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8612 /****************************************************************
8613 _spoolss_GetPrinterDataEx
8615 From MSDN documentation of GetPrinterDataEx: pass request
8616 to GetPrinterData if key is "PrinterDriverData".
8617 ****************************************************************/
8619 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8620 struct spoolss_GetPrinterDataEx *r)
8623 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8624 REGISTRY_VALUE *val = NULL;
8625 NT_PRINTER_INFO_LEVEL *printer = NULL;
8626 int snum = 0;
8627 WERROR result = WERR_OK;
8629 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8631 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8632 r->in.key_name, r->in.value_name));
8634 /* in case of problem, return some default values */
8636 *r->out.needed = 0;
8637 *r->out.type = REG_NONE;
8639 if (!Printer) {
8640 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8641 OUR_HANDLE(r->in.handle)));
8642 result = WERR_BADFID;
8643 goto done;
8646 /* Is the handle to a printer or to the server? */
8648 if (Printer->printer_type == SPLHND_SERVER) {
8649 DEBUG(10,("_spoolss_GetPrinterDataEx: "
8650 "Not implemented for server handles yet\n"));
8651 result = WERR_INVALID_PARAM;
8652 goto done;
8655 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8656 return WERR_BADFID;
8659 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8660 if (!W_ERROR_IS_OK(result)) {
8661 goto done;
8664 /* check to see if the keyname is valid */
8665 if (!strlen(r->in.key_name)) {
8666 result = WERR_INVALID_PARAM;
8667 goto done;
8670 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8671 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8672 "Invalid keyname [%s]\n", r->in.key_name ));
8673 result = WERR_BADFILE;
8674 goto done;
8677 /* When given a new keyname, we should just create it */
8679 val = get_printer_data(printer->info_2,
8680 r->in.key_name, r->in.value_name);
8681 if (!val) {
8682 result = WERR_BADFILE;
8683 goto done;
8686 *r->out.needed = regval_size(val);
8688 if (*r->out.needed > r->in.offered) {
8689 result = WERR_MORE_DATA;
8690 goto done;
8693 *r->out.type = regval_type(val);
8695 memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
8697 done:
8698 if (printer) {
8699 free_a_printer(&printer, 2);
8702 return result;
8705 /****************************************************************
8706 _spoolss_SetPrinterDataEx
8707 ****************************************************************/
8709 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8710 struct spoolss_SetPrinterDataEx *r)
8712 NT_PRINTER_INFO_LEVEL *printer = NULL;
8713 int snum = 0;
8714 WERROR result = WERR_OK;
8715 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8716 char *oid_string;
8718 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8720 /* From MSDN documentation of SetPrinterDataEx: pass request to
8721 SetPrinterData if key is "PrinterDriverData" */
8723 if (!Printer) {
8724 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8725 OUR_HANDLE(r->in.handle)));
8726 return WERR_BADFID;
8729 if (Printer->printer_type == SPLHND_SERVER) {
8730 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8731 "Not implemented for server handles yet\n"));
8732 return WERR_INVALID_PARAM;
8735 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8736 return WERR_BADFID;
8740 * Access check : NT returns "access denied" if you make a
8741 * SetPrinterData call without the necessary privildge.
8742 * we were originally returning OK if nothing changed
8743 * which made Win2k issue **a lot** of SetPrinterData
8744 * when connecting to a printer --jerry
8747 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8748 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8749 "change denied by handle access permissions\n"));
8750 return WERR_ACCESS_DENIED;
8753 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8754 if (!W_ERROR_IS_OK(result)) {
8755 return result;
8758 /* check for OID in valuename */
8760 oid_string = strchr(r->in.value_name, ',');
8761 if (oid_string) {
8762 *oid_string = '\0';
8763 oid_string++;
8766 /* save the registry data */
8768 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8769 r->in.type, r->in.buffer, r->in.offered);
8771 if (W_ERROR_IS_OK(result)) {
8772 /* save the OID if one was specified */
8773 if (oid_string) {
8774 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8775 r->in.key_name, SPOOL_OID_KEY);
8776 if (!str) {
8777 result = WERR_NOMEM;
8778 goto done;
8782 * I'm not checking the status here on purpose. Don't know
8783 * if this is right, but I'm returning the status from the
8784 * previous set_printer_dataex() call. I have no idea if
8785 * this is right. --jerry
8788 set_printer_dataex(printer, str, r->in.value_name,
8789 REG_SZ, (uint8_t *)oid_string,
8790 strlen(oid_string)+1);
8793 result = mod_a_printer(printer, 2);
8796 done:
8797 free_a_printer(&printer, 2);
8799 return result;
8802 /****************************************************************
8803 _spoolss_DeletePrinterDataEx
8804 ****************************************************************/
8806 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8807 struct spoolss_DeletePrinterDataEx *r)
8809 POLICY_HND *handle = r->in.handle;
8810 NT_PRINTER_INFO_LEVEL *printer = NULL;
8811 int snum=0;
8812 WERROR status = WERR_OK;
8813 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8815 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8817 if (!Printer) {
8818 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8819 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8820 return WERR_BADFID;
8823 if (!get_printer_snum(p, handle, &snum, NULL))
8824 return WERR_BADFID;
8826 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8827 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8828 "printer properties change denied by handle\n"));
8829 return WERR_ACCESS_DENIED;
8832 if (!r->in.value_name || !r->in.key_name) {
8833 return WERR_NOMEM;
8836 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8837 if (!W_ERROR_IS_OK(status))
8838 return status;
8840 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8842 if ( W_ERROR_IS_OK(status) )
8843 mod_a_printer( printer, 2 );
8845 free_a_printer(&printer, 2);
8847 return status;
8850 /****************************************************************
8851 _spoolss_EnumPrinterKey
8852 ****************************************************************/
8854 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8855 struct spoolss_EnumPrinterKey *r)
8857 fstring *keynames = NULL;
8858 int num_keys;
8859 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8860 NT_PRINTER_DATA *data;
8861 NT_PRINTER_INFO_LEVEL *printer = NULL;
8862 int snum = 0;
8863 WERROR result = WERR_BADFILE;
8864 int i;
8865 const char **array = NULL;
8868 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8870 if (!Printer) {
8871 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8872 OUR_HANDLE(r->in.handle)));
8873 return WERR_BADFID;
8876 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8877 return WERR_BADFID;
8880 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8881 if (!W_ERROR_IS_OK(result)) {
8882 return result;
8885 /* get the list of subkey names */
8887 data = printer->info_2->data;
8889 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8890 if (num_keys == -1) {
8891 result = WERR_BADFILE;
8892 goto done;
8895 *r->out.needed = 4;
8897 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
8898 if (!array) {
8899 result = WERR_NOMEM;
8900 goto done;
8903 for (i=0; i < num_keys; i++) {
8904 array[i] = talloc_strdup(array, keynames[i]);
8905 if (!array[i]) {
8906 result = WERR_NOMEM;
8907 goto done;
8910 *r->out.needed += strlen_m_term(keynames[i]) * 2;
8913 if (r->in.offered < *r->out.needed) {
8914 result = WERR_MORE_DATA;
8915 goto done;
8918 result = WERR_OK;
8920 *r->out.key_buffer = array;
8922 done:
8923 if (!W_ERROR_IS_OK(result)) {
8924 TALLOC_FREE(array);
8925 ZERO_STRUCTP(r->out.key_buffer);
8928 free_a_printer(&printer, 2);
8929 SAFE_FREE(keynames);
8931 return result;
8934 /****************************************************************
8935 _spoolss_DeletePrinterKey
8936 ****************************************************************/
8938 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8939 struct spoolss_DeletePrinterKey *r)
8941 POLICY_HND *handle = r->in.handle;
8942 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8943 NT_PRINTER_INFO_LEVEL *printer = NULL;
8944 int snum=0;
8945 WERROR status;
8947 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8949 if (!Printer) {
8950 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8951 OUR_HANDLE(handle)));
8952 return WERR_BADFID;
8955 /* if keyname == NULL, return error */
8957 if ( !r->in.key_name )
8958 return WERR_INVALID_PARAM;
8960 if (!get_printer_snum(p, handle, &snum, NULL))
8961 return WERR_BADFID;
8963 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8964 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8965 "printer properties change denied by handle\n"));
8966 return WERR_ACCESS_DENIED;
8969 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8970 if (!W_ERROR_IS_OK(status))
8971 return status;
8973 /* delete the key and all subneys */
8975 status = delete_all_printer_data( printer->info_2, r->in.key_name );
8977 if ( W_ERROR_IS_OK(status) )
8978 status = mod_a_printer(printer, 2);
8980 free_a_printer( &printer, 2 );
8982 return status;
8985 /****************************************************************
8986 ****************************************************************/
8988 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8989 REGISTRY_VALUE *v,
8990 struct spoolss_PrinterEnumValues *r)
8992 WERROR result;
8994 r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
8995 W_ERROR_HAVE_NO_MEMORY(r->data);
8997 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
8998 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9000 r->type = regval_type(v);
9001 r->data_length = regval_size(v);
9003 if (r->data_length) {
9004 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9005 regval_size(v));
9006 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9007 r->data,
9008 r->type);
9009 if (!W_ERROR_IS_OK(result)) {
9010 return result;
9014 return WERR_OK;
9017 /********************************************************************
9018 * spoolss_enumprinterdataex
9019 ********************************************************************/
9021 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9023 POLICY_HND *handle = &q_u->handle;
9024 uint32 in_size = q_u->size;
9025 uint32 num_entries,
9026 needed;
9027 NT_PRINTER_INFO_LEVEL *printer = NULL;
9028 PRINTER_ENUM_VALUES *enum_values = NULL;
9029 NT_PRINTER_DATA *p_data;
9030 fstring key;
9031 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9032 int snum;
9033 WERROR result;
9034 int key_index;
9035 int i;
9036 REGISTRY_VALUE *val;
9037 char *value_name;
9038 uint32 data_len;
9041 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9043 if (!Printer) {
9044 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9045 return WERR_BADFID;
9049 * first check for a keyname of NULL or "". Win2k seems to send
9050 * this a lot and we should send back WERR_INVALID_PARAM
9051 * no need to spend time looking up the printer in this case.
9052 * --jerry
9055 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9056 if ( !strlen(key) ) {
9057 result = WERR_INVALID_PARAM;
9058 goto done;
9061 /* get the printer off of disk */
9063 if (!get_printer_snum(p,handle, &snum, NULL))
9064 return WERR_BADFID;
9066 ZERO_STRUCT(printer);
9067 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9068 if (!W_ERROR_IS_OK(result))
9069 return result;
9071 /* now look for a match on the key name */
9073 p_data = printer->info_2->data;
9075 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9076 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9078 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9079 result = WERR_INVALID_PARAM;
9080 goto done;
9083 result = WERR_OK;
9084 needed = 0;
9086 /* allocate the memory for the array of pointers -- if necessary */
9088 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9089 if ( num_entries )
9091 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9093 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9094 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9095 result = WERR_NOMEM;
9096 goto done;
9099 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9103 * loop through all params and build the array to pass
9104 * back to the client
9107 for ( i=0; i<num_entries; i++ )
9109 /* lookup the registry value */
9111 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9112 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9114 /* copy the data */
9116 value_name = regval_name( val );
9117 init_unistr( &enum_values[i].valuename, value_name );
9118 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9119 enum_values[i].type = regval_type( val );
9121 data_len = regval_size( val );
9122 if ( data_len ) {
9123 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9125 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9126 data_len ));
9127 result = WERR_NOMEM;
9128 goto done;
9131 enum_values[i].data_len = data_len;
9133 /* keep track of the size of the array in bytes */
9135 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9138 /* housekeeping information in the reply */
9140 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9141 * the hand marshalled container size is a multiple
9142 * of 4 bytes for RPC alignment.
9145 if (needed % 4) {
9146 needed += 4-(needed % 4);
9149 r_u->needed = needed;
9150 r_u->returned = num_entries;
9152 if (needed > in_size) {
9153 result = WERR_MORE_DATA;
9154 goto done;
9157 /* copy data into the reply */
9159 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9160 response buffer size is != the offered buffer size
9162 r_u->ctr.size = r_u->needed;
9164 r_u->ctr.size = in_size;
9166 r_u->ctr.size_of_array = r_u->returned;
9167 r_u->ctr.values = enum_values;
9169 done:
9170 if ( printer )
9171 free_a_printer(&printer, 2);
9173 return result;
9176 /****************************************************************************
9177 ****************************************************************************/
9179 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9180 const char *servername,
9181 const char *environment,
9182 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9184 WERROR werr;
9185 char *path = NULL;
9187 werr = compose_spoolss_server_path(mem_ctx,
9188 servername,
9189 environment,
9190 SPOOLSS_PRTPROCS_PATH,
9191 &path);
9192 if (!W_ERROR_IS_OK(werr)) {
9193 return werr;
9196 DEBUG(4,("print processor directory: [%s]\n", path));
9198 r->directory_name = path;
9200 return WERR_OK;
9203 /****************************************************************
9204 _spoolss_GetPrintProcessorDirectory
9205 ****************************************************************/
9207 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9208 struct spoolss_GetPrintProcessorDirectory *r)
9210 WERROR result;
9212 /* that's an [in out] buffer */
9214 if (!r->in.buffer && (r->in.offered != 0)) {
9215 return WERR_INVALID_PARAM;
9218 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9219 r->in.level));
9221 *r->out.needed = 0;
9223 /* r->in.level is ignored */
9225 result = getprintprocessordirectory_level_1(p->mem_ctx,
9226 r->in.server,
9227 r->in.environment,
9228 &r->out.info->info1);
9229 if (!W_ERROR_IS_OK(result)) {
9230 TALLOC_FREE(r->out.info);
9231 return result;
9234 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9235 r->out.info, r->in.level);
9236 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9238 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9241 /*******************************************************************
9242 ********************************************************************/
9244 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9245 const char *dllname)
9247 enum ndr_err_code ndr_err;
9248 struct spoolss_MonitorUi ui;
9250 ui.dll_name = dllname;
9252 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9253 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9254 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9255 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9257 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9260 /*******************************************************************
9261 Streams the monitor UI DLL name in UNICODE
9262 *******************************************************************/
9264 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9265 NT_USER_TOKEN *token, DATA_BLOB *in,
9266 DATA_BLOB *out, uint32_t *needed)
9268 const char *dllname = "tcpmonui.dll";
9270 *needed = (strlen(dllname)+1) * 2;
9272 if (out->length < *needed) {
9273 return WERR_INSUFFICIENT_BUFFER;
9276 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9277 return WERR_NOMEM;
9280 return WERR_OK;
9283 /*******************************************************************
9284 ********************************************************************/
9286 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9287 struct spoolss_PortData1 *port1,
9288 const DATA_BLOB *buf)
9290 enum ndr_err_code ndr_err;
9291 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9292 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9293 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9294 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9296 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9299 /*******************************************************************
9300 ********************************************************************/
9302 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9303 struct spoolss_PortData2 *port2,
9304 const DATA_BLOB *buf)
9306 enum ndr_err_code ndr_err;
9307 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9308 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9309 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9310 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9312 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9315 /*******************************************************************
9316 Create a new TCP/IP port
9317 *******************************************************************/
9319 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9320 NT_USER_TOKEN *token, DATA_BLOB *in,
9321 DATA_BLOB *out, uint32_t *needed)
9323 struct spoolss_PortData1 port1;
9324 struct spoolss_PortData2 port2;
9325 char *device_uri = NULL;
9326 uint32_t version;
9328 const char *portname;
9329 const char *hostaddress;
9330 const char *queue;
9331 uint32_t port_number;
9332 uint32_t protocol;
9334 /* peek for spoolss_PortData version */
9336 if (!in || (in->length < (128 + 4))) {
9337 return WERR_GENERAL_FAILURE;
9340 version = IVAL(in->data, 128);
9342 switch (version) {
9343 case 1:
9344 ZERO_STRUCT(port1);
9346 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9347 return WERR_NOMEM;
9350 portname = port1.portname;
9351 hostaddress = port1.hostaddress;
9352 queue = port1.queue;
9353 protocol = port1.protocol;
9354 port_number = port1.port_number;
9356 break;
9357 case 2:
9358 ZERO_STRUCT(port2);
9360 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9361 return WERR_NOMEM;
9364 portname = port2.portname;
9365 hostaddress = port2.hostaddress;
9366 queue = port2.queue;
9367 protocol = port2.protocol;
9368 port_number = port2.port_number;
9370 break;
9371 default:
9372 DEBUG(1,("xcvtcp_addport: "
9373 "unknown version of port_data: %d\n", version));
9374 return WERR_UNKNOWN_PORT;
9377 /* create the device URI and call the add_port_hook() */
9379 switch (protocol) {
9380 case PROTOCOL_RAWTCP_TYPE:
9381 device_uri = talloc_asprintf(mem_ctx,
9382 "socket://%s:%d/", hostaddress,
9383 port_number);
9384 break;
9386 case PROTOCOL_LPR_TYPE:
9387 device_uri = talloc_asprintf(mem_ctx,
9388 "lpr://%s/%s", hostaddress, queue );
9389 break;
9391 default:
9392 return WERR_UNKNOWN_PORT;
9395 if (!device_uri) {
9396 return WERR_NOMEM;
9399 return add_port_hook(mem_ctx, token, portname, device_uri);
9402 /*******************************************************************
9403 *******************************************************************/
9405 struct xcv_api_table xcvtcp_cmds[] = {
9406 { "MonitorUI", xcvtcp_monitorui },
9407 { "AddPort", xcvtcp_addport},
9408 { NULL, NULL }
9411 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9412 NT_USER_TOKEN *token, const char *command,
9413 DATA_BLOB *inbuf,
9414 DATA_BLOB *outbuf,
9415 uint32_t *needed )
9417 int i;
9419 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9421 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9422 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9423 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9426 return WERR_BADFUNC;
9429 /*******************************************************************
9430 *******************************************************************/
9431 #if 0 /* don't support management using the "Local Port" monitor */
9433 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9434 NT_USER_TOKEN *token, DATA_BLOB *in,
9435 DATA_BLOB *out, uint32_t *needed)
9437 const char *dllname = "localui.dll";
9439 *needed = (strlen(dllname)+1) * 2;
9441 if (out->length < *needed) {
9442 return WERR_INSUFFICIENT_BUFFER;
9445 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9446 return WERR_NOMEM;
9449 return WERR_OK;
9452 /*******************************************************************
9453 *******************************************************************/
9455 struct xcv_api_table xcvlocal_cmds[] = {
9456 { "MonitorUI", xcvlocal_monitorui },
9457 { NULL, NULL }
9459 #else
9460 struct xcv_api_table xcvlocal_cmds[] = {
9461 { NULL, NULL }
9463 #endif
9467 /*******************************************************************
9468 *******************************************************************/
9470 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9471 NT_USER_TOKEN *token, const char *command,
9472 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9473 uint32_t *needed)
9475 int i;
9477 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9479 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9480 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9481 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9483 return WERR_BADFUNC;
9486 /****************************************************************
9487 _spoolss_XcvData
9488 ****************************************************************/
9490 WERROR _spoolss_XcvData(pipes_struct *p,
9491 struct spoolss_XcvData *r)
9493 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9494 DATA_BLOB out_data = data_blob_null;
9495 WERROR werror;
9497 if (!Printer) {
9498 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9499 OUR_HANDLE(r->in.handle)));
9500 return WERR_BADFID;
9503 /* Has to be a handle to the TCP/IP port monitor */
9505 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9506 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9507 return WERR_BADFID;
9510 /* requires administrative access to the server */
9512 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9513 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9514 return WERR_ACCESS_DENIED;
9517 /* Allocate the outgoing buffer */
9519 if (r->in.out_data_size) {
9520 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9521 if (out_data.data == NULL) {
9522 return WERR_NOMEM;
9526 switch ( Printer->printer_type ) {
9527 case SPLHND_PORTMON_TCP:
9528 werror = process_xcvtcp_command(p->mem_ctx,
9529 p->server_info->ptok,
9530 r->in.function_name,
9531 &r->in.in_data, &out_data,
9532 r->out.needed);
9533 break;
9534 case SPLHND_PORTMON_LOCAL:
9535 werror = process_xcvlocal_command(p->mem_ctx,
9536 p->server_info->ptok,
9537 r->in.function_name,
9538 &r->in.in_data, &out_data,
9539 r->out.needed);
9540 break;
9541 default:
9542 werror = WERR_INVALID_PRINT_MONITOR;
9545 if (!W_ERROR_IS_OK(werror)) {
9546 return werror;
9549 *r->out.status_code = 0;
9551 memcpy(r->out.out_data, out_data.data, out_data.length);
9553 return WERR_OK;
9556 /****************************************************************
9557 _spoolss_AddPrintProcessor
9558 ****************************************************************/
9560 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9561 struct spoolss_AddPrintProcessor *r)
9563 /* for now, just indicate success and ignore the add. We'll
9564 automatically set the winprint processor for printer
9565 entries later. Used to debug the LexMark Optra S 1855 PCL
9566 driver --jerry */
9568 return WERR_OK;
9571 /****************************************************************
9572 _spoolss_AddPrinter
9573 ****************************************************************/
9575 WERROR _spoolss_AddPrinter(pipes_struct *p,
9576 struct spoolss_AddPrinter *r)
9578 p->rng_fault_state = true;
9579 return WERR_NOT_SUPPORTED;
9582 /****************************************************************
9583 _spoolss_GetPrinterDriver
9584 ****************************************************************/
9586 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9587 struct spoolss_GetPrinterDriver *r)
9589 p->rng_fault_state = true;
9590 return WERR_NOT_SUPPORTED;
9593 /****************************************************************
9594 _spoolss_ReadPrinter
9595 ****************************************************************/
9597 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9598 struct spoolss_ReadPrinter *r)
9600 p->rng_fault_state = true;
9601 return WERR_NOT_SUPPORTED;
9604 /****************************************************************
9605 _spoolss_WaitForPrinterChange
9606 ****************************************************************/
9608 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9609 struct spoolss_WaitForPrinterChange *r)
9611 p->rng_fault_state = true;
9612 return WERR_NOT_SUPPORTED;
9615 /****************************************************************
9616 _spoolss_AddPort
9617 ****************************************************************/
9619 WERROR _spoolss_AddPort(pipes_struct *p,
9620 struct spoolss_AddPort *r)
9622 p->rng_fault_state = true;
9623 return WERR_NOT_SUPPORTED;
9626 /****************************************************************
9627 _spoolss_ConfigurePort
9628 ****************************************************************/
9630 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9631 struct spoolss_ConfigurePort *r)
9633 p->rng_fault_state = true;
9634 return WERR_NOT_SUPPORTED;
9637 /****************************************************************
9638 _spoolss_DeletePort
9639 ****************************************************************/
9641 WERROR _spoolss_DeletePort(pipes_struct *p,
9642 struct spoolss_DeletePort *r)
9644 p->rng_fault_state = true;
9645 return WERR_NOT_SUPPORTED;
9648 /****************************************************************
9649 _spoolss_CreatePrinterIC
9650 ****************************************************************/
9652 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9653 struct spoolss_CreatePrinterIC *r)
9655 p->rng_fault_state = true;
9656 return WERR_NOT_SUPPORTED;
9659 /****************************************************************
9660 _spoolss_PlayGDIScriptOnPrinterIC
9661 ****************************************************************/
9663 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9664 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9666 p->rng_fault_state = true;
9667 return WERR_NOT_SUPPORTED;
9670 /****************************************************************
9671 _spoolss_DeletePrinterIC
9672 ****************************************************************/
9674 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9675 struct spoolss_DeletePrinterIC *r)
9677 p->rng_fault_state = true;
9678 return WERR_NOT_SUPPORTED;
9681 /****************************************************************
9682 _spoolss_AddPrinterConnection
9683 ****************************************************************/
9685 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9686 struct spoolss_AddPrinterConnection *r)
9688 p->rng_fault_state = true;
9689 return WERR_NOT_SUPPORTED;
9692 /****************************************************************
9693 _spoolss_DeletePrinterConnection
9694 ****************************************************************/
9696 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9697 struct spoolss_DeletePrinterConnection *r)
9699 p->rng_fault_state = true;
9700 return WERR_NOT_SUPPORTED;
9703 /****************************************************************
9704 _spoolss_PrinterMessageBox
9705 ****************************************************************/
9707 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9708 struct spoolss_PrinterMessageBox *r)
9710 p->rng_fault_state = true;
9711 return WERR_NOT_SUPPORTED;
9714 /****************************************************************
9715 _spoolss_AddMonitor
9716 ****************************************************************/
9718 WERROR _spoolss_AddMonitor(pipes_struct *p,
9719 struct spoolss_AddMonitor *r)
9721 p->rng_fault_state = true;
9722 return WERR_NOT_SUPPORTED;
9725 /****************************************************************
9726 _spoolss_DeleteMonitor
9727 ****************************************************************/
9729 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9730 struct spoolss_DeleteMonitor *r)
9732 p->rng_fault_state = true;
9733 return WERR_NOT_SUPPORTED;
9736 /****************************************************************
9737 _spoolss_DeletePrintProcessor
9738 ****************************************************************/
9740 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9741 struct spoolss_DeletePrintProcessor *r)
9743 p->rng_fault_state = true;
9744 return WERR_NOT_SUPPORTED;
9747 /****************************************************************
9748 _spoolss_AddPrintProvidor
9749 ****************************************************************/
9751 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9752 struct spoolss_AddPrintProvidor *r)
9754 p->rng_fault_state = true;
9755 return WERR_NOT_SUPPORTED;
9758 /****************************************************************
9759 _spoolss_DeletePrintProvidor
9760 ****************************************************************/
9762 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9763 struct spoolss_DeletePrintProvidor *r)
9765 p->rng_fault_state = true;
9766 return WERR_NOT_SUPPORTED;
9769 /****************************************************************
9770 _spoolss_FindFirstPrinterChangeNotification
9771 ****************************************************************/
9773 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9774 struct spoolss_FindFirstPrinterChangeNotification *r)
9776 p->rng_fault_state = true;
9777 return WERR_NOT_SUPPORTED;
9780 /****************************************************************
9781 _spoolss_FindNextPrinterChangeNotification
9782 ****************************************************************/
9784 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9785 struct spoolss_FindNextPrinterChangeNotification *r)
9787 p->rng_fault_state = true;
9788 return WERR_NOT_SUPPORTED;
9791 /****************************************************************
9792 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9793 ****************************************************************/
9795 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9796 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9798 p->rng_fault_state = true;
9799 return WERR_NOT_SUPPORTED;
9802 /****************************************************************
9803 _spoolss_ReplyOpenPrinter
9804 ****************************************************************/
9806 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9807 struct spoolss_ReplyOpenPrinter *r)
9809 p->rng_fault_state = true;
9810 return WERR_NOT_SUPPORTED;
9813 /****************************************************************
9814 _spoolss_RouterReplyPrinter
9815 ****************************************************************/
9817 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9818 struct spoolss_RouterReplyPrinter *r)
9820 p->rng_fault_state = true;
9821 return WERR_NOT_SUPPORTED;
9824 /****************************************************************
9825 _spoolss_ReplyClosePrinter
9826 ****************************************************************/
9828 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9829 struct spoolss_ReplyClosePrinter *r)
9831 p->rng_fault_state = true;
9832 return WERR_NOT_SUPPORTED;
9835 /****************************************************************
9836 _spoolss_AddPortEx
9837 ****************************************************************/
9839 WERROR _spoolss_AddPortEx(pipes_struct *p,
9840 struct spoolss_AddPortEx *r)
9842 p->rng_fault_state = true;
9843 return WERR_NOT_SUPPORTED;
9846 /****************************************************************
9847 _spoolss_RouterFindFirstPrinterChangeNotification
9848 ****************************************************************/
9850 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9851 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9853 p->rng_fault_state = true;
9854 return WERR_NOT_SUPPORTED;
9857 /****************************************************************
9858 _spoolss_SpoolerInit
9859 ****************************************************************/
9861 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9862 struct spoolss_SpoolerInit *r)
9864 p->rng_fault_state = true;
9865 return WERR_NOT_SUPPORTED;
9868 /****************************************************************
9869 _spoolss_ResetPrinterEx
9870 ****************************************************************/
9872 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9873 struct spoolss_ResetPrinterEx *r)
9875 p->rng_fault_state = true;
9876 return WERR_NOT_SUPPORTED;
9879 /****************************************************************
9880 _spoolss_RouterReplyPrinterEx
9881 ****************************************************************/
9883 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9884 struct spoolss_RouterReplyPrinterEx *r)
9886 p->rng_fault_state = true;
9887 return WERR_NOT_SUPPORTED;
9890 /****************************************************************
9891 _spoolss_44
9892 ****************************************************************/
9894 WERROR _spoolss_44(pipes_struct *p,
9895 struct spoolss_44 *r)
9897 p->rng_fault_state = true;
9898 return WERR_NOT_SUPPORTED;
9901 /****************************************************************
9902 _spoolss_47
9903 ****************************************************************/
9905 WERROR _spoolss_47(pipes_struct *p,
9906 struct spoolss_47 *r)
9908 p->rng_fault_state = true;
9909 return WERR_NOT_SUPPORTED;
9912 /****************************************************************
9913 _spoolss_4a
9914 ****************************************************************/
9916 WERROR _spoolss_4a(pipes_struct *p,
9917 struct spoolss_4a *r)
9919 p->rng_fault_state = true;
9920 return WERR_NOT_SUPPORTED;
9923 /****************************************************************
9924 _spoolss_4b
9925 ****************************************************************/
9927 WERROR _spoolss_4b(pipes_struct *p,
9928 struct spoolss_4b *r)
9930 p->rng_fault_state = true;
9931 return WERR_NOT_SUPPORTED;
9934 /****************************************************************
9935 _spoolss_4c
9936 ****************************************************************/
9938 WERROR _spoolss_4c(pipes_struct *p,
9939 struct spoolss_4c *r)
9941 p->rng_fault_state = true;
9942 return WERR_NOT_SUPPORTED;
9945 /****************************************************************
9946 _spoolss_EnumPrinterDataEx
9947 ****************************************************************/
9949 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9950 struct spoolss_EnumPrinterDataEx *r)
9952 p->rng_fault_state = true;
9953 return WERR_NOT_SUPPORTED;
9956 /****************************************************************
9957 _spoolss_53
9958 ****************************************************************/
9960 WERROR _spoolss_53(pipes_struct *p,
9961 struct spoolss_53 *r)
9963 p->rng_fault_state = true;
9964 return WERR_NOT_SUPPORTED;
9967 /****************************************************************
9968 _spoolss_55
9969 ****************************************************************/
9971 WERROR _spoolss_55(pipes_struct *p,
9972 struct spoolss_55 *r)
9974 p->rng_fault_state = true;
9975 return WERR_NOT_SUPPORTED;
9978 /****************************************************************
9979 _spoolss_56
9980 ****************************************************************/
9982 WERROR _spoolss_56(pipes_struct *p,
9983 struct spoolss_56 *r)
9985 p->rng_fault_state = true;
9986 return WERR_NOT_SUPPORTED;
9989 /****************************************************************
9990 _spoolss_57
9991 ****************************************************************/
9993 WERROR _spoolss_57(pipes_struct *p,
9994 struct spoolss_57 *r)
9996 p->rng_fault_state = true;
9997 return WERR_NOT_SUPPORTED;
10000 /****************************************************************
10001 _spoolss_5a
10002 ****************************************************************/
10004 WERROR _spoolss_5a(pipes_struct *p,
10005 struct spoolss_5a *r)
10007 p->rng_fault_state = true;
10008 return WERR_NOT_SUPPORTED;
10011 /****************************************************************
10012 _spoolss_5b
10013 ****************************************************************/
10015 WERROR _spoolss_5b(pipes_struct *p,
10016 struct spoolss_5b *r)
10018 p->rng_fault_state = true;
10019 return WERR_NOT_SUPPORTED;
10022 /****************************************************************
10023 _spoolss_5c
10024 ****************************************************************/
10026 WERROR _spoolss_5c(pipes_struct *p,
10027 struct spoolss_5c *r)
10029 p->rng_fault_state = true;
10030 return WERR_NOT_SUPPORTED;
10033 /****************************************************************
10034 _spoolss_5d
10035 ****************************************************************/
10037 WERROR _spoolss_5d(pipes_struct *p,
10038 struct spoolss_5d *r)
10040 p->rng_fault_state = true;
10041 return WERR_NOT_SUPPORTED;
10044 /****************************************************************
10045 _spoolss_5e
10046 ****************************************************************/
10048 WERROR _spoolss_5e(pipes_struct *p,
10049 struct spoolss_5e *r)
10051 p->rng_fault_state = true;
10052 return WERR_NOT_SUPPORTED;
10055 /****************************************************************
10056 _spoolss_5f
10057 ****************************************************************/
10059 WERROR _spoolss_5f(pipes_struct *p,
10060 struct spoolss_5f *r)
10062 p->rng_fault_state = true;
10063 return WERR_NOT_SUPPORTED;