s3-registry: only include registry headers when really needed.
[Samba.git] / source3 / rpc_server / srv_spoolss_nt.c
blob823b051e92e7f61a8812cc14922635f20eae57d9
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "librpc/gen_ndr/messaging.h"
33 #include "registry.h"
35 /* macros stolen from s4 spoolss server */
36 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
37 ((info)?ndr_size_##fn(info, level, ic, 0):0)
39 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
40 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
42 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
43 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
45 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
48 extern userdom_struct current_user_info;
50 #undef DBGC_CLASS
51 #define DBGC_CLASS DBGC_RPC_SRV
53 #ifndef MAX_OPEN_PRINTER_EXS
54 #define MAX_OPEN_PRINTER_EXS 50
55 #endif
57 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
58 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
60 static Printer_entry *printers_list;
62 typedef struct _counter_printer_0 {
63 struct _counter_printer_0 *next;
64 struct _counter_printer_0 *prev;
66 int snum;
67 uint32_t counter;
68 } counter_printer_0;
70 static counter_printer_0 *counter_list;
72 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
73 static uint32_t smb_connections = 0;
76 /* in printing/nt_printing.c */
78 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
80 /* API table for Xcv Monitor functions */
82 struct xcv_api_table {
83 const char *name;
84 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
87 /********************************************************************
88 * Canonicalize servername.
89 ********************************************************************/
91 static const char *canon_servername(const char *servername)
93 const char *pservername = servername;
94 while (*pservername == '\\') {
95 pservername++;
97 return pservername;
100 /* translate between internal status numbers and NT status numbers */
101 static int nt_printj_status(int v)
103 switch (v) {
104 case LPQ_QUEUED:
105 return 0;
106 case LPQ_PAUSED:
107 return JOB_STATUS_PAUSED;
108 case LPQ_SPOOLING:
109 return JOB_STATUS_SPOOLING;
110 case LPQ_PRINTING:
111 return JOB_STATUS_PRINTING;
112 case LPQ_ERROR:
113 return JOB_STATUS_ERROR;
114 case LPQ_DELETING:
115 return JOB_STATUS_DELETING;
116 case LPQ_OFFLINE:
117 return JOB_STATUS_OFFLINE;
118 case LPQ_PAPEROUT:
119 return JOB_STATUS_PAPEROUT;
120 case LPQ_PRINTED:
121 return JOB_STATUS_PRINTED;
122 case LPQ_DELETED:
123 return JOB_STATUS_DELETED;
124 case LPQ_BLOCKED:
125 return JOB_STATUS_BLOCKED_DEVQ;
126 case LPQ_USER_INTERVENTION:
127 return JOB_STATUS_USER_INTERVENTION;
129 return 0;
132 static int nt_printq_status(int v)
134 switch (v) {
135 case LPQ_PAUSED:
136 return PRINTER_STATUS_PAUSED;
137 case LPQ_QUEUED:
138 case LPQ_SPOOLING:
139 case LPQ_PRINTING:
140 return 0;
142 return 0;
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
151 WERROR result;
152 NTSTATUS status;
155 * Tell the specific printing tdb we no longer want messages for this printer
156 * by deregistering our PID.
159 if (!print_notify_deregister_pid(snum))
160 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162 /* weird if the test succeds !!! */
163 if (smb_connections==0) {
164 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
165 return;
168 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
169 handle,
170 &result);
171 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 win_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
178 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
179 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181 messaging_deregister(smbd_messaging_context(),
182 MSG_PRINTER_NOTIFY2, NULL);
184 /* Tell the connections db we're no longer interested in
185 * printer notify messages. */
187 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
190 smb_connections--;
193 /****************************************************************************
194 Functions to free a printer entry datastruct.
195 ****************************************************************************/
197 static int printer_entry_destructor(Printer_entry *Printer)
199 if (Printer->notify.client_connected == true) {
200 int snum = -1;
202 if ( Printer->printer_type == SPLHND_SERVER) {
203 snum = -1;
204 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
205 } else if (Printer->printer_type == SPLHND_PRINTER) {
206 snum = print_queue_snum(Printer->sharename);
207 if (snum != -1)
208 srv_spoolss_replycloseprinter(snum,
209 &Printer->notify.client_hnd);
213 Printer->notify.flags=0;
214 Printer->notify.options=0;
215 Printer->notify.localmachine[0]='\0';
216 Printer->notify.printerlocal=0;
217 TALLOC_FREE(Printer->notify.option);
218 Printer->notify.client_connected = false;
220 free_nt_devicemode( &Printer->nt_devmode );
221 free_a_printer( &Printer->printer_info, 2 );
223 /* Remove from the internal list. */
224 DLIST_REMOVE(printers_list, Printer);
225 return 0;
228 /****************************************************************************
229 find printer index by handle
230 ****************************************************************************/
232 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
233 struct policy_handle *hnd)
235 Printer_entry *find_printer = NULL;
237 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
238 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
239 return NULL;
242 return find_printer;
245 /****************************************************************************
246 Close printer index by handle.
247 ****************************************************************************/
249 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
251 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
253 if (!Printer) {
254 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
255 OUR_HANDLE(hnd)));
256 return false;
259 close_policy_hnd(p, hnd);
261 return true;
264 /****************************************************************************
265 Delete a printer given a handle.
266 ****************************************************************************/
268 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
270 char *cmd = lp_deleteprinter_cmd();
271 char *command = NULL;
272 int ret;
273 SE_PRIV se_printop = SE_PRINT_OPERATOR;
274 bool is_print_op = false;
276 /* can't fail if we don't try */
278 if ( !*cmd )
279 return WERR_OK;
281 command = talloc_asprintf(ctx,
282 "%s \"%s\"",
283 cmd, sharename);
284 if (!command) {
285 return WERR_NOMEM;
287 if ( token )
288 is_print_op = user_has_privileges( token, &se_printop );
290 DEBUG(10,("Running [%s]\n", command));
292 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
294 if ( is_print_op )
295 become_root();
297 if ( (ret = smbrun(command, NULL)) == 0 ) {
298 /* Tell everyone we updated smb.conf. */
299 message_send_all(smbd_messaging_context(),
300 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
303 if ( is_print_op )
304 unbecome_root();
306 /********** END SePrintOperatorPrivlege BLOCK **********/
308 DEBUGADD(10,("returned [%d]\n", ret));
310 TALLOC_FREE(command);
312 if (ret != 0)
313 return WERR_BADFID; /* What to return here? */
315 /* go ahead and re-read the services immediately */
316 become_root();
317 reload_services(false);
318 unbecome_root();
320 if ( lp_servicenumber( sharename ) > 0 )
321 return WERR_ACCESS_DENIED;
323 return WERR_OK;
326 /****************************************************************************
327 Delete a printer given a handle.
328 ****************************************************************************/
330 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
332 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
334 if (!Printer) {
335 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
336 OUR_HANDLE(hnd)));
337 return WERR_BADFID;
341 * It turns out that Windows allows delete printer on a handle
342 * opened by an admin user, then used on a pipe handle created
343 * by an anonymous user..... but they're working on security.... riiight !
344 * JRA.
347 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
348 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
349 return WERR_ACCESS_DENIED;
352 /* this does not need a become root since the access check has been
353 done on the handle already */
355 if (del_a_printer( Printer->sharename ) != 0) {
356 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
357 return WERR_BADFID;
360 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
361 Printer->sharename );
364 /****************************************************************************
365 Return the snum of a printer corresponding to an handle.
366 ****************************************************************************/
368 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
369 int *number, struct share_params **params)
371 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
373 if (!Printer) {
374 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
375 OUR_HANDLE(hnd)));
376 return false;
379 switch (Printer->printer_type) {
380 case SPLHND_PRINTER:
381 DEBUG(4,("short name:%s\n", Printer->sharename));
382 *number = print_queue_snum(Printer->sharename);
383 return (*number != -1);
384 case SPLHND_SERVER:
385 return false;
386 default:
387 return false;
391 /****************************************************************************
392 Set printer handle type.
393 Check if it's \\server or \\server\printer
394 ****************************************************************************/
396 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
398 DEBUG(3,("Setting printer type=%s\n", handlename));
400 if ( strlen(handlename) < 3 ) {
401 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
402 return false;
405 /* it's a print server */
406 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
407 DEBUGADD(4,("Printer is a print server\n"));
408 Printer->printer_type = SPLHND_SERVER;
410 /* it's a printer (set_printer_hnd_name() will handle port monitors */
411 else {
412 DEBUGADD(4,("Printer is a printer\n"));
413 Printer->printer_type = SPLHND_PRINTER;
416 return true;
419 /****************************************************************************
420 Set printer handle name.. Accept names like \\server, \\server\printer,
421 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
422 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
423 XcvDataPort() interface.
424 ****************************************************************************/
426 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
428 int snum;
429 int n_services=lp_numservices();
430 char *aprinter, *printername;
431 const char *servername;
432 fstring sname;
433 bool found = false;
434 NT_PRINTER_INFO_LEVEL *printer = NULL;
435 WERROR result;
437 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
438 (unsigned long)strlen(handlename)));
440 aprinter = CONST_DISCARD(char *, handlename);
441 if ( *handlename == '\\' ) {
442 servername = canon_servername(handlename);
443 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
444 *aprinter = '\0';
445 aprinter++;
447 } else {
448 servername = global_myname();
451 /* save the servername to fill in replies on this handle */
453 if ( !is_myname_or_ipaddr( servername ) )
454 return false;
456 fstrcpy( Printer->servername, servername );
458 if ( Printer->printer_type == SPLHND_SERVER )
459 return true;
461 if ( Printer->printer_type != SPLHND_PRINTER )
462 return false;
464 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
466 /* check for the Port Monitor Interface */
468 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
469 Printer->printer_type = SPLHND_PORTMON_TCP;
470 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
471 found = true;
473 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
474 Printer->printer_type = SPLHND_PORTMON_LOCAL;
475 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
476 found = true;
479 /* Search all sharenames first as this is easier than pulling
480 the printer_info_2 off of disk. Don't use find_service() since
481 that calls out to map_username() */
483 /* do another loop to look for printernames */
485 for (snum=0; !found && snum<n_services; snum++) {
487 /* no point going on if this is not a printer */
489 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
490 continue;
492 fstrcpy(sname, lp_servicename(snum));
493 if ( strequal( aprinter, sname ) ) {
494 found = true;
495 break;
498 /* no point looking up the printer object if
499 we aren't allowing printername != sharename */
501 if ( lp_force_printername(snum) )
502 continue;
504 fstrcpy(sname, lp_servicename(snum));
506 printer = NULL;
508 /* This call doesn't fill in the location or comment from
509 * a CUPS server for efficiency with large numbers of printers.
510 * JRA.
513 result = get_a_printer_search( NULL, &printer, 2, sname );
514 if ( !W_ERROR_IS_OK(result) ) {
515 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
516 sname, win_errstr(result)));
517 continue;
520 /* printername is always returned as \\server\printername */
521 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
522 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
523 printer->info_2->printername));
524 free_a_printer( &printer, 2);
525 continue;
528 printername++;
530 if ( strequal(printername, aprinter) ) {
531 free_a_printer( &printer, 2);
532 found = true;
533 break;
536 DEBUGADD(10, ("printername: %s\n", printername));
538 free_a_printer( &printer, 2);
541 free_a_printer( &printer, 2);
543 if ( !found ) {
544 DEBUGADD(4,("Printer not found\n"));
545 return false;
548 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
550 fstrcpy(Printer->sharename, sname);
552 return true;
555 /****************************************************************************
556 Find first available printer slot. creates a printer handle for you.
557 ****************************************************************************/
559 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
560 const char *name, uint32_t access_granted)
562 Printer_entry *new_printer;
564 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
566 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
567 if (new_printer == NULL) {
568 return false;
570 talloc_set_destructor(new_printer, printer_entry_destructor);
572 if (!create_policy_hnd(p, hnd, new_printer)) {
573 TALLOC_FREE(new_printer);
574 return false;
577 /* Add to the internal list. */
578 DLIST_ADD(printers_list, new_printer);
580 new_printer->notify.option=NULL;
582 if (!set_printer_hnd_printertype(new_printer, name)) {
583 close_printer_handle(p, hnd);
584 return false;
587 if (!set_printer_hnd_name(new_printer, name)) {
588 close_printer_handle(p, hnd);
589 return false;
592 new_printer->access_granted = access_granted;
594 DEBUG(5, ("%d printer handles active\n",
595 (int)num_pipe_handles(p->pipe_handles)));
597 return true;
600 /***************************************************************************
601 check to see if the client motify handle is monitoring the notification
602 given by (notify_type, notify_field).
603 **************************************************************************/
605 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
606 uint16_t notify_field)
608 return true;
611 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
612 uint16_t notify_field)
614 struct spoolss_NotifyOption *option = p->notify.option;
615 uint32_t i, j;
618 * Flags should always be zero when the change notify
619 * is registered by the client's spooler. A user Win32 app
620 * might use the flags though instead of the NOTIFY_OPTION_INFO
621 * --jerry
624 if (!option) {
625 return false;
628 if (p->notify.flags)
629 return is_monitoring_event_flags(
630 p->notify.flags, notify_type, notify_field);
632 for (i = 0; i < option->count; i++) {
634 /* Check match for notify_type */
636 if (option->types[i].type != notify_type)
637 continue;
639 /* Check match for field */
641 for (j = 0; j < option->types[i].count; j++) {
642 if (option->types[i].fields[j].field == notify_field) {
643 return true;
648 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
649 p->servername, p->sharename, notify_type, notify_field));
651 return false;
654 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
655 _data->data.integer[0] = _integer; \
656 _data->data.integer[1] = 0;
659 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
660 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
661 if (!_data->data.string.string) {\
662 _data->data.string.size = 0; \
664 _data->data.string.size = strlen_m_term(_p) * 2;
666 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
667 _data->data.devmode.devmode = _devmode;
669 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
670 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
671 if (!_data->data.sd.sd) { \
672 _data->data.sd.sd_size = 0; \
674 _data->data.sd.sd_size = _size;
676 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
677 struct tm *t,
678 const char **pp,
679 uint32_t *plen)
681 struct spoolss_Time st;
682 uint32_t len = 16;
683 char *p;
685 if (!init_systemtime(&st, t)) {
686 return;
689 p = talloc_array(mem_ctx, char, len);
690 if (!p) {
691 return;
695 * Systemtime must be linearized as a set of UINT16's.
696 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
699 SSVAL(p, 0, st.year);
700 SSVAL(p, 2, st.month);
701 SSVAL(p, 4, st.day_of_week);
702 SSVAL(p, 6, st.day);
703 SSVAL(p, 8, st.hour);
704 SSVAL(p, 10, st.minute);
705 SSVAL(p, 12, st.second);
706 SSVAL(p, 14, st.millisecond);
708 *pp = p;
709 *plen = len;
712 /* Convert a notification message to a struct spoolss_Notify */
714 static void notify_one_value(struct spoolss_notify_msg *msg,
715 struct spoolss_Notify *data,
716 TALLOC_CTX *mem_ctx)
718 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
721 static void notify_string(struct spoolss_notify_msg *msg,
722 struct spoolss_Notify *data,
723 TALLOC_CTX *mem_ctx)
725 /* The length of the message includes the trailing \0 */
727 data->data.string.size = msg->len * 2;
728 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
729 if (!data->data.string.string) {
730 data->data.string.size = 0;
731 return;
735 static void notify_system_time(struct spoolss_notify_msg *msg,
736 struct spoolss_Notify *data,
737 TALLOC_CTX *mem_ctx)
739 data->data.string.string = NULL;
740 data->data.string.size = 0;
742 if (msg->len != sizeof(time_t)) {
743 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
744 msg->len));
745 return;
748 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
749 &data->data.string.string,
750 &data->data.string.size);
753 struct notify2_message_table {
754 const char *name;
755 void (*fn)(struct spoolss_notify_msg *msg,
756 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
759 static struct notify2_message_table printer_notify_table[] = {
760 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
761 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
762 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
763 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
764 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
765 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
766 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
767 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
768 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
769 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
770 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
771 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
772 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
773 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
774 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
775 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
776 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
777 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
778 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
781 static struct notify2_message_table job_notify_table[] = {
782 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
783 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
784 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
785 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
786 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
787 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
788 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
789 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
790 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
791 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
792 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
793 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
794 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
795 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
796 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
797 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
798 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
799 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
800 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
801 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
802 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
803 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
804 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
805 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
809 /***********************************************************************
810 Allocate talloc context for container object
811 **********************************************************************/
813 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
815 if ( !ctr )
816 return;
818 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
820 return;
823 /***********************************************************************
824 release all allocated memory and zero out structure
825 **********************************************************************/
827 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
829 if ( !ctr )
830 return;
832 if ( ctr->ctx )
833 talloc_destroy(ctr->ctx);
835 ZERO_STRUCTP(ctr);
837 return;
840 /***********************************************************************
841 **********************************************************************/
843 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
845 if ( !ctr )
846 return NULL;
848 return ctr->ctx;
851 /***********************************************************************
852 **********************************************************************/
854 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
856 if ( !ctr || !ctr->msg_groups )
857 return NULL;
859 if ( idx >= ctr->num_groups )
860 return NULL;
862 return &ctr->msg_groups[idx];
866 /***********************************************************************
867 How many groups of change messages do we have ?
868 **********************************************************************/
870 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
872 if ( !ctr )
873 return 0;
875 return ctr->num_groups;
878 /***********************************************************************
879 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
880 **********************************************************************/
882 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
884 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
885 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
886 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
887 int i, new_slot;
889 if ( !ctr || !msg )
890 return 0;
892 /* loop over all groups looking for a matching printer name */
894 for ( i=0; i<ctr->num_groups; i++ ) {
895 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
896 break;
899 /* add a new group? */
901 if ( i == ctr->num_groups ) {
902 ctr->num_groups++;
904 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
905 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
906 return 0;
908 ctr->msg_groups = groups;
910 /* clear the new entry and set the printer name */
912 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
913 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
916 /* add the change messages; 'i' is the correct index now regardless */
918 msg_grp = &ctr->msg_groups[i];
920 msg_grp->num_msgs++;
922 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
923 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
924 return 0;
926 msg_grp->msgs = msg_list;
928 new_slot = msg_grp->num_msgs-1;
929 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
931 /* need to allocate own copy of data */
933 if ( msg->len != 0 )
934 msg_grp->msgs[new_slot].notify.data = (char *)
935 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
937 return ctr->num_groups;
940 void construct_info_data(struct spoolss_Notify *info_data,
941 enum spoolss_NotifyType type,
942 uint16_t field,
943 int id);
945 /***********************************************************************
946 Send a change notication message on all handles which have a call
947 back registered
948 **********************************************************************/
950 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
952 Printer_entry *p;
953 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
954 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
955 SPOOLSS_NOTIFY_MSG *messages;
956 int sending_msg_count;
958 if ( !msg_group ) {
959 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
960 return;
963 messages = msg_group->msgs;
965 if ( !messages ) {
966 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
967 return;
970 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
972 /* loop over all printers */
974 for (p = printers_list; p; p = p->next) {
975 struct spoolss_Notify *notifies;
976 uint32_t count = 0;
977 uint32_t id;
978 int i;
980 /* Is there notification on this handle? */
982 if ( !p->notify.client_connected )
983 continue;
985 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
987 /* For this printer? Print servers always receive
988 notifications. */
990 if ( ( p->printer_type == SPLHND_PRINTER ) &&
991 ( !strequal(msg_group->printername, p->sharename) ) )
992 continue;
994 DEBUG(10,("Our printer\n"));
996 /* allocate the max entries possible */
998 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
999 if (!notifies) {
1000 return;
1003 /* build the array of change notifications */
1005 sending_msg_count = 0;
1007 for ( i=0; i<msg_group->num_msgs; i++ ) {
1008 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1010 /* Are we monitoring this event? */
1012 if (!is_monitoring_event(p, msg->type, msg->field))
1013 continue;
1015 sending_msg_count++;
1018 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1019 msg->type, msg->field, p->sharename));
1022 * if the is a printer notification handle and not a job notification
1023 * type, then set the id to 0. Other wise just use what was specified
1024 * in the message.
1026 * When registering change notification on a print server handle
1027 * we always need to send back the id (snum) matching the printer
1028 * for which the change took place. For change notify registered
1029 * on a printer handle, this does not matter and the id should be 0.
1031 * --jerry
1034 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1035 id = 0;
1036 else
1037 id = msg->id;
1040 /* Convert unix jobid to smb jobid */
1042 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1043 id = sysjob_to_jobid(msg->id);
1045 if (id == -1) {
1046 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1047 goto done;
1051 construct_info_data( &notifies[count], msg->type, msg->field, id );
1053 switch(msg->type) {
1054 case PRINTER_NOTIFY_TYPE:
1055 if ( printer_notify_table[msg->field].fn )
1056 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1057 break;
1059 case JOB_NOTIFY_TYPE:
1060 if ( job_notify_table[msg->field].fn )
1061 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1062 break;
1064 default:
1065 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1066 goto done;
1069 count++;
1072 if ( sending_msg_count ) {
1073 NTSTATUS status;
1074 WERROR werr;
1075 union spoolss_ReplyPrinterInfo info;
1076 struct spoolss_NotifyInfo info0;
1077 uint32_t reply_result;
1079 info0.version = 0x2;
1080 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1081 info0.count = count;
1082 info0.notifies = notifies;
1084 info.info0 = &info0;
1086 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1087 &p->notify.client_hnd,
1088 p->notify.change, /* color */
1089 p->notify.flags,
1090 &reply_result,
1091 0, /* reply_type, must be 0 */
1092 info,
1093 &werr);
1094 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1095 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1096 notify_cli_pipe->srv_name_slash,
1097 win_errstr(werr)));
1099 switch (reply_result) {
1100 case 0:
1101 break;
1102 case PRINTER_NOTIFY_INFO_DISCARDED:
1103 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1104 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1105 break;
1106 default:
1107 break;
1112 done:
1113 DEBUG(8,("send_notify2_changes: Exit...\n"));
1114 return;
1117 /***********************************************************************
1118 **********************************************************************/
1120 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1123 uint32_t tv_sec, tv_usec;
1124 size_t offset = 0;
1126 /* Unpack message */
1128 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1129 msg->printer);
1131 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1132 &tv_sec, &tv_usec,
1133 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1135 if (msg->len == 0)
1136 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1137 &msg->notify.value[0], &msg->notify.value[1]);
1138 else
1139 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1140 &msg->len, &msg->notify.data);
1142 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1143 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1145 tv->tv_sec = tv_sec;
1146 tv->tv_usec = tv_usec;
1148 if (msg->len == 0)
1149 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1150 msg->notify.value[1]));
1151 else
1152 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1154 return true;
1157 /********************************************************************
1158 Receive a notify2 message list
1159 ********************************************************************/
1161 static void receive_notify2_message_list(struct messaging_context *msg,
1162 void *private_data,
1163 uint32_t msg_type,
1164 struct server_id server_id,
1165 DATA_BLOB *data)
1167 size_t msg_count, i;
1168 char *buf = (char *)data->data;
1169 char *msg_ptr;
1170 size_t msg_len;
1171 SPOOLSS_NOTIFY_MSG notify;
1172 SPOOLSS_NOTIFY_MSG_CTR messages;
1173 int num_groups;
1175 if (data->length < 4) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1177 return;
1180 msg_count = IVAL(buf, 0);
1181 msg_ptr = buf + 4;
1183 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1185 if (msg_count == 0) {
1186 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1187 return;
1190 /* initialize the container */
1192 ZERO_STRUCT( messages );
1193 notify_msg_ctr_init( &messages );
1196 * build message groups for each printer identified
1197 * in a change_notify msg. Remember that a PCN message
1198 * includes the handle returned for the srv_spoolss_replyopenprinter()
1199 * call. Therefore messages are grouped according to printer handle.
1202 for ( i=0; i<msg_count; i++ ) {
1203 struct timeval msg_tv;
1205 if (msg_ptr + 4 - buf > data->length) {
1206 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1207 return;
1210 msg_len = IVAL(msg_ptr,0);
1211 msg_ptr += 4;
1213 if (msg_ptr + msg_len - buf > data->length) {
1214 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1215 return;
1218 /* unpack messages */
1220 ZERO_STRUCT( notify );
1221 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1222 msg_ptr += msg_len;
1224 /* add to correct list in container */
1226 notify_msg_ctr_addmsg( &messages, &notify );
1228 /* free memory that might have been allocated by notify2_unpack_msg() */
1230 if ( notify.len != 0 )
1231 SAFE_FREE( notify.notify.data );
1234 /* process each group of messages */
1236 num_groups = notify_msg_ctr_numgroups( &messages );
1237 for ( i=0; i<num_groups; i++ )
1238 send_notify2_changes( &messages, i );
1241 /* cleanup */
1243 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1244 (uint32_t)msg_count ));
1246 notify_msg_ctr_destroy( &messages );
1248 return;
1251 /********************************************************************
1252 Send a message to ourself about new driver being installed
1253 so we can upgrade the information for each printer bound to this
1254 driver
1255 ********************************************************************/
1257 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1259 int len = strlen(drivername);
1261 if (!len)
1262 return false;
1264 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1265 drivername));
1267 messaging_send_buf(smbd_messaging_context(), procid_self(),
1268 MSG_PRINTER_DRVUPGRADE,
1269 (uint8_t *)drivername, len+1);
1271 return true;
1274 /**********************************************************************
1275 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1276 over all printers, upgrading ones as necessary
1277 **********************************************************************/
1279 void do_drv_upgrade_printer(struct messaging_context *msg,
1280 void *private_data,
1281 uint32_t msg_type,
1282 struct server_id server_id,
1283 DATA_BLOB *data)
1285 fstring drivername;
1286 int snum;
1287 int n_services = lp_numservices();
1288 size_t len;
1290 len = MIN(data->length,sizeof(drivername)-1);
1291 strncpy(drivername, (const char *)data->data, len);
1293 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1295 /* Iterate the printer list */
1297 for (snum=0; snum<n_services; snum++)
1299 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1301 WERROR result;
1302 NT_PRINTER_INFO_LEVEL *printer = NULL;
1304 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1305 if (!W_ERROR_IS_OK(result))
1306 continue;
1308 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1310 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1312 /* all we care about currently is the change_id */
1314 result = mod_a_printer(printer, 2);
1315 if (!W_ERROR_IS_OK(result)) {
1316 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1317 win_errstr(result)));
1321 free_a_printer(&printer, 2);
1325 /* all done */
1328 /********************************************************************
1329 Update the cache for all printq's with a registered client
1330 connection
1331 ********************************************************************/
1333 void update_monitored_printq_cache( void )
1335 Printer_entry *printer = printers_list;
1336 int snum;
1338 /* loop through all printers and update the cache where
1339 client_connected == true */
1340 while ( printer )
1342 if ( (printer->printer_type == SPLHND_PRINTER)
1343 && printer->notify.client_connected )
1345 snum = print_queue_snum(printer->sharename);
1346 print_queue_status( snum, NULL, NULL );
1349 printer = printer->next;
1352 return;
1354 /********************************************************************
1355 Send a message to ourself about new driver being installed
1356 so we can upgrade the information for each printer bound to this
1357 driver
1358 ********************************************************************/
1360 static bool srv_spoolss_reset_printerdata(char* drivername)
1362 int len = strlen(drivername);
1364 if (!len)
1365 return false;
1367 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1368 drivername));
1370 messaging_send_buf(smbd_messaging_context(), procid_self(),
1371 MSG_PRINTERDATA_INIT_RESET,
1372 (uint8_t *)drivername, len+1);
1374 return true;
1377 /**********************************************************************
1378 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1379 over all printers, resetting printer data as neessary
1380 **********************************************************************/
1382 void reset_all_printerdata(struct messaging_context *msg,
1383 void *private_data,
1384 uint32_t msg_type,
1385 struct server_id server_id,
1386 DATA_BLOB *data)
1388 fstring drivername;
1389 int snum;
1390 int n_services = lp_numservices();
1391 size_t len;
1393 len = MIN( data->length, sizeof(drivername)-1 );
1394 strncpy( drivername, (const char *)data->data, len );
1396 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1398 /* Iterate the printer list */
1400 for ( snum=0; snum<n_services; snum++ )
1402 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1404 WERROR result;
1405 NT_PRINTER_INFO_LEVEL *printer = NULL;
1407 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1408 if ( !W_ERROR_IS_OK(result) )
1409 continue;
1412 * if the printer is bound to the driver,
1413 * then reset to the new driver initdata
1416 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1418 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1420 if ( !set_driver_init(printer, 2) ) {
1421 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1422 printer->info_2->printername, printer->info_2->drivername));
1425 result = mod_a_printer( printer, 2 );
1426 if ( !W_ERROR_IS_OK(result) ) {
1427 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1428 get_dos_error_msg(result)));
1432 free_a_printer( &printer, 2 );
1436 /* all done */
1438 return;
1441 /****************************************************************
1442 _spoolss_OpenPrinter
1443 ****************************************************************/
1445 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1446 struct spoolss_OpenPrinter *r)
1448 struct spoolss_OpenPrinterEx e;
1449 WERROR werr;
1451 ZERO_STRUCT(e.in.userlevel);
1453 e.in.printername = r->in.printername;
1454 e.in.datatype = r->in.datatype;
1455 e.in.devmode_ctr = r->in.devmode_ctr;
1456 e.in.access_mask = r->in.access_mask;
1457 e.in.level = 0;
1459 e.out.handle = r->out.handle;
1461 werr = _spoolss_OpenPrinterEx(p, &e);
1463 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1464 /* OpenPrinterEx returns this for a bad
1465 * printer name. We must return WERR_INVALID_PRINTER_NAME
1466 * instead.
1468 werr = WERR_INVALID_PRINTER_NAME;
1471 return werr;
1474 /********************************************************************
1475 ********************************************************************/
1477 bool convert_devicemode(const char *printername,
1478 const struct spoolss_DeviceMode *devmode,
1479 NT_DEVICEMODE **pp_nt_devmode)
1481 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1484 * Ensure nt_devmode is a valid pointer
1485 * as we will be overwriting it.
1488 if (nt_devmode == NULL) {
1489 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1490 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1491 return false;
1494 fstrcpy(nt_devmode->devicename, devmode->devicename);
1495 fstrcpy(nt_devmode->formname, devmode->formname);
1497 nt_devmode->devicename[31] = '\0';
1498 nt_devmode->formname[31] = '\0';
1500 nt_devmode->specversion = devmode->specversion;
1501 nt_devmode->driverversion = devmode->driverversion;
1502 nt_devmode->size = devmode->size;
1503 nt_devmode->fields = devmode->fields;
1504 nt_devmode->orientation = devmode->orientation;
1505 nt_devmode->papersize = devmode->papersize;
1506 nt_devmode->paperlength = devmode->paperlength;
1507 nt_devmode->paperwidth = devmode->paperwidth;
1508 nt_devmode->scale = devmode->scale;
1509 nt_devmode->copies = devmode->copies;
1510 nt_devmode->defaultsource = devmode->defaultsource;
1511 nt_devmode->printquality = devmode->printquality;
1512 nt_devmode->color = devmode->color;
1513 nt_devmode->duplex = devmode->duplex;
1514 nt_devmode->yresolution = devmode->yresolution;
1515 nt_devmode->ttoption = devmode->ttoption;
1516 nt_devmode->collate = devmode->collate;
1518 nt_devmode->logpixels = devmode->logpixels;
1519 nt_devmode->bitsperpel = devmode->bitsperpel;
1520 nt_devmode->pelswidth = devmode->pelswidth;
1521 nt_devmode->pelsheight = devmode->pelsheight;
1522 nt_devmode->displayflags = devmode->displayflags;
1523 nt_devmode->displayfrequency = devmode->displayfrequency;
1524 nt_devmode->icmmethod = devmode->icmmethod;
1525 nt_devmode->icmintent = devmode->icmintent;
1526 nt_devmode->mediatype = devmode->mediatype;
1527 nt_devmode->dithertype = devmode->dithertype;
1528 nt_devmode->reserved1 = devmode->reserved1;
1529 nt_devmode->reserved2 = devmode->reserved2;
1530 nt_devmode->panningwidth = devmode->panningwidth;
1531 nt_devmode->panningheight = devmode->panningheight;
1534 * Only change private and driverextra if the incoming devmode
1535 * has a new one. JRA.
1538 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1539 SAFE_FREE(nt_devmode->nt_dev_private);
1540 nt_devmode->driverextra = devmode->__driverextra_length;
1541 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1542 return false;
1543 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1546 *pp_nt_devmode = nt_devmode;
1548 return true;
1551 /****************************************************************
1552 _spoolss_OpenPrinterEx
1553 ****************************************************************/
1555 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1556 struct spoolss_OpenPrinterEx *r)
1558 int snum;
1559 Printer_entry *Printer=NULL;
1561 if (!r->in.printername) {
1562 return WERR_INVALID_PARAM;
1565 /* some sanity check because you can open a printer or a print server */
1566 /* aka: \\server\printer or \\server */
1568 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1570 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1571 ZERO_STRUCTP(r->out.handle);
1572 return WERR_INVALID_PARAM;
1575 Printer = find_printer_index_by_hnd(p, r->out.handle);
1576 if ( !Printer ) {
1577 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1578 "handle we created for printer %s\n", r->in.printername));
1579 close_printer_handle(p, r->out.handle);
1580 ZERO_STRUCTP(r->out.handle);
1581 return WERR_INVALID_PARAM;
1585 * First case: the user is opening the print server:
1587 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1588 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1590 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1591 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1592 * or if the user is listed in the smb.conf printer admin parameter.
1594 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1595 * client view printer folder, but does not show the MSAPW.
1597 * Note: this test needs code to check access rights here too. Jeremy
1598 * could you look at this?
1600 * Second case: the user is opening a printer:
1601 * NT doesn't let us connect to a printer if the connecting user
1602 * doesn't have print permission.
1604 * Third case: user is opening a Port Monitor
1605 * access checks same as opening a handle to the print server.
1608 switch (Printer->printer_type )
1610 case SPLHND_SERVER:
1611 case SPLHND_PORTMON_TCP:
1612 case SPLHND_PORTMON_LOCAL:
1613 /* Printserver handles use global struct... */
1615 snum = -1;
1617 /* Map standard access rights to object specific access rights */
1619 se_map_standard(&r->in.access_mask,
1620 &printserver_std_mapping);
1622 /* Deny any object specific bits that don't apply to print
1623 servers (i.e printer and job specific bits) */
1625 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1627 if (r->in.access_mask &
1628 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1629 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1630 close_printer_handle(p, r->out.handle);
1631 ZERO_STRUCTP(r->out.handle);
1632 return WERR_ACCESS_DENIED;
1635 /* Allow admin access */
1637 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1639 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1641 if (!lp_ms_add_printer_wizard()) {
1642 close_printer_handle(p, r->out.handle);
1643 ZERO_STRUCTP(r->out.handle);
1644 return WERR_ACCESS_DENIED;
1647 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1648 and not a printer admin, then fail */
1650 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1651 !user_has_privileges(p->server_info->ptok,
1652 &se_printop ) &&
1653 !token_contains_name_in_list(
1654 uidtoname(p->server_info->utok.uid),
1655 NULL, NULL,
1656 p->server_info->ptok,
1657 lp_printer_admin(snum))) {
1658 close_printer_handle(p, r->out.handle);
1659 ZERO_STRUCTP(r->out.handle);
1660 return WERR_ACCESS_DENIED;
1663 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1665 else
1667 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1670 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1671 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1673 /* We fall through to return WERR_OK */
1674 break;
1676 case SPLHND_PRINTER:
1677 /* NT doesn't let us connect to a printer if the connecting user
1678 doesn't have print permission. */
1680 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1681 close_printer_handle(p, r->out.handle);
1682 ZERO_STRUCTP(r->out.handle);
1683 return WERR_BADFID;
1686 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1687 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1690 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1692 /* map an empty access mask to the minimum access mask */
1693 if (r->in.access_mask == 0x0)
1694 r->in.access_mask = PRINTER_ACCESS_USE;
1697 * If we are not serving the printer driver for this printer,
1698 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1699 * will keep NT clients happy --jerry
1702 if (lp_use_client_driver(snum)
1703 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1705 r->in.access_mask = PRINTER_ACCESS_USE;
1708 /* check smb.conf parameters and the the sec_desc */
1710 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1711 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1712 ZERO_STRUCTP(r->out.handle);
1713 return WERR_ACCESS_DENIED;
1716 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1717 p->server_info->ptok, snum) ||
1718 !print_access_check(p->server_info, snum,
1719 r->in.access_mask)) {
1720 DEBUG(3, ("access DENIED for printer open\n"));
1721 close_printer_handle(p, r->out.handle);
1722 ZERO_STRUCTP(r->out.handle);
1723 return WERR_ACCESS_DENIED;
1726 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1727 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1728 close_printer_handle(p, r->out.handle);
1729 ZERO_STRUCTP(r->out.handle);
1730 return WERR_ACCESS_DENIED;
1733 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1734 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1735 else
1736 r->in.access_mask = PRINTER_ACCESS_USE;
1738 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1739 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1741 break;
1743 default:
1744 /* sanity check to prevent programmer error */
1745 ZERO_STRUCTP(r->out.handle);
1746 return WERR_BADFID;
1749 Printer->access_granted = r->in.access_mask;
1752 * If the client sent a devmode in the OpenPrinter() call, then
1753 * save it here in case we get a job submission on this handle
1756 if ((Printer->printer_type != SPLHND_SERVER) &&
1757 r->in.devmode_ctr.devmode) {
1758 convert_devicemode(Printer->sharename,
1759 r->in.devmode_ctr.devmode,
1760 &Printer->nt_devmode);
1763 #if 0 /* JERRY -- I'm doubtful this is really effective */
1764 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1765 optimization in Windows 2000 clients --jerry */
1767 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1768 && (RA_WIN2K == get_remote_arch()) )
1770 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1771 sys_usleep( 500000 );
1773 #endif
1775 return WERR_OK;
1778 /****************************************************************************
1779 ****************************************************************************/
1781 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1782 NT_PRINTER_INFO_LEVEL_2 *d)
1784 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1786 if (!r || !d) {
1787 return false;
1790 d->attributes = r->attributes;
1791 d->priority = r->priority;
1792 d->default_priority = r->defaultpriority;
1793 d->starttime = r->starttime;
1794 d->untiltime = r->untiltime;
1795 d->status = r->status;
1796 d->cjobs = r->cjobs;
1798 fstrcpy(d->servername, r->servername);
1799 fstrcpy(d->printername, r->printername);
1800 fstrcpy(d->sharename, r->sharename);
1801 fstrcpy(d->portname, r->portname);
1802 fstrcpy(d->drivername, r->drivername);
1803 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1804 fstrcpy(d->location, r->location);
1805 fstrcpy(d->sepfile, r->sepfile);
1806 fstrcpy(d->printprocessor, r->printprocessor);
1807 fstrcpy(d->datatype, r->datatype);
1808 fstrcpy(d->parameters, r->parameters);
1810 return true;
1813 /****************************************************************************
1814 ****************************************************************************/
1816 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1817 NT_PRINTER_INFO_LEVEL *printer)
1819 bool ret;
1821 switch (info_ctr->level) {
1822 case 2:
1823 /* allocate memory if needed. Messy because
1824 convert_printer_info is used to update an existing
1825 printer or build a new one */
1827 if (!printer->info_2) {
1828 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1829 if (!printer->info_2) {
1830 DEBUG(0,("convert_printer_info: "
1831 "talloc() failed!\n"));
1832 return false;
1836 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1837 printer->info_2);
1838 printer->info_2->setuptime = time(NULL);
1839 return ret;
1842 return false;
1845 /****************************************************************
1846 _spoolss_ClosePrinter
1847 ****************************************************************/
1849 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1850 struct spoolss_ClosePrinter *r)
1852 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1854 if (Printer && Printer->document_started) {
1855 struct spoolss_EndDocPrinter e;
1857 e.in.handle = r->in.handle;
1859 _spoolss_EndDocPrinter(p, &e);
1862 if (!close_printer_handle(p, r->in.handle))
1863 return WERR_BADFID;
1865 /* clear the returned printer handle. Observed behavior
1866 from Win2k server. Don't think this really matters.
1867 Previous code just copied the value of the closed
1868 handle. --jerry */
1870 ZERO_STRUCTP(r->out.handle);
1872 return WERR_OK;
1875 /****************************************************************
1876 _spoolss_DeletePrinter
1877 ****************************************************************/
1879 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1880 struct spoolss_DeletePrinter *r)
1882 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1883 WERROR result;
1885 if (Printer && Printer->document_started) {
1886 struct spoolss_EndDocPrinter e;
1888 e.in.handle = r->in.handle;
1890 _spoolss_EndDocPrinter(p, &e);
1893 result = delete_printer_handle(p, r->in.handle);
1895 update_c_setprinter(false);
1897 return result;
1900 /*******************************************************************
1901 * static function to lookup the version id corresponding to an
1902 * long architecture string
1903 ******************************************************************/
1905 static const struct print_architecture_table_node archi_table[]= {
1907 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1908 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1909 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1910 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1911 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1912 {"Windows IA64", SPL_ARCH_IA64, 3 },
1913 {"Windows x64", SPL_ARCH_X64, 3 },
1914 {NULL, "", -1 }
1917 static int get_version_id(const char *arch)
1919 int i;
1921 for (i=0; archi_table[i].long_archi != NULL; i++)
1923 if (strcmp(arch, archi_table[i].long_archi) == 0)
1924 return (archi_table[i].version);
1927 return -1;
1930 /****************************************************************
1931 _spoolss_DeletePrinterDriver
1932 ****************************************************************/
1934 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1935 struct spoolss_DeletePrinterDriver *r)
1938 struct spoolss_DriverInfo8 *info = NULL;
1939 struct spoolss_DriverInfo8 *info_win2k = NULL;
1940 int version;
1941 WERROR status;
1942 WERROR status_win2k = WERR_ACCESS_DENIED;
1943 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1945 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1946 and not a printer admin, then fail */
1948 if ( (p->server_info->utok.uid != sec_initial_uid())
1949 && !user_has_privileges(p->server_info->ptok, &se_printop )
1950 && !token_contains_name_in_list(
1951 uidtoname(p->server_info->utok.uid), NULL,
1952 NULL, p->server_info->ptok,
1953 lp_printer_admin(-1)) )
1955 return WERR_ACCESS_DENIED;
1958 /* check that we have a valid driver name first */
1960 if ((version = get_version_id(r->in.architecture)) == -1)
1961 return WERR_INVALID_ENVIRONMENT;
1963 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1964 r->in.architecture,
1965 version)))
1967 /* try for Win2k driver if "Windows NT x86" */
1969 if ( version == 2 ) {
1970 version = 3;
1971 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1972 &info,
1973 r->in.driver,
1974 r->in.architecture,
1975 version))) {
1976 status = WERR_UNKNOWN_PRINTER_DRIVER;
1977 goto done;
1980 /* otherwise it was a failure */
1981 else {
1982 status = WERR_UNKNOWN_PRINTER_DRIVER;
1983 goto done;
1988 if (printer_driver_in_use(info)) {
1989 status = WERR_PRINTER_DRIVER_IN_USE;
1990 goto done;
1993 if ( version == 2 )
1995 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1996 &info_win2k,
1997 r->in.driver,
1998 r->in.architecture, 3)))
2000 /* if we get to here, we now have 2 driver info structures to remove */
2001 /* remove the Win2k driver first*/
2003 status_win2k = delete_printer_driver(
2004 p, info_win2k, 3, false);
2005 free_a_printer_driver(info_win2k);
2007 /* this should not have failed---if it did, report to client */
2008 if ( !W_ERROR_IS_OK(status_win2k) )
2010 status = status_win2k;
2011 goto done;
2016 status = delete_printer_driver(p, info, version, false);
2018 /* if at least one of the deletes succeeded return OK */
2020 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2021 status = WERR_OK;
2023 done:
2024 free_a_printer_driver(info);
2026 return status;
2029 /****************************************************************
2030 _spoolss_DeletePrinterDriverEx
2031 ****************************************************************/
2033 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2034 struct spoolss_DeletePrinterDriverEx *r)
2036 struct spoolss_DriverInfo8 *info = NULL;
2037 struct spoolss_DriverInfo8 *info_win2k = NULL;
2038 int version;
2039 bool delete_files;
2040 WERROR status;
2041 WERROR status_win2k = WERR_ACCESS_DENIED;
2042 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2044 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2045 and not a printer admin, then fail */
2047 if ( (p->server_info->utok.uid != sec_initial_uid())
2048 && !user_has_privileges(p->server_info->ptok, &se_printop )
2049 && !token_contains_name_in_list(
2050 uidtoname(p->server_info->utok.uid), NULL, NULL,
2051 p->server_info->ptok, lp_printer_admin(-1)) )
2053 return WERR_ACCESS_DENIED;
2056 /* check that we have a valid driver name first */
2057 if ((version = get_version_id(r->in.architecture)) == -1) {
2058 /* this is what NT returns */
2059 return WERR_INVALID_ENVIRONMENT;
2062 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2063 version = r->in.version;
2065 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2066 r->in.architecture, version);
2068 if ( !W_ERROR_IS_OK(status) )
2071 * if the client asked for a specific version,
2072 * or this is something other than Windows NT x86,
2073 * then we've failed
2076 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2077 goto done;
2079 /* try for Win2k driver if "Windows NT x86" */
2081 version = 3;
2082 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2083 r->in.architecture,
2084 version))) {
2085 status = WERR_UNKNOWN_PRINTER_DRIVER;
2086 goto done;
2090 if (printer_driver_in_use(info)) {
2091 status = WERR_PRINTER_DRIVER_IN_USE;
2092 goto done;
2096 * we have a couple of cases to consider.
2097 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2098 * then the delete should fail if **any** files overlap with
2099 * other drivers
2100 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2101 * non-overlapping files
2102 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2103 * is set, the do not delete any files
2104 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2107 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2109 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2111 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2112 /* no idea of the correct error here */
2113 status = WERR_ACCESS_DENIED;
2114 goto done;
2118 /* also check for W32X86/3 if necessary; maybe we already have? */
2120 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2121 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2122 r->in.driver,
2123 r->in.architecture, 3)))
2126 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2127 /* no idea of the correct error here */
2128 free_a_printer_driver(info_win2k);
2129 status = WERR_ACCESS_DENIED;
2130 goto done;
2133 /* if we get to here, we now have 2 driver info structures to remove */
2134 /* remove the Win2k driver first*/
2136 status_win2k = delete_printer_driver(
2137 p, info_win2k, 3, delete_files);
2138 free_a_printer_driver(info_win2k);
2140 /* this should not have failed---if it did, report to client */
2142 if ( !W_ERROR_IS_OK(status_win2k) )
2143 goto done;
2147 status = delete_printer_driver(p, info, version, delete_files);
2149 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2150 status = WERR_OK;
2151 done:
2152 free_a_printer_driver(info);
2154 return status;
2158 /****************************************************************************
2159 Internal routine for removing printerdata
2160 ***************************************************************************/
2162 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2164 return delete_printer_data( printer->info_2, key, value );
2167 /****************************************************************************
2168 Internal routine for storing printerdata
2169 ***************************************************************************/
2171 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2172 const char *key, const char *value,
2173 uint32_t type, uint8_t *data, int real_len)
2175 /* the registry objects enforce uniqueness based on value name */
2177 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2180 /********************************************************************
2181 GetPrinterData on a printer server Handle.
2182 ********************************************************************/
2184 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2185 const char *value,
2186 enum winreg_Type *type,
2187 union spoolss_PrinterData *data)
2189 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2191 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2192 *type = REG_DWORD;
2193 data->value = 0x00;
2194 return WERR_OK;
2197 if (!StrCaseCmp(value, "BeepEnabled")) {
2198 *type = REG_DWORD;
2199 data->value = 0x00;
2200 return WERR_OK;
2203 if (!StrCaseCmp(value, "EventLog")) {
2204 *type = REG_DWORD;
2205 /* formally was 0x1b */
2206 data->value = 0x00;
2207 return WERR_OK;
2210 if (!StrCaseCmp(value, "NetPopup")) {
2211 *type = REG_DWORD;
2212 data->value = 0x00;
2213 return WERR_OK;
2216 if (!StrCaseCmp(value, "MajorVersion")) {
2217 *type = REG_DWORD;
2219 /* Windows NT 4.0 seems to not allow uploading of drivers
2220 to a server that reports 0x3 as the MajorVersion.
2221 need to investigate more how Win2k gets around this .
2222 -- jerry */
2224 if (RA_WINNT == get_remote_arch()) {
2225 data->value = 0x02;
2226 } else {
2227 data->value = 0x03;
2230 return WERR_OK;
2233 if (!StrCaseCmp(value, "MinorVersion")) {
2234 *type = REG_DWORD;
2235 data->value = 0x00;
2236 return WERR_OK;
2239 /* REG_BINARY
2240 * uint32_t size = 0x114
2241 * uint32_t major = 5
2242 * uint32_t minor = [0|1]
2243 * uint32_t build = [2195|2600]
2244 * extra unicode string = e.g. "Service Pack 3"
2246 if (!StrCaseCmp(value, "OSVersion")) {
2247 DATA_BLOB blob;
2248 enum ndr_err_code ndr_err;
2249 struct spoolss_OSVersion os;
2251 os.major = 5; /* Windows 2000 == 5.0 */
2252 os.minor = 0;
2253 os.build = 2195; /* build */
2254 os.extra_string = ""; /* leave extra string empty */
2256 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2257 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2258 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2259 return WERR_GENERAL_FAILURE;
2262 *type = REG_BINARY;
2263 data->binary = blob;
2265 return WERR_OK;
2269 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2270 *type = REG_SZ;
2272 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2273 W_ERROR_HAVE_NO_MEMORY(data->string);
2275 return WERR_OK;
2278 if (!StrCaseCmp(value, "Architecture")) {
2279 *type = REG_SZ;
2280 data->string = talloc_strdup(mem_ctx,
2281 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2282 W_ERROR_HAVE_NO_MEMORY(data->string);
2284 return WERR_OK;
2287 if (!StrCaseCmp(value, "DsPresent")) {
2288 *type = REG_DWORD;
2290 /* only show the publish check box if we are a
2291 member of a AD domain */
2293 if (lp_security() == SEC_ADS) {
2294 data->value = 0x01;
2295 } else {
2296 data->value = 0x00;
2298 return WERR_OK;
2301 if (!StrCaseCmp(value, "DNSMachineName")) {
2302 const char *hostname = get_mydnsfullname();
2304 if (!hostname) {
2305 return WERR_BADFILE;
2308 *type = REG_SZ;
2309 data->string = talloc_strdup(mem_ctx, hostname);
2310 W_ERROR_HAVE_NO_MEMORY(data->string);
2312 return WERR_OK;
2315 *type = REG_NONE;
2317 return WERR_INVALID_PARAM;
2320 /****************************************************************
2321 _spoolss_GetPrinterData
2322 ****************************************************************/
2324 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2325 struct spoolss_GetPrinterData *r)
2327 struct spoolss_GetPrinterDataEx r2;
2329 r2.in.handle = r->in.handle;
2330 r2.in.key_name = "PrinterDriverData";
2331 r2.in.value_name = r->in.value_name;
2332 r2.in.offered = r->in.offered;
2333 r2.out.type = r->out.type;
2334 r2.out.data = r->out.data;
2335 r2.out.needed = r->out.needed;
2337 return _spoolss_GetPrinterDataEx(p, &r2);
2340 /*********************************************************
2341 Connect to the client machine.
2342 **********************************************************/
2344 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2345 struct sockaddr_storage *client_ss, const char *remote_machine)
2347 NTSTATUS ret;
2348 struct cli_state *the_cli;
2349 struct sockaddr_storage rm_addr;
2350 char addr[INET6_ADDRSTRLEN];
2352 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2353 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2354 remote_machine));
2355 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2356 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2357 return false;
2359 print_sockaddr(addr, sizeof(addr), &rm_addr);
2360 } else {
2361 rm_addr = *client_ss;
2362 print_sockaddr(addr, sizeof(addr), &rm_addr);
2363 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2364 addr));
2367 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2368 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2369 addr));
2370 return false;
2373 /* setup the connection */
2374 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2375 &rm_addr, 0, "IPC$", "IPC",
2376 "", /* username */
2377 "", /* domain */
2378 "", /* password */
2379 0, lp_client_signing(), NULL );
2381 if ( !NT_STATUS_IS_OK( ret ) ) {
2382 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2383 remote_machine ));
2384 return false;
2387 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2388 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2389 cli_shutdown(the_cli);
2390 return false;
2394 * Ok - we have an anonymous connection to the IPC$ share.
2395 * Now start the NT Domain stuff :-).
2398 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2399 if (!NT_STATUS_IS_OK(ret)) {
2400 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2401 remote_machine, nt_errstr(ret)));
2402 cli_shutdown(the_cli);
2403 return false;
2406 return true;
2409 /***************************************************************************
2410 Connect to the client.
2411 ****************************************************************************/
2413 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2414 uint32_t localprinter, uint32_t type,
2415 struct policy_handle *handle,
2416 struct sockaddr_storage *client_ss)
2418 WERROR result;
2419 NTSTATUS status;
2422 * If it's the first connection, contact the client
2423 * and connect to the IPC$ share anonymously
2425 if (smb_connections==0) {
2426 fstring unix_printer;
2428 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2430 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2431 return false;
2433 messaging_register(smbd_messaging_context(), NULL,
2434 MSG_PRINTER_NOTIFY2,
2435 receive_notify2_message_list);
2436 /* Tell the connections db we're now interested in printer
2437 * notify messages. */
2438 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2442 * Tell the specific printing tdb we want messages for this printer
2443 * by registering our PID.
2446 if (!print_notify_register_pid(snum))
2447 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2449 smb_connections++;
2451 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2452 printer,
2453 localprinter,
2454 type,
2456 NULL,
2457 handle,
2458 &result);
2459 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2460 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2461 win_errstr(result)));
2463 return (W_ERROR_IS_OK(result));
2466 /****************************************************************
2467 ****************************************************************/
2469 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2470 const struct spoolss_NotifyOption *r)
2472 struct spoolss_NotifyOption *option;
2473 uint32_t i,k;
2475 if (!r) {
2476 return NULL;
2479 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2480 if (!option) {
2481 return NULL;
2484 *option = *r;
2486 if (!option->count) {
2487 return option;
2490 option->types = talloc_zero_array(option,
2491 struct spoolss_NotifyOptionType, option->count);
2492 if (!option->types) {
2493 talloc_free(option);
2494 return NULL;
2497 for (i=0; i < option->count; i++) {
2498 option->types[i] = r->types[i];
2500 if (option->types[i].count) {
2501 option->types[i].fields = talloc_zero_array(option,
2502 union spoolss_Field, option->types[i].count);
2503 if (!option->types[i].fields) {
2504 talloc_free(option);
2505 return NULL;
2507 for (k=0; k<option->types[i].count; k++) {
2508 option->types[i].fields[k] =
2509 r->types[i].fields[k];
2514 return option;
2517 /****************************************************************
2518 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2520 * before replying OK: status=0 a rpc call is made to the workstation
2521 * asking ReplyOpenPrinter
2523 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2524 * called from api_spoolss_rffpcnex
2525 ****************************************************************/
2527 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2528 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2530 int snum = -1;
2531 struct spoolss_NotifyOption *option = r->in.notify_options;
2532 struct sockaddr_storage client_ss;
2534 /* store the notify value in the printer struct */
2536 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2538 if (!Printer) {
2539 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2540 "Invalid handle (%s:%u:%u).\n",
2541 OUR_HANDLE(r->in.handle)));
2542 return WERR_BADFID;
2545 Printer->notify.flags = r->in.flags;
2546 Printer->notify.options = r->in.options;
2547 Printer->notify.printerlocal = r->in.printer_local;
2549 TALLOC_FREE(Printer->notify.option);
2550 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2552 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2554 /* Connect to the client machine and send a ReplyOpenPrinter */
2556 if ( Printer->printer_type == SPLHND_SERVER)
2557 snum = -1;
2558 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2559 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2560 return WERR_BADFID;
2562 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2563 "client_address is %s\n", p->client_address));
2565 if (!interpret_string_addr(&client_ss, p->client_address,
2566 AI_NUMERICHOST)) {
2567 return WERR_SERVER_UNAVAILABLE;
2570 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2571 Printer->notify.printerlocal, 1,
2572 &Printer->notify.client_hnd, &client_ss))
2573 return WERR_SERVER_UNAVAILABLE;
2575 Printer->notify.client_connected = true;
2577 return WERR_OK;
2580 /*******************************************************************
2581 * fill a notify_info_data with the servername
2582 ********************************************************************/
2584 static void spoolss_notify_server_name(int snum,
2585 struct spoolss_Notify *data,
2586 print_queue_struct *queue,
2587 NT_PRINTER_INFO_LEVEL *printer,
2588 TALLOC_CTX *mem_ctx)
2590 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2593 /*******************************************************************
2594 * fill a notify_info_data with the printername (not including the servername).
2595 ********************************************************************/
2597 static void spoolss_notify_printer_name(int snum,
2598 struct spoolss_Notify *data,
2599 print_queue_struct *queue,
2600 NT_PRINTER_INFO_LEVEL *printer,
2601 TALLOC_CTX *mem_ctx)
2603 /* the notify name should not contain the \\server\ part */
2604 char *p = strrchr(printer->info_2->printername, '\\');
2606 if (!p) {
2607 p = printer->info_2->printername;
2608 } else {
2609 p++;
2612 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2615 /*******************************************************************
2616 * fill a notify_info_data with the servicename
2617 ********************************************************************/
2619 static void spoolss_notify_share_name(int snum,
2620 struct spoolss_Notify *data,
2621 print_queue_struct *queue,
2622 NT_PRINTER_INFO_LEVEL *printer,
2623 TALLOC_CTX *mem_ctx)
2625 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2628 /*******************************************************************
2629 * fill a notify_info_data with the port name
2630 ********************************************************************/
2632 static void spoolss_notify_port_name(int snum,
2633 struct spoolss_Notify *data,
2634 print_queue_struct *queue,
2635 NT_PRINTER_INFO_LEVEL *printer,
2636 TALLOC_CTX *mem_ctx)
2638 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2641 /*******************************************************************
2642 * fill a notify_info_data with the printername
2643 * but it doesn't exist, have to see what to do
2644 ********************************************************************/
2646 static void spoolss_notify_driver_name(int snum,
2647 struct spoolss_Notify *data,
2648 print_queue_struct *queue,
2649 NT_PRINTER_INFO_LEVEL *printer,
2650 TALLOC_CTX *mem_ctx)
2652 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2655 /*******************************************************************
2656 * fill a notify_info_data with the comment
2657 ********************************************************************/
2659 static void spoolss_notify_comment(int snum,
2660 struct spoolss_Notify *data,
2661 print_queue_struct *queue,
2662 NT_PRINTER_INFO_LEVEL *printer,
2663 TALLOC_CTX *mem_ctx)
2665 char *p;
2667 if (*printer->info_2->comment == '\0') {
2668 p = lp_comment(snum);
2669 } else {
2670 p = printer->info_2->comment;
2673 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2676 /*******************************************************************
2677 * fill a notify_info_data with the comment
2678 * location = "Room 1, floor 2, building 3"
2679 ********************************************************************/
2681 static void spoolss_notify_location(int snum,
2682 struct spoolss_Notify *data,
2683 print_queue_struct *queue,
2684 NT_PRINTER_INFO_LEVEL *printer,
2685 TALLOC_CTX *mem_ctx)
2687 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2690 /*******************************************************************
2691 * fill a notify_info_data with the device mode
2692 * jfm:xxxx don't to it for know but that's a real problem !!!
2693 ********************************************************************/
2695 static void spoolss_notify_devmode(int snum,
2696 struct spoolss_Notify *data,
2697 print_queue_struct *queue,
2698 NT_PRINTER_INFO_LEVEL *printer,
2699 TALLOC_CTX *mem_ctx)
2701 /* for a dummy implementation we have to zero the fields */
2702 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2705 /*******************************************************************
2706 * fill a notify_info_data with the separator file name
2707 ********************************************************************/
2709 static void spoolss_notify_sepfile(int snum,
2710 struct spoolss_Notify *data,
2711 print_queue_struct *queue,
2712 NT_PRINTER_INFO_LEVEL *printer,
2713 TALLOC_CTX *mem_ctx)
2715 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2718 /*******************************************************************
2719 * fill a notify_info_data with the print processor
2720 * jfm:xxxx return always winprint to indicate we don't do anything to it
2721 ********************************************************************/
2723 static void spoolss_notify_print_processor(int snum,
2724 struct spoolss_Notify *data,
2725 print_queue_struct *queue,
2726 NT_PRINTER_INFO_LEVEL *printer,
2727 TALLOC_CTX *mem_ctx)
2729 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2732 /*******************************************************************
2733 * fill a notify_info_data with the print processor options
2734 * jfm:xxxx send an empty string
2735 ********************************************************************/
2737 static void spoolss_notify_parameters(int snum,
2738 struct spoolss_Notify *data,
2739 print_queue_struct *queue,
2740 NT_PRINTER_INFO_LEVEL *printer,
2741 TALLOC_CTX *mem_ctx)
2743 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2746 /*******************************************************************
2747 * fill a notify_info_data with the data type
2748 * jfm:xxxx always send RAW as data type
2749 ********************************************************************/
2751 static void spoolss_notify_datatype(int snum,
2752 struct spoolss_Notify *data,
2753 print_queue_struct *queue,
2754 NT_PRINTER_INFO_LEVEL *printer,
2755 TALLOC_CTX *mem_ctx)
2757 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2760 /*******************************************************************
2761 * fill a notify_info_data with the security descriptor
2762 * jfm:xxxx send an null pointer to say no security desc
2763 * have to implement security before !
2764 ********************************************************************/
2766 static void spoolss_notify_security_desc(int snum,
2767 struct spoolss_Notify *data,
2768 print_queue_struct *queue,
2769 NT_PRINTER_INFO_LEVEL *printer,
2770 TALLOC_CTX *mem_ctx)
2772 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2773 printer->info_2->secdesc_buf->sd_size,
2774 printer->info_2->secdesc_buf->sd);
2777 /*******************************************************************
2778 * fill a notify_info_data with the attributes
2779 * jfm:xxxx a samba printer is always shared
2780 ********************************************************************/
2782 static void spoolss_notify_attributes(int snum,
2783 struct spoolss_Notify *data,
2784 print_queue_struct *queue,
2785 NT_PRINTER_INFO_LEVEL *printer,
2786 TALLOC_CTX *mem_ctx)
2788 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2791 /*******************************************************************
2792 * fill a notify_info_data with the priority
2793 ********************************************************************/
2795 static void spoolss_notify_priority(int snum,
2796 struct spoolss_Notify *data,
2797 print_queue_struct *queue,
2798 NT_PRINTER_INFO_LEVEL *printer,
2799 TALLOC_CTX *mem_ctx)
2801 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2804 /*******************************************************************
2805 * fill a notify_info_data with the default priority
2806 ********************************************************************/
2808 static void spoolss_notify_default_priority(int snum,
2809 struct spoolss_Notify *data,
2810 print_queue_struct *queue,
2811 NT_PRINTER_INFO_LEVEL *printer,
2812 TALLOC_CTX *mem_ctx)
2814 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2817 /*******************************************************************
2818 * fill a notify_info_data with the start time
2819 ********************************************************************/
2821 static void spoolss_notify_start_time(int snum,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 NT_PRINTER_INFO_LEVEL *printer,
2825 TALLOC_CTX *mem_ctx)
2827 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2830 /*******************************************************************
2831 * fill a notify_info_data with the until time
2832 ********************************************************************/
2834 static void spoolss_notify_until_time(int snum,
2835 struct spoolss_Notify *data,
2836 print_queue_struct *queue,
2837 NT_PRINTER_INFO_LEVEL *printer,
2838 TALLOC_CTX *mem_ctx)
2840 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2843 /*******************************************************************
2844 * fill a notify_info_data with the status
2845 ********************************************************************/
2847 static void spoolss_notify_status(int snum,
2848 struct spoolss_Notify *data,
2849 print_queue_struct *queue,
2850 NT_PRINTER_INFO_LEVEL *printer,
2851 TALLOC_CTX *mem_ctx)
2853 print_status_struct status;
2855 print_queue_length(snum, &status);
2856 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2859 /*******************************************************************
2860 * fill a notify_info_data with the number of jobs queued
2861 ********************************************************************/
2863 static void spoolss_notify_cjobs(int snum,
2864 struct spoolss_Notify *data,
2865 print_queue_struct *queue,
2866 NT_PRINTER_INFO_LEVEL *printer,
2867 TALLOC_CTX *mem_ctx)
2869 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2872 /*******************************************************************
2873 * fill a notify_info_data with the average ppm
2874 ********************************************************************/
2876 static void spoolss_notify_average_ppm(int snum,
2877 struct spoolss_Notify *data,
2878 print_queue_struct *queue,
2879 NT_PRINTER_INFO_LEVEL *printer,
2880 TALLOC_CTX *mem_ctx)
2882 /* always respond 8 pages per minutes */
2883 /* a little hard ! */
2884 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2887 /*******************************************************************
2888 * fill a notify_info_data with username
2889 ********************************************************************/
2891 static void spoolss_notify_username(int snum,
2892 struct spoolss_Notify *data,
2893 print_queue_struct *queue,
2894 NT_PRINTER_INFO_LEVEL *printer,
2895 TALLOC_CTX *mem_ctx)
2897 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2900 /*******************************************************************
2901 * fill a notify_info_data with job status
2902 ********************************************************************/
2904 static void spoolss_notify_job_status(int snum,
2905 struct spoolss_Notify *data,
2906 print_queue_struct *queue,
2907 NT_PRINTER_INFO_LEVEL *printer,
2908 TALLOC_CTX *mem_ctx)
2910 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2913 /*******************************************************************
2914 * fill a notify_info_data with job name
2915 ********************************************************************/
2917 static void spoolss_notify_job_name(int snum,
2918 struct spoolss_Notify *data,
2919 print_queue_struct *queue,
2920 NT_PRINTER_INFO_LEVEL *printer,
2921 TALLOC_CTX *mem_ctx)
2923 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2926 /*******************************************************************
2927 * fill a notify_info_data with job status
2928 ********************************************************************/
2930 static void spoolss_notify_job_status_string(int snum,
2931 struct spoolss_Notify *data,
2932 print_queue_struct *queue,
2933 NT_PRINTER_INFO_LEVEL *printer,
2934 TALLOC_CTX *mem_ctx)
2937 * Now we're returning job status codes we just return a "" here. JRA.
2940 const char *p = "";
2942 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2943 p = "unknown";
2945 switch (queue->status) {
2946 case LPQ_QUEUED:
2947 p = "Queued";
2948 break;
2949 case LPQ_PAUSED:
2950 p = ""; /* NT provides the paused string */
2951 break;
2952 case LPQ_SPOOLING:
2953 p = "Spooling";
2954 break;
2955 case LPQ_PRINTING:
2956 p = "Printing";
2957 break;
2959 #endif /* NO LONGER NEEDED. */
2961 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2964 /*******************************************************************
2965 * fill a notify_info_data with job time
2966 ********************************************************************/
2968 static void spoolss_notify_job_time(int snum,
2969 struct spoolss_Notify *data,
2970 print_queue_struct *queue,
2971 NT_PRINTER_INFO_LEVEL *printer,
2972 TALLOC_CTX *mem_ctx)
2974 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2977 /*******************************************************************
2978 * fill a notify_info_data with job size
2979 ********************************************************************/
2981 static void spoolss_notify_job_size(int snum,
2982 struct spoolss_Notify *data,
2983 print_queue_struct *queue,
2984 NT_PRINTER_INFO_LEVEL *printer,
2985 TALLOC_CTX *mem_ctx)
2987 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2990 /*******************************************************************
2991 * fill a notify_info_data with page info
2992 ********************************************************************/
2993 static void spoolss_notify_total_pages(int snum,
2994 struct spoolss_Notify *data,
2995 print_queue_struct *queue,
2996 NT_PRINTER_INFO_LEVEL *printer,
2997 TALLOC_CTX *mem_ctx)
2999 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3002 /*******************************************************************
3003 * fill a notify_info_data with pages printed info.
3004 ********************************************************************/
3005 static void spoolss_notify_pages_printed(int snum,
3006 struct spoolss_Notify *data,
3007 print_queue_struct *queue,
3008 NT_PRINTER_INFO_LEVEL *printer,
3009 TALLOC_CTX *mem_ctx)
3011 /* Add code when back-end tracks this */
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3015 /*******************************************************************
3016 Fill a notify_info_data with job position.
3017 ********************************************************************/
3019 static void spoolss_notify_job_position(int snum,
3020 struct spoolss_Notify *data,
3021 print_queue_struct *queue,
3022 NT_PRINTER_INFO_LEVEL *printer,
3023 TALLOC_CTX *mem_ctx)
3025 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3028 /*******************************************************************
3029 Fill a notify_info_data with submitted time.
3030 ********************************************************************/
3032 static void spoolss_notify_submitted_time(int snum,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 NT_PRINTER_INFO_LEVEL *printer,
3036 TALLOC_CTX *mem_ctx)
3038 data->data.string.string = NULL;
3039 data->data.string.size = 0;
3041 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3042 &data->data.string.string,
3043 &data->data.string.size);
3047 struct s_notify_info_data_table
3049 enum spoolss_NotifyType type;
3050 uint16_t field;
3051 const char *name;
3052 enum spoolss_NotifyTable variable_type;
3053 void (*fn) (int snum, struct spoolss_Notify *data,
3054 print_queue_struct *queue,
3055 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3058 /* A table describing the various print notification constants and
3059 whether the notification data is a pointer to a variable sized
3060 buffer, a one value uint32_t or a two value uint32_t. */
3062 static const struct s_notify_info_data_table notify_info_data_table[] =
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3090 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3091 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3092 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3093 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3094 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3095 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3100 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3101 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3102 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3103 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3104 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3105 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3106 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3115 /*******************************************************************
3116 Return the variable_type of info_data structure.
3117 ********************************************************************/
3119 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3120 uint16_t field)
3122 int i=0;
3124 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3125 if ( (notify_info_data_table[i].type == type) &&
3126 (notify_info_data_table[i].field == field) ) {
3127 return notify_info_data_table[i].variable_type;
3131 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3133 return 0;
3136 /****************************************************************************
3137 ****************************************************************************/
3139 static bool search_notify(enum spoolss_NotifyType type,
3140 uint16_t field,
3141 int *value)
3143 int i;
3145 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3146 if (notify_info_data_table[i].type == type &&
3147 notify_info_data_table[i].field == field &&
3148 notify_info_data_table[i].fn != NULL) {
3149 *value = i;
3150 return true;
3154 return false;
3157 /****************************************************************************
3158 ****************************************************************************/
3160 void construct_info_data(struct spoolss_Notify *info_data,
3161 enum spoolss_NotifyType type,
3162 uint16_t field,
3163 int id)
3165 info_data->type = type;
3166 info_data->field.field = field;
3167 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3168 info_data->job_id = id;
3171 /*******************************************************************
3173 * fill a notify_info struct with info asked
3175 ********************************************************************/
3177 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3178 struct spoolss_NotifyInfo *info,
3179 int snum,
3180 const struct spoolss_NotifyOptionType *option_type,
3181 uint32_t id,
3182 TALLOC_CTX *mem_ctx)
3184 int field_num,j;
3185 enum spoolss_NotifyType type;
3186 uint16_t field;
3188 struct spoolss_Notify *current_data;
3189 NT_PRINTER_INFO_LEVEL *printer = NULL;
3190 print_queue_struct *queue=NULL;
3192 type = option_type->type;
3194 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3195 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3196 option_type->count, lp_servicename(snum)));
3198 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3199 return false;
3201 for(field_num=0; field_num < option_type->count; field_num++) {
3202 field = option_type->fields[field_num].field;
3204 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3206 if (!search_notify(type, field, &j) )
3207 continue;
3209 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3210 struct spoolss_Notify,
3211 info->count + 1);
3212 if (info->notifies == NULL) {
3213 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3214 free_a_printer(&printer, 2);
3215 return false;
3218 current_data = &info->notifies[info->count];
3220 construct_info_data(current_data, type, field, id);
3222 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3223 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3225 notify_info_data_table[j].fn(snum, current_data, queue,
3226 printer, mem_ctx);
3228 info->count++;
3231 free_a_printer(&printer, 2);
3232 return true;
3235 /*******************************************************************
3237 * fill a notify_info struct with info asked
3239 ********************************************************************/
3241 static bool construct_notify_jobs_info(print_queue_struct *queue,
3242 struct spoolss_NotifyInfo *info,
3243 NT_PRINTER_INFO_LEVEL *printer,
3244 int snum,
3245 const struct spoolss_NotifyOptionType *option_type,
3246 uint32_t id,
3247 TALLOC_CTX *mem_ctx)
3249 int field_num,j;
3250 enum spoolss_NotifyType type;
3251 uint16_t field;
3252 struct spoolss_Notify *current_data;
3254 DEBUG(4,("construct_notify_jobs_info\n"));
3256 type = option_type->type;
3258 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3259 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3260 option_type->count));
3262 for(field_num=0; field_num<option_type->count; field_num++) {
3263 field = option_type->fields[field_num].field;
3265 if (!search_notify(type, field, &j) )
3266 continue;
3268 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3269 struct spoolss_Notify,
3270 info->count + 1);
3271 if (info->notifies == NULL) {
3272 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3273 return false;
3276 current_data=&(info->notifies[info->count]);
3278 construct_info_data(current_data, type, field, id);
3279 notify_info_data_table[j].fn(snum, current_data, queue,
3280 printer, mem_ctx);
3281 info->count++;
3284 return true;
3288 * JFM: The enumeration is not that simple, it's even non obvious.
3290 * let's take an example: I want to monitor the PRINTER SERVER for
3291 * the printer's name and the number of jobs currently queued.
3292 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3293 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3295 * I have 3 printers on the back of my server.
3297 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3298 * structures.
3299 * Number Data Id
3300 * 1 printer 1 name 1
3301 * 2 printer 1 cjob 1
3302 * 3 printer 2 name 2
3303 * 4 printer 2 cjob 2
3304 * 5 printer 3 name 3
3305 * 6 printer 3 name 3
3307 * that's the print server case, the printer case is even worse.
3310 /*******************************************************************
3312 * enumerate all printers on the printserver
3313 * fill a notify_info struct with info asked
3315 ********************************************************************/
3317 static WERROR printserver_notify_info(pipes_struct *p,
3318 struct policy_handle *hnd,
3319 struct spoolss_NotifyInfo *info,
3320 TALLOC_CTX *mem_ctx)
3322 int snum;
3323 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3324 int n_services=lp_numservices();
3325 int i;
3326 struct spoolss_NotifyOption *option;
3327 struct spoolss_NotifyOptionType option_type;
3329 DEBUG(4,("printserver_notify_info\n"));
3331 if (!Printer)
3332 return WERR_BADFID;
3334 option = Printer->notify.option;
3336 info->version = 2;
3337 info->notifies = NULL;
3338 info->count = 0;
3340 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3341 sending a ffpcn() request first */
3343 if ( !option )
3344 return WERR_BADFID;
3346 for (i=0; i<option->count; i++) {
3347 option_type = option->types[i];
3349 if (option_type.type != PRINTER_NOTIFY_TYPE)
3350 continue;
3352 for (snum=0; snum<n_services; snum++)
3354 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3355 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3359 #if 0
3361 * Debugging information, don't delete.
3364 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3365 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3366 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3368 for (i=0; i<info->count; i++) {
3369 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3370 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3371 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3373 #endif
3375 return WERR_OK;
3378 /*******************************************************************
3380 * fill a notify_info struct with info asked
3382 ********************************************************************/
3384 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3385 struct spoolss_NotifyInfo *info,
3386 TALLOC_CTX *mem_ctx)
3388 int snum;
3389 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3390 int i;
3391 uint32_t id;
3392 struct spoolss_NotifyOption *option;
3393 struct spoolss_NotifyOptionType option_type;
3394 int count,j;
3395 print_queue_struct *queue=NULL;
3396 print_status_struct status;
3398 DEBUG(4,("printer_notify_info\n"));
3400 if (!Printer)
3401 return WERR_BADFID;
3403 option = Printer->notify.option;
3404 id = 0x0;
3406 info->version = 2;
3407 info->notifies = NULL;
3408 info->count = 0;
3410 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3411 sending a ffpcn() request first */
3413 if ( !option )
3414 return WERR_BADFID;
3416 get_printer_snum(p, hnd, &snum, NULL);
3418 for (i=0; i<option->count; i++) {
3419 option_type = option->types[i];
3421 switch (option_type.type) {
3422 case PRINTER_NOTIFY_TYPE:
3423 if(construct_notify_printer_info(Printer, info, snum,
3424 &option_type, id,
3425 mem_ctx))
3426 id--;
3427 break;
3429 case JOB_NOTIFY_TYPE: {
3430 NT_PRINTER_INFO_LEVEL *printer = NULL;
3432 count = print_queue_status(snum, &queue, &status);
3434 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3435 goto done;
3437 for (j=0; j<count; j++) {
3438 construct_notify_jobs_info(&queue[j], info,
3439 printer, snum,
3440 &option_type,
3441 queue[j].job,
3442 mem_ctx);
3445 free_a_printer(&printer, 2);
3447 done:
3448 SAFE_FREE(queue);
3449 break;
3455 * Debugging information, don't delete.
3458 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3459 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3460 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3462 for (i=0; i<info->count; i++) {
3463 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3464 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3465 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3468 return WERR_OK;
3471 /****************************************************************
3472 _spoolss_RouterRefreshPrinterChangeNotify
3473 ****************************************************************/
3475 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3476 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3478 struct spoolss_NotifyInfo *info;
3480 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3481 WERROR result = WERR_BADFID;
3483 /* we always have a spoolss_NotifyInfo struct */
3484 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3485 if (!info) {
3486 result = WERR_NOMEM;
3487 goto done;
3490 *r->out.info = info;
3492 if (!Printer) {
3493 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3494 "Invalid handle (%s:%u:%u).\n",
3495 OUR_HANDLE(r->in.handle)));
3496 goto done;
3499 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3502 * We are now using the change value, and
3503 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3504 * I don't have a global notification system, I'm sending back all the
3505 * informations even when _NOTHING_ has changed.
3508 /* We need to keep track of the change value to send back in
3509 RRPCN replies otherwise our updates are ignored. */
3511 Printer->notify.fnpcn = true;
3513 if (Printer->notify.client_connected) {
3514 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3515 "Saving change value in request [%x]\n",
3516 r->in.change_low));
3517 Printer->notify.change = r->in.change_low;
3520 /* just ignore the spoolss_NotifyOption */
3522 switch (Printer->printer_type) {
3523 case SPLHND_SERVER:
3524 result = printserver_notify_info(p, r->in.handle,
3525 info, p->mem_ctx);
3526 break;
3528 case SPLHND_PRINTER:
3529 result = printer_notify_info(p, r->in.handle,
3530 info, p->mem_ctx);
3531 break;
3534 Printer->notify.fnpcn = false;
3536 done:
3537 return result;
3540 /********************************************************************
3541 * construct_printer_info_0
3542 * fill a printer_info_0 struct
3543 ********************************************************************/
3545 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3546 const NT_PRINTER_INFO_LEVEL *ntprinter,
3547 struct spoolss_PrinterInfo0 *r,
3548 int snum)
3550 int count;
3551 counter_printer_0 *session_counter;
3552 time_t setuptime;
3553 print_status_struct status;
3555 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3556 W_ERROR_HAVE_NO_MEMORY(r->printername);
3558 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3559 W_ERROR_HAVE_NO_MEMORY(r->servername);
3561 count = print_queue_length(snum, &status);
3563 /* check if we already have a counter for this printer */
3564 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3565 if (session_counter->snum == snum)
3566 break;
3569 /* it's the first time, add it to the list */
3570 if (session_counter == NULL) {
3571 session_counter = SMB_MALLOC_P(counter_printer_0);
3572 W_ERROR_HAVE_NO_MEMORY(session_counter);
3573 ZERO_STRUCTP(session_counter);
3574 session_counter->snum = snum;
3575 session_counter->counter = 0;
3576 DLIST_ADD(counter_list, session_counter);
3579 /* increment it */
3580 session_counter->counter++;
3582 r->cjobs = count;
3583 r->total_jobs = 0;
3584 r->total_bytes = 0;
3586 setuptime = (time_t)ntprinter->info_2->setuptime;
3588 init_systemtime(&r->time, gmtime(&setuptime));
3590 /* JFM:
3591 * the global_counter should be stored in a TDB as it's common to all the clients
3592 * and should be zeroed on samba startup
3594 r->global_counter = session_counter->counter;
3595 r->total_pages = 0;
3596 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3597 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3598 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3599 r->free_build = SPOOLSS_RELEASE_BUILD;
3600 r->spooling = 0;
3601 r->max_spooling = 0;
3602 r->session_counter = session_counter->counter;
3603 r->num_error_out_of_paper = 0x0;
3604 r->num_error_not_ready = 0x0; /* number of print failure */
3605 r->job_error = 0x0;
3606 r->number_of_processors = 0x1;
3607 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3608 r->high_part_total_bytes = 0x0;
3609 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3610 r->last_error = WERR_OK;
3611 r->status = nt_printq_status(status.status);
3612 r->enumerate_network_printers = 0x0;
3613 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3614 r->processor_architecture = 0x0;
3615 r->processor_level = 0x6; /* 6 ???*/
3616 r->ref_ic = 0;
3617 r->reserved2 = 0;
3618 r->reserved3 = 0;
3620 return WERR_OK;
3623 /****************************************************************************
3624 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3625 should be valid upon entry
3626 ****************************************************************************/
3628 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3629 struct spoolss_DeviceMode *r,
3630 const NT_DEVICEMODE *ntdevmode)
3632 if (!r || !ntdevmode) {
3633 return WERR_INVALID_PARAM;
3636 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3637 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3639 r->specversion = ntdevmode->specversion;
3640 r->driverversion = ntdevmode->driverversion;
3641 r->size = ntdevmode->size;
3642 r->__driverextra_length = ntdevmode->driverextra;
3643 r->fields = ntdevmode->fields;
3645 r->orientation = ntdevmode->orientation;
3646 r->papersize = ntdevmode->papersize;
3647 r->paperlength = ntdevmode->paperlength;
3648 r->paperwidth = ntdevmode->paperwidth;
3649 r->scale = ntdevmode->scale;
3650 r->copies = ntdevmode->copies;
3651 r->defaultsource = ntdevmode->defaultsource;
3652 r->printquality = ntdevmode->printquality;
3653 r->color = ntdevmode->color;
3654 r->duplex = ntdevmode->duplex;
3655 r->yresolution = ntdevmode->yresolution;
3656 r->ttoption = ntdevmode->ttoption;
3657 r->collate = ntdevmode->collate;
3659 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3660 W_ERROR_HAVE_NO_MEMORY(r->formname);
3662 r->logpixels = ntdevmode->logpixels;
3663 r->bitsperpel = ntdevmode->bitsperpel;
3664 r->pelswidth = ntdevmode->pelswidth;
3665 r->pelsheight = ntdevmode->pelsheight;
3666 r->displayflags = ntdevmode->displayflags;
3667 r->displayfrequency = ntdevmode->displayfrequency;
3668 r->icmmethod = ntdevmode->icmmethod;
3669 r->icmintent = ntdevmode->icmintent;
3670 r->mediatype = ntdevmode->mediatype;
3671 r->dithertype = ntdevmode->dithertype;
3672 r->reserved1 = ntdevmode->reserved1;
3673 r->reserved2 = ntdevmode->reserved2;
3674 r->panningwidth = ntdevmode->panningwidth;
3675 r->panningheight = ntdevmode->panningheight;
3677 if (ntdevmode->nt_dev_private != NULL) {
3678 r->driverextra_data = data_blob_talloc(mem_ctx,
3679 ntdevmode->nt_dev_private,
3680 ntdevmode->driverextra);
3681 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3684 return WERR_OK;
3688 /****************************************************************************
3689 Create a spoolss_DeviceMode struct. Returns talloced memory.
3690 ****************************************************************************/
3692 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3693 const char *servicename)
3695 WERROR result;
3696 NT_PRINTER_INFO_LEVEL *printer = NULL;
3697 struct spoolss_DeviceMode *devmode = NULL;
3699 DEBUG(7,("construct_dev_mode\n"));
3701 DEBUGADD(8,("getting printer characteristics\n"));
3703 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3704 return NULL;
3706 if (!printer->info_2->devmode) {
3707 DEBUG(5, ("BONG! There was no device mode!\n"));
3708 goto done;
3711 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3712 if (!devmode) {
3713 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3714 goto done;
3717 DEBUGADD(8,("loading DEVICEMODE\n"));
3719 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3720 if (!W_ERROR_IS_OK(result)) {
3721 TALLOC_FREE(devmode);
3724 done:
3725 free_a_printer(&printer,2);
3727 return devmode;
3730 /********************************************************************
3731 * construct_printer_info1
3732 * fill a spoolss_PrinterInfo1 struct
3733 ********************************************************************/
3735 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3736 const NT_PRINTER_INFO_LEVEL *ntprinter,
3737 uint32_t flags,
3738 struct spoolss_PrinterInfo1 *r,
3739 int snum)
3741 r->flags = flags;
3743 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3744 ntprinter->info_2->printername,
3745 ntprinter->info_2->drivername,
3746 ntprinter->info_2->location);
3747 W_ERROR_HAVE_NO_MEMORY(r->description);
3749 if (*ntprinter->info_2->comment == '\0') {
3750 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3751 } else {
3752 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3754 W_ERROR_HAVE_NO_MEMORY(r->comment);
3756 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3757 W_ERROR_HAVE_NO_MEMORY(r->name);
3759 return WERR_OK;
3762 /********************************************************************
3763 * construct_printer_info2
3764 * fill a spoolss_PrinterInfo2 struct
3765 ********************************************************************/
3767 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3768 const NT_PRINTER_INFO_LEVEL *ntprinter,
3769 struct spoolss_PrinterInfo2 *r,
3770 int snum)
3772 int count;
3774 print_status_struct status;
3776 count = print_queue_length(snum, &status);
3778 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3779 W_ERROR_HAVE_NO_MEMORY(r->servername);
3780 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3781 W_ERROR_HAVE_NO_MEMORY(r->printername);
3782 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3783 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3784 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3785 W_ERROR_HAVE_NO_MEMORY(r->portname);
3786 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3787 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3789 if (*ntprinter->info_2->comment == '\0') {
3790 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3791 } else {
3792 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3794 W_ERROR_HAVE_NO_MEMORY(r->comment);
3796 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3797 W_ERROR_HAVE_NO_MEMORY(r->location);
3798 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3799 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3800 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3801 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3802 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3803 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3804 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3805 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3807 r->attributes = ntprinter->info_2->attributes;
3809 r->priority = ntprinter->info_2->priority;
3810 r->defaultpriority = ntprinter->info_2->default_priority;
3811 r->starttime = ntprinter->info_2->starttime;
3812 r->untiltime = ntprinter->info_2->untiltime;
3813 r->status = nt_printq_status(status.status);
3814 r->cjobs = count;
3815 r->averageppm = ntprinter->info_2->averageppm;
3817 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3818 if (!r->devmode) {
3819 DEBUG(8,("Returning NULL Devicemode!\n"));
3822 r->secdesc = NULL;
3824 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3825 /* don't use talloc_steal() here unless you do a deep steal of all
3826 the SEC_DESC members */
3828 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3831 return WERR_OK;
3834 /********************************************************************
3835 * construct_printer_info3
3836 * fill a spoolss_PrinterInfo3 struct
3837 ********************************************************************/
3839 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3840 const NT_PRINTER_INFO_LEVEL *ntprinter,
3841 struct spoolss_PrinterInfo3 *r,
3842 int snum)
3844 /* These are the components of the SD we are returning. */
3846 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3847 /* don't use talloc_steal() here unless you do a deep steal of all
3848 the SEC_DESC members */
3850 r->secdesc = dup_sec_desc(mem_ctx,
3851 ntprinter->info_2->secdesc_buf->sd);
3852 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3855 return WERR_OK;
3858 /********************************************************************
3859 * construct_printer_info4
3860 * fill a spoolss_PrinterInfo4 struct
3861 ********************************************************************/
3863 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3864 const NT_PRINTER_INFO_LEVEL *ntprinter,
3865 struct spoolss_PrinterInfo4 *r,
3866 int snum)
3868 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3869 W_ERROR_HAVE_NO_MEMORY(r->printername);
3870 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3871 W_ERROR_HAVE_NO_MEMORY(r->servername);
3873 r->attributes = ntprinter->info_2->attributes;
3875 return WERR_OK;
3878 /********************************************************************
3879 * construct_printer_info5
3880 * fill a spoolss_PrinterInfo5 struct
3881 ********************************************************************/
3883 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3884 const NT_PRINTER_INFO_LEVEL *ntprinter,
3885 struct spoolss_PrinterInfo5 *r,
3886 int snum)
3888 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3889 W_ERROR_HAVE_NO_MEMORY(r->printername);
3890 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3891 W_ERROR_HAVE_NO_MEMORY(r->portname);
3893 r->attributes = ntprinter->info_2->attributes;
3895 /* these two are not used by NT+ according to MSDN */
3897 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3898 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3900 return WERR_OK;
3903 /********************************************************************
3904 * construct_printer_info_6
3905 * fill a spoolss_PrinterInfo6 struct
3906 ********************************************************************/
3908 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3909 const NT_PRINTER_INFO_LEVEL *ntprinter,
3910 struct spoolss_PrinterInfo6 *r,
3911 int snum)
3913 int count;
3914 print_status_struct status;
3916 count = print_queue_length(snum, &status);
3918 r->status = nt_printq_status(status.status);
3920 return WERR_OK;
3923 /********************************************************************
3924 * construct_printer_info7
3925 * fill a spoolss_PrinterInfo7 struct
3926 ********************************************************************/
3928 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3929 Printer_entry *print_hnd,
3930 struct spoolss_PrinterInfo7 *r,
3931 int snum)
3933 struct GUID guid;
3935 if (is_printer_published(print_hnd, snum, &guid)) {
3936 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3937 r->action = DSPRINT_PUBLISH;
3938 } else {
3939 r->guid = talloc_strdup(mem_ctx, "");
3940 r->action = DSPRINT_UNPUBLISH;
3942 W_ERROR_HAVE_NO_MEMORY(r->guid);
3944 return WERR_OK;
3947 /********************************************************************
3948 * construct_printer_info8
3949 * fill a spoolss_PrinterInfo8 struct
3950 ********************************************************************/
3952 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3953 const NT_PRINTER_INFO_LEVEL *ntprinter,
3954 struct spoolss_DeviceModeInfo *r,
3955 int snum)
3957 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3958 if (!r->devmode) {
3959 DEBUG(8,("Returning NULL Devicemode!\n"));
3962 return WERR_OK;
3966 /********************************************************************
3967 ********************************************************************/
3969 static bool snum_is_shared_printer(int snum)
3971 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3974 /********************************************************************
3975 Spoolss_enumprinters.
3976 ********************************************************************/
3978 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3979 uint32_t level,
3980 uint32_t flags,
3981 union spoolss_PrinterInfo **info_p,
3982 uint32_t *count_p)
3984 int snum;
3985 int n_services = lp_numservices();
3986 union spoolss_PrinterInfo *info = NULL;
3987 uint32_t count = 0;
3988 WERROR result = WERR_OK;
3990 *count_p = 0;
3991 *info_p = NULL;
3993 for (snum = 0; snum < n_services; snum++) {
3995 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3997 if (!snum_is_shared_printer(snum)) {
3998 continue;
4001 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4002 lp_servicename(snum), snum));
4004 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4005 union spoolss_PrinterInfo,
4006 count + 1);
4007 if (!info) {
4008 result = WERR_NOMEM;
4009 goto out;
4012 result = get_a_printer(NULL, &ntprinter, 2,
4013 lp_const_servicename(snum));
4014 if (!W_ERROR_IS_OK(result)) {
4015 goto out;
4018 switch (level) {
4019 case 0:
4020 result = construct_printer_info0(info, ntprinter,
4021 &info[count].info0, snum);
4022 break;
4023 case 1:
4024 result = construct_printer_info1(info, ntprinter, flags,
4025 &info[count].info1, snum);
4026 break;
4027 case 2:
4028 result = construct_printer_info2(info, ntprinter,
4029 &info[count].info2, snum);
4030 break;
4031 case 4:
4032 result = construct_printer_info4(info, ntprinter,
4033 &info[count].info4, snum);
4034 break;
4035 case 5:
4036 result = construct_printer_info5(info, ntprinter,
4037 &info[count].info5, snum);
4038 break;
4040 default:
4041 result = WERR_UNKNOWN_LEVEL;
4042 free_a_printer(&ntprinter, 2);
4043 goto out;
4046 free_a_printer(&ntprinter, 2);
4047 if (!W_ERROR_IS_OK(result)) {
4048 goto out;
4051 count++;
4054 *count_p = count;
4055 *info_p = info;
4057 out:
4058 if (!W_ERROR_IS_OK(result)) {
4059 TALLOC_FREE(info);
4060 return result;
4063 *info_p = info;
4065 return WERR_OK;
4068 /********************************************************************
4069 * handle enumeration of printers at level 0
4070 ********************************************************************/
4072 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4073 uint32_t flags,
4074 const char *servername,
4075 union spoolss_PrinterInfo **info,
4076 uint32_t *count)
4078 DEBUG(4,("enum_all_printers_info_0\n"));
4080 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4084 /********************************************************************
4085 ********************************************************************/
4087 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4088 uint32_t flags,
4089 union spoolss_PrinterInfo **info,
4090 uint32_t *count)
4092 DEBUG(4,("enum_all_printers_info_1\n"));
4094 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4097 /********************************************************************
4098 enum_all_printers_info_1_local.
4099 *********************************************************************/
4101 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4102 union spoolss_PrinterInfo **info,
4103 uint32_t *count)
4105 DEBUG(4,("enum_all_printers_info_1_local\n"));
4107 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4110 /********************************************************************
4111 enum_all_printers_info_1_name.
4112 *********************************************************************/
4114 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4115 const char *name,
4116 union spoolss_PrinterInfo **info,
4117 uint32_t *count)
4119 const char *s = name;
4121 DEBUG(4,("enum_all_printers_info_1_name\n"));
4123 if ((name[0] == '\\') && (name[1] == '\\')) {
4124 s = name + 2;
4127 if (!is_myname_or_ipaddr(s)) {
4128 return WERR_INVALID_NAME;
4131 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4134 /********************************************************************
4135 enum_all_printers_info_1_network.
4136 *********************************************************************/
4138 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4139 const char *name,
4140 union spoolss_PrinterInfo **info,
4141 uint32_t *count)
4143 const char *s = name;
4145 DEBUG(4,("enum_all_printers_info_1_network\n"));
4147 /* If we respond to a enum_printers level 1 on our name with flags
4148 set to PRINTER_ENUM_REMOTE with a list of printers then these
4149 printers incorrectly appear in the APW browse list.
4150 Specifically the printers for the server appear at the workgroup
4151 level where all the other servers in the domain are
4152 listed. Windows responds to this call with a
4153 WERR_CAN_NOT_COMPLETE so we should do the same. */
4155 if (name[0] == '\\' && name[1] == '\\') {
4156 s = name + 2;
4159 if (is_myname_or_ipaddr(s)) {
4160 return WERR_CAN_NOT_COMPLETE;
4163 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4166 /********************************************************************
4167 * api_spoolss_enumprinters
4169 * called from api_spoolss_enumprinters (see this to understand)
4170 ********************************************************************/
4172 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4173 union spoolss_PrinterInfo **info,
4174 uint32_t *count)
4176 DEBUG(4,("enum_all_printers_info_2\n"));
4178 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4181 /********************************************************************
4182 * handle enumeration of printers at level 1
4183 ********************************************************************/
4185 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4186 uint32_t flags,
4187 const char *name,
4188 union spoolss_PrinterInfo **info,
4189 uint32_t *count)
4191 /* Not all the flags are equals */
4193 if (flags & PRINTER_ENUM_LOCAL) {
4194 return enum_all_printers_info_1_local(mem_ctx, info, count);
4197 if (flags & PRINTER_ENUM_NAME) {
4198 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4201 if (flags & PRINTER_ENUM_NETWORK) {
4202 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4205 return WERR_OK; /* NT4sp5 does that */
4208 /********************************************************************
4209 * handle enumeration of printers at level 2
4210 ********************************************************************/
4212 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4213 uint32_t flags,
4214 const char *servername,
4215 union spoolss_PrinterInfo **info,
4216 uint32_t *count)
4218 if (flags & PRINTER_ENUM_LOCAL) {
4219 return enum_all_printers_info_2(mem_ctx, info, count);
4222 if (flags & PRINTER_ENUM_NAME) {
4223 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4224 return WERR_INVALID_NAME;
4227 return enum_all_printers_info_2(mem_ctx, info, count);
4230 if (flags & PRINTER_ENUM_REMOTE) {
4231 return WERR_UNKNOWN_LEVEL;
4234 return WERR_OK;
4237 /********************************************************************
4238 * handle enumeration of printers at level 4
4239 ********************************************************************/
4241 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4242 uint32_t flags,
4243 const char *servername,
4244 union spoolss_PrinterInfo **info,
4245 uint32_t *count)
4247 DEBUG(4,("enum_all_printers_info_4\n"));
4249 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4253 /********************************************************************
4254 * handle enumeration of printers at level 5
4255 ********************************************************************/
4257 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4258 uint32_t flags,
4259 const char *servername,
4260 union spoolss_PrinterInfo **info,
4261 uint32_t *count)
4263 DEBUG(4,("enum_all_printers_info_5\n"));
4265 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4268 /****************************************************************
4269 _spoolss_EnumPrinters
4270 ****************************************************************/
4272 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4273 struct spoolss_EnumPrinters *r)
4275 const char *name = NULL;
4276 WERROR result;
4278 /* that's an [in out] buffer */
4280 if (!r->in.buffer && (r->in.offered != 0)) {
4281 return WERR_INVALID_PARAM;
4284 DEBUG(4,("_spoolss_EnumPrinters\n"));
4286 *r->out.needed = 0;
4287 *r->out.count = 0;
4288 *r->out.info = NULL;
4291 * Level 1:
4292 * flags==PRINTER_ENUM_NAME
4293 * if name=="" then enumerates all printers
4294 * if name!="" then enumerate the printer
4295 * flags==PRINTER_ENUM_REMOTE
4296 * name is NULL, enumerate printers
4297 * Level 2: name!="" enumerates printers, name can't be NULL
4298 * Level 3: doesn't exist
4299 * Level 4: does a local registry lookup
4300 * Level 5: same as Level 2
4303 if (r->in.server) {
4304 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4305 W_ERROR_HAVE_NO_MEMORY(name);
4308 switch (r->in.level) {
4309 case 0:
4310 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4311 r->out.info, r->out.count);
4312 break;
4313 case 1:
4314 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4315 r->out.info, r->out.count);
4316 break;
4317 case 2:
4318 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4319 r->out.info, r->out.count);
4320 break;
4321 case 4:
4322 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4323 r->out.info, r->out.count);
4324 break;
4325 case 5:
4326 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4327 r->out.info, r->out.count);
4328 break;
4329 default:
4330 return WERR_UNKNOWN_LEVEL;
4333 if (!W_ERROR_IS_OK(result)) {
4334 return result;
4337 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4338 spoolss_EnumPrinters, NULL,
4339 *r->out.info, r->in.level,
4340 *r->out.count);
4341 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4342 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4344 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4347 /****************************************************************
4348 _spoolss_GetPrinter
4349 ****************************************************************/
4351 WERROR _spoolss_GetPrinter(pipes_struct *p,
4352 struct spoolss_GetPrinter *r)
4354 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4355 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4356 WERROR result = WERR_OK;
4358 int snum;
4360 /* that's an [in out] buffer */
4362 if (!r->in.buffer && (r->in.offered != 0)) {
4363 return WERR_INVALID_PARAM;
4366 *r->out.needed = 0;
4368 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4369 return WERR_BADFID;
4372 result = get_a_printer(Printer, &ntprinter, 2,
4373 lp_const_servicename(snum));
4374 if (!W_ERROR_IS_OK(result)) {
4375 return result;
4378 switch (r->in.level) {
4379 case 0:
4380 result = construct_printer_info0(p->mem_ctx, ntprinter,
4381 &r->out.info->info0, snum);
4382 break;
4383 case 1:
4384 result = construct_printer_info1(p->mem_ctx, ntprinter,
4385 PRINTER_ENUM_ICON8,
4386 &r->out.info->info1, snum);
4387 break;
4388 case 2:
4389 result = construct_printer_info2(p->mem_ctx, ntprinter,
4390 &r->out.info->info2, snum);
4391 break;
4392 case 3:
4393 result = construct_printer_info3(p->mem_ctx, ntprinter,
4394 &r->out.info->info3, snum);
4395 break;
4396 case 4:
4397 result = construct_printer_info4(p->mem_ctx, ntprinter,
4398 &r->out.info->info4, snum);
4399 break;
4400 case 5:
4401 result = construct_printer_info5(p->mem_ctx, ntprinter,
4402 &r->out.info->info5, snum);
4403 break;
4404 case 6:
4405 result = construct_printer_info6(p->mem_ctx, ntprinter,
4406 &r->out.info->info6, snum);
4407 break;
4408 case 7:
4409 result = construct_printer_info7(p->mem_ctx, Printer,
4410 &r->out.info->info7, snum);
4411 break;
4412 case 8:
4413 result = construct_printer_info8(p->mem_ctx, ntprinter,
4414 &r->out.info->info8, snum);
4415 break;
4416 default:
4417 result = WERR_UNKNOWN_LEVEL;
4418 break;
4421 free_a_printer(&ntprinter, 2);
4423 if (!W_ERROR_IS_OK(result)) {
4424 TALLOC_FREE(r->out.info);
4425 return result;
4428 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4429 r->out.info, r->in.level);
4430 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4432 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4435 /********************************************************************
4436 ********************************************************************/
4438 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4439 const char **string_array,
4440 const char *cservername)
4442 int i, num_strings = 0;
4443 const char **array = NULL;
4445 if (!string_array) {
4446 return NULL;
4449 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4451 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4452 cservername, string_array[i]);
4453 if (!str) {
4454 TALLOC_FREE(array);
4455 return NULL;
4459 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4460 TALLOC_FREE(array);
4461 return NULL;
4465 if (i > 0) {
4466 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4467 &array, &num_strings);
4470 return array;
4473 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4474 do { \
4475 if (in && strlen(in)) { \
4476 out = talloc_strdup(mem_ctx, in); \
4477 W_ERROR_HAVE_NO_MEMORY(out); \
4478 } else { \
4479 out = NULL; \
4481 } while (0);
4483 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4484 do { \
4485 if (in && strlen(in)) { \
4486 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4487 } else { \
4488 out = talloc_strdup(mem_ctx, ""); \
4490 W_ERROR_HAVE_NO_MEMORY(out); \
4491 } while (0);
4493 /********************************************************************
4494 * fill a spoolss_DriverInfo1 struct
4495 ********************************************************************/
4497 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4498 struct spoolss_DriverInfo1 *r,
4499 const struct spoolss_DriverInfo8 *driver,
4500 const char *servername)
4502 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4503 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4505 return WERR_OK;
4508 /********************************************************************
4509 * fill a spoolss_DriverInfo2 struct
4510 ********************************************************************/
4512 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4513 struct spoolss_DriverInfo2 *r,
4514 const struct spoolss_DriverInfo8 *driver,
4515 const char *servername)
4518 const char *cservername = canon_servername(servername);
4520 r->version = driver->version;
4522 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4523 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4524 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4525 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4527 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4528 driver->driver_path,
4529 r->driver_path);
4531 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4532 driver->data_file,
4533 r->data_file);
4535 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4536 driver->config_file,
4537 r->config_file);
4539 return WERR_OK;
4542 /********************************************************************
4543 * fill a spoolss_DriverInfo3 struct
4544 ********************************************************************/
4546 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4547 struct spoolss_DriverInfo3 *r,
4548 const struct spoolss_DriverInfo8 *driver,
4549 const char *servername)
4551 const char *cservername = canon_servername(servername);
4553 r->version = driver->version;
4555 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4556 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4557 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4558 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4560 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4561 driver->driver_path,
4562 r->driver_path);
4564 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4565 driver->data_file,
4566 r->data_file);
4568 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4569 driver->config_file,
4570 r->config_file);
4572 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4573 driver->help_file,
4574 r->help_file);
4576 FILL_DRIVER_STRING(mem_ctx,
4577 driver->monitor_name,
4578 r->monitor_name);
4580 FILL_DRIVER_STRING(mem_ctx,
4581 driver->default_datatype,
4582 r->default_datatype);
4584 r->dependent_files = string_array_from_driver_info(mem_ctx,
4585 driver->dependent_files,
4586 cservername);
4587 return WERR_OK;
4590 /********************************************************************
4591 * fill a spoolss_DriverInfo4 struct
4592 ********************************************************************/
4594 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4595 struct spoolss_DriverInfo4 *r,
4596 const struct spoolss_DriverInfo8 *driver,
4597 const char *servername)
4599 const char *cservername = canon_servername(servername);
4601 r->version = driver->version;
4603 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4604 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4605 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4606 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4608 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4609 driver->driver_path,
4610 r->driver_path);
4612 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4613 driver->data_file,
4614 r->data_file);
4616 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4617 driver->config_file,
4618 r->config_file);
4620 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4621 driver->help_file,
4622 r->help_file);
4624 r->dependent_files = string_array_from_driver_info(mem_ctx,
4625 driver->dependent_files,
4626 cservername);
4628 FILL_DRIVER_STRING(mem_ctx,
4629 driver->monitor_name,
4630 r->monitor_name);
4632 FILL_DRIVER_STRING(mem_ctx,
4633 driver->default_datatype,
4634 r->default_datatype);
4636 r->previous_names = string_array_from_driver_info(mem_ctx,
4637 driver->previous_names,
4638 cservername);
4640 return WERR_OK;
4643 /********************************************************************
4644 * fill a spoolss_DriverInfo5 struct
4645 ********************************************************************/
4647 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4648 struct spoolss_DriverInfo5 *r,
4649 const struct spoolss_DriverInfo8 *driver,
4650 const char *servername)
4652 const char *cservername = canon_servername(servername);
4654 r->version = driver->version;
4656 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4657 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4658 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4659 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4661 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4662 driver->driver_path,
4663 r->driver_path);
4665 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4666 driver->data_file,
4667 r->data_file);
4669 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4670 driver->config_file,
4671 r->config_file);
4673 r->driver_attributes = 0;
4674 r->config_version = 0;
4675 r->driver_version = 0;
4677 return WERR_OK;
4679 /********************************************************************
4680 * fill a spoolss_DriverInfo6 struct
4681 ********************************************************************/
4683 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4684 struct spoolss_DriverInfo6 *r,
4685 const struct spoolss_DriverInfo8 *driver,
4686 const char *servername)
4688 const char *cservername = canon_servername(servername);
4690 r->version = driver->version;
4692 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4693 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4694 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4695 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4697 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4698 driver->driver_path,
4699 r->driver_path);
4701 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4702 driver->data_file,
4703 r->data_file);
4705 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4706 driver->config_file,
4707 r->config_file);
4709 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4710 driver->help_file,
4711 r->help_file);
4713 FILL_DRIVER_STRING(mem_ctx,
4714 driver->monitor_name,
4715 r->monitor_name);
4717 FILL_DRIVER_STRING(mem_ctx,
4718 driver->default_datatype,
4719 r->default_datatype);
4721 r->dependent_files = string_array_from_driver_info(mem_ctx,
4722 driver->dependent_files,
4723 cservername);
4724 r->previous_names = string_array_from_driver_info(mem_ctx,
4725 driver->previous_names,
4726 cservername);
4728 r->driver_date = driver->driver_date;
4729 r->driver_version = driver->driver_version;
4731 FILL_DRIVER_STRING(mem_ctx,
4732 driver->manufacturer_name,
4733 r->manufacturer_name);
4734 FILL_DRIVER_STRING(mem_ctx,
4735 driver->manufacturer_url,
4736 r->manufacturer_url);
4737 FILL_DRIVER_STRING(mem_ctx,
4738 driver->hardware_id,
4739 r->hardware_id);
4740 FILL_DRIVER_STRING(mem_ctx,
4741 driver->provider,
4742 r->provider);
4744 return WERR_OK;
4747 /********************************************************************
4748 * fill a spoolss_DriverInfo8 struct
4749 ********************************************************************/
4751 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4752 struct spoolss_DriverInfo8 *r,
4753 const struct spoolss_DriverInfo8 *driver,
4754 const char *servername)
4756 const char *cservername = canon_servername(servername);
4758 r->version = driver->version;
4760 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4761 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4762 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4763 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4765 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4766 driver->driver_path,
4767 r->driver_path);
4769 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4770 driver->data_file,
4771 r->data_file);
4773 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4774 driver->config_file,
4775 r->config_file);
4777 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4778 driver->help_file,
4779 r->help_file);
4781 FILL_DRIVER_STRING(mem_ctx,
4782 driver->monitor_name,
4783 r->monitor_name);
4785 FILL_DRIVER_STRING(mem_ctx,
4786 driver->default_datatype,
4787 r->default_datatype);
4789 r->dependent_files = string_array_from_driver_info(mem_ctx,
4790 driver->dependent_files,
4791 cservername);
4792 r->previous_names = string_array_from_driver_info(mem_ctx,
4793 driver->previous_names,
4794 cservername);
4796 r->driver_date = driver->driver_date;
4797 r->driver_version = driver->driver_version;
4799 FILL_DRIVER_STRING(mem_ctx,
4800 driver->manufacturer_name,
4801 r->manufacturer_name);
4802 FILL_DRIVER_STRING(mem_ctx,
4803 driver->manufacturer_url,
4804 r->manufacturer_url);
4805 FILL_DRIVER_STRING(mem_ctx,
4806 driver->hardware_id,
4807 r->hardware_id);
4808 FILL_DRIVER_STRING(mem_ctx,
4809 driver->provider,
4810 r->provider);
4812 FILL_DRIVER_STRING(mem_ctx,
4813 driver->print_processor,
4814 r->print_processor);
4815 FILL_DRIVER_STRING(mem_ctx,
4816 driver->vendor_setup,
4817 r->vendor_setup);
4819 r->color_profiles = string_array_from_driver_info(mem_ctx,
4820 driver->color_profiles,
4821 cservername);
4823 FILL_DRIVER_STRING(mem_ctx,
4824 driver->inf_path,
4825 r->inf_path);
4827 r->printer_driver_attributes = driver->printer_driver_attributes;
4829 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4830 driver->core_driver_dependencies,
4831 cservername);
4833 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4834 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4836 return WERR_OK;
4839 #if 0 /* disabled until marshalling issues are resolved - gd */
4840 /********************************************************************
4841 ********************************************************************/
4843 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4844 struct spoolss_DriverFileInfo *r,
4845 const char *cservername,
4846 const char *file_name,
4847 enum spoolss_DriverFileType file_type,
4848 uint32_t file_version)
4850 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4851 cservername, file_name);
4852 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4853 r->file_type = file_type;
4854 r->file_version = file_version;
4856 return WERR_OK;
4859 /********************************************************************
4860 ********************************************************************/
4862 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4863 const struct spoolss_DriverInfo8 *driver,
4864 const char *cservername,
4865 struct spoolss_DriverFileInfo **info_p,
4866 uint32_t *count_p)
4868 struct spoolss_DriverFileInfo *info = NULL;
4869 uint32_t count = 0;
4870 WERROR result;
4871 uint32_t i;
4873 *info_p = NULL;
4874 *count_p = 0;
4876 if (strlen(driver->driver_path)) {
4877 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4878 struct spoolss_DriverFileInfo,
4879 count + 1);
4880 W_ERROR_HAVE_NO_MEMORY(info);
4881 result = fill_spoolss_DriverFileInfo(info,
4882 &info[count],
4883 cservername,
4884 driver->driver_path,
4885 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4887 W_ERROR_NOT_OK_RETURN(result);
4888 count++;
4891 if (strlen(driver->config_file)) {
4892 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4893 struct spoolss_DriverFileInfo,
4894 count + 1);
4895 W_ERROR_HAVE_NO_MEMORY(info);
4896 result = fill_spoolss_DriverFileInfo(info,
4897 &info[count],
4898 cservername,
4899 driver->config_file,
4900 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4902 W_ERROR_NOT_OK_RETURN(result);
4903 count++;
4906 if (strlen(driver->data_file)) {
4907 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4908 struct spoolss_DriverFileInfo,
4909 count + 1);
4910 W_ERROR_HAVE_NO_MEMORY(info);
4911 result = fill_spoolss_DriverFileInfo(info,
4912 &info[count],
4913 cservername,
4914 driver->data_file,
4915 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4917 W_ERROR_NOT_OK_RETURN(result);
4918 count++;
4921 if (strlen(driver->help_file)) {
4922 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4923 struct spoolss_DriverFileInfo,
4924 count + 1);
4925 W_ERROR_HAVE_NO_MEMORY(info);
4926 result = fill_spoolss_DriverFileInfo(info,
4927 &info[count],
4928 cservername,
4929 driver->help_file,
4930 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4932 W_ERROR_NOT_OK_RETURN(result);
4933 count++;
4936 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4937 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4938 struct spoolss_DriverFileInfo,
4939 count + 1);
4940 W_ERROR_HAVE_NO_MEMORY(info);
4941 result = fill_spoolss_DriverFileInfo(info,
4942 &info[count],
4943 cservername,
4944 driver->dependent_files[i],
4945 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4947 W_ERROR_NOT_OK_RETURN(result);
4948 count++;
4951 *info_p = info;
4952 *count_p = count;
4954 return WERR_OK;
4957 /********************************************************************
4958 * fill a spoolss_DriverInfo101 struct
4959 ********************************************************************/
4961 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4962 struct spoolss_DriverInfo101 *r,
4963 const struct spoolss_DriverInfo8 *driver,
4964 const char *servername)
4966 const char *cservername = canon_servername(servername);
4967 WERROR result;
4969 r->version = driver->version;
4971 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4972 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4973 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4974 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4976 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4977 cservername,
4978 &r->file_info,
4979 &r->file_count);
4980 if (!W_ERROR_IS_OK(result)) {
4981 return result;
4984 FILL_DRIVER_STRING(mem_ctx,
4985 driver->monitor_name,
4986 r->monitor_name);
4988 FILL_DRIVER_STRING(mem_ctx,
4989 driver->default_datatype,
4990 r->default_datatype);
4992 r->previous_names = string_array_from_driver_info(mem_ctx,
4993 driver->previous_names,
4994 cservername);
4995 r->driver_date = driver->driver_date;
4996 r->driver_version = driver->driver_version;
4998 FILL_DRIVER_STRING(mem_ctx,
4999 driver->manufacturer_name,
5000 r->manufacturer_name);
5001 FILL_DRIVER_STRING(mem_ctx,
5002 driver->manufacturer_url,
5003 r->manufacturer_url);
5004 FILL_DRIVER_STRING(mem_ctx,
5005 driver->hardware_id,
5006 r->hardware_id);
5007 FILL_DRIVER_STRING(mem_ctx,
5008 driver->provider,
5009 r->provider);
5011 return WERR_OK;
5013 #endif
5014 /********************************************************************
5015 ********************************************************************/
5017 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5018 uint32_t level,
5019 union spoolss_DriverInfo *r,
5020 int snum,
5021 const char *servername,
5022 const char *architecture,
5023 uint32_t version)
5025 NT_PRINTER_INFO_LEVEL *printer = NULL;
5026 struct spoolss_DriverInfo8 *driver;
5027 WERROR result;
5029 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5031 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5032 win_errstr(result)));
5034 if (!W_ERROR_IS_OK(result)) {
5035 return WERR_INVALID_PRINTER_NAME;
5038 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5039 architecture, version);
5041 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5042 win_errstr(result)));
5044 if (!W_ERROR_IS_OK(result)) {
5046 * Is this a W2k client ?
5049 if (version < 3) {
5050 free_a_printer(&printer, 2);
5051 return WERR_UNKNOWN_PRINTER_DRIVER;
5054 /* Yes - try again with a WinNT driver. */
5055 version = 2;
5056 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5057 architecture, version);
5058 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5059 win_errstr(result)));
5060 if (!W_ERROR_IS_OK(result)) {
5061 free_a_printer(&printer, 2);
5062 return WERR_UNKNOWN_PRINTER_DRIVER;
5066 switch (level) {
5067 case 1:
5068 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5069 break;
5070 case 2:
5071 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5072 break;
5073 case 3:
5074 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5075 break;
5076 case 4:
5077 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5078 break;
5079 case 5:
5080 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5081 break;
5082 case 6:
5083 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5084 break;
5085 case 8:
5086 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5087 break;
5088 #if 0 /* disabled until marshalling issues are resolved - gd */
5089 case 101:
5090 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5091 break;
5092 #endif
5093 default:
5094 result = WERR_UNKNOWN_LEVEL;
5095 break;
5098 free_a_printer(&printer, 2);
5099 free_a_printer_driver(driver);
5101 return result;
5104 /****************************************************************
5105 _spoolss_GetPrinterDriver2
5106 ****************************************************************/
5108 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5109 struct spoolss_GetPrinterDriver2 *r)
5111 Printer_entry *printer;
5112 WERROR result;
5114 const char *servername;
5115 int snum;
5117 /* that's an [in out] buffer */
5119 if (!r->in.buffer && (r->in.offered != 0)) {
5120 return WERR_INVALID_PARAM;
5123 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5125 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5126 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5127 return WERR_INVALID_PRINTER_NAME;
5130 *r->out.needed = 0;
5131 *r->out.server_major_version = 0;
5132 *r->out.server_minor_version = 0;
5134 servername = get_server_name(printer);
5136 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5137 return WERR_BADFID;
5140 result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5141 r->out.info, snum,
5142 servername,
5143 r->in.architecture,
5144 r->in.client_major_version);
5145 if (!W_ERROR_IS_OK(result)) {
5146 TALLOC_FREE(r->out.info);
5147 return result;
5150 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5151 r->out.info, r->in.level);
5152 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5154 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5158 /****************************************************************
5159 _spoolss_StartPagePrinter
5160 ****************************************************************/
5162 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5163 struct spoolss_StartPagePrinter *r)
5165 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5167 if (!Printer) {
5168 DEBUG(3,("_spoolss_StartPagePrinter: "
5169 "Error in startpageprinter printer handle\n"));
5170 return WERR_BADFID;
5173 Printer->page_started = true;
5174 return WERR_OK;
5177 /****************************************************************
5178 _spoolss_EndPagePrinter
5179 ****************************************************************/
5181 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5182 struct spoolss_EndPagePrinter *r)
5184 int snum;
5186 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5188 if (!Printer) {
5189 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5190 OUR_HANDLE(r->in.handle)));
5191 return WERR_BADFID;
5194 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5195 return WERR_BADFID;
5197 Printer->page_started = false;
5198 print_job_endpage(snum, Printer->jobid);
5200 return WERR_OK;
5203 /****************************************************************
5204 _spoolss_StartDocPrinter
5205 ****************************************************************/
5207 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5208 struct spoolss_StartDocPrinter *r)
5210 struct spoolss_DocumentInfo1 *info_1;
5211 int snum;
5212 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5214 if (!Printer) {
5215 DEBUG(2,("_spoolss_StartDocPrinter: "
5216 "Invalid handle (%s:%u:%u)\n",
5217 OUR_HANDLE(r->in.handle)));
5218 return WERR_BADFID;
5221 if (r->in.level != 1) {
5222 return WERR_UNKNOWN_LEVEL;
5225 info_1 = r->in.info.info1;
5228 * a nice thing with NT is it doesn't listen to what you tell it.
5229 * when asked to send _only_ RAW datas, it tries to send datas
5230 * in EMF format.
5232 * So I add checks like in NT Server ...
5235 if (info_1->datatype) {
5236 if (strcmp(info_1->datatype, "RAW") != 0) {
5237 *r->out.job_id = 0;
5238 return WERR_INVALID_DATATYPE;
5242 /* get the share number of the printer */
5243 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5244 return WERR_BADFID;
5247 Printer->jobid = print_job_start(p->server_info, snum,
5248 info_1->document_name,
5249 Printer->nt_devmode);
5251 /* An error occured in print_job_start() so return an appropriate
5252 NT error code. */
5254 if (Printer->jobid == -1) {
5255 return map_werror_from_unix(errno);
5258 Printer->document_started = true;
5259 *r->out.job_id = Printer->jobid;
5261 return WERR_OK;
5264 /****************************************************************
5265 _spoolss_EndDocPrinter
5266 ****************************************************************/
5268 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5269 struct spoolss_EndDocPrinter *r)
5271 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5272 int snum;
5274 if (!Printer) {
5275 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5276 OUR_HANDLE(r->in.handle)));
5277 return WERR_BADFID;
5280 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5281 return WERR_BADFID;
5284 Printer->document_started = false;
5285 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5286 /* error codes unhandled so far ... */
5288 return WERR_OK;
5291 /****************************************************************
5292 _spoolss_WritePrinter
5293 ****************************************************************/
5295 WERROR _spoolss_WritePrinter(pipes_struct *p,
5296 struct spoolss_WritePrinter *r)
5298 ssize_t buffer_written;
5299 int snum;
5300 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5302 if (!Printer) {
5303 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5304 OUR_HANDLE(r->in.handle)));
5305 *r->out.num_written = r->in._data_size;
5306 return WERR_BADFID;
5309 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5310 return WERR_BADFID;
5312 buffer_written = print_job_write(snum, Printer->jobid,
5313 (const char *)r->in.data.data,
5314 (SMB_OFF_T)-1,
5315 (size_t)r->in._data_size);
5316 if (buffer_written == (ssize_t)-1) {
5317 *r->out.num_written = 0;
5318 if (errno == ENOSPC)
5319 return WERR_NO_SPOOL_SPACE;
5320 else
5321 return WERR_ACCESS_DENIED;
5324 *r->out.num_written = r->in._data_size;
5326 return WERR_OK;
5329 /********************************************************************
5330 * api_spoolss_getprinter
5331 * called from the spoolss dispatcher
5333 ********************************************************************/
5335 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5336 pipes_struct *p)
5338 int snum;
5339 WERROR errcode = WERR_BADFUNC;
5340 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5342 if (!Printer) {
5343 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5344 OUR_HANDLE(handle)));
5345 return WERR_BADFID;
5348 if (!get_printer_snum(p, handle, &snum, NULL))
5349 return WERR_BADFID;
5351 switch (command) {
5352 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5353 errcode = print_queue_pause(p->server_info, snum);
5354 break;
5355 case SPOOLSS_PRINTER_CONTROL_RESUME:
5356 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5357 errcode = print_queue_resume(p->server_info, snum);
5358 break;
5359 case SPOOLSS_PRINTER_CONTROL_PURGE:
5360 errcode = print_queue_purge(p->server_info, snum);
5361 break;
5362 default:
5363 return WERR_UNKNOWN_LEVEL;
5366 return errcode;
5370 /****************************************************************
5371 _spoolss_AbortPrinter
5372 * From MSDN: "Deletes printer's spool file if printer is configured
5373 * for spooling"
5374 ****************************************************************/
5376 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5377 struct spoolss_AbortPrinter *r)
5379 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5380 int snum;
5381 WERROR errcode = WERR_OK;
5383 if (!Printer) {
5384 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5385 OUR_HANDLE(r->in.handle)));
5386 return WERR_BADFID;
5389 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5390 return WERR_BADFID;
5392 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5394 return errcode;
5397 /********************************************************************
5398 * called by spoolss_api_setprinter
5399 * when updating a printer description
5400 ********************************************************************/
5402 static WERROR update_printer_sec(struct policy_handle *handle,
5403 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5405 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5406 WERROR result;
5407 int snum;
5409 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5411 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5412 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5413 OUR_HANDLE(handle)));
5415 result = WERR_BADFID;
5416 goto done;
5419 if (!secdesc_ctr) {
5420 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5421 result = WERR_INVALID_PARAM;
5422 goto done;
5425 /* Check the user has permissions to change the security
5426 descriptor. By experimentation with two NT machines, the user
5427 requires Full Access to the printer to change security
5428 information. */
5430 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5431 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5432 result = WERR_ACCESS_DENIED;
5433 goto done;
5436 /* NT seems to like setting the security descriptor even though
5437 nothing may have actually changed. */
5439 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5440 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5441 result = WERR_BADFID;
5442 goto done;
5445 if (DEBUGLEVEL >= 10) {
5446 SEC_ACL *the_acl;
5447 int i;
5449 the_acl = old_secdesc_ctr->sd->dacl;
5450 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5451 PRINTERNAME(snum), the_acl->num_aces));
5453 for (i = 0; i < the_acl->num_aces; i++) {
5454 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5455 &the_acl->aces[i].trustee),
5456 the_acl->aces[i].access_mask));
5459 the_acl = secdesc_ctr->sd->dacl;
5461 if (the_acl) {
5462 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5463 PRINTERNAME(snum), the_acl->num_aces));
5465 for (i = 0; i < the_acl->num_aces; i++) {
5466 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5467 &the_acl->aces[i].trustee),
5468 the_acl->aces[i].access_mask));
5470 } else {
5471 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5475 new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5476 if (!new_secdesc_ctr) {
5477 result = WERR_NOMEM;
5478 goto done;
5481 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5482 result = WERR_OK;
5483 goto done;
5486 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5488 done:
5490 return result;
5493 /********************************************************************
5494 Canonicalize printer info from a client
5496 ATTN: It does not matter what we set the servername to hear
5497 since we do the necessary work in get_a_printer() to set it to
5498 the correct value based on what the client sent in the
5499 _spoolss_open_printer_ex().
5500 ********************************************************************/
5502 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5504 fstring printername;
5505 const char *p;
5507 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5508 "portname=%s drivername=%s comment=%s location=%s\n",
5509 info->servername, info->printername, info->sharename,
5510 info->portname, info->drivername, info->comment, info->location));
5512 /* we force some elements to "correct" values */
5513 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5514 fstrcpy(info->sharename, lp_servicename(snum));
5516 /* check to see if we allow printername != sharename */
5518 if ( lp_force_printername(snum) ) {
5519 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5520 global_myname(), info->sharename );
5521 } else {
5523 /* make sure printername is in \\server\printername format */
5525 fstrcpy( printername, info->printername );
5526 p = printername;
5527 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5528 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5529 p++;
5532 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5533 global_myname(), p );
5536 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5537 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5541 return true;
5544 /****************************************************************************
5545 ****************************************************************************/
5547 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5549 char *cmd = lp_addport_cmd();
5550 char *command = NULL;
5551 int ret;
5552 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5553 bool is_print_op = false;
5555 if ( !*cmd ) {
5556 return WERR_ACCESS_DENIED;
5559 command = talloc_asprintf(ctx,
5560 "%s \"%s\" \"%s\"", cmd, portname, uri );
5561 if (!command) {
5562 return WERR_NOMEM;
5565 if ( token )
5566 is_print_op = user_has_privileges( token, &se_printop );
5568 DEBUG(10,("Running [%s]\n", command));
5570 /********* BEGIN SePrintOperatorPrivilege **********/
5572 if ( is_print_op )
5573 become_root();
5575 ret = smbrun(command, NULL);
5577 if ( is_print_op )
5578 unbecome_root();
5580 /********* END SePrintOperatorPrivilege **********/
5582 DEBUGADD(10,("returned [%d]\n", ret));
5584 TALLOC_FREE(command);
5586 if ( ret != 0 ) {
5587 return WERR_ACCESS_DENIED;
5590 return WERR_OK;
5593 /****************************************************************************
5594 ****************************************************************************/
5596 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5598 char *cmd = lp_addprinter_cmd();
5599 char **qlines;
5600 char *command = NULL;
5601 int numlines;
5602 int ret;
5603 int fd;
5604 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5605 bool is_print_op = false;
5606 char *remote_machine = talloc_strdup(ctx, "%m");
5608 if (!remote_machine) {
5609 return false;
5611 remote_machine = talloc_sub_basic(ctx,
5612 current_user_info.smb_name,
5613 current_user_info.domain,
5614 remote_machine);
5615 if (!remote_machine) {
5616 return false;
5619 command = talloc_asprintf(ctx,
5620 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5621 cmd, printer->info_2->printername, printer->info_2->sharename,
5622 printer->info_2->portname, printer->info_2->drivername,
5623 printer->info_2->location, printer->info_2->comment, remote_machine);
5624 if (!command) {
5625 return false;
5628 if ( token )
5629 is_print_op = user_has_privileges( token, &se_printop );
5631 DEBUG(10,("Running [%s]\n", command));
5633 /********* BEGIN SePrintOperatorPrivilege **********/
5635 if ( is_print_op )
5636 become_root();
5638 if ( (ret = smbrun(command, &fd)) == 0 ) {
5639 /* Tell everyone we updated smb.conf. */
5640 message_send_all(smbd_messaging_context(),
5641 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5644 if ( is_print_op )
5645 unbecome_root();
5647 /********* END SePrintOperatorPrivilege **********/
5649 DEBUGADD(10,("returned [%d]\n", ret));
5651 TALLOC_FREE(command);
5652 TALLOC_FREE(remote_machine);
5654 if ( ret != 0 ) {
5655 if (fd != -1)
5656 close(fd);
5657 return false;
5660 /* reload our services immediately */
5661 become_root();
5662 reload_services(false);
5663 unbecome_root();
5665 numlines = 0;
5666 /* Get lines and convert them back to dos-codepage */
5667 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5668 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5669 close(fd);
5671 /* Set the portname to what the script says the portname should be. */
5672 /* but don't require anything to be return from the script exit a good error code */
5674 if (numlines) {
5675 /* Set the portname to what the script says the portname should be. */
5676 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5677 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5680 TALLOC_FREE(qlines);
5681 return true;
5685 /********************************************************************
5686 * Called by spoolss_api_setprinter
5687 * when updating a printer description.
5688 ********************************************************************/
5690 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5691 struct spoolss_SetPrinterInfoCtr *info_ctr,
5692 struct spoolss_DeviceMode *devmode)
5694 int snum;
5695 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5696 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5697 WERROR result;
5698 DATA_BLOB buffer;
5699 fstring asc_buffer;
5701 DEBUG(8,("update_printer\n"));
5703 result = WERR_OK;
5705 if (!Printer) {
5706 result = WERR_BADFID;
5707 goto done;
5710 if (!get_printer_snum(p, handle, &snum, NULL)) {
5711 result = WERR_BADFID;
5712 goto done;
5715 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5716 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5717 result = WERR_BADFID;
5718 goto done;
5721 DEBUGADD(8,("Converting info_2 struct\n"));
5724 * convert_printer_info converts the incoming
5725 * info from the client and overwrites the info
5726 * just read from the tdb in the pointer 'printer'.
5729 if (!convert_printer_info(info_ctr, printer)) {
5730 result = WERR_NOMEM;
5731 goto done;
5734 if (devmode) {
5735 /* we have a valid devmode
5736 convert it and link it*/
5738 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5739 if (!convert_devicemode(printer->info_2->printername, devmode,
5740 &printer->info_2->devmode)) {
5741 result = WERR_NOMEM;
5742 goto done;
5746 /* Do sanity check on the requested changes for Samba */
5748 if (!check_printer_ok(printer->info_2, snum)) {
5749 result = WERR_INVALID_PARAM;
5750 goto done;
5753 /* FIXME!!! If the driver has changed we really should verify that
5754 it is installed before doing much else --jerry */
5756 /* Check calling user has permission to update printer description */
5758 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5759 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5760 result = WERR_ACCESS_DENIED;
5761 goto done;
5764 /* Call addprinter hook */
5765 /* Check changes to see if this is really needed */
5767 if ( *lp_addprinter_cmd()
5768 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5769 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5770 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5771 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5773 /* add_printer_hook() will call reload_services() */
5775 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5776 printer) ) {
5777 result = WERR_ACCESS_DENIED;
5778 goto done;
5783 * When a *new* driver is bound to a printer, the drivername is used to
5784 * lookup previously saved driver initialization info, which is then
5785 * bound to the printer, simulating what happens in the Windows arch.
5787 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5789 if (!set_driver_init(printer, 2))
5791 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5792 printer->info_2->drivername));
5795 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5796 printer->info_2->drivername));
5798 notify_printer_driver(snum, printer->info_2->drivername);
5802 * flag which changes actually occured. This is a small subset of
5803 * all the possible changes. We also have to update things in the
5804 * DsSpooler key.
5807 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5808 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->comment);
5809 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5810 REG_SZ, buffer.data, buffer.length);
5812 notify_printer_comment(snum, printer->info_2->comment);
5815 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5816 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->sharename);
5817 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5818 REG_SZ, buffer.data, buffer.length);
5820 notify_printer_sharename(snum, printer->info_2->sharename);
5823 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5824 char *pname;
5826 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5827 pname++;
5828 else
5829 pname = printer->info_2->printername;
5832 push_reg_sz(talloc_tos(), NULL, &buffer, pname);
5833 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5834 REG_SZ, buffer.data, buffer.length);
5836 notify_printer_printername( snum, pname );
5839 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5840 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->portname);
5841 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5842 REG_SZ, buffer.data, buffer.length);
5844 notify_printer_port(snum, printer->info_2->portname);
5847 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5848 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->location);
5849 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5850 REG_SZ, buffer.data, buffer.length);
5852 notify_printer_location(snum, printer->info_2->location);
5855 /* here we need to update some more DsSpooler keys */
5856 /* uNCName, serverName, shortServerName */
5858 push_reg_sz(talloc_tos(), NULL, &buffer, global_myname());
5859 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5860 REG_SZ, buffer.data, buffer.length);
5861 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5862 REG_SZ, buffer.data, buffer.length);
5864 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5865 global_myname(), printer->info_2->sharename );
5866 push_reg_sz(talloc_tos(), NULL, &buffer, asc_buffer);
5867 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5868 REG_SZ, buffer.data, buffer.length);
5870 /* Update printer info */
5871 result = mod_a_printer(printer, 2);
5873 done:
5874 free_a_printer(&printer, 2);
5875 free_a_printer(&old_printer, 2);
5878 return result;
5881 /****************************************************************************
5882 ****************************************************************************/
5883 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5884 struct policy_handle *handle,
5885 struct spoolss_SetPrinterInfo7 *info7)
5887 #ifdef HAVE_ADS
5888 int snum;
5889 Printer_entry *Printer;
5891 if ( lp_security() != SEC_ADS ) {
5892 return WERR_UNKNOWN_LEVEL;
5895 Printer = find_printer_index_by_hnd(p, handle);
5897 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5899 if (!Printer)
5900 return WERR_BADFID;
5902 if (!get_printer_snum(p, handle, &snum, NULL))
5903 return WERR_BADFID;
5905 nt_printer_publish(Printer, snum, info7->action);
5907 return WERR_OK;
5908 #else
5909 return WERR_UNKNOWN_LEVEL;
5910 #endif
5913 /********************************************************************
5914 ********************************************************************/
5916 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5917 struct spoolss_DeviceMode *devmode)
5919 int snum;
5920 NT_PRINTER_INFO_LEVEL *printer = NULL;
5921 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5922 WERROR result;
5924 DEBUG(8,("update_printer_devmode\n"));
5926 result = WERR_OK;
5928 if (!Printer) {
5929 result = WERR_BADFID;
5930 goto done;
5933 if (!get_printer_snum(p, handle, &snum, NULL)) {
5934 result = WERR_BADFID;
5935 goto done;
5938 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5939 result = WERR_BADFID;
5940 goto done;
5943 if (devmode) {
5944 /* we have a valid devmode
5945 convert it and link it*/
5947 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5948 if (!convert_devicemode(printer->info_2->printername, devmode,
5949 &printer->info_2->devmode)) {
5950 result = WERR_NOMEM;
5951 goto done;
5955 /* Check calling user has permission to update printer description */
5957 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5958 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5959 result = WERR_ACCESS_DENIED;
5960 goto done;
5964 /* Update printer info */
5965 result = mod_a_printer(printer, 2);
5967 done:
5968 free_a_printer(&printer, 2);
5970 return result;
5974 /****************************************************************
5975 _spoolss_SetPrinter
5976 ****************************************************************/
5978 WERROR _spoolss_SetPrinter(pipes_struct *p,
5979 struct spoolss_SetPrinter *r)
5981 WERROR result;
5983 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5985 if (!Printer) {
5986 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5987 OUR_HANDLE(r->in.handle)));
5988 return WERR_BADFID;
5991 /* check the level */
5992 switch (r->in.info_ctr->level) {
5993 case 0:
5994 return control_printer(r->in.handle, r->in.command, p);
5995 case 2:
5996 result = update_printer(p, r->in.handle,
5997 r->in.info_ctr,
5998 r->in.devmode_ctr->devmode);
5999 if (!W_ERROR_IS_OK(result))
6000 return result;
6001 if (r->in.secdesc_ctr->sd)
6002 result = update_printer_sec(r->in.handle, p,
6003 r->in.secdesc_ctr);
6004 return result;
6005 case 3:
6006 return update_printer_sec(r->in.handle, p,
6007 r->in.secdesc_ctr);
6008 case 7:
6009 return publish_or_unpublish_printer(p, r->in.handle,
6010 r->in.info_ctr->info.info7);
6011 case 8:
6012 return update_printer_devmode(p, r->in.handle,
6013 r->in.devmode_ctr->devmode);
6014 default:
6015 return WERR_UNKNOWN_LEVEL;
6019 /****************************************************************
6020 _spoolss_FindClosePrinterNotify
6021 ****************************************************************/
6023 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6024 struct spoolss_FindClosePrinterNotify *r)
6026 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6028 if (!Printer) {
6029 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6030 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6031 return WERR_BADFID;
6034 if (Printer->notify.client_connected == true) {
6035 int snum = -1;
6037 if ( Printer->printer_type == SPLHND_SERVER)
6038 snum = -1;
6039 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6040 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6041 return WERR_BADFID;
6043 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6046 Printer->notify.flags=0;
6047 Printer->notify.options=0;
6048 Printer->notify.localmachine[0]='\0';
6049 Printer->notify.printerlocal=0;
6050 TALLOC_FREE(Printer->notify.option);
6051 Printer->notify.client_connected = false;
6053 return WERR_OK;
6056 /****************************************************************
6057 _spoolss_AddJob
6058 ****************************************************************/
6060 WERROR _spoolss_AddJob(pipes_struct *p,
6061 struct spoolss_AddJob *r)
6063 if (!r->in.buffer && (r->in.offered != 0)) {
6064 return WERR_INVALID_PARAM;
6067 /* this is what a NT server returns for AddJob. AddJob must fail on
6068 * non-local printers */
6070 if (r->in.level != 1) {
6071 return WERR_UNKNOWN_LEVEL;
6074 return WERR_INVALID_PARAM;
6077 /****************************************************************************
6078 fill_job_info1
6079 ****************************************************************************/
6081 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6082 struct spoolss_JobInfo1 *r,
6083 const print_queue_struct *queue,
6084 int position, int snum,
6085 const NT_PRINTER_INFO_LEVEL *ntprinter)
6087 struct tm *t;
6089 t = gmtime(&queue->time);
6091 r->job_id = queue->job;
6093 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6094 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6095 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6096 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6097 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6098 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6099 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6100 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6101 r->data_type = talloc_strdup(mem_ctx, "RAW");
6102 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6103 r->text_status = talloc_strdup(mem_ctx, "");
6104 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6106 r->status = nt_printj_status(queue->status);
6107 r->priority = queue->priority;
6108 r->position = position;
6109 r->total_pages = queue->page_count;
6110 r->pages_printed = 0; /* ??? */
6112 init_systemtime(&r->submitted, t);
6114 return WERR_OK;
6117 /****************************************************************************
6118 fill_job_info2
6119 ****************************************************************************/
6121 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6122 struct spoolss_JobInfo2 *r,
6123 const print_queue_struct *queue,
6124 int position, int snum,
6125 const NT_PRINTER_INFO_LEVEL *ntprinter,
6126 struct spoolss_DeviceMode *devmode)
6128 struct tm *t;
6130 t = gmtime(&queue->time);
6132 r->job_id = queue->job;
6134 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6135 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6136 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6137 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6138 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6139 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6140 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6141 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6142 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6143 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6144 r->data_type = talloc_strdup(mem_ctx, "RAW");
6145 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6146 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6147 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6148 r->parameters = talloc_strdup(mem_ctx, "");
6149 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6150 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6151 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6153 r->devmode = devmode;
6155 r->text_status = talloc_strdup(mem_ctx, "");
6156 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6158 r->secdesc = NULL;
6160 r->status = nt_printj_status(queue->status);
6161 r->priority = queue->priority;
6162 r->position = position;
6163 r->start_time = 0;
6164 r->until_time = 0;
6165 r->total_pages = queue->page_count;
6166 r->size = queue->size;
6167 init_systemtime(&r->submitted, t);
6168 r->time = 0;
6169 r->pages_printed = 0; /* ??? */
6171 return WERR_OK;
6174 /****************************************************************************
6175 fill_job_info3
6176 ****************************************************************************/
6178 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6179 struct spoolss_JobInfo3 *r,
6180 const print_queue_struct *queue,
6181 const print_queue_struct *next_queue,
6182 int position, int snum,
6183 const NT_PRINTER_INFO_LEVEL *ntprinter)
6185 r->job_id = queue->job;
6186 r->next_job_id = 0;
6187 if (next_queue) {
6188 r->next_job_id = next_queue->job;
6190 r->reserved = 0;
6192 return WERR_OK;
6195 /****************************************************************************
6196 Enumjobs at level 1.
6197 ****************************************************************************/
6199 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6200 const print_queue_struct *queue,
6201 uint32_t num_queues, int snum,
6202 const NT_PRINTER_INFO_LEVEL *ntprinter,
6203 union spoolss_JobInfo **info_p,
6204 uint32_t *count)
6206 union spoolss_JobInfo *info;
6207 int i;
6208 WERROR result = WERR_OK;
6210 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6211 W_ERROR_HAVE_NO_MEMORY(info);
6213 *count = num_queues;
6215 for (i=0; i<*count; i++) {
6216 result = fill_job_info1(info,
6217 &info[i].info1,
6218 &queue[i],
6220 snum,
6221 ntprinter);
6222 if (!W_ERROR_IS_OK(result)) {
6223 goto out;
6227 out:
6228 if (!W_ERROR_IS_OK(result)) {
6229 TALLOC_FREE(info);
6230 *count = 0;
6231 return result;
6234 *info_p = info;
6236 return WERR_OK;
6239 /****************************************************************************
6240 Enumjobs at level 2.
6241 ****************************************************************************/
6243 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6244 const print_queue_struct *queue,
6245 uint32_t num_queues, int snum,
6246 const NT_PRINTER_INFO_LEVEL *ntprinter,
6247 union spoolss_JobInfo **info_p,
6248 uint32_t *count)
6250 union spoolss_JobInfo *info;
6251 int i;
6252 WERROR result = WERR_OK;
6254 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6255 W_ERROR_HAVE_NO_MEMORY(info);
6257 *count = num_queues;
6259 for (i=0; i<*count; i++) {
6261 struct spoolss_DeviceMode *devmode;
6263 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6264 if (!devmode) {
6265 result = WERR_NOMEM;
6266 goto out;
6269 result = fill_job_info2(info,
6270 &info[i].info2,
6271 &queue[i],
6273 snum,
6274 ntprinter,
6275 devmode);
6276 if (!W_ERROR_IS_OK(result)) {
6277 goto out;
6281 out:
6282 if (!W_ERROR_IS_OK(result)) {
6283 TALLOC_FREE(info);
6284 *count = 0;
6285 return result;
6288 *info_p = info;
6290 return WERR_OK;
6293 /****************************************************************************
6294 Enumjobs at level 3.
6295 ****************************************************************************/
6297 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6298 const print_queue_struct *queue,
6299 uint32_t num_queues, int snum,
6300 const NT_PRINTER_INFO_LEVEL *ntprinter,
6301 union spoolss_JobInfo **info_p,
6302 uint32_t *count)
6304 union spoolss_JobInfo *info;
6305 int i;
6306 WERROR result = WERR_OK;
6308 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6309 W_ERROR_HAVE_NO_MEMORY(info);
6311 *count = num_queues;
6313 for (i=0; i<*count; i++) {
6314 const print_queue_struct *next_queue = NULL;
6316 if (i+1 < *count) {
6317 next_queue = &queue[i+1];
6320 result = fill_job_info3(info,
6321 &info[i].info3,
6322 &queue[i],
6323 next_queue,
6325 snum,
6326 ntprinter);
6327 if (!W_ERROR_IS_OK(result)) {
6328 goto out;
6332 out:
6333 if (!W_ERROR_IS_OK(result)) {
6334 TALLOC_FREE(info);
6335 *count = 0;
6336 return result;
6339 *info_p = info;
6341 return WERR_OK;
6344 /****************************************************************
6345 _spoolss_EnumJobs
6346 ****************************************************************/
6348 WERROR _spoolss_EnumJobs(pipes_struct *p,
6349 struct spoolss_EnumJobs *r)
6351 WERROR result;
6352 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6353 int snum;
6354 print_status_struct prt_status;
6355 print_queue_struct *queue = NULL;
6356 uint32_t count;
6358 /* that's an [in out] buffer */
6360 if (!r->in.buffer && (r->in.offered != 0)) {
6361 return WERR_INVALID_PARAM;
6364 DEBUG(4,("_spoolss_EnumJobs\n"));
6366 *r->out.needed = 0;
6367 *r->out.count = 0;
6368 *r->out.info = NULL;
6370 /* lookup the printer snum and tdb entry */
6372 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6373 return WERR_BADFID;
6376 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6377 if (!W_ERROR_IS_OK(result)) {
6378 return result;
6381 count = print_queue_status(snum, &queue, &prt_status);
6382 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6383 count, prt_status.status, prt_status.message));
6385 if (count == 0) {
6386 SAFE_FREE(queue);
6387 free_a_printer(&ntprinter, 2);
6388 return WERR_OK;
6391 switch (r->in.level) {
6392 case 1:
6393 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6394 ntprinter, r->out.info, r->out.count);
6395 break;
6396 case 2:
6397 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6398 ntprinter, r->out.info, r->out.count);
6399 break;
6400 case 3:
6401 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6402 ntprinter, r->out.info, r->out.count);
6403 break;
6404 default:
6405 result = WERR_UNKNOWN_LEVEL;
6406 break;
6409 SAFE_FREE(queue);
6410 free_a_printer(&ntprinter, 2);
6412 if (!W_ERROR_IS_OK(result)) {
6413 return result;
6416 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6417 spoolss_EnumJobs, NULL,
6418 *r->out.info, r->in.level,
6419 *r->out.count);
6420 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6421 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6423 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6426 /****************************************************************
6427 _spoolss_ScheduleJob
6428 ****************************************************************/
6430 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6431 struct spoolss_ScheduleJob *r)
6433 return WERR_OK;
6436 /****************************************************************
6437 ****************************************************************/
6439 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6440 const char *printer_name,
6441 uint32_t job_id,
6442 struct spoolss_SetJobInfo1 *r)
6444 char *old_doc_name;
6446 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6447 return WERR_BADFID;
6450 if (strequal(old_doc_name, r->document_name)) {
6451 return WERR_OK;
6454 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6455 return WERR_BADFID;
6458 return WERR_OK;
6461 /****************************************************************
6462 _spoolss_SetJob
6463 ****************************************************************/
6465 WERROR _spoolss_SetJob(pipes_struct *p,
6466 struct spoolss_SetJob *r)
6468 int snum;
6469 WERROR errcode = WERR_BADFUNC;
6471 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6472 return WERR_BADFID;
6475 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6476 return WERR_INVALID_PRINTER_NAME;
6479 switch (r->in.command) {
6480 case SPOOLSS_JOB_CONTROL_CANCEL:
6481 case SPOOLSS_JOB_CONTROL_DELETE:
6482 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6483 errcode = WERR_OK;
6485 break;
6486 case SPOOLSS_JOB_CONTROL_PAUSE:
6487 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6488 errcode = WERR_OK;
6490 break;
6491 case SPOOLSS_JOB_CONTROL_RESTART:
6492 case SPOOLSS_JOB_CONTROL_RESUME:
6493 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6494 errcode = WERR_OK;
6496 break;
6497 case 0:
6498 errcode = WERR_OK;
6499 break;
6500 default:
6501 return WERR_UNKNOWN_LEVEL;
6504 if (!W_ERROR_IS_OK(errcode)) {
6505 return errcode;
6508 if (r->in.ctr == NULL) {
6509 return errcode;
6512 switch (r->in.ctr->level) {
6513 case 1:
6514 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6515 r->in.job_id,
6516 r->in.ctr->info.info1);
6517 break;
6518 case 2:
6519 case 3:
6520 case 4:
6521 default:
6522 return WERR_UNKNOWN_LEVEL;
6525 return errcode;
6528 /****************************************************************************
6529 Enumerates all printer drivers by level and architecture.
6530 ****************************************************************************/
6532 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6533 const char *servername,
6534 const char *architecture,
6535 uint32_t level,
6536 union spoolss_DriverInfo **info_p,
6537 uint32_t *count_p)
6539 int i;
6540 int ndrivers;
6541 uint32_t version;
6542 fstring *list = NULL;
6543 struct spoolss_DriverInfo8 *driver;
6544 union spoolss_DriverInfo *info = NULL;
6545 uint32_t count = 0;
6546 WERROR result = WERR_OK;
6548 *count_p = 0;
6549 *info_p = NULL;
6551 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6552 list = NULL;
6553 ndrivers = get_ntdrivers(&list, architecture, version);
6554 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6555 ndrivers, architecture, version));
6557 if (ndrivers == -1) {
6558 result = WERR_NOMEM;
6559 goto out;
6562 if (ndrivers != 0) {
6563 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6564 union spoolss_DriverInfo,
6565 count + ndrivers);
6566 if (!info) {
6567 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6568 "failed to enlarge driver info buffer!\n"));
6569 result = WERR_NOMEM;
6570 goto out;
6574 for (i=0; i<ndrivers; i++) {
6575 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6576 ZERO_STRUCT(driver);
6577 result = get_a_printer_driver(mem_ctx, &driver, list[i],
6578 architecture, version);
6579 if (!W_ERROR_IS_OK(result)) {
6580 goto out;
6583 switch (level) {
6584 case 1:
6585 result = fill_printer_driver_info1(info, &info[count+i].info1,
6586 driver, servername);
6587 break;
6588 case 2:
6589 result = fill_printer_driver_info2(info, &info[count+i].info2,
6590 driver, servername);
6591 break;
6592 case 3:
6593 result = fill_printer_driver_info3(info, &info[count+i].info3,
6594 driver, servername);
6595 break;
6596 case 4:
6597 result = fill_printer_driver_info4(info, &info[count+i].info4,
6598 driver, servername);
6599 break;
6600 case 5:
6601 result = fill_printer_driver_info5(info, &info[count+i].info5,
6602 driver, servername);
6603 break;
6604 case 6:
6605 result = fill_printer_driver_info6(info, &info[count+i].info6,
6606 driver, servername);
6607 break;
6608 case 8:
6609 result = fill_printer_driver_info8(info, &info[count+i].info8,
6610 driver, servername);
6611 break;
6612 default:
6613 result = WERR_UNKNOWN_LEVEL;
6614 break;
6617 free_a_printer_driver(driver);
6619 if (!W_ERROR_IS_OK(result)) {
6620 goto out;
6624 count += ndrivers;
6625 SAFE_FREE(list);
6628 out:
6629 SAFE_FREE(list);
6631 if (!W_ERROR_IS_OK(result)) {
6632 TALLOC_FREE(info);
6633 return result;
6636 *info_p = info;
6637 *count_p = count;
6639 return WERR_OK;
6642 /****************************************************************************
6643 Enumerates all printer drivers by level.
6644 ****************************************************************************/
6646 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6647 const char *servername,
6648 const char *architecture,
6649 uint32_t level,
6650 union spoolss_DriverInfo **info_p,
6651 uint32_t *count_p)
6653 uint32_t a,i;
6654 WERROR result = WERR_OK;
6656 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6658 for (a=0; archi_table[a].long_archi != NULL; a++) {
6660 union spoolss_DriverInfo *info = NULL;
6661 uint32_t count = 0;
6663 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6664 servername,
6665 archi_table[a].long_archi,
6666 level,
6667 &info,
6668 &count);
6669 if (!W_ERROR_IS_OK(result)) {
6670 continue;
6673 for (i=0; i < count; i++) {
6674 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6675 info[i], info_p, count_p);
6679 return result;
6682 return enumprinterdrivers_level_by_architecture(mem_ctx,
6683 servername,
6684 architecture,
6685 level,
6686 info_p,
6687 count_p);
6690 /****************************************************************
6691 _spoolss_EnumPrinterDrivers
6692 ****************************************************************/
6694 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6695 struct spoolss_EnumPrinterDrivers *r)
6697 const char *cservername;
6698 WERROR result;
6700 /* that's an [in out] buffer */
6702 if (!r->in.buffer && (r->in.offered != 0)) {
6703 return WERR_INVALID_PARAM;
6706 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6708 *r->out.needed = 0;
6709 *r->out.count = 0;
6710 *r->out.info = NULL;
6712 cservername = canon_servername(r->in.server);
6714 if (!is_myname_or_ipaddr(cservername)) {
6715 return WERR_UNKNOWN_PRINTER_DRIVER;
6718 result = enumprinterdrivers_level(p->mem_ctx, cservername,
6719 r->in.environment,
6720 r->in.level,
6721 r->out.info,
6722 r->out.count);
6723 if (!W_ERROR_IS_OK(result)) {
6724 return result;
6727 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6728 spoolss_EnumPrinterDrivers, NULL,
6729 *r->out.info, r->in.level,
6730 *r->out.count);
6731 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6732 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6734 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6737 /****************************************************************************
6738 ****************************************************************************/
6740 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6741 struct spoolss_FormInfo1 *r,
6742 const nt_forms_struct *form)
6744 r->form_name = talloc_strdup(mem_ctx, form->name);
6745 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6747 r->flags = form->flag;
6748 r->size.width = form->width;
6749 r->size.height = form->length;
6750 r->area.left = form->left;
6751 r->area.top = form->top;
6752 r->area.right = form->right;
6753 r->area.bottom = form->bottom;
6755 return WERR_OK;
6758 /****************************************************************
6759 spoolss_enumforms_level1
6760 ****************************************************************/
6762 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6763 const nt_forms_struct *builtin_forms,
6764 uint32_t num_builtin_forms,
6765 const nt_forms_struct *user_forms,
6766 uint32_t num_user_forms,
6767 union spoolss_FormInfo **info_p,
6768 uint32_t *count)
6770 union spoolss_FormInfo *info;
6771 WERROR result = WERR_OK;
6772 int i;
6774 *count = num_builtin_forms + num_user_forms;
6776 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6777 W_ERROR_HAVE_NO_MEMORY(info);
6779 /* construct the list of form structures */
6780 for (i=0; i<num_builtin_forms; i++) {
6781 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6782 result = fill_form_info_1(info, &info[i].info1,
6783 &builtin_forms[i]);
6784 if (!W_ERROR_IS_OK(result)) {
6785 goto out;
6789 for (i=0; i<num_user_forms; i++) {
6790 DEBUGADD(6,("Filling user form number [%d]\n",i));
6791 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6792 &user_forms[i]);
6793 if (!W_ERROR_IS_OK(result)) {
6794 goto out;
6798 out:
6799 if (!W_ERROR_IS_OK(result)) {
6800 TALLOC_FREE(info);
6801 *count = 0;
6802 return result;
6805 *info_p = info;
6807 return WERR_OK;
6810 /****************************************************************
6811 _spoolss_EnumForms
6812 ****************************************************************/
6814 WERROR _spoolss_EnumForms(pipes_struct *p,
6815 struct spoolss_EnumForms *r)
6817 WERROR result;
6818 nt_forms_struct *user_forms = NULL;
6819 nt_forms_struct *builtin_forms = NULL;
6820 uint32_t num_user_forms;
6821 uint32_t num_builtin_forms;
6823 *r->out.count = 0;
6824 *r->out.needed = 0;
6825 *r->out.info = NULL;
6827 /* that's an [in out] buffer */
6829 if (!r->in.buffer && (r->in.offered != 0) ) {
6830 return WERR_INVALID_PARAM;
6833 DEBUG(4,("_spoolss_EnumForms\n"));
6834 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6835 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6837 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6838 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6839 num_user_forms = get_ntforms(&user_forms);
6840 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6842 if (num_user_forms + num_builtin_forms == 0) {
6843 SAFE_FREE(builtin_forms);
6844 SAFE_FREE(user_forms);
6845 return WERR_NO_MORE_ITEMS;
6848 switch (r->in.level) {
6849 case 1:
6850 result = spoolss_enumforms_level1(p->mem_ctx,
6851 builtin_forms,
6852 num_builtin_forms,
6853 user_forms,
6854 num_user_forms,
6855 r->out.info,
6856 r->out.count);
6857 break;
6858 default:
6859 result = WERR_UNKNOWN_LEVEL;
6860 break;
6863 SAFE_FREE(user_forms);
6864 SAFE_FREE(builtin_forms);
6866 if (!W_ERROR_IS_OK(result)) {
6867 return result;
6870 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6871 spoolss_EnumForms, NULL,
6872 *r->out.info, r->in.level,
6873 *r->out.count);
6874 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6875 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6877 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6880 /****************************************************************
6881 ****************************************************************/
6883 static WERROR find_form_byname(const char *name,
6884 nt_forms_struct *form)
6886 nt_forms_struct *list = NULL;
6887 int num_forms = 0, i = 0;
6889 if (get_a_builtin_ntform_by_string(name, form)) {
6890 return WERR_OK;
6893 num_forms = get_ntforms(&list);
6894 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6896 if (num_forms == 0) {
6897 return WERR_BADFID;
6900 /* Check if the requested name is in the list of form structures */
6901 for (i = 0; i < num_forms; i++) {
6903 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6905 if (strequal(name, list[i].name)) {
6906 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6907 *form = list[i];
6908 SAFE_FREE(list);
6909 return WERR_OK;
6913 SAFE_FREE(list);
6915 return WERR_BADFID;
6918 /****************************************************************
6919 _spoolss_GetForm
6920 ****************************************************************/
6922 WERROR _spoolss_GetForm(pipes_struct *p,
6923 struct spoolss_GetForm *r)
6925 WERROR result;
6926 nt_forms_struct form;
6928 /* that's an [in out] buffer */
6930 if (!r->in.buffer && (r->in.offered != 0)) {
6931 return WERR_INVALID_PARAM;
6934 DEBUG(4,("_spoolss_GetForm\n"));
6935 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6936 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6938 result = find_form_byname(r->in.form_name, &form);
6939 if (!W_ERROR_IS_OK(result)) {
6940 TALLOC_FREE(r->out.info);
6941 return result;
6944 switch (r->in.level) {
6945 case 1:
6946 result = fill_form_info_1(p->mem_ctx,
6947 &r->out.info->info1,
6948 &form);
6949 break;
6951 default:
6952 result = WERR_UNKNOWN_LEVEL;
6953 break;
6956 if (!W_ERROR_IS_OK(result)) {
6957 TALLOC_FREE(r->out.info);
6958 return result;
6961 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6962 r->out.info, r->in.level);
6963 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6965 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6968 /****************************************************************************
6969 ****************************************************************************/
6971 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6972 struct spoolss_PortInfo1 *r,
6973 const char *name)
6975 r->port_name = talloc_strdup(mem_ctx, name);
6976 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6978 return WERR_OK;
6981 /****************************************************************************
6982 TODO: This probably needs distinguish between TCP/IP and Local ports
6983 somehow.
6984 ****************************************************************************/
6986 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6987 struct spoolss_PortInfo2 *r,
6988 const char *name)
6990 r->port_name = talloc_strdup(mem_ctx, name);
6991 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6993 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6994 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6996 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6997 W_ERROR_HAVE_NO_MEMORY(r->description);
6999 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7000 r->reserved = 0;
7002 return WERR_OK;
7006 /****************************************************************************
7007 wrapper around the enumer ports command
7008 ****************************************************************************/
7010 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7012 char *cmd = lp_enumports_cmd();
7013 char **qlines = NULL;
7014 char *command = NULL;
7015 int numlines;
7016 int ret;
7017 int fd;
7019 *count = 0;
7020 *lines = NULL;
7022 /* if no hook then just fill in the default port */
7024 if ( !*cmd ) {
7025 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7026 return WERR_NOMEM;
7028 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7029 TALLOC_FREE(qlines);
7030 return WERR_NOMEM;
7032 qlines[1] = NULL;
7033 numlines = 1;
7035 else {
7036 /* we have a valid enumport command */
7038 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7039 if (!command) {
7040 return WERR_NOMEM;
7043 DEBUG(10,("Running [%s]\n", command));
7044 ret = smbrun(command, &fd);
7045 DEBUG(10,("Returned [%d]\n", ret));
7046 TALLOC_FREE(command);
7047 if (ret != 0) {
7048 if (fd != -1) {
7049 close(fd);
7051 return WERR_ACCESS_DENIED;
7054 numlines = 0;
7055 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7056 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7057 close(fd);
7060 *count = numlines;
7061 *lines = qlines;
7063 return WERR_OK;
7066 /****************************************************************************
7067 enumports level 1.
7068 ****************************************************************************/
7070 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7071 union spoolss_PortInfo **info_p,
7072 uint32_t *count)
7074 union spoolss_PortInfo *info = NULL;
7075 int i=0;
7076 WERROR result = WERR_OK;
7077 char **qlines = NULL;
7078 int numlines = 0;
7080 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7081 if (!W_ERROR_IS_OK(result)) {
7082 goto out;
7085 if (numlines) {
7086 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7087 if (!info) {
7088 DEBUG(10,("Returning WERR_NOMEM\n"));
7089 result = WERR_NOMEM;
7090 goto out;
7093 for (i=0; i<numlines; i++) {
7094 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7095 result = fill_port_1(info, &info[i].info1, qlines[i]);
7096 if (!W_ERROR_IS_OK(result)) {
7097 goto out;
7101 TALLOC_FREE(qlines);
7103 out:
7104 if (!W_ERROR_IS_OK(result)) {
7105 TALLOC_FREE(info);
7106 TALLOC_FREE(qlines);
7107 *count = 0;
7108 *info_p = NULL;
7109 return result;
7112 *info_p = info;
7113 *count = numlines;
7115 return WERR_OK;
7118 /****************************************************************************
7119 enumports level 2.
7120 ****************************************************************************/
7122 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7123 union spoolss_PortInfo **info_p,
7124 uint32_t *count)
7126 union spoolss_PortInfo *info = NULL;
7127 int i=0;
7128 WERROR result = WERR_OK;
7129 char **qlines = NULL;
7130 int numlines = 0;
7132 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7133 if (!W_ERROR_IS_OK(result)) {
7134 goto out;
7137 if (numlines) {
7138 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7139 if (!info) {
7140 DEBUG(10,("Returning WERR_NOMEM\n"));
7141 result = WERR_NOMEM;
7142 goto out;
7145 for (i=0; i<numlines; i++) {
7146 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7147 result = fill_port_2(info, &info[i].info2, qlines[i]);
7148 if (!W_ERROR_IS_OK(result)) {
7149 goto out;
7153 TALLOC_FREE(qlines);
7155 out:
7156 if (!W_ERROR_IS_OK(result)) {
7157 TALLOC_FREE(info);
7158 TALLOC_FREE(qlines);
7159 *count = 0;
7160 *info_p = NULL;
7161 return result;
7164 *info_p = info;
7165 *count = numlines;
7167 return WERR_OK;
7170 /****************************************************************
7171 _spoolss_EnumPorts
7172 ****************************************************************/
7174 WERROR _spoolss_EnumPorts(pipes_struct *p,
7175 struct spoolss_EnumPorts *r)
7177 WERROR result;
7179 /* that's an [in out] buffer */
7181 if (!r->in.buffer && (r->in.offered != 0)) {
7182 return WERR_INVALID_PARAM;
7185 DEBUG(4,("_spoolss_EnumPorts\n"));
7187 *r->out.count = 0;
7188 *r->out.needed = 0;
7189 *r->out.info = NULL;
7191 switch (r->in.level) {
7192 case 1:
7193 result = enumports_level_1(p->mem_ctx, r->out.info,
7194 r->out.count);
7195 break;
7196 case 2:
7197 result = enumports_level_2(p->mem_ctx, r->out.info,
7198 r->out.count);
7199 break;
7200 default:
7201 return WERR_UNKNOWN_LEVEL;
7204 if (!W_ERROR_IS_OK(result)) {
7205 return result;
7208 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7209 spoolss_EnumPorts, NULL,
7210 *r->out.info, r->in.level,
7211 *r->out.count);
7212 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7213 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7215 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7218 /****************************************************************************
7219 ****************************************************************************/
7221 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7222 const char *server,
7223 struct spoolss_SetPrinterInfoCtr *info_ctr,
7224 struct spoolss_DeviceMode *devmode,
7225 struct security_descriptor *sec_desc,
7226 struct spoolss_UserLevelCtr *user_ctr,
7227 struct policy_handle *handle)
7229 NT_PRINTER_INFO_LEVEL *printer = NULL;
7230 fstring name;
7231 int snum;
7232 WERROR err = WERR_OK;
7234 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7235 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7236 return WERR_NOMEM;
7239 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7240 if (!convert_printer_info(info_ctr, printer)) {
7241 free_a_printer(&printer, 2);
7242 return WERR_NOMEM;
7245 /* samba does not have a concept of local, non-shared printers yet, so
7246 * make sure we always setup sharename - gd */
7247 if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7248 DEBUG(5, ("spoolss_addprinterex_level_2: "
7249 "no sharename has been set, setting printername %s as sharename\n",
7250 printer->info_2->printername));
7251 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7254 /* check to see if the printer already exists */
7256 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7257 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7258 printer->info_2->sharename));
7259 free_a_printer(&printer, 2);
7260 return WERR_PRINTER_ALREADY_EXISTS;
7263 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7264 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7265 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7266 printer->info_2->printername));
7267 free_a_printer(&printer, 2);
7268 return WERR_PRINTER_ALREADY_EXISTS;
7272 /* validate printer info struct */
7273 if (!info_ctr->info.info2->printername ||
7274 strlen(info_ctr->info.info2->printername) == 0) {
7275 free_a_printer(&printer,2);
7276 return WERR_INVALID_PRINTER_NAME;
7278 if (!info_ctr->info.info2->portname ||
7279 strlen(info_ctr->info.info2->portname) == 0) {
7280 free_a_printer(&printer,2);
7281 return WERR_UNKNOWN_PORT;
7283 if (!info_ctr->info.info2->drivername ||
7284 strlen(info_ctr->info.info2->drivername) == 0) {
7285 free_a_printer(&printer,2);
7286 return WERR_UNKNOWN_PRINTER_DRIVER;
7288 if (!info_ctr->info.info2->printprocessor ||
7289 strlen(info_ctr->info.info2->printprocessor) == 0) {
7290 free_a_printer(&printer,2);
7291 return WERR_UNKNOWN_PRINTPROCESSOR;
7294 /* FIXME!!! smbd should check to see if the driver is installed before
7295 trying to add a printer like this --jerry */
7297 if (*lp_addprinter_cmd() ) {
7298 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7299 printer) ) {
7300 free_a_printer(&printer,2);
7301 return WERR_ACCESS_DENIED;
7303 } else {
7304 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7305 "smb.conf parameter \"addprinter command\" is defined. This"
7306 "parameter must exist for this call to succeed\n",
7307 printer->info_2->sharename ));
7310 /* use our primary netbios name since get_a_printer() will convert
7311 it to what the client expects on a case by case basis */
7313 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7314 printer->info_2->sharename);
7317 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7318 free_a_printer(&printer,2);
7319 return WERR_ACCESS_DENIED;
7322 /* you must be a printer admin to add a new printer */
7323 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7324 free_a_printer(&printer,2);
7325 return WERR_ACCESS_DENIED;
7329 * Do sanity check on the requested changes for Samba.
7332 if (!check_printer_ok(printer->info_2, snum)) {
7333 free_a_printer(&printer,2);
7334 return WERR_INVALID_PARAM;
7338 * When a printer is created, the drivername bound to the printer is used
7339 * to lookup previously saved driver initialization info, which is then
7340 * bound to the new printer, simulating what happens in the Windows arch.
7343 if (!devmode)
7345 set_driver_init(printer, 2);
7347 else
7349 /* A valid devmode was included, convert and link it
7351 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7353 if (!convert_devicemode(printer->info_2->printername, devmode,
7354 &printer->info_2->devmode)) {
7355 return WERR_NOMEM;
7359 /* write the ASCII on disk */
7360 err = mod_a_printer(printer, 2);
7361 if (!W_ERROR_IS_OK(err)) {
7362 free_a_printer(&printer,2);
7363 return err;
7366 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7367 /* Handle open failed - remove addition. */
7368 del_a_printer(printer->info_2->sharename);
7369 free_a_printer(&printer,2);
7370 ZERO_STRUCTP(handle);
7371 return WERR_ACCESS_DENIED;
7374 update_c_setprinter(false);
7375 free_a_printer(&printer,2);
7377 return WERR_OK;
7380 /****************************************************************
7381 _spoolss_AddPrinterEx
7382 ****************************************************************/
7384 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7385 struct spoolss_AddPrinterEx *r)
7387 switch (r->in.info_ctr->level) {
7388 case 1:
7389 /* we don't handle yet */
7390 /* but I know what to do ... */
7391 return WERR_UNKNOWN_LEVEL;
7392 case 2:
7393 return spoolss_addprinterex_level_2(p, r->in.server,
7394 r->in.info_ctr,
7395 r->in.devmode_ctr->devmode,
7396 r->in.secdesc_ctr->sd,
7397 r->in.userlevel_ctr,
7398 r->out.handle);
7399 default:
7400 return WERR_UNKNOWN_LEVEL;
7404 /****************************************************************
7405 _spoolss_AddPrinter
7406 ****************************************************************/
7408 WERROR _spoolss_AddPrinter(pipes_struct *p,
7409 struct spoolss_AddPrinter *r)
7411 struct spoolss_AddPrinterEx a;
7412 struct spoolss_UserLevelCtr userlevel_ctr;
7414 ZERO_STRUCT(userlevel_ctr);
7416 userlevel_ctr.level = 1;
7418 a.in.server = r->in.server;
7419 a.in.info_ctr = r->in.info_ctr;
7420 a.in.devmode_ctr = r->in.devmode_ctr;
7421 a.in.secdesc_ctr = r->in.secdesc_ctr;
7422 a.in.userlevel_ctr = &userlevel_ctr;
7423 a.out.handle = r->out.handle;
7425 return _spoolss_AddPrinterEx(p, &a);
7428 /****************************************************************
7429 _spoolss_AddPrinterDriverEx
7430 ****************************************************************/
7432 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7433 struct spoolss_AddPrinterDriverEx *r)
7435 WERROR err = WERR_OK;
7436 char *driver_name = NULL;
7437 uint32_t version;
7438 const char *fn;
7440 switch (p->hdr_req.opnum) {
7441 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7442 fn = "_spoolss_AddPrinterDriver";
7443 break;
7444 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7445 fn = "_spoolss_AddPrinterDriverEx";
7446 break;
7447 default:
7448 return WERR_INVALID_PARAM;
7452 * we only support the semantics of AddPrinterDriver()
7453 * i.e. only copy files that are newer than existing ones
7456 if (r->in.flags == 0) {
7457 return WERR_INVALID_PARAM;
7460 if (r->in.flags != APD_COPY_NEW_FILES) {
7461 return WERR_ACCESS_DENIED;
7464 /* FIXME */
7465 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7466 /* Clever hack from Martin Zielinski <mz@seh.de>
7467 * to allow downgrade from level 8 (Vista).
7469 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7470 r->in.info_ctr->level));
7471 return WERR_UNKNOWN_LEVEL;
7474 DEBUG(5,("Cleaning driver's information\n"));
7475 err = clean_up_driver_struct(p, r->in.info_ctr);
7476 if (!W_ERROR_IS_OK(err))
7477 goto done;
7479 DEBUG(5,("Moving driver to final destination\n"));
7480 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7481 &err)) ) {
7482 goto done;
7485 if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7486 err = WERR_ACCESS_DENIED;
7487 goto done;
7491 * I think this is where he DrvUpgradePrinter() hook would be
7492 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7493 * server. Right now, we just need to send ourselves a message
7494 * to update each printer bound to this driver. --jerry
7497 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7498 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7499 fn, driver_name));
7503 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7504 * decide if the driver init data should be deleted. The rules are:
7505 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7506 * 2) delete init data only if there is no 2k/Xp driver
7507 * 3) always delete init data
7508 * The generalized rule is always use init data from the highest order driver.
7509 * It is necessary to follow the driver install by an initialization step to
7510 * finish off this process.
7513 switch (version) {
7515 * 9x printer driver - never delete init data
7517 case 0:
7518 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7519 fn, driver_name));
7520 break;
7523 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7524 * there is no 2k/Xp driver init data for this driver name.
7526 case 2:
7528 struct spoolss_DriverInfo8 *driver1;
7530 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, driver_name, "Windows NT x86", 3))) {
7532 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7534 if (!del_driver_init(driver_name))
7535 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7536 fn, driver_name));
7537 } else {
7539 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7541 free_a_printer_driver(driver1);
7542 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7543 fn, driver_name));
7546 break;
7549 * 2k or Xp printer driver - always delete init data
7551 case 3:
7552 if (!del_driver_init(driver_name))
7553 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7554 fn, driver_name));
7555 break;
7557 default:
7558 DEBUG(0,("%s: invalid level=%d\n", fn,
7559 r->in.info_ctr->level));
7560 break;
7564 done:
7565 return err;
7568 /****************************************************************
7569 _spoolss_AddPrinterDriver
7570 ****************************************************************/
7572 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7573 struct spoolss_AddPrinterDriver *r)
7575 struct spoolss_AddPrinterDriverEx a;
7577 switch (r->in.info_ctr->level) {
7578 case 2:
7579 case 3:
7580 case 4:
7581 case 5:
7582 break;
7583 default:
7584 return WERR_UNKNOWN_LEVEL;
7587 a.in.servername = r->in.servername;
7588 a.in.info_ctr = r->in.info_ctr;
7589 a.in.flags = APD_COPY_NEW_FILES;
7591 return _spoolss_AddPrinterDriverEx(p, &a);
7594 /****************************************************************************
7595 ****************************************************************************/
7597 struct _spoolss_paths {
7598 int type;
7599 const char *share;
7600 const char *dir;
7603 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7605 static const struct _spoolss_paths spoolss_paths[]= {
7606 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7607 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7610 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7611 const char *servername,
7612 const char *environment,
7613 int component,
7614 char **path)
7616 const char *pservername = NULL;
7617 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7618 const char *short_archi;
7620 *path = NULL;
7622 /* environment may be empty */
7623 if (environment && strlen(environment)) {
7624 long_archi = environment;
7627 /* servername may be empty */
7628 if (servername && strlen(servername)) {
7629 pservername = canon_servername(servername);
7631 if (!is_myname_or_ipaddr(pservername)) {
7632 return WERR_INVALID_PARAM;
7636 if (!(short_archi = get_short_archi(long_archi))) {
7637 return WERR_INVALID_ENVIRONMENT;
7640 switch (component) {
7641 case SPOOLSS_PRTPROCS_PATH:
7642 case SPOOLSS_DRIVER_PATH:
7643 if (pservername) {
7644 *path = talloc_asprintf(mem_ctx,
7645 "\\\\%s\\%s\\%s",
7646 pservername,
7647 spoolss_paths[component].share,
7648 short_archi);
7649 } else {
7650 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7651 SPOOLSS_DEFAULT_SERVER_PATH,
7652 spoolss_paths[component].dir,
7653 short_archi);
7655 break;
7656 default:
7657 return WERR_INVALID_PARAM;
7660 if (!*path) {
7661 return WERR_NOMEM;
7664 return WERR_OK;
7667 /****************************************************************************
7668 ****************************************************************************/
7670 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7671 const char *servername,
7672 const char *environment,
7673 struct spoolss_DriverDirectoryInfo1 *r)
7675 WERROR werr;
7676 char *path = NULL;
7678 werr = compose_spoolss_server_path(mem_ctx,
7679 servername,
7680 environment,
7681 SPOOLSS_DRIVER_PATH,
7682 &path);
7683 if (!W_ERROR_IS_OK(werr)) {
7684 return werr;
7687 DEBUG(4,("printer driver directory: [%s]\n", path));
7689 r->directory_name = path;
7691 return WERR_OK;
7694 /****************************************************************
7695 _spoolss_GetPrinterDriverDirectory
7696 ****************************************************************/
7698 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7699 struct spoolss_GetPrinterDriverDirectory *r)
7701 WERROR werror;
7703 /* that's an [in out] buffer */
7705 if (!r->in.buffer && (r->in.offered != 0)) {
7706 return WERR_INVALID_PARAM;
7709 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7710 r->in.level));
7712 *r->out.needed = 0;
7714 /* r->in.level is ignored */
7716 werror = getprinterdriverdir_level_1(p->mem_ctx,
7717 r->in.server,
7718 r->in.environment,
7719 &r->out.info->info1);
7720 if (!W_ERROR_IS_OK(werror)) {
7721 TALLOC_FREE(r->out.info);
7722 return werror;
7725 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7726 r->out.info, r->in.level);
7727 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7729 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7732 /****************************************************************
7733 _spoolss_EnumPrinterData
7734 ****************************************************************/
7736 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7737 struct spoolss_EnumPrinterData *r)
7739 WERROR result;
7740 struct spoolss_EnumPrinterDataEx r2;
7741 uint32_t count;
7742 struct spoolss_PrinterEnumValues *info, *val = NULL;
7743 uint32_t needed;
7745 r2.in.handle = r->in.handle;
7746 r2.in.key_name = "PrinterDriverData";
7747 r2.in.offered = 0;
7748 r2.out.count = &count;
7749 r2.out.info = &info;
7750 r2.out.needed = &needed;
7752 result = _spoolss_EnumPrinterDataEx(p, &r2);
7753 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7754 r2.in.offered = needed;
7755 result = _spoolss_EnumPrinterDataEx(p, &r2);
7757 if (!W_ERROR_IS_OK(result)) {
7758 return result;
7762 * The NT machine wants to know the biggest size of value and data
7764 * cf: MSDN EnumPrinterData remark section
7767 if (!r->in.value_offered && !r->in.data_offered) {
7768 uint32_t biggest_valuesize = 0;
7769 uint32_t biggest_datasize = 0;
7770 int i, name_length;
7772 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7774 for (i=0; i<count; i++) {
7776 name_length = strlen(info[i].value_name);
7777 if (strlen(info[i].value_name) > biggest_valuesize) {
7778 biggest_valuesize = name_length;
7781 if (info[i].data_length > biggest_datasize) {
7782 biggest_datasize = info[i].data_length;
7785 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7786 biggest_datasize));
7789 /* the value is an UNICODE string but real_value_size is the length
7790 in bytes including the trailing 0 */
7792 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7793 *r->out.data_needed = biggest_datasize;
7795 DEBUG(6,("final values: [%d], [%d]\n",
7796 *r->out.value_needed, *r->out.data_needed));
7798 return WERR_OK;
7801 if (r->in.enum_index < count) {
7802 val = &info[r->in.enum_index];
7805 if (val == NULL) {
7806 /* out_value should default to "" or else NT4 has
7807 problems unmarshalling the response */
7809 if (r->in.value_offered) {
7810 *r->out.value_needed = 1;
7811 r->out.value_name = talloc_strdup(r, "");
7812 if (!r->out.value_name) {
7813 return WERR_NOMEM;
7815 } else {
7816 r->out.value_name = NULL;
7817 *r->out.value_needed = 0;
7820 /* the data is counted in bytes */
7822 *r->out.data_needed = r->in.data_offered;
7824 result = WERR_NO_MORE_ITEMS;
7825 } else {
7827 * the value is:
7828 * - counted in bytes in the request
7829 * - counted in UNICODE chars in the max reply
7830 * - counted in bytes in the real size
7832 * take a pause *before* coding not *during* coding
7835 /* name */
7836 if (r->in.value_offered) {
7837 r->out.value_name = talloc_strdup(r, val->value_name);
7838 if (!r->out.value_name) {
7839 return WERR_NOMEM;
7841 *r->out.value_needed = val->value_name_len;
7842 } else {
7843 r->out.value_name = NULL;
7844 *r->out.value_needed = 0;
7847 /* type */
7849 *r->out.type = val->type;
7851 /* data - counted in bytes */
7854 * See the section "Dynamically Typed Query Parameters"
7855 * in MS-RPRN.
7858 if (r->out.data && val->data && val->data->data &&
7859 val->data_length && r->in.data_offered) {
7860 memcpy(r->out.data, val->data->data,
7861 MIN(val->data_length,r->in.data_offered));
7864 *r->out.data_needed = val->data_length;
7866 result = WERR_OK;
7869 return result;
7872 /****************************************************************
7873 _spoolss_SetPrinterData
7874 ****************************************************************/
7876 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7877 struct spoolss_SetPrinterData *r)
7879 struct spoolss_SetPrinterDataEx r2;
7881 r2.in.handle = r->in.handle;
7882 r2.in.key_name = "PrinterDriverData";
7883 r2.in.value_name = r->in.value_name;
7884 r2.in.type = r->in.type;
7885 r2.in.data = r->in.data;
7886 r2.in.offered = r->in.offered;
7888 return _spoolss_SetPrinterDataEx(p, &r2);
7891 /****************************************************************
7892 _spoolss_ResetPrinter
7893 ****************************************************************/
7895 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7896 struct spoolss_ResetPrinter *r)
7898 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7899 int snum;
7901 DEBUG(5,("_spoolss_ResetPrinter\n"));
7904 * All we do is to check to see if the handle and queue is valid.
7905 * This call really doesn't mean anything to us because we only
7906 * support RAW printing. --jerry
7909 if (!Printer) {
7910 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7911 OUR_HANDLE(r->in.handle)));
7912 return WERR_BADFID;
7915 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7916 return WERR_BADFID;
7919 /* blindly return success */
7920 return WERR_OK;
7923 /****************************************************************
7924 _spoolss_DeletePrinterData
7925 ****************************************************************/
7927 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7928 struct spoolss_DeletePrinterData *r)
7930 struct spoolss_DeletePrinterDataEx r2;
7932 r2.in.handle = r->in.handle;
7933 r2.in.key_name = "PrinterDriverData";
7934 r2.in.value_name = r->in.value_name;
7936 return _spoolss_DeletePrinterDataEx(p, &r2);
7939 /****************************************************************
7940 _spoolss_AddForm
7941 ****************************************************************/
7943 WERROR _spoolss_AddForm(pipes_struct *p,
7944 struct spoolss_AddForm *r)
7946 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7947 nt_forms_struct tmpForm;
7948 int snum = -1;
7949 WERROR status = WERR_OK;
7950 NT_PRINTER_INFO_LEVEL *printer = NULL;
7951 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7953 int count=0;
7954 nt_forms_struct *list=NULL;
7955 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7956 int i;
7958 DEBUG(5,("_spoolss_AddForm\n"));
7960 if (!Printer) {
7961 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7962 OUR_HANDLE(r->in.handle)));
7963 return WERR_BADFID;
7967 /* forms can be added on printer or on the print server handle */
7969 if ( Printer->printer_type == SPLHND_PRINTER )
7971 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7972 return WERR_BADFID;
7974 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7975 if (!W_ERROR_IS_OK(status))
7976 goto done;
7979 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7980 and not a printer admin, then fail */
7982 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7983 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7984 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7985 NULL, NULL,
7986 p->server_info->ptok,
7987 lp_printer_admin(snum))) {
7988 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7989 status = WERR_ACCESS_DENIED;
7990 goto done;
7993 switch (form->flags) {
7994 case SPOOLSS_FORM_USER:
7995 case SPOOLSS_FORM_BUILTIN:
7996 case SPOOLSS_FORM_PRINTER:
7997 break;
7998 default:
7999 status = WERR_INVALID_PARAM;
8000 goto done;
8003 /* can't add if builtin */
8005 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8006 status = WERR_FILE_EXISTS;
8007 goto done;
8010 count = get_ntforms(&list);
8012 for (i=0; i < count; i++) {
8013 if (strequal(form->form_name, list[i].name)) {
8014 status = WERR_FILE_EXISTS;
8015 goto done;
8019 if(!add_a_form(&list, form, &count)) {
8020 status = WERR_NOMEM;
8021 goto done;
8024 become_root();
8025 write_ntforms(&list, count);
8026 unbecome_root();
8029 * ChangeID must always be set if this is a printer
8032 if ( Printer->printer_type == SPLHND_PRINTER )
8033 status = mod_a_printer(printer, 2);
8035 done:
8036 if ( printer )
8037 free_a_printer(&printer, 2);
8038 SAFE_FREE(list);
8040 return status;
8043 /****************************************************************
8044 _spoolss_DeleteForm
8045 ****************************************************************/
8047 WERROR _spoolss_DeleteForm(pipes_struct *p,
8048 struct spoolss_DeleteForm *r)
8050 const char *form_name = r->in.form_name;
8051 nt_forms_struct tmpForm;
8052 int count=0;
8053 nt_forms_struct *list=NULL;
8054 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8055 int snum = -1;
8056 WERROR status = WERR_OK;
8057 NT_PRINTER_INFO_LEVEL *printer = NULL;
8058 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8059 bool ret = false;
8061 DEBUG(5,("_spoolss_DeleteForm\n"));
8063 if (!Printer) {
8064 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8065 OUR_HANDLE(r->in.handle)));
8066 return WERR_BADFID;
8069 /* forms can be deleted on printer of on the print server handle */
8071 if ( Printer->printer_type == SPLHND_PRINTER )
8073 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8074 return WERR_BADFID;
8076 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8077 if (!W_ERROR_IS_OK(status))
8078 goto done;
8081 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8082 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8083 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8084 NULL, NULL,
8085 p->server_info->ptok,
8086 lp_printer_admin(snum))) {
8087 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8088 return WERR_ACCESS_DENIED;
8092 /* can't delete if builtin */
8094 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8095 status = WERR_INVALID_PARAM;
8096 goto done;
8099 count = get_ntforms(&list);
8101 become_root();
8102 ret = delete_a_form(&list, form_name, &count, &status);
8103 unbecome_root();
8104 if (ret == false) {
8105 goto done;
8109 * ChangeID must always be set if this is a printer
8112 if ( Printer->printer_type == SPLHND_PRINTER )
8113 status = mod_a_printer(printer, 2);
8115 done:
8116 if ( printer )
8117 free_a_printer(&printer, 2);
8118 SAFE_FREE(list);
8120 return status;
8123 /****************************************************************
8124 _spoolss_SetForm
8125 ****************************************************************/
8127 WERROR _spoolss_SetForm(pipes_struct *p,
8128 struct spoolss_SetForm *r)
8130 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8131 nt_forms_struct tmpForm;
8132 int snum = -1;
8133 WERROR status = WERR_OK;
8134 NT_PRINTER_INFO_LEVEL *printer = NULL;
8135 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8137 int count=0;
8138 nt_forms_struct *list=NULL;
8139 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8141 DEBUG(5,("_spoolss_SetForm\n"));
8143 if (!Printer) {
8144 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8145 OUR_HANDLE(r->in.handle)));
8146 return WERR_BADFID;
8149 /* forms can be modified on printer of on the print server handle */
8151 if ( Printer->printer_type == SPLHND_PRINTER )
8153 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8154 return WERR_BADFID;
8156 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8157 if (!W_ERROR_IS_OK(status))
8158 goto done;
8161 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8162 and not a printer admin, then fail */
8164 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8165 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8166 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8167 NULL, NULL,
8168 p->server_info->ptok,
8169 lp_printer_admin(snum))) {
8170 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8171 status = WERR_ACCESS_DENIED;
8172 goto done;
8175 /* can't set if builtin */
8176 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8177 status = WERR_INVALID_PARAM;
8178 goto done;
8181 count = get_ntforms(&list);
8182 update_a_form(&list, form, count);
8183 become_root();
8184 write_ntforms(&list, count);
8185 unbecome_root();
8188 * ChangeID must always be set if this is a printer
8191 if ( Printer->printer_type == SPLHND_PRINTER )
8192 status = mod_a_printer(printer, 2);
8195 done:
8196 if ( printer )
8197 free_a_printer(&printer, 2);
8198 SAFE_FREE(list);
8200 return status;
8203 /****************************************************************************
8204 fill_print_processor1
8205 ****************************************************************************/
8207 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8208 struct spoolss_PrintProcessorInfo1 *r,
8209 const char *print_processor_name)
8211 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8212 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8214 return WERR_OK;
8217 /****************************************************************************
8218 enumprintprocessors level 1.
8219 ****************************************************************************/
8221 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8222 union spoolss_PrintProcessorInfo **info_p,
8223 uint32_t *count)
8225 union spoolss_PrintProcessorInfo *info;
8226 WERROR result;
8228 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8229 W_ERROR_HAVE_NO_MEMORY(info);
8231 *count = 1;
8233 result = fill_print_processor1(info, &info[0].info1, "winprint");
8234 if (!W_ERROR_IS_OK(result)) {
8235 goto out;
8238 out:
8239 if (!W_ERROR_IS_OK(result)) {
8240 TALLOC_FREE(info);
8241 *count = 0;
8242 return result;
8245 *info_p = info;
8247 return WERR_OK;
8250 /****************************************************************
8251 _spoolss_EnumPrintProcessors
8252 ****************************************************************/
8254 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8255 struct spoolss_EnumPrintProcessors *r)
8257 WERROR result;
8259 /* that's an [in out] buffer */
8261 if (!r->in.buffer && (r->in.offered != 0)) {
8262 return WERR_INVALID_PARAM;
8265 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8268 * Enumerate the print processors ...
8270 * Just reply with "winprint", to keep NT happy
8271 * and I can use my nice printer checker.
8274 *r->out.count = 0;
8275 *r->out.needed = 0;
8276 *r->out.info = NULL;
8278 switch (r->in.level) {
8279 case 1:
8280 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8281 r->out.count);
8282 break;
8283 default:
8284 return WERR_UNKNOWN_LEVEL;
8287 if (!W_ERROR_IS_OK(result)) {
8288 return result;
8291 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8292 spoolss_EnumPrintProcessors, NULL,
8293 *r->out.info, r->in.level,
8294 *r->out.count);
8295 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8296 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8298 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8301 /****************************************************************************
8302 fill_printprocdatatype1
8303 ****************************************************************************/
8305 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8306 struct spoolss_PrintProcDataTypesInfo1 *r,
8307 const char *name_array)
8309 r->name_array = talloc_strdup(mem_ctx, name_array);
8310 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8312 return WERR_OK;
8315 /****************************************************************************
8316 enumprintprocdatatypes level 1.
8317 ****************************************************************************/
8319 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8320 union spoolss_PrintProcDataTypesInfo **info_p,
8321 uint32_t *count)
8323 WERROR result;
8324 union spoolss_PrintProcDataTypesInfo *info;
8326 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8327 W_ERROR_HAVE_NO_MEMORY(info);
8329 *count = 1;
8331 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8332 if (!W_ERROR_IS_OK(result)) {
8333 goto out;
8336 out:
8337 if (!W_ERROR_IS_OK(result)) {
8338 TALLOC_FREE(info);
8339 *count = 0;
8340 return result;
8343 *info_p = info;
8345 return WERR_OK;
8348 /****************************************************************
8349 _spoolss_EnumPrintProcDataTypes
8350 ****************************************************************/
8352 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8353 struct spoolss_EnumPrintProcDataTypes *r)
8355 WERROR result;
8357 /* that's an [in out] buffer */
8359 if (!r->in.buffer && (r->in.offered != 0)) {
8360 return WERR_INVALID_PARAM;
8363 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8365 *r->out.count = 0;
8366 *r->out.needed = 0;
8367 *r->out.info = NULL;
8369 switch (r->in.level) {
8370 case 1:
8371 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8372 r->out.count);
8373 break;
8374 default:
8375 return WERR_UNKNOWN_LEVEL;
8378 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8379 spoolss_EnumPrintProcDataTypes, NULL,
8380 *r->out.info, r->in.level,
8381 *r->out.count);
8382 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8383 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8385 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8388 /****************************************************************************
8389 fill_monitor_1
8390 ****************************************************************************/
8392 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8393 struct spoolss_MonitorInfo1 *r,
8394 const char *monitor_name)
8396 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8397 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8399 return WERR_OK;
8402 /****************************************************************************
8403 fill_monitor_2
8404 ****************************************************************************/
8406 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8407 struct spoolss_MonitorInfo2 *r,
8408 const char *monitor_name,
8409 const char *environment,
8410 const char *dll_name)
8412 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8413 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8414 r->environment = talloc_strdup(mem_ctx, environment);
8415 W_ERROR_HAVE_NO_MEMORY(r->environment);
8416 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8417 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8419 return WERR_OK;
8422 /****************************************************************************
8423 enumprintmonitors level 1.
8424 ****************************************************************************/
8426 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8427 union spoolss_MonitorInfo **info_p,
8428 uint32_t *count)
8430 union spoolss_MonitorInfo *info;
8431 WERROR result = WERR_OK;
8433 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8434 W_ERROR_HAVE_NO_MEMORY(info);
8436 *count = 2;
8438 result = fill_monitor_1(info, &info[0].info1,
8439 SPL_LOCAL_PORT);
8440 if (!W_ERROR_IS_OK(result)) {
8441 goto out;
8444 result = fill_monitor_1(info, &info[1].info1,
8445 SPL_TCPIP_PORT);
8446 if (!W_ERROR_IS_OK(result)) {
8447 goto out;
8450 out:
8451 if (!W_ERROR_IS_OK(result)) {
8452 TALLOC_FREE(info);
8453 *count = 0;
8454 return result;
8457 *info_p = info;
8459 return WERR_OK;
8462 /****************************************************************************
8463 enumprintmonitors level 2.
8464 ****************************************************************************/
8466 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8467 union spoolss_MonitorInfo **info_p,
8468 uint32_t *count)
8470 union spoolss_MonitorInfo *info;
8471 WERROR result = WERR_OK;
8473 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8474 W_ERROR_HAVE_NO_MEMORY(info);
8476 *count = 2;
8478 result = fill_monitor_2(info, &info[0].info2,
8479 SPL_LOCAL_PORT,
8480 "Windows NT X86", /* FIXME */
8481 "localmon.dll");
8482 if (!W_ERROR_IS_OK(result)) {
8483 goto out;
8486 result = fill_monitor_2(info, &info[1].info2,
8487 SPL_TCPIP_PORT,
8488 "Windows NT X86", /* FIXME */
8489 "tcpmon.dll");
8490 if (!W_ERROR_IS_OK(result)) {
8491 goto out;
8494 out:
8495 if (!W_ERROR_IS_OK(result)) {
8496 TALLOC_FREE(info);
8497 *count = 0;
8498 return result;
8501 *info_p = info;
8503 return WERR_OK;
8506 /****************************************************************
8507 _spoolss_EnumMonitors
8508 ****************************************************************/
8510 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8511 struct spoolss_EnumMonitors *r)
8513 WERROR result;
8515 /* that's an [in out] buffer */
8517 if (!r->in.buffer && (r->in.offered != 0)) {
8518 return WERR_INVALID_PARAM;
8521 DEBUG(5,("_spoolss_EnumMonitors\n"));
8524 * Enumerate the print monitors ...
8526 * Just reply with "Local Port", to keep NT happy
8527 * and I can use my nice printer checker.
8530 *r->out.count = 0;
8531 *r->out.needed = 0;
8532 *r->out.info = NULL;
8534 switch (r->in.level) {
8535 case 1:
8536 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8537 r->out.count);
8538 break;
8539 case 2:
8540 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8541 r->out.count);
8542 break;
8543 default:
8544 return WERR_UNKNOWN_LEVEL;
8547 if (!W_ERROR_IS_OK(result)) {
8548 return result;
8551 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8552 spoolss_EnumMonitors, NULL,
8553 *r->out.info, r->in.level,
8554 *r->out.count);
8555 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8556 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8558 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8561 /****************************************************************************
8562 ****************************************************************************/
8564 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8565 const print_queue_struct *queue,
8566 int count, int snum,
8567 const NT_PRINTER_INFO_LEVEL *ntprinter,
8568 uint32_t jobid,
8569 struct spoolss_JobInfo1 *r)
8571 int i = 0;
8572 bool found = false;
8574 for (i=0; i<count; i++) {
8575 if (queue[i].job == (int)jobid) {
8576 found = true;
8577 break;
8581 if (found == false) {
8582 /* NT treats not found as bad param... yet another bad choice */
8583 return WERR_INVALID_PARAM;
8586 return fill_job_info1(mem_ctx,
8588 &queue[i],
8590 snum,
8591 ntprinter);
8594 /****************************************************************************
8595 ****************************************************************************/
8597 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8598 const print_queue_struct *queue,
8599 int count, int snum,
8600 const NT_PRINTER_INFO_LEVEL *ntprinter,
8601 uint32_t jobid,
8602 struct spoolss_JobInfo2 *r)
8604 int i = 0;
8605 bool found = false;
8606 struct spoolss_DeviceMode *devmode;
8607 NT_DEVICEMODE *nt_devmode;
8608 WERROR result;
8610 for (i=0; i<count; i++) {
8611 if (queue[i].job == (int)jobid) {
8612 found = true;
8613 break;
8617 if (found == false) {
8618 /* NT treats not found as bad param... yet another bad
8619 choice */
8620 return WERR_INVALID_PARAM;
8624 * if the print job does not have a DEVMODE associated with it,
8625 * just use the one for the printer. A NULL devicemode is not
8626 * a failure condition
8629 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8630 if (nt_devmode) {
8631 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8632 W_ERROR_HAVE_NO_MEMORY(devmode);
8633 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8634 if (!W_ERROR_IS_OK(result)) {
8635 return result;
8637 } else {
8638 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8639 W_ERROR_HAVE_NO_MEMORY(devmode);
8642 return fill_job_info2(mem_ctx,
8644 &queue[i],
8646 snum,
8647 ntprinter,
8648 devmode);
8651 /****************************************************************
8652 _spoolss_GetJob
8653 ****************************************************************/
8655 WERROR _spoolss_GetJob(pipes_struct *p,
8656 struct spoolss_GetJob *r)
8658 WERROR result = WERR_OK;
8659 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8660 int snum;
8661 int count;
8662 print_queue_struct *queue = NULL;
8663 print_status_struct prt_status;
8665 /* that's an [in out] buffer */
8667 if (!r->in.buffer && (r->in.offered != 0)) {
8668 return WERR_INVALID_PARAM;
8671 DEBUG(5,("_spoolss_GetJob\n"));
8673 *r->out.needed = 0;
8675 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8676 return WERR_BADFID;
8679 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8680 if (!W_ERROR_IS_OK(result)) {
8681 return result;
8684 count = print_queue_status(snum, &queue, &prt_status);
8686 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8687 count, prt_status.status, prt_status.message));
8689 switch (r->in.level) {
8690 case 1:
8691 result = getjob_level_1(p->mem_ctx,
8692 queue, count, snum, ntprinter,
8693 r->in.job_id, &r->out.info->info1);
8694 break;
8695 case 2:
8696 result = getjob_level_2(p->mem_ctx,
8697 queue, count, snum, ntprinter,
8698 r->in.job_id, &r->out.info->info2);
8699 break;
8700 default:
8701 result = WERR_UNKNOWN_LEVEL;
8702 break;
8705 SAFE_FREE(queue);
8706 free_a_printer(&ntprinter, 2);
8708 if (!W_ERROR_IS_OK(result)) {
8709 TALLOC_FREE(r->out.info);
8710 return result;
8713 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8714 r->out.info, r->in.level);
8715 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8717 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8720 /****************************************************************
8721 _spoolss_GetPrinterDataEx
8722 ****************************************************************/
8724 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8725 struct spoolss_GetPrinterDataEx *r)
8728 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8729 struct regval_blob *val = NULL;
8730 NT_PRINTER_INFO_LEVEL *printer = NULL;
8731 int snum = 0;
8732 WERROR result = WERR_OK;
8733 DATA_BLOB blob;
8735 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8737 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8738 r->in.key_name, r->in.value_name));
8740 /* in case of problem, return some default values */
8742 *r->out.needed = 0;
8743 *r->out.type = REG_NONE;
8745 if (!Printer) {
8746 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8747 OUR_HANDLE(r->in.handle)));
8748 result = WERR_BADFID;
8749 goto done;
8752 /* Is the handle to a printer or to the server? */
8754 if (Printer->printer_type == SPLHND_SERVER) {
8756 union spoolss_PrinterData data;
8758 result = getprinterdata_printer_server(p->mem_ctx,
8759 r->in.value_name,
8760 r->out.type,
8761 &data);
8762 if (!W_ERROR_IS_OK(result)) {
8763 goto done;
8766 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8767 *r->out.type, &data);
8768 if (!W_ERROR_IS_OK(result)) {
8769 goto done;
8772 *r->out.needed = blob.length;
8774 if (r->in.offered >= *r->out.needed) {
8775 memcpy(r->out.data, blob.data, blob.length);
8778 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8781 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8782 result = WERR_BADFID;
8783 goto done;
8786 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8787 if (!W_ERROR_IS_OK(result)) {
8788 goto done;
8791 /* check to see if the keyname is valid */
8792 if (!strlen(r->in.key_name)) {
8793 result = WERR_INVALID_PARAM;
8794 goto done;
8797 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8799 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8800 strequal(r->in.value_name, "ChangeId")) {
8801 *r->out.type = REG_DWORD;
8802 *r->out.needed = 4;
8803 if (r->in.offered >= *r->out.needed) {
8804 SIVAL(r->out.data, 0, printer->info_2->changeid);
8805 result = WERR_OK;
8807 goto done;
8810 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8811 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8812 "Invalid keyname [%s]\n", r->in.key_name ));
8813 result = WERR_BADFILE;
8814 goto done;
8817 val = get_printer_data(printer->info_2,
8818 r->in.key_name, r->in.value_name);
8819 if (!val) {
8820 result = WERR_BADFILE;
8821 goto done;
8824 *r->out.needed = regval_size(val);
8825 *r->out.type = regval_type(val);
8827 if (r->in.offered >= *r->out.needed) {
8828 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8830 done:
8831 if (printer) {
8832 free_a_printer(&printer, 2);
8835 if (!W_ERROR_IS_OK(result)) {
8836 return result;
8839 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8840 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8842 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8845 /****************************************************************
8846 _spoolss_SetPrinterDataEx
8847 ****************************************************************/
8849 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8850 struct spoolss_SetPrinterDataEx *r)
8852 NT_PRINTER_INFO_LEVEL *printer = NULL;
8853 int snum = 0;
8854 WERROR result = WERR_OK;
8855 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8856 char *oid_string;
8858 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8860 /* From MSDN documentation of SetPrinterDataEx: pass request to
8861 SetPrinterData if key is "PrinterDriverData" */
8863 if (!Printer) {
8864 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8865 OUR_HANDLE(r->in.handle)));
8866 return WERR_BADFID;
8869 if (Printer->printer_type == SPLHND_SERVER) {
8870 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8871 "Not implemented for server handles yet\n"));
8872 return WERR_INVALID_PARAM;
8875 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8876 return WERR_BADFID;
8880 * Access check : NT returns "access denied" if you make a
8881 * SetPrinterData call without the necessary privildge.
8882 * we were originally returning OK if nothing changed
8883 * which made Win2k issue **a lot** of SetPrinterData
8884 * when connecting to a printer --jerry
8887 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8888 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8889 "change denied by handle access permissions\n"));
8890 return WERR_ACCESS_DENIED;
8893 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8894 if (!W_ERROR_IS_OK(result)) {
8895 return result;
8898 /* check for OID in valuename */
8900 oid_string = strchr(r->in.value_name, ',');
8901 if (oid_string) {
8902 *oid_string = '\0';
8903 oid_string++;
8907 * When client side code sets a magic printer data key, detect it and save
8908 * the current printer data and the magic key's data (its the DEVMODE) for
8909 * future printer/driver initializations.
8911 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8912 /* Set devmode and printer initialization info */
8913 result = save_driver_init(printer, 2, r->in.data, r->in.offered);
8915 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8917 goto done;
8920 /* save the registry data */
8922 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8923 r->in.type, r->in.data, r->in.offered);
8925 if (W_ERROR_IS_OK(result)) {
8926 /* save the OID if one was specified */
8927 if (oid_string) {
8928 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8929 r->in.key_name, SPOOL_OID_KEY);
8930 if (!str) {
8931 result = WERR_NOMEM;
8932 goto done;
8936 * I'm not checking the status here on purpose. Don't know
8937 * if this is right, but I'm returning the status from the
8938 * previous set_printer_dataex() call. I have no idea if
8939 * this is right. --jerry
8942 set_printer_dataex(printer, str, r->in.value_name,
8943 REG_SZ, (uint8_t *)oid_string,
8944 strlen(oid_string)+1);
8947 result = mod_a_printer(printer, 2);
8950 done:
8951 free_a_printer(&printer, 2);
8953 return result;
8956 /****************************************************************
8957 _spoolss_DeletePrinterDataEx
8958 ****************************************************************/
8960 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8961 struct spoolss_DeletePrinterDataEx *r)
8963 NT_PRINTER_INFO_LEVEL *printer = NULL;
8964 int snum=0;
8965 WERROR status = WERR_OK;
8966 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8968 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8970 if (!Printer) {
8971 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8972 "Invalid handle (%s:%u:%u).\n",
8973 OUR_HANDLE(r->in.handle)));
8974 return WERR_BADFID;
8977 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8978 return WERR_BADFID;
8980 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8981 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8982 "printer properties change denied by handle\n"));
8983 return WERR_ACCESS_DENIED;
8986 if (!r->in.value_name || !r->in.key_name) {
8987 return WERR_NOMEM;
8990 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8991 if (!W_ERROR_IS_OK(status))
8992 return status;
8994 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8996 if ( W_ERROR_IS_OK(status) )
8997 mod_a_printer( printer, 2 );
8999 free_a_printer(&printer, 2);
9001 return status;
9004 /****************************************************************
9005 _spoolss_EnumPrinterKey
9006 ****************************************************************/
9008 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9009 struct spoolss_EnumPrinterKey *r)
9011 fstring *keynames = NULL;
9012 int num_keys;
9013 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9014 NT_PRINTER_DATA *data;
9015 NT_PRINTER_INFO_LEVEL *printer = NULL;
9016 int snum = 0;
9017 WERROR result = WERR_BADFILE;
9018 int i;
9019 const char **array = NULL;
9020 DATA_BLOB blob;
9022 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9024 if (!Printer) {
9025 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9026 OUR_HANDLE(r->in.handle)));
9027 return WERR_BADFID;
9030 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9031 return WERR_BADFID;
9034 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9035 if (!W_ERROR_IS_OK(result)) {
9036 return result;
9039 /* get the list of subkey names */
9041 data = printer->info_2->data;
9043 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9044 if (num_keys == -1) {
9045 result = WERR_BADFILE;
9046 goto done;
9049 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
9050 if (!array) {
9051 result = WERR_NOMEM;
9052 goto done;
9055 if (!num_keys) {
9056 array[0] = talloc_strdup(array, "");
9057 if (!array[0]) {
9058 result = WERR_NOMEM;
9059 goto done;
9063 for (i=0; i < num_keys; i++) {
9065 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9066 keynames[i]));
9068 array[i] = talloc_strdup(array, keynames[i]);
9069 if (!array[i]) {
9070 result = WERR_NOMEM;
9071 goto done;
9075 if (!push_reg_multi_sz(p->mem_ctx, NULL, &blob, array)) {
9076 result = WERR_NOMEM;
9077 goto done;
9080 *r->out._ndr_size = r->in.offered / 2;
9081 *r->out.needed = blob.length;
9083 if (r->in.offered < *r->out.needed) {
9084 result = WERR_MORE_DATA;
9085 } else {
9086 result = WERR_OK;
9087 r->out.key_buffer->string_array = array;
9090 done:
9091 if (!W_ERROR_IS_OK(result)) {
9092 TALLOC_FREE(array);
9093 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9094 *r->out.needed = 0;
9098 free_a_printer(&printer, 2);
9099 SAFE_FREE(keynames);
9101 return result;
9104 /****************************************************************
9105 _spoolss_DeletePrinterKey
9106 ****************************************************************/
9108 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9109 struct spoolss_DeletePrinterKey *r)
9111 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9112 NT_PRINTER_INFO_LEVEL *printer = NULL;
9113 int snum=0;
9114 WERROR status;
9116 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9118 if (!Printer) {
9119 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9120 OUR_HANDLE(r->in.handle)));
9121 return WERR_BADFID;
9124 /* if keyname == NULL, return error */
9126 if ( !r->in.key_name )
9127 return WERR_INVALID_PARAM;
9129 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9130 return WERR_BADFID;
9132 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9133 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9134 "printer properties change denied by handle\n"));
9135 return WERR_ACCESS_DENIED;
9138 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9139 if (!W_ERROR_IS_OK(status))
9140 return status;
9142 /* delete the key and all subneys */
9144 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9146 if ( W_ERROR_IS_OK(status) )
9147 status = mod_a_printer(printer, 2);
9149 free_a_printer( &printer, 2 );
9151 return status;
9154 /****************************************************************
9155 ****************************************************************/
9157 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9158 struct regval_blob *v,
9159 struct spoolss_PrinterEnumValues *r)
9161 r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9162 W_ERROR_HAVE_NO_MEMORY(r->data);
9164 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9165 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9167 r->value_name_len = strlen_m_term(regval_name(v)) * 2;
9169 r->type = regval_type(v);
9170 r->data_length = regval_size(v);
9172 if (r->data_length) {
9173 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9176 return WERR_OK;
9179 /****************************************************************
9180 _spoolss_EnumPrinterDataEx
9181 ****************************************************************/
9183 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9184 struct spoolss_EnumPrinterDataEx *r)
9186 uint32_t count = 0;
9187 NT_PRINTER_INFO_LEVEL *printer = NULL;
9188 struct spoolss_PrinterEnumValues *info = NULL;
9189 NT_PRINTER_DATA *p_data;
9190 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9191 int snum;
9192 WERROR result;
9193 int key_index;
9194 int i;
9196 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9198 *r->out.count = 0;
9199 *r->out.needed = 0;
9200 *r->out.info = NULL;
9202 if (!Printer) {
9203 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9204 OUR_HANDLE(r->in.handle)));
9205 return WERR_BADFID;
9209 * first check for a keyname of NULL or "". Win2k seems to send
9210 * this a lot and we should send back WERR_INVALID_PARAM
9211 * no need to spend time looking up the printer in this case.
9212 * --jerry
9215 if (!strlen(r->in.key_name)) {
9216 result = WERR_INVALID_PARAM;
9217 goto done;
9220 /* get the printer off of disk */
9222 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9223 return WERR_BADFID;
9226 ZERO_STRUCT(printer);
9227 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9228 if (!W_ERROR_IS_OK(result)) {
9229 return result;
9232 /* now look for a match on the key name */
9234 p_data = printer->info_2->data;
9236 key_index = lookup_printerkey(p_data, r->in.key_name);
9237 if (key_index == -1) {
9238 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9239 r->in.key_name));
9240 result = WERR_INVALID_PARAM;
9241 goto done;
9244 /* allocate the memory for the array of pointers -- if necessary */
9246 count = regval_ctr_numvals(p_data->keys[key_index].values);
9247 if (!count) {
9248 result = WERR_OK; /* ??? */
9249 goto done;
9252 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9253 struct spoolss_PrinterEnumValues,
9254 count);
9255 if (!info) {
9256 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9257 result = WERR_NOMEM;
9258 goto done;
9262 * loop through all params and build the array to pass
9263 * back to the client
9266 for (i=0; i < count; i++) {
9268 struct regval_blob *val;
9270 /* lookup the registry value */
9272 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9274 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9276 /* copy the data */
9278 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9279 if (!W_ERROR_IS_OK(result)) {
9280 goto done;
9284 #if 0 /* FIXME - gd */
9285 /* housekeeping information in the reply */
9287 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9288 * the hand marshalled container size is a multiple
9289 * of 4 bytes for RPC alignment.
9292 if (needed % 4) {
9293 needed += 4-(needed % 4);
9295 #endif
9296 *r->out.count = count;
9297 *r->out.info = info;
9299 done:
9301 if (printer) {
9302 free_a_printer(&printer, 2);
9305 if (!W_ERROR_IS_OK(result)) {
9306 return result;
9309 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9310 spoolss_EnumPrinterDataEx, NULL,
9311 *r->out.info,
9312 *r->out.count);
9313 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9314 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9316 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9319 /****************************************************************************
9320 ****************************************************************************/
9322 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9323 const char *servername,
9324 const char *environment,
9325 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9327 WERROR werr;
9328 char *path = NULL;
9330 werr = compose_spoolss_server_path(mem_ctx,
9331 servername,
9332 environment,
9333 SPOOLSS_PRTPROCS_PATH,
9334 &path);
9335 if (!W_ERROR_IS_OK(werr)) {
9336 return werr;
9339 DEBUG(4,("print processor directory: [%s]\n", path));
9341 r->directory_name = path;
9343 return WERR_OK;
9346 /****************************************************************
9347 _spoolss_GetPrintProcessorDirectory
9348 ****************************************************************/
9350 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9351 struct spoolss_GetPrintProcessorDirectory *r)
9353 WERROR result;
9355 /* that's an [in out] buffer */
9357 if (!r->in.buffer && (r->in.offered != 0)) {
9358 return WERR_INVALID_PARAM;
9361 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9362 r->in.level));
9364 *r->out.needed = 0;
9366 /* r->in.level is ignored */
9368 /* We always should reply with a local print processor directory so that
9369 * users are not forced to have a [prnproc$] share on the Samba spoolss
9370 * server - Guenther */
9372 result = getprintprocessordirectory_level_1(p->mem_ctx,
9373 NULL, /* r->in.server */
9374 r->in.environment,
9375 &r->out.info->info1);
9376 if (!W_ERROR_IS_OK(result)) {
9377 TALLOC_FREE(r->out.info);
9378 return result;
9381 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9382 r->out.info, r->in.level);
9383 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9385 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9388 /*******************************************************************
9389 ********************************************************************/
9391 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9392 const char *dllname)
9394 enum ndr_err_code ndr_err;
9395 struct spoolss_MonitorUi ui;
9397 ui.dll_name = dllname;
9399 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9400 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9401 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9402 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9404 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9407 /*******************************************************************
9408 Streams the monitor UI DLL name in UNICODE
9409 *******************************************************************/
9411 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9412 NT_USER_TOKEN *token, DATA_BLOB *in,
9413 DATA_BLOB *out, uint32_t *needed)
9415 const char *dllname = "tcpmonui.dll";
9417 *needed = (strlen(dllname)+1) * 2;
9419 if (out->length < *needed) {
9420 return WERR_INSUFFICIENT_BUFFER;
9423 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9424 return WERR_NOMEM;
9427 return WERR_OK;
9430 /*******************************************************************
9431 ********************************************************************/
9433 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9434 struct spoolss_PortData1 *port1,
9435 const DATA_BLOB *buf)
9437 enum ndr_err_code ndr_err;
9438 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9439 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9440 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9441 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9443 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9446 /*******************************************************************
9447 ********************************************************************/
9449 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9450 struct spoolss_PortData2 *port2,
9451 const DATA_BLOB *buf)
9453 enum ndr_err_code ndr_err;
9454 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9455 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9456 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9457 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9459 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9462 /*******************************************************************
9463 Create a new TCP/IP port
9464 *******************************************************************/
9466 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9467 NT_USER_TOKEN *token, DATA_BLOB *in,
9468 DATA_BLOB *out, uint32_t *needed)
9470 struct spoolss_PortData1 port1;
9471 struct spoolss_PortData2 port2;
9472 char *device_uri = NULL;
9473 uint32_t version;
9475 const char *portname;
9476 const char *hostaddress;
9477 const char *queue;
9478 uint32_t port_number;
9479 uint32_t protocol;
9481 /* peek for spoolss_PortData version */
9483 if (!in || (in->length < (128 + 4))) {
9484 return WERR_GENERAL_FAILURE;
9487 version = IVAL(in->data, 128);
9489 switch (version) {
9490 case 1:
9491 ZERO_STRUCT(port1);
9493 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9494 return WERR_NOMEM;
9497 portname = port1.portname;
9498 hostaddress = port1.hostaddress;
9499 queue = port1.queue;
9500 protocol = port1.protocol;
9501 port_number = port1.port_number;
9503 break;
9504 case 2:
9505 ZERO_STRUCT(port2);
9507 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9508 return WERR_NOMEM;
9511 portname = port2.portname;
9512 hostaddress = port2.hostaddress;
9513 queue = port2.queue;
9514 protocol = port2.protocol;
9515 port_number = port2.port_number;
9517 break;
9518 default:
9519 DEBUG(1,("xcvtcp_addport: "
9520 "unknown version of port_data: %d\n", version));
9521 return WERR_UNKNOWN_PORT;
9524 /* create the device URI and call the add_port_hook() */
9526 switch (protocol) {
9527 case PROTOCOL_RAWTCP_TYPE:
9528 device_uri = talloc_asprintf(mem_ctx,
9529 "socket://%s:%d/", hostaddress,
9530 port_number);
9531 break;
9533 case PROTOCOL_LPR_TYPE:
9534 device_uri = talloc_asprintf(mem_ctx,
9535 "lpr://%s/%s", hostaddress, queue );
9536 break;
9538 default:
9539 return WERR_UNKNOWN_PORT;
9542 if (!device_uri) {
9543 return WERR_NOMEM;
9546 return add_port_hook(mem_ctx, token, portname, device_uri);
9549 /*******************************************************************
9550 *******************************************************************/
9552 struct xcv_api_table xcvtcp_cmds[] = {
9553 { "MonitorUI", xcvtcp_monitorui },
9554 { "AddPort", xcvtcp_addport},
9555 { NULL, NULL }
9558 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9559 NT_USER_TOKEN *token, const char *command,
9560 DATA_BLOB *inbuf,
9561 DATA_BLOB *outbuf,
9562 uint32_t *needed )
9564 int i;
9566 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9568 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9569 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9570 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9573 return WERR_BADFUNC;
9576 /*******************************************************************
9577 *******************************************************************/
9578 #if 0 /* don't support management using the "Local Port" monitor */
9580 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9581 NT_USER_TOKEN *token, DATA_BLOB *in,
9582 DATA_BLOB *out, uint32_t *needed)
9584 const char *dllname = "localui.dll";
9586 *needed = (strlen(dllname)+1) * 2;
9588 if (out->length < *needed) {
9589 return WERR_INSUFFICIENT_BUFFER;
9592 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9593 return WERR_NOMEM;
9596 return WERR_OK;
9599 /*******************************************************************
9600 *******************************************************************/
9602 struct xcv_api_table xcvlocal_cmds[] = {
9603 { "MonitorUI", xcvlocal_monitorui },
9604 { NULL, NULL }
9606 #else
9607 struct xcv_api_table xcvlocal_cmds[] = {
9608 { NULL, NULL }
9610 #endif
9614 /*******************************************************************
9615 *******************************************************************/
9617 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9618 NT_USER_TOKEN *token, const char *command,
9619 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9620 uint32_t *needed)
9622 int i;
9624 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9626 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9627 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9628 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9630 return WERR_BADFUNC;
9633 /****************************************************************
9634 _spoolss_XcvData
9635 ****************************************************************/
9637 WERROR _spoolss_XcvData(pipes_struct *p,
9638 struct spoolss_XcvData *r)
9640 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9641 DATA_BLOB out_data = data_blob_null;
9642 WERROR werror;
9644 if (!Printer) {
9645 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9646 OUR_HANDLE(r->in.handle)));
9647 return WERR_BADFID;
9650 /* Has to be a handle to the TCP/IP port monitor */
9652 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9653 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9654 return WERR_BADFID;
9657 /* requires administrative access to the server */
9659 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9660 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9661 return WERR_ACCESS_DENIED;
9664 /* Allocate the outgoing buffer */
9666 if (r->in.out_data_size) {
9667 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9668 if (out_data.data == NULL) {
9669 return WERR_NOMEM;
9673 switch ( Printer->printer_type ) {
9674 case SPLHND_PORTMON_TCP:
9675 werror = process_xcvtcp_command(p->mem_ctx,
9676 p->server_info->ptok,
9677 r->in.function_name,
9678 &r->in.in_data, &out_data,
9679 r->out.needed);
9680 break;
9681 case SPLHND_PORTMON_LOCAL:
9682 werror = process_xcvlocal_command(p->mem_ctx,
9683 p->server_info->ptok,
9684 r->in.function_name,
9685 &r->in.in_data, &out_data,
9686 r->out.needed);
9687 break;
9688 default:
9689 werror = WERR_INVALID_PRINT_MONITOR;
9692 if (!W_ERROR_IS_OK(werror)) {
9693 return werror;
9696 *r->out.status_code = 0;
9698 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9699 memcpy(r->out.out_data, out_data.data,
9700 MIN(r->in.out_data_size, out_data.length));
9703 return WERR_OK;
9706 /****************************************************************
9707 _spoolss_AddPrintProcessor
9708 ****************************************************************/
9710 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9711 struct spoolss_AddPrintProcessor *r)
9713 /* for now, just indicate success and ignore the add. We'll
9714 automatically set the winprint processor for printer
9715 entries later. Used to debug the LexMark Optra S 1855 PCL
9716 driver --jerry */
9718 return WERR_OK;
9721 /****************************************************************
9722 _spoolss_AddPort
9723 ****************************************************************/
9725 WERROR _spoolss_AddPort(pipes_struct *p,
9726 struct spoolss_AddPort *r)
9728 /* do what w2k3 does */
9730 return WERR_NOT_SUPPORTED;
9733 /****************************************************************
9734 _spoolss_GetPrinterDriver
9735 ****************************************************************/
9737 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9738 struct spoolss_GetPrinterDriver *r)
9740 p->rng_fault_state = true;
9741 return WERR_NOT_SUPPORTED;
9744 /****************************************************************
9745 _spoolss_ReadPrinter
9746 ****************************************************************/
9748 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9749 struct spoolss_ReadPrinter *r)
9751 p->rng_fault_state = true;
9752 return WERR_NOT_SUPPORTED;
9755 /****************************************************************
9756 _spoolss_WaitForPrinterChange
9757 ****************************************************************/
9759 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9760 struct spoolss_WaitForPrinterChange *r)
9762 p->rng_fault_state = true;
9763 return WERR_NOT_SUPPORTED;
9766 /****************************************************************
9767 _spoolss_ConfigurePort
9768 ****************************************************************/
9770 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9771 struct spoolss_ConfigurePort *r)
9773 p->rng_fault_state = true;
9774 return WERR_NOT_SUPPORTED;
9777 /****************************************************************
9778 _spoolss_DeletePort
9779 ****************************************************************/
9781 WERROR _spoolss_DeletePort(pipes_struct *p,
9782 struct spoolss_DeletePort *r)
9784 p->rng_fault_state = true;
9785 return WERR_NOT_SUPPORTED;
9788 /****************************************************************
9789 _spoolss_CreatePrinterIC
9790 ****************************************************************/
9792 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9793 struct spoolss_CreatePrinterIC *r)
9795 p->rng_fault_state = true;
9796 return WERR_NOT_SUPPORTED;
9799 /****************************************************************
9800 _spoolss_PlayGDIScriptOnPrinterIC
9801 ****************************************************************/
9803 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9804 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9806 p->rng_fault_state = true;
9807 return WERR_NOT_SUPPORTED;
9810 /****************************************************************
9811 _spoolss_DeletePrinterIC
9812 ****************************************************************/
9814 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9815 struct spoolss_DeletePrinterIC *r)
9817 p->rng_fault_state = true;
9818 return WERR_NOT_SUPPORTED;
9821 /****************************************************************
9822 _spoolss_AddPrinterConnection
9823 ****************************************************************/
9825 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9826 struct spoolss_AddPrinterConnection *r)
9828 p->rng_fault_state = true;
9829 return WERR_NOT_SUPPORTED;
9832 /****************************************************************
9833 _spoolss_DeletePrinterConnection
9834 ****************************************************************/
9836 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9837 struct spoolss_DeletePrinterConnection *r)
9839 p->rng_fault_state = true;
9840 return WERR_NOT_SUPPORTED;
9843 /****************************************************************
9844 _spoolss_PrinterMessageBox
9845 ****************************************************************/
9847 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9848 struct spoolss_PrinterMessageBox *r)
9850 p->rng_fault_state = true;
9851 return WERR_NOT_SUPPORTED;
9854 /****************************************************************
9855 _spoolss_AddMonitor
9856 ****************************************************************/
9858 WERROR _spoolss_AddMonitor(pipes_struct *p,
9859 struct spoolss_AddMonitor *r)
9861 p->rng_fault_state = true;
9862 return WERR_NOT_SUPPORTED;
9865 /****************************************************************
9866 _spoolss_DeleteMonitor
9867 ****************************************************************/
9869 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9870 struct spoolss_DeleteMonitor *r)
9872 p->rng_fault_state = true;
9873 return WERR_NOT_SUPPORTED;
9876 /****************************************************************
9877 _spoolss_DeletePrintProcessor
9878 ****************************************************************/
9880 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9881 struct spoolss_DeletePrintProcessor *r)
9883 p->rng_fault_state = true;
9884 return WERR_NOT_SUPPORTED;
9887 /****************************************************************
9888 _spoolss_AddPrintProvidor
9889 ****************************************************************/
9891 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9892 struct spoolss_AddPrintProvidor *r)
9894 p->rng_fault_state = true;
9895 return WERR_NOT_SUPPORTED;
9898 /****************************************************************
9899 _spoolss_DeletePrintProvidor
9900 ****************************************************************/
9902 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9903 struct spoolss_DeletePrintProvidor *r)
9905 p->rng_fault_state = true;
9906 return WERR_NOT_SUPPORTED;
9909 /****************************************************************
9910 _spoolss_FindFirstPrinterChangeNotification
9911 ****************************************************************/
9913 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9914 struct spoolss_FindFirstPrinterChangeNotification *r)
9916 p->rng_fault_state = true;
9917 return WERR_NOT_SUPPORTED;
9920 /****************************************************************
9921 _spoolss_FindNextPrinterChangeNotification
9922 ****************************************************************/
9924 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9925 struct spoolss_FindNextPrinterChangeNotification *r)
9927 p->rng_fault_state = true;
9928 return WERR_NOT_SUPPORTED;
9931 /****************************************************************
9932 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9933 ****************************************************************/
9935 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9936 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9938 p->rng_fault_state = true;
9939 return WERR_NOT_SUPPORTED;
9942 /****************************************************************
9943 _spoolss_ReplyOpenPrinter
9944 ****************************************************************/
9946 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9947 struct spoolss_ReplyOpenPrinter *r)
9949 p->rng_fault_state = true;
9950 return WERR_NOT_SUPPORTED;
9953 /****************************************************************
9954 _spoolss_RouterReplyPrinter
9955 ****************************************************************/
9957 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9958 struct spoolss_RouterReplyPrinter *r)
9960 p->rng_fault_state = true;
9961 return WERR_NOT_SUPPORTED;
9964 /****************************************************************
9965 _spoolss_ReplyClosePrinter
9966 ****************************************************************/
9968 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9969 struct spoolss_ReplyClosePrinter *r)
9971 p->rng_fault_state = true;
9972 return WERR_NOT_SUPPORTED;
9975 /****************************************************************
9976 _spoolss_AddPortEx
9977 ****************************************************************/
9979 WERROR _spoolss_AddPortEx(pipes_struct *p,
9980 struct spoolss_AddPortEx *r)
9982 p->rng_fault_state = true;
9983 return WERR_NOT_SUPPORTED;
9986 /****************************************************************
9987 _spoolss_RouterFindFirstPrinterChangeNotification
9988 ****************************************************************/
9990 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9991 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9993 p->rng_fault_state = true;
9994 return WERR_NOT_SUPPORTED;
9997 /****************************************************************
9998 _spoolss_SpoolerInit
9999 ****************************************************************/
10001 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10002 struct spoolss_SpoolerInit *r)
10004 p->rng_fault_state = true;
10005 return WERR_NOT_SUPPORTED;
10008 /****************************************************************
10009 _spoolss_ResetPrinterEx
10010 ****************************************************************/
10012 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10013 struct spoolss_ResetPrinterEx *r)
10015 p->rng_fault_state = true;
10016 return WERR_NOT_SUPPORTED;
10019 /****************************************************************
10020 _spoolss_RouterReplyPrinterEx
10021 ****************************************************************/
10023 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10024 struct spoolss_RouterReplyPrinterEx *r)
10026 p->rng_fault_state = true;
10027 return WERR_NOT_SUPPORTED;
10030 /****************************************************************
10031 _spoolss_44
10032 ****************************************************************/
10034 WERROR _spoolss_44(pipes_struct *p,
10035 struct spoolss_44 *r)
10037 p->rng_fault_state = true;
10038 return WERR_NOT_SUPPORTED;
10041 /****************************************************************
10042 _spoolss_47
10043 ****************************************************************/
10045 WERROR _spoolss_47(pipes_struct *p,
10046 struct spoolss_47 *r)
10048 p->rng_fault_state = true;
10049 return WERR_NOT_SUPPORTED;
10052 /****************************************************************
10053 _spoolss_4a
10054 ****************************************************************/
10056 WERROR _spoolss_4a(pipes_struct *p,
10057 struct spoolss_4a *r)
10059 p->rng_fault_state = true;
10060 return WERR_NOT_SUPPORTED;
10063 /****************************************************************
10064 _spoolss_4b
10065 ****************************************************************/
10067 WERROR _spoolss_4b(pipes_struct *p,
10068 struct spoolss_4b *r)
10070 p->rng_fault_state = true;
10071 return WERR_NOT_SUPPORTED;
10074 /****************************************************************
10075 _spoolss_4c
10076 ****************************************************************/
10078 WERROR _spoolss_4c(pipes_struct *p,
10079 struct spoolss_4c *r)
10081 p->rng_fault_state = true;
10082 return WERR_NOT_SUPPORTED;
10085 /****************************************************************
10086 _spoolss_53
10087 ****************************************************************/
10089 WERROR _spoolss_53(pipes_struct *p,
10090 struct spoolss_53 *r)
10092 p->rng_fault_state = true;
10093 return WERR_NOT_SUPPORTED;
10096 /****************************************************************
10097 _spoolss_55
10098 ****************************************************************/
10100 WERROR _spoolss_55(pipes_struct *p,
10101 struct spoolss_55 *r)
10103 p->rng_fault_state = true;
10104 return WERR_NOT_SUPPORTED;
10107 /****************************************************************
10108 _spoolss_56
10109 ****************************************************************/
10111 WERROR _spoolss_56(pipes_struct *p,
10112 struct spoolss_56 *r)
10114 p->rng_fault_state = true;
10115 return WERR_NOT_SUPPORTED;
10118 /****************************************************************
10119 _spoolss_57
10120 ****************************************************************/
10122 WERROR _spoolss_57(pipes_struct *p,
10123 struct spoolss_57 *r)
10125 p->rng_fault_state = true;
10126 return WERR_NOT_SUPPORTED;
10129 /****************************************************************
10130 _spoolss_5a
10131 ****************************************************************/
10133 WERROR _spoolss_5a(pipes_struct *p,
10134 struct spoolss_5a *r)
10136 p->rng_fault_state = true;
10137 return WERR_NOT_SUPPORTED;
10140 /****************************************************************
10141 _spoolss_5b
10142 ****************************************************************/
10144 WERROR _spoolss_5b(pipes_struct *p,
10145 struct spoolss_5b *r)
10147 p->rng_fault_state = true;
10148 return WERR_NOT_SUPPORTED;
10151 /****************************************************************
10152 _spoolss_5c
10153 ****************************************************************/
10155 WERROR _spoolss_5c(pipes_struct *p,
10156 struct spoolss_5c *r)
10158 p->rng_fault_state = true;
10159 return WERR_NOT_SUPPORTED;
10162 /****************************************************************
10163 _spoolss_5d
10164 ****************************************************************/
10166 WERROR _spoolss_5d(pipes_struct *p,
10167 struct spoolss_5d *r)
10169 p->rng_fault_state = true;
10170 return WERR_NOT_SUPPORTED;
10173 /****************************************************************
10174 _spoolss_5e
10175 ****************************************************************/
10177 WERROR _spoolss_5e(pipes_struct *p,
10178 struct spoolss_5e *r)
10180 p->rng_fault_state = true;
10181 return WERR_NOT_SUPPORTED;
10184 /****************************************************************
10185 _spoolss_5f
10186 ****************************************************************/
10188 WERROR _spoolss_5f(pipes_struct *p,
10189 struct spoolss_5f *r)
10191 p->rng_fault_state = true;
10192 return WERR_NOT_SUPPORTED;
10195 /****************************************************************
10196 _spoolss_60
10197 ****************************************************************/
10199 WERROR _spoolss_60(pipes_struct *p,
10200 struct spoolss_60 *r)
10202 p->rng_fault_state = true;
10203 return WERR_NOT_SUPPORTED;
10206 /****************************************************************
10207 _spoolss_61
10208 ****************************************************************/
10210 WERROR _spoolss_61(pipes_struct *p,
10211 struct spoolss_61 *r)
10213 p->rng_fault_state = true;
10214 return WERR_NOT_SUPPORTED;
10217 /****************************************************************
10218 _spoolss_62
10219 ****************************************************************/
10221 WERROR _spoolss_62(pipes_struct *p,
10222 struct spoolss_62 *r)
10224 p->rng_fault_state = true;
10225 return WERR_NOT_SUPPORTED;
10228 /****************************************************************
10229 _spoolss_63
10230 ****************************************************************/
10232 WERROR _spoolss_63(pipes_struct *p,
10233 struct spoolss_63 *r)
10235 p->rng_fault_state = true;
10236 return WERR_NOT_SUPPORTED;
10239 /****************************************************************
10240 _spoolss_64
10241 ****************************************************************/
10243 WERROR _spoolss_64(pipes_struct *p,
10244 struct spoolss_64 *r)
10246 p->rng_fault_state = true;
10247 return WERR_NOT_SUPPORTED;
10250 /****************************************************************
10251 _spoolss_65
10252 ****************************************************************/
10254 WERROR _spoolss_65(pipes_struct *p,
10255 struct spoolss_65 *r)
10257 p->rng_fault_state = true;
10258 return WERR_NOT_SUPPORTED;
10261 /****************************************************************
10262 _spoolss_GetCorePrinterDrivers
10263 ****************************************************************/
10265 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10266 struct spoolss_GetCorePrinterDrivers *r)
10268 p->rng_fault_state = true;
10269 return WERR_NOT_SUPPORTED;
10272 /****************************************************************
10273 _spoolss_67
10274 ****************************************************************/
10276 WERROR _spoolss_67(pipes_struct *p,
10277 struct spoolss_67 *r)
10279 p->rng_fault_state = true;
10280 return WERR_NOT_SUPPORTED;
10283 /****************************************************************
10284 _spoolss_GetPrinterDriverPackagePath
10285 ****************************************************************/
10287 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10288 struct spoolss_GetPrinterDriverPackagePath *r)
10290 p->rng_fault_state = true;
10291 return WERR_NOT_SUPPORTED;
10294 /****************************************************************
10295 _spoolss_69
10296 ****************************************************************/
10298 WERROR _spoolss_69(pipes_struct *p,
10299 struct spoolss_69 *r)
10301 p->rng_fault_state = true;
10302 return WERR_NOT_SUPPORTED;
10305 /****************************************************************
10306 _spoolss_6a
10307 ****************************************************************/
10309 WERROR _spoolss_6a(pipes_struct *p,
10310 struct spoolss_6a *r)
10312 p->rng_fault_state = true;
10313 return WERR_NOT_SUPPORTED;
10316 /****************************************************************
10317 _spoolss_6b
10318 ****************************************************************/
10320 WERROR _spoolss_6b(pipes_struct *p,
10321 struct spoolss_6b *r)
10323 p->rng_fault_state = true;
10324 return WERR_NOT_SUPPORTED;
10327 /****************************************************************
10328 _spoolss_6c
10329 ****************************************************************/
10331 WERROR _spoolss_6c(pipes_struct *p,
10332 struct spoolss_6c *r)
10334 p->rng_fault_state = true;
10335 return WERR_NOT_SUPPORTED;
10338 /****************************************************************
10339 _spoolss_6d
10340 ****************************************************************/
10342 WERROR _spoolss_6d(pipes_struct *p,
10343 struct spoolss_6d *r)
10345 p->rng_fault_state = true;
10346 return WERR_NOT_SUPPORTED;