s3-spoolss: Set c_setprinter always to 0.
[Samba.git] / source3 / rpc_server / srv_spoolss_nt.c
blob71daeb9d59b2c977758404f48109e6a698714561
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.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "includes.h"
31 #include "srv_spoolss_util.h"
32 #include "../librpc/gen_ndr/srv_spoolss.h"
33 #include "../librpc/gen_ndr/cli_spoolss.h"
34 #include "rpc_client/init_spoolss.h"
35 #include "librpc/gen_ndr/messaging.h"
36 #include "registry.h"
37 #include "registry/reg_objects.h"
39 /* macros stolen from s4 spoolss server */
40 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
41 ((info)?ndr_size_##fn(info, level, 0):0)
43 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
44 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
46 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
47 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
49 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
52 extern userdom_struct current_user_info;
54 #undef DBGC_CLASS
55 #define DBGC_CLASS DBGC_RPC_SRV
57 #ifndef MAX_OPEN_PRINTER_EXS
58 #define MAX_OPEN_PRINTER_EXS 50
59 #endif
61 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
63 static Printer_entry *printers_list;
65 typedef struct _counter_printer_0 {
66 struct _counter_printer_0 *next;
67 struct _counter_printer_0 *prev;
69 int snum;
70 uint32_t counter;
71 } counter_printer_0;
73 static counter_printer_0 *counter_list;
75 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
76 static uint32_t smb_connections = 0;
79 /* in printing/nt_printing.c */
81 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
83 /* API table for Xcv Monitor functions */
85 struct xcv_api_table {
86 const char *name;
87 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
90 /********************************************************************
91 * Canonicalize servername.
92 ********************************************************************/
94 static const char *canon_servername(const char *servername)
96 const char *pservername = servername;
97 while (*pservername == '\\') {
98 pservername++;
100 return pservername;
103 /* translate between internal status numbers and NT status numbers */
104 static int nt_printj_status(int v)
106 switch (v) {
107 case LPQ_QUEUED:
108 return 0;
109 case LPQ_PAUSED:
110 return JOB_STATUS_PAUSED;
111 case LPQ_SPOOLING:
112 return JOB_STATUS_SPOOLING;
113 case LPQ_PRINTING:
114 return JOB_STATUS_PRINTING;
115 case LPQ_ERROR:
116 return JOB_STATUS_ERROR;
117 case LPQ_DELETING:
118 return JOB_STATUS_DELETING;
119 case LPQ_OFFLINE:
120 return JOB_STATUS_OFFLINE;
121 case LPQ_PAPEROUT:
122 return JOB_STATUS_PAPEROUT;
123 case LPQ_PRINTED:
124 return JOB_STATUS_PRINTED;
125 case LPQ_DELETED:
126 return JOB_STATUS_DELETED;
127 case LPQ_BLOCKED:
128 return JOB_STATUS_BLOCKED_DEVQ;
129 case LPQ_USER_INTERVENTION:
130 return JOB_STATUS_USER_INTERVENTION;
132 return 0;
135 static int nt_printq_status(int v)
137 switch (v) {
138 case LPQ_PAUSED:
139 return PRINTER_STATUS_PAUSED;
140 case LPQ_QUEUED:
141 case LPQ_SPOOLING:
142 case LPQ_PRINTING:
143 return 0;
145 return 0;
148 /***************************************************************************
149 Disconnect from the client
150 ****************************************************************************/
152 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
154 WERROR result;
155 NTSTATUS status;
158 * Tell the specific printing tdb we no longer want messages for this printer
159 * by deregistering our PID.
162 if (!print_notify_deregister_pid(snum))
163 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
165 /* weird if the test succeds !!! */
166 if (smb_connections==0) {
167 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
168 return;
171 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
172 handle,
173 &result);
174 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
175 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
176 win_errstr(result)));
178 /* if it's the last connection, deconnect the IPC$ share */
179 if (smb_connections==1) {
181 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
182 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
184 messaging_deregister(smbd_messaging_context(),
185 MSG_PRINTER_NOTIFY2, NULL);
187 /* Tell the connections db we're no longer interested in
188 * printer notify messages. */
190 serverid_register_msg_flags(
191 messaging_server_id(smbd_messaging_context()),
192 false, FLAG_MSG_PRINT_NOTIFY);
195 smb_connections--;
198 /****************************************************************************
199 Functions to free a printer entry datastruct.
200 ****************************************************************************/
202 static int printer_entry_destructor(Printer_entry *Printer)
204 if (Printer->notify.client_connected == true) {
205 int snum = -1;
207 if ( Printer->printer_type == SPLHND_SERVER) {
208 snum = -1;
209 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
210 } else if (Printer->printer_type == SPLHND_PRINTER) {
211 snum = print_queue_snum(Printer->sharename);
212 if (snum != -1)
213 srv_spoolss_replycloseprinter(snum,
214 &Printer->notify.client_hnd);
218 Printer->notify.flags=0;
219 Printer->notify.options=0;
220 Printer->notify.localmachine[0]='\0';
221 Printer->notify.printerlocal=0;
222 TALLOC_FREE(Printer->notify.option);
223 Printer->notify.client_connected = false;
225 TALLOC_FREE(Printer->devmode);
226 free_a_printer( &Printer->printer_info, 2 );
228 /* Remove from the internal list. */
229 DLIST_REMOVE(printers_list, Printer);
230 return 0;
233 /****************************************************************************
234 find printer index by handle
235 ****************************************************************************/
237 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
238 struct policy_handle *hnd)
240 Printer_entry *find_printer = NULL;
242 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
243 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
244 return NULL;
247 return find_printer;
250 /****************************************************************************
251 Close printer index by handle.
252 ****************************************************************************/
254 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
256 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
258 if (!Printer) {
259 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
260 OUR_HANDLE(hnd)));
261 return false;
264 close_policy_hnd(p, hnd);
266 return true;
269 /****************************************************************************
270 Delete a printer given a handle.
271 ****************************************************************************/
273 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
275 char *cmd = lp_deleteprinter_cmd();
276 char *command = NULL;
277 int ret;
278 SE_PRIV se_printop = SE_PRINT_OPERATOR;
279 bool is_print_op = false;
281 /* can't fail if we don't try */
283 if ( !*cmd )
284 return WERR_OK;
286 command = talloc_asprintf(ctx,
287 "%s \"%s\"",
288 cmd, sharename);
289 if (!command) {
290 return WERR_NOMEM;
292 if ( token )
293 is_print_op = user_has_privileges( token, &se_printop );
295 DEBUG(10,("Running [%s]\n", command));
297 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
299 if ( is_print_op )
300 become_root();
302 if ( (ret = smbrun(command, NULL)) == 0 ) {
303 /* Tell everyone we updated smb.conf. */
304 message_send_all(smbd_messaging_context(),
305 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
308 if ( is_print_op )
309 unbecome_root();
311 /********** END SePrintOperatorPrivlege BLOCK **********/
313 DEBUGADD(10,("returned [%d]\n", ret));
315 TALLOC_FREE(command);
317 if (ret != 0)
318 return WERR_BADFID; /* What to return here? */
320 /* go ahead and re-read the services immediately */
321 become_root();
322 reload_services(false);
323 unbecome_root();
325 if ( lp_servicenumber( sharename ) > 0 )
326 return WERR_ACCESS_DENIED;
328 return WERR_OK;
331 /****************************************************************************
332 Delete a printer given a handle.
333 ****************************************************************************/
335 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
337 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
339 if (!Printer) {
340 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
341 OUR_HANDLE(hnd)));
342 return WERR_BADFID;
346 * It turns out that Windows allows delete printer on a handle
347 * opened by an admin user, then used on a pipe handle created
348 * by an anonymous user..... but they're working on security.... riiight !
349 * JRA.
352 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
353 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
354 return WERR_ACCESS_DENIED;
357 /* this does not need a become root since the access check has been
358 done on the handle already */
360 if (del_a_printer( Printer->sharename ) != 0) {
361 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
362 return WERR_BADFID;
365 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
366 Printer->sharename );
369 /****************************************************************************
370 Return the snum of a printer corresponding to an handle.
371 ****************************************************************************/
373 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
374 int *number, struct share_params **params)
376 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
378 if (!Printer) {
379 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
380 OUR_HANDLE(hnd)));
381 return false;
384 switch (Printer->printer_type) {
385 case SPLHND_PRINTER:
386 DEBUG(4,("short name:%s\n", Printer->sharename));
387 *number = print_queue_snum(Printer->sharename);
388 return (*number != -1);
389 case SPLHND_SERVER:
390 return false;
391 default:
392 return false;
396 /****************************************************************************
397 Set printer handle type.
398 Check if it's \\server or \\server\printer
399 ****************************************************************************/
401 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
403 DEBUG(3,("Setting printer type=%s\n", handlename));
405 if ( strlen(handlename) < 3 ) {
406 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
407 return false;
410 /* it's a print server */
411 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
412 DEBUGADD(4,("Printer is a print server\n"));
413 Printer->printer_type = SPLHND_SERVER;
415 /* it's a printer (set_printer_hnd_name() will handle port monitors */
416 else {
417 DEBUGADD(4,("Printer is a printer\n"));
418 Printer->printer_type = SPLHND_PRINTER;
421 return true;
424 /****************************************************************************
425 Set printer handle name.. Accept names like \\server, \\server\printer,
426 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
427 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
428 XcvDataPort() interface.
429 ****************************************************************************/
431 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
432 struct auth_serversupplied_info *server_info,
433 Printer_entry *Printer,
434 const char *handlename)
436 int snum;
437 int n_services=lp_numservices();
438 char *aprinter;
439 const char *printername;
440 const char *servername;
441 fstring sname;
442 bool found = false;
443 struct spoolss_PrinterInfo2 *info2 = NULL;
444 WERROR result;
446 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
447 (unsigned long)strlen(handlename)));
449 aprinter = CONST_DISCARD(char *, handlename);
450 if ( *handlename == '\\' ) {
451 servername = canon_servername(handlename);
452 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
453 *aprinter = '\0';
454 aprinter++;
456 if (!is_myname_or_ipaddr(servername)) {
457 return false;
460 fstrcpy(Printer->servername, servername);
463 if (Printer->printer_type == SPLHND_SERVER) {
464 return true;
467 if (Printer->printer_type != SPLHND_PRINTER) {
468 return false;
471 DEBUGADD(5, ("searching for [%s]\n", aprinter));
473 /* check for the Port Monitor Interface */
474 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
475 Printer->printer_type = SPLHND_PORTMON_TCP;
476 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
477 found = true;
479 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
480 Printer->printer_type = SPLHND_PORTMON_LOCAL;
481 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
482 found = true;
485 /* Search all sharenames first as this is easier than pulling
486 the printer_info_2 off of disk. Don't use find_service() since
487 that calls out to map_username() */
489 /* do another loop to look for printernames */
490 for (snum = 0; !found && snum < n_services; snum++) {
491 const char *printer = lp_const_servicename(snum);
493 /* no point going on if this is not a printer */
494 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
495 continue;
498 /* ignore [printers] share */
499 if (strequal(printer, "printers")) {
500 continue;
503 fstrcpy(sname, printer);
504 if (strequal(aprinter, printer)) {
505 found = true;
506 break;
509 /* no point looking up the printer object if
510 we aren't allowing printername != sharename */
511 if (lp_force_printername(snum)) {
512 continue;
515 result = winreg_get_printer(mem_ctx,
516 server_info,
517 servername,
518 sname,
519 &info2);
520 if ( !W_ERROR_IS_OK(result) ) {
521 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
522 sname, win_errstr(result)));
523 continue;
526 printername = strrchr(info2->printername, '\\');
527 if (printername == NULL) {
528 printername = info2->printername;
529 } else {
530 printername++;
533 if (strequal(printername, aprinter)) {
534 found = true;
535 break;
538 DEBUGADD(10, ("printername: %s\n", printername));
540 TALLOC_FREE(info2);
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(p->mem_ctx, p->server_info, 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)));
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(),
1268 messaging_server_id(smbd_messaging_context()),
1269 MSG_PRINTER_DRVUPGRADE,
1270 (uint8_t *)drivername, len+1);
1272 return true;
1275 /**********************************************************************
1276 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1277 over all printers, upgrading ones as necessary
1278 **********************************************************************/
1280 void do_drv_upgrade_printer(struct messaging_context *msg,
1281 void *private_data,
1282 uint32_t msg_type,
1283 struct server_id server_id,
1284 DATA_BLOB *data)
1286 fstring drivername;
1287 int snum;
1288 int n_services = lp_numservices();
1289 size_t len;
1291 len = MIN(data->length,sizeof(drivername)-1);
1292 strncpy(drivername, (const char *)data->data, len);
1294 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1296 /* Iterate the printer list */
1298 for (snum=0; snum<n_services; snum++)
1300 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1302 WERROR result;
1303 NT_PRINTER_INFO_LEVEL *printer = NULL;
1305 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1306 if (!W_ERROR_IS_OK(result))
1307 continue;
1309 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1311 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1313 /* all we care about currently is the change_id */
1315 result = mod_a_printer(printer, 2);
1316 if (!W_ERROR_IS_OK(result)) {
1317 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1318 win_errstr(result)));
1322 free_a_printer(&printer, 2);
1326 /* all done */
1329 /********************************************************************
1330 Update the cache for all printq's with a registered client
1331 connection
1332 ********************************************************************/
1334 void update_monitored_printq_cache( void )
1336 Printer_entry *printer = printers_list;
1337 int snum;
1339 /* loop through all printers and update the cache where
1340 client_connected == true */
1341 while ( printer )
1343 if ( (printer->printer_type == SPLHND_PRINTER)
1344 && printer->notify.client_connected )
1346 snum = print_queue_snum(printer->sharename);
1347 print_queue_status( snum, NULL, NULL );
1350 printer = printer->next;
1353 return;
1356 /****************************************************************
1357 _spoolss_OpenPrinter
1358 ****************************************************************/
1360 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1361 struct spoolss_OpenPrinter *r)
1363 struct spoolss_OpenPrinterEx e;
1364 WERROR werr;
1366 ZERO_STRUCT(e.in.userlevel);
1368 e.in.printername = r->in.printername;
1369 e.in.datatype = r->in.datatype;
1370 e.in.devmode_ctr = r->in.devmode_ctr;
1371 e.in.access_mask = r->in.access_mask;
1372 e.in.level = 0;
1374 e.out.handle = r->out.handle;
1376 werr = _spoolss_OpenPrinterEx(p, &e);
1378 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1379 /* OpenPrinterEx returns this for a bad
1380 * printer name. We must return WERR_INVALID_PRINTER_NAME
1381 * instead.
1383 werr = WERR_INVALID_PRINTER_NAME;
1386 return werr;
1389 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1390 struct spoolss_DeviceMode *orig,
1391 struct spoolss_DeviceMode **dest)
1393 struct spoolss_DeviceMode *dm;
1395 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1396 if (!dm) {
1397 return WERR_NOMEM;
1400 /* copy all values, then duplicate strings and structs */
1401 *dm = *orig;
1403 dm->devicename = talloc_strdup(dm, orig->devicename);
1404 if (!dm->devicename) {
1405 return WERR_NOMEM;
1407 dm->formname = talloc_strdup(dm, orig->formname);
1408 if (!dm->formname) {
1409 return WERR_NOMEM;
1411 if (orig->driverextra_data.data) {
1412 dm->driverextra_data.data =
1413 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1414 orig->driverextra_data.length);
1415 if (!dm->driverextra_data.data) {
1416 return WERR_NOMEM;
1420 *dest = dm;
1421 return WERR_OK;
1424 /****************************************************************
1425 _spoolss_OpenPrinterEx
1426 ****************************************************************/
1428 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1429 struct spoolss_OpenPrinterEx *r)
1431 int snum;
1432 Printer_entry *Printer=NULL;
1434 if (!r->in.printername) {
1435 return WERR_INVALID_PARAM;
1438 /* some sanity check because you can open a printer or a print server */
1439 /* aka: \\server\printer or \\server */
1441 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1443 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1444 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1445 " for printer %s\n", r->in.printername));
1446 ZERO_STRUCTP(r->out.handle);
1447 return WERR_INVALID_PARAM;
1450 Printer = find_printer_index_by_hnd(p, r->out.handle);
1451 if ( !Printer ) {
1452 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1453 "handle we created for printer %s\n", r->in.printername));
1454 close_printer_handle(p, r->out.handle);
1455 ZERO_STRUCTP(r->out.handle);
1456 return WERR_INVALID_PARAM;
1460 * First case: the user is opening the print server:
1462 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1463 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1465 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1466 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1467 * or if the user is listed in the smb.conf printer admin parameter.
1469 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1470 * client view printer folder, but does not show the MSAPW.
1472 * Note: this test needs code to check access rights here too. Jeremy
1473 * could you look at this?
1475 * Second case: the user is opening a printer:
1476 * NT doesn't let us connect to a printer if the connecting user
1477 * doesn't have print permission.
1479 * Third case: user is opening a Port Monitor
1480 * access checks same as opening a handle to the print server.
1483 switch (Printer->printer_type )
1485 case SPLHND_SERVER:
1486 case SPLHND_PORTMON_TCP:
1487 case SPLHND_PORTMON_LOCAL:
1488 /* Printserver handles use global struct... */
1490 snum = -1;
1492 /* Map standard access rights to object specific access rights */
1494 se_map_standard(&r->in.access_mask,
1495 &printserver_std_mapping);
1497 /* Deny any object specific bits that don't apply to print
1498 servers (i.e printer and job specific bits) */
1500 r->in.access_mask &= SEC_MASK_SPECIFIC;
1502 if (r->in.access_mask &
1503 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1504 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1505 close_printer_handle(p, r->out.handle);
1506 ZERO_STRUCTP(r->out.handle);
1507 return WERR_ACCESS_DENIED;
1510 /* Allow admin access */
1512 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1514 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1516 if (!lp_ms_add_printer_wizard()) {
1517 close_printer_handle(p, r->out.handle);
1518 ZERO_STRUCTP(r->out.handle);
1519 return WERR_ACCESS_DENIED;
1522 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1523 and not a printer admin, then fail */
1525 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1526 !user_has_privileges(p->server_info->ptok,
1527 &se_printop ) &&
1528 !token_contains_name_in_list(
1529 uidtoname(p->server_info->utok.uid),
1530 p->server_info->info3->base.domain.string,
1531 NULL,
1532 p->server_info->ptok,
1533 lp_printer_admin(snum))) {
1534 close_printer_handle(p, r->out.handle);
1535 ZERO_STRUCTP(r->out.handle);
1536 return WERR_ACCESS_DENIED;
1539 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1541 else
1543 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1546 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1547 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1549 /* We fall through to return WERR_OK */
1550 break;
1552 case SPLHND_PRINTER:
1553 /* NT doesn't let us connect to a printer if the connecting user
1554 doesn't have print permission. */
1556 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1557 close_printer_handle(p, r->out.handle);
1558 ZERO_STRUCTP(r->out.handle);
1559 return WERR_BADFID;
1562 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1563 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1566 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1568 /* map an empty access mask to the minimum access mask */
1569 if (r->in.access_mask == 0x0)
1570 r->in.access_mask = PRINTER_ACCESS_USE;
1573 * If we are not serving the printer driver for this printer,
1574 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1575 * will keep NT clients happy --jerry
1578 if (lp_use_client_driver(snum)
1579 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1581 r->in.access_mask = PRINTER_ACCESS_USE;
1584 /* check smb.conf parameters and the the sec_desc */
1586 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1587 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1588 ZERO_STRUCTP(r->out.handle);
1589 return WERR_ACCESS_DENIED;
1592 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1593 p->server_info->ptok, snum) ||
1594 !print_access_check(p->server_info, snum,
1595 r->in.access_mask)) {
1596 DEBUG(3, ("access DENIED for printer open\n"));
1597 close_printer_handle(p, r->out.handle);
1598 ZERO_STRUCTP(r->out.handle);
1599 return WERR_ACCESS_DENIED;
1602 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1603 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1604 close_printer_handle(p, r->out.handle);
1605 ZERO_STRUCTP(r->out.handle);
1606 return WERR_ACCESS_DENIED;
1609 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1610 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1611 else
1612 r->in.access_mask = PRINTER_ACCESS_USE;
1614 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1615 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1617 winreg_create_printer(p->mem_ctx,
1618 p->server_info,
1619 Printer->servername,
1620 lp_const_servicename(snum));
1622 break;
1624 default:
1625 /* sanity check to prevent programmer error */
1626 ZERO_STRUCTP(r->out.handle);
1627 return WERR_BADFID;
1630 Printer->access_granted = r->in.access_mask;
1633 * If the client sent a devmode in the OpenPrinter() call, then
1634 * save it here in case we get a job submission on this handle
1637 if ((Printer->printer_type != SPLHND_SERVER) &&
1638 r->in.devmode_ctr.devmode) {
1639 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1640 &Printer->devmode);
1643 #if 0 /* JERRY -- I'm doubtful this is really effective */
1644 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1645 optimization in Windows 2000 clients --jerry */
1647 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1648 && (RA_WIN2K == get_remote_arch()) )
1650 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1651 sys_usleep( 500000 );
1653 #endif
1655 return WERR_OK;
1658 /****************************************************************
1659 _spoolss_ClosePrinter
1660 ****************************************************************/
1662 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1663 struct spoolss_ClosePrinter *r)
1665 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1667 if (Printer && Printer->document_started) {
1668 struct spoolss_EndDocPrinter e;
1670 e.in.handle = r->in.handle;
1672 _spoolss_EndDocPrinter(p, &e);
1675 if (!close_printer_handle(p, r->in.handle))
1676 return WERR_BADFID;
1678 /* clear the returned printer handle. Observed behavior
1679 from Win2k server. Don't think this really matters.
1680 Previous code just copied the value of the closed
1681 handle. --jerry */
1683 ZERO_STRUCTP(r->out.handle);
1685 return WERR_OK;
1688 /****************************************************************
1689 _spoolss_DeletePrinter
1690 ****************************************************************/
1692 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1693 struct spoolss_DeletePrinter *r)
1695 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1696 WERROR result;
1697 int snum;
1699 if (Printer && Printer->document_started) {
1700 struct spoolss_EndDocPrinter e;
1702 e.in.handle = r->in.handle;
1704 _spoolss_EndDocPrinter(p, &e);
1707 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1708 winreg_delete_printer_key(p->mem_ctx,
1709 p->server_info,
1710 lp_const_servicename(snum),
1711 "");
1714 result = delete_printer_handle(p, r->in.handle);
1716 return result;
1719 /*******************************************************************
1720 * static function to lookup the version id corresponding to an
1721 * long architecture string
1722 ******************************************************************/
1724 static const struct print_architecture_table_node archi_table[]= {
1726 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1727 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1728 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1729 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1730 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1731 {"Windows IA64", SPL_ARCH_IA64, 3 },
1732 {"Windows x64", SPL_ARCH_X64, 3 },
1733 {NULL, "", -1 }
1736 static int get_version_id(const char *arch)
1738 int i;
1740 for (i=0; archi_table[i].long_archi != NULL; i++)
1742 if (strcmp(arch, archi_table[i].long_archi) == 0)
1743 return (archi_table[i].version);
1746 return -1;
1749 /****************************************************************
1750 _spoolss_DeletePrinterDriver
1751 ****************************************************************/
1753 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1754 struct spoolss_DeletePrinterDriver *r)
1757 struct spoolss_DriverInfo8 *info = NULL;
1758 struct spoolss_DriverInfo8 *info_win2k = NULL;
1759 int version;
1760 WERROR status;
1761 WERROR status_win2k = WERR_ACCESS_DENIED;
1762 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1764 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1765 and not a printer admin, then fail */
1767 if ( (p->server_info->utok.uid != sec_initial_uid())
1768 && !user_has_privileges(p->server_info->ptok, &se_printop )
1769 && !token_contains_name_in_list(
1770 uidtoname(p->server_info->utok.uid),
1771 p->server_info->info3->base.domain.string,
1772 NULL,
1773 p->server_info->ptok,
1774 lp_printer_admin(-1)) )
1776 return WERR_ACCESS_DENIED;
1779 /* check that we have a valid driver name first */
1781 if ((version = get_version_id(r->in.architecture)) == -1)
1782 return WERR_INVALID_ENVIRONMENT;
1784 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1785 r->in.architecture,
1786 version)))
1788 /* try for Win2k driver if "Windows NT x86" */
1790 if ( version == 2 ) {
1791 version = 3;
1792 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1793 &info,
1794 r->in.driver,
1795 r->in.architecture,
1796 version))) {
1797 status = WERR_UNKNOWN_PRINTER_DRIVER;
1798 goto done;
1801 /* otherwise it was a failure */
1802 else {
1803 status = WERR_UNKNOWN_PRINTER_DRIVER;
1804 goto done;
1809 if (printer_driver_in_use(info)) {
1810 status = WERR_PRINTER_DRIVER_IN_USE;
1811 goto done;
1814 if ( version == 2 )
1816 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1817 &info_win2k,
1818 r->in.driver,
1819 r->in.architecture, 3)))
1821 /* if we get to here, we now have 2 driver info structures to remove */
1822 /* remove the Win2k driver first*/
1824 status_win2k = delete_printer_driver(
1825 p, info_win2k, 3, false);
1826 free_a_printer_driver(info_win2k);
1828 /* this should not have failed---if it did, report to client */
1829 if ( !W_ERROR_IS_OK(status_win2k) )
1831 status = status_win2k;
1832 goto done;
1837 status = delete_printer_driver(p, info, version, false);
1839 /* if at least one of the deletes succeeded return OK */
1841 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1842 status = WERR_OK;
1844 done:
1845 free_a_printer_driver(info);
1847 return status;
1850 /****************************************************************
1851 _spoolss_DeletePrinterDriverEx
1852 ****************************************************************/
1854 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1855 struct spoolss_DeletePrinterDriverEx *r)
1857 struct spoolss_DriverInfo8 *info = NULL;
1858 struct spoolss_DriverInfo8 *info_win2k = NULL;
1859 int version;
1860 bool delete_files;
1861 WERROR status;
1862 WERROR status_win2k = WERR_ACCESS_DENIED;
1863 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1865 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1866 and not a printer admin, then fail */
1868 if ( (p->server_info->utok.uid != sec_initial_uid())
1869 && !user_has_privileges(p->server_info->ptok, &se_printop )
1870 && !token_contains_name_in_list(
1871 uidtoname(p->server_info->utok.uid),
1872 p->server_info->info3->base.domain.string,
1873 NULL,
1874 p->server_info->ptok, lp_printer_admin(-1)) )
1876 return WERR_ACCESS_DENIED;
1879 /* check that we have a valid driver name first */
1880 if ((version = get_version_id(r->in.architecture)) == -1) {
1881 /* this is what NT returns */
1882 return WERR_INVALID_ENVIRONMENT;
1885 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1886 version = r->in.version;
1888 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1889 r->in.architecture, version);
1891 if ( !W_ERROR_IS_OK(status) )
1894 * if the client asked for a specific version,
1895 * or this is something other than Windows NT x86,
1896 * then we've failed
1899 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1900 goto done;
1902 /* try for Win2k driver if "Windows NT x86" */
1904 version = 3;
1905 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1906 r->in.architecture,
1907 version))) {
1908 status = WERR_UNKNOWN_PRINTER_DRIVER;
1909 goto done;
1913 if (printer_driver_in_use(info)) {
1914 status = WERR_PRINTER_DRIVER_IN_USE;
1915 goto done;
1919 * we have a couple of cases to consider.
1920 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1921 * then the delete should fail if **any** files overlap with
1922 * other drivers
1923 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1924 * non-overlapping files
1925 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1926 * is set, the do not delete any files
1927 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1930 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1932 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1934 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
1935 /* no idea of the correct error here */
1936 status = WERR_ACCESS_DENIED;
1937 goto done;
1941 /* also check for W32X86/3 if necessary; maybe we already have? */
1943 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
1944 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
1945 r->in.driver,
1946 r->in.architecture, 3)))
1949 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
1950 /* no idea of the correct error here */
1951 free_a_printer_driver(info_win2k);
1952 status = WERR_ACCESS_DENIED;
1953 goto done;
1956 /* if we get to here, we now have 2 driver info structures to remove */
1957 /* remove the Win2k driver first*/
1959 status_win2k = delete_printer_driver(
1960 p, info_win2k, 3, delete_files);
1961 free_a_printer_driver(info_win2k);
1963 /* this should not have failed---if it did, report to client */
1965 if ( !W_ERROR_IS_OK(status_win2k) )
1966 goto done;
1970 status = delete_printer_driver(p, info, version, delete_files);
1972 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1973 status = WERR_OK;
1974 done:
1975 free_a_printer_driver(info);
1977 return status;
1981 /****************************************************************************
1982 Internal routine for storing printerdata
1983 ***************************************************************************/
1985 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
1986 const char *key, const char *value,
1987 uint32_t type, uint8_t *data, int real_len)
1989 /* the registry objects enforce uniqueness based on value name */
1991 return add_printer_data( printer->info_2, key, value, type, data, real_len );
1994 /********************************************************************
1995 GetPrinterData on a printer server Handle.
1996 ********************************************************************/
1998 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
1999 const char *value,
2000 enum winreg_Type *type,
2001 union spoolss_PrinterData *data)
2003 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2005 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2006 *type = REG_DWORD;
2007 data->value = 0x00;
2008 return WERR_OK;
2011 if (!StrCaseCmp(value, "BeepEnabled")) {
2012 *type = REG_DWORD;
2013 data->value = 0x00;
2014 return WERR_OK;
2017 if (!StrCaseCmp(value, "EventLog")) {
2018 *type = REG_DWORD;
2019 /* formally was 0x1b */
2020 data->value = 0x00;
2021 return WERR_OK;
2024 if (!StrCaseCmp(value, "NetPopup")) {
2025 *type = REG_DWORD;
2026 data->value = 0x00;
2027 return WERR_OK;
2030 if (!StrCaseCmp(value, "MajorVersion")) {
2031 *type = REG_DWORD;
2033 /* Windows NT 4.0 seems to not allow uploading of drivers
2034 to a server that reports 0x3 as the MajorVersion.
2035 need to investigate more how Win2k gets around this .
2036 -- jerry */
2038 if (RA_WINNT == get_remote_arch()) {
2039 data->value = 0x02;
2040 } else {
2041 data->value = 0x03;
2044 return WERR_OK;
2047 if (!StrCaseCmp(value, "MinorVersion")) {
2048 *type = REG_DWORD;
2049 data->value = 0x00;
2050 return WERR_OK;
2053 /* REG_BINARY
2054 * uint32_t size = 0x114
2055 * uint32_t major = 5
2056 * uint32_t minor = [0|1]
2057 * uint32_t build = [2195|2600]
2058 * extra unicode string = e.g. "Service Pack 3"
2060 if (!StrCaseCmp(value, "OSVersion")) {
2061 DATA_BLOB blob;
2062 enum ndr_err_code ndr_err;
2063 struct spoolss_OSVersion os;
2065 os.major = 5; /* Windows 2000 == 5.0 */
2066 os.minor = 0;
2067 os.build = 2195; /* build */
2068 os.extra_string = ""; /* leave extra string empty */
2070 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2071 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2072 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2073 return WERR_GENERAL_FAILURE;
2076 *type = REG_BINARY;
2077 data->binary = blob;
2079 return WERR_OK;
2083 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2084 *type = REG_SZ;
2086 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2087 W_ERROR_HAVE_NO_MEMORY(data->string);
2089 return WERR_OK;
2092 if (!StrCaseCmp(value, "Architecture")) {
2093 *type = REG_SZ;
2094 data->string = talloc_strdup(mem_ctx,
2095 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2096 W_ERROR_HAVE_NO_MEMORY(data->string);
2098 return WERR_OK;
2101 if (!StrCaseCmp(value, "DsPresent")) {
2102 *type = REG_DWORD;
2104 /* only show the publish check box if we are a
2105 member of a AD domain */
2107 if (lp_security() == SEC_ADS) {
2108 data->value = 0x01;
2109 } else {
2110 data->value = 0x00;
2112 return WERR_OK;
2115 if (!StrCaseCmp(value, "DNSMachineName")) {
2116 const char *hostname = get_mydnsfullname();
2118 if (!hostname) {
2119 return WERR_BADFILE;
2122 *type = REG_SZ;
2123 data->string = talloc_strdup(mem_ctx, hostname);
2124 W_ERROR_HAVE_NO_MEMORY(data->string);
2126 return WERR_OK;
2129 *type = REG_NONE;
2131 return WERR_INVALID_PARAM;
2134 /****************************************************************
2135 _spoolss_GetPrinterData
2136 ****************************************************************/
2138 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2139 struct spoolss_GetPrinterData *r)
2141 struct spoolss_GetPrinterDataEx r2;
2143 r2.in.handle = r->in.handle;
2144 r2.in.key_name = "PrinterDriverData";
2145 r2.in.value_name = r->in.value_name;
2146 r2.in.offered = r->in.offered;
2147 r2.out.type = r->out.type;
2148 r2.out.data = r->out.data;
2149 r2.out.needed = r->out.needed;
2151 return _spoolss_GetPrinterDataEx(p, &r2);
2154 /*********************************************************
2155 Connect to the client machine.
2156 **********************************************************/
2158 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2159 struct sockaddr_storage *client_ss, const char *remote_machine)
2161 NTSTATUS ret;
2162 struct cli_state *the_cli;
2163 struct sockaddr_storage rm_addr;
2164 char addr[INET6_ADDRSTRLEN];
2166 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2167 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2168 remote_machine));
2169 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2170 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2171 return false;
2173 print_sockaddr(addr, sizeof(addr), &rm_addr);
2174 } else {
2175 rm_addr = *client_ss;
2176 print_sockaddr(addr, sizeof(addr), &rm_addr);
2177 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2178 addr));
2181 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2182 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2183 addr));
2184 return false;
2187 /* setup the connection */
2188 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2189 &rm_addr, 0, "IPC$", "IPC",
2190 "", /* username */
2191 "", /* domain */
2192 "", /* password */
2193 0, lp_client_signing(), NULL );
2195 if ( !NT_STATUS_IS_OK( ret ) ) {
2196 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2197 remote_machine ));
2198 return false;
2201 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2202 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2203 cli_shutdown(the_cli);
2204 return false;
2208 * Ok - we have an anonymous connection to the IPC$ share.
2209 * Now start the NT Domain stuff :-).
2212 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2213 if (!NT_STATUS_IS_OK(ret)) {
2214 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2215 remote_machine, nt_errstr(ret)));
2216 cli_shutdown(the_cli);
2217 return false;
2220 return true;
2223 /***************************************************************************
2224 Connect to the client.
2225 ****************************************************************************/
2227 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2228 uint32_t localprinter, uint32_t type,
2229 struct policy_handle *handle,
2230 struct sockaddr_storage *client_ss)
2232 WERROR result;
2233 NTSTATUS status;
2236 * If it's the first connection, contact the client
2237 * and connect to the IPC$ share anonymously
2239 if (smb_connections==0) {
2240 fstring unix_printer;
2242 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2244 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2245 return false;
2247 messaging_register(smbd_messaging_context(), NULL,
2248 MSG_PRINTER_NOTIFY2,
2249 receive_notify2_message_list);
2250 /* Tell the connections db we're now interested in printer
2251 * notify messages. */
2252 serverid_register_msg_flags(
2253 messaging_server_id(smbd_messaging_context()),
2254 true, FLAG_MSG_PRINT_NOTIFY);
2258 * Tell the specific printing tdb we want messages for this printer
2259 * by registering our PID.
2262 if (!print_notify_register_pid(snum))
2263 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2265 smb_connections++;
2267 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2268 printer,
2269 localprinter,
2270 type,
2272 NULL,
2273 handle,
2274 &result);
2275 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2276 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2277 win_errstr(result)));
2279 return (W_ERROR_IS_OK(result));
2282 /****************************************************************
2283 ****************************************************************/
2285 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2286 const struct spoolss_NotifyOption *r)
2288 struct spoolss_NotifyOption *option;
2289 uint32_t i,k;
2291 if (!r) {
2292 return NULL;
2295 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2296 if (!option) {
2297 return NULL;
2300 *option = *r;
2302 if (!option->count) {
2303 return option;
2306 option->types = talloc_zero_array(option,
2307 struct spoolss_NotifyOptionType, option->count);
2308 if (!option->types) {
2309 talloc_free(option);
2310 return NULL;
2313 for (i=0; i < option->count; i++) {
2314 option->types[i] = r->types[i];
2316 if (option->types[i].count) {
2317 option->types[i].fields = talloc_zero_array(option,
2318 union spoolss_Field, option->types[i].count);
2319 if (!option->types[i].fields) {
2320 talloc_free(option);
2321 return NULL;
2323 for (k=0; k<option->types[i].count; k++) {
2324 option->types[i].fields[k] =
2325 r->types[i].fields[k];
2330 return option;
2333 /****************************************************************
2334 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2336 * before replying OK: status=0 a rpc call is made to the workstation
2337 * asking ReplyOpenPrinter
2339 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2340 * called from api_spoolss_rffpcnex
2341 ****************************************************************/
2343 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2344 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2346 int snum = -1;
2347 struct spoolss_NotifyOption *option = r->in.notify_options;
2348 struct sockaddr_storage client_ss;
2350 /* store the notify value in the printer struct */
2352 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2354 if (!Printer) {
2355 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2356 "Invalid handle (%s:%u:%u).\n",
2357 OUR_HANDLE(r->in.handle)));
2358 return WERR_BADFID;
2361 Printer->notify.flags = r->in.flags;
2362 Printer->notify.options = r->in.options;
2363 Printer->notify.printerlocal = r->in.printer_local;
2365 TALLOC_FREE(Printer->notify.option);
2366 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2368 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2370 /* Connect to the client machine and send a ReplyOpenPrinter */
2372 if ( Printer->printer_type == SPLHND_SERVER)
2373 snum = -1;
2374 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2375 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2376 return WERR_BADFID;
2378 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2379 "client_address is %s\n", p->client_address));
2381 if (!interpret_string_addr(&client_ss, p->client_address,
2382 AI_NUMERICHOST)) {
2383 return WERR_SERVER_UNAVAILABLE;
2386 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2387 Printer->notify.printerlocal, 1,
2388 &Printer->notify.client_hnd, &client_ss))
2389 return WERR_SERVER_UNAVAILABLE;
2391 Printer->notify.client_connected = true;
2393 return WERR_OK;
2396 /*******************************************************************
2397 * fill a notify_info_data with the servername
2398 ********************************************************************/
2400 static void spoolss_notify_server_name(int snum,
2401 struct spoolss_Notify *data,
2402 print_queue_struct *queue,
2403 NT_PRINTER_INFO_LEVEL *printer,
2404 TALLOC_CTX *mem_ctx)
2406 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2409 /*******************************************************************
2410 * fill a notify_info_data with the printername (not including the servername).
2411 ********************************************************************/
2413 static void spoolss_notify_printer_name(int snum,
2414 struct spoolss_Notify *data,
2415 print_queue_struct *queue,
2416 NT_PRINTER_INFO_LEVEL *printer,
2417 TALLOC_CTX *mem_ctx)
2419 /* the notify name should not contain the \\server\ part */
2420 char *p = strrchr(printer->info_2->printername, '\\');
2422 if (!p) {
2423 p = printer->info_2->printername;
2424 } else {
2425 p++;
2428 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2431 /*******************************************************************
2432 * fill a notify_info_data with the servicename
2433 ********************************************************************/
2435 static void spoolss_notify_share_name(int snum,
2436 struct spoolss_Notify *data,
2437 print_queue_struct *queue,
2438 NT_PRINTER_INFO_LEVEL *printer,
2439 TALLOC_CTX *mem_ctx)
2441 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2444 /*******************************************************************
2445 * fill a notify_info_data with the port name
2446 ********************************************************************/
2448 static void spoolss_notify_port_name(int snum,
2449 struct spoolss_Notify *data,
2450 print_queue_struct *queue,
2451 NT_PRINTER_INFO_LEVEL *printer,
2452 TALLOC_CTX *mem_ctx)
2454 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2457 /*******************************************************************
2458 * fill a notify_info_data with the printername
2459 * but it doesn't exist, have to see what to do
2460 ********************************************************************/
2462 static void spoolss_notify_driver_name(int snum,
2463 struct spoolss_Notify *data,
2464 print_queue_struct *queue,
2465 NT_PRINTER_INFO_LEVEL *printer,
2466 TALLOC_CTX *mem_ctx)
2468 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2471 /*******************************************************************
2472 * fill a notify_info_data with the comment
2473 ********************************************************************/
2475 static void spoolss_notify_comment(int snum,
2476 struct spoolss_Notify *data,
2477 print_queue_struct *queue,
2478 NT_PRINTER_INFO_LEVEL *printer,
2479 TALLOC_CTX *mem_ctx)
2481 char *p;
2483 if (*printer->info_2->comment == '\0') {
2484 p = lp_comment(snum);
2485 } else {
2486 p = printer->info_2->comment;
2489 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2492 /*******************************************************************
2493 * fill a notify_info_data with the comment
2494 * location = "Room 1, floor 2, building 3"
2495 ********************************************************************/
2497 static void spoolss_notify_location(int snum,
2498 struct spoolss_Notify *data,
2499 print_queue_struct *queue,
2500 NT_PRINTER_INFO_LEVEL *printer,
2501 TALLOC_CTX *mem_ctx)
2503 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2506 /*******************************************************************
2507 * fill a notify_info_data with the device mode
2508 * jfm:xxxx don't to it for know but that's a real problem !!!
2509 ********************************************************************/
2511 static void spoolss_notify_devmode(int snum,
2512 struct spoolss_Notify *data,
2513 print_queue_struct *queue,
2514 NT_PRINTER_INFO_LEVEL *printer,
2515 TALLOC_CTX *mem_ctx)
2517 /* for a dummy implementation we have to zero the fields */
2518 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2521 /*******************************************************************
2522 * fill a notify_info_data with the separator file name
2523 ********************************************************************/
2525 static void spoolss_notify_sepfile(int snum,
2526 struct spoolss_Notify *data,
2527 print_queue_struct *queue,
2528 NT_PRINTER_INFO_LEVEL *printer,
2529 TALLOC_CTX *mem_ctx)
2531 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2534 /*******************************************************************
2535 * fill a notify_info_data with the print processor
2536 * jfm:xxxx return always winprint to indicate we don't do anything to it
2537 ********************************************************************/
2539 static void spoolss_notify_print_processor(int snum,
2540 struct spoolss_Notify *data,
2541 print_queue_struct *queue,
2542 NT_PRINTER_INFO_LEVEL *printer,
2543 TALLOC_CTX *mem_ctx)
2545 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2548 /*******************************************************************
2549 * fill a notify_info_data with the print processor options
2550 * jfm:xxxx send an empty string
2551 ********************************************************************/
2553 static void spoolss_notify_parameters(int snum,
2554 struct spoolss_Notify *data,
2555 print_queue_struct *queue,
2556 NT_PRINTER_INFO_LEVEL *printer,
2557 TALLOC_CTX *mem_ctx)
2559 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2562 /*******************************************************************
2563 * fill a notify_info_data with the data type
2564 * jfm:xxxx always send RAW as data type
2565 ********************************************************************/
2567 static void spoolss_notify_datatype(int snum,
2568 struct spoolss_Notify *data,
2569 print_queue_struct *queue,
2570 NT_PRINTER_INFO_LEVEL *printer,
2571 TALLOC_CTX *mem_ctx)
2573 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2576 /*******************************************************************
2577 * fill a notify_info_data with the security descriptor
2578 * jfm:xxxx send an null pointer to say no security desc
2579 * have to implement security before !
2580 ********************************************************************/
2582 static void spoolss_notify_security_desc(int snum,
2583 struct spoolss_Notify *data,
2584 print_queue_struct *queue,
2585 NT_PRINTER_INFO_LEVEL *printer,
2586 TALLOC_CTX *mem_ctx)
2588 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2589 printer->info_2->secdesc_buf->sd_size,
2590 printer->info_2->secdesc_buf->sd);
2593 /*******************************************************************
2594 * fill a notify_info_data with the attributes
2595 * jfm:xxxx a samba printer is always shared
2596 ********************************************************************/
2598 static void spoolss_notify_attributes(int snum,
2599 struct spoolss_Notify *data,
2600 print_queue_struct *queue,
2601 NT_PRINTER_INFO_LEVEL *printer,
2602 TALLOC_CTX *mem_ctx)
2604 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2607 /*******************************************************************
2608 * fill a notify_info_data with the priority
2609 ********************************************************************/
2611 static void spoolss_notify_priority(int snum,
2612 struct spoolss_Notify *data,
2613 print_queue_struct *queue,
2614 NT_PRINTER_INFO_LEVEL *printer,
2615 TALLOC_CTX *mem_ctx)
2617 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2620 /*******************************************************************
2621 * fill a notify_info_data with the default priority
2622 ********************************************************************/
2624 static void spoolss_notify_default_priority(int snum,
2625 struct spoolss_Notify *data,
2626 print_queue_struct *queue,
2627 NT_PRINTER_INFO_LEVEL *printer,
2628 TALLOC_CTX *mem_ctx)
2630 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2633 /*******************************************************************
2634 * fill a notify_info_data with the start time
2635 ********************************************************************/
2637 static void spoolss_notify_start_time(int snum,
2638 struct spoolss_Notify *data,
2639 print_queue_struct *queue,
2640 NT_PRINTER_INFO_LEVEL *printer,
2641 TALLOC_CTX *mem_ctx)
2643 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2646 /*******************************************************************
2647 * fill a notify_info_data with the until time
2648 ********************************************************************/
2650 static void spoolss_notify_until_time(int snum,
2651 struct spoolss_Notify *data,
2652 print_queue_struct *queue,
2653 NT_PRINTER_INFO_LEVEL *printer,
2654 TALLOC_CTX *mem_ctx)
2656 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2659 /*******************************************************************
2660 * fill a notify_info_data with the status
2661 ********************************************************************/
2663 static void spoolss_notify_status(int snum,
2664 struct spoolss_Notify *data,
2665 print_queue_struct *queue,
2666 NT_PRINTER_INFO_LEVEL *printer,
2667 TALLOC_CTX *mem_ctx)
2669 print_status_struct status;
2671 print_queue_length(snum, &status);
2672 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2675 /*******************************************************************
2676 * fill a notify_info_data with the number of jobs queued
2677 ********************************************************************/
2679 static void spoolss_notify_cjobs(int snum,
2680 struct spoolss_Notify *data,
2681 print_queue_struct *queue,
2682 NT_PRINTER_INFO_LEVEL *printer,
2683 TALLOC_CTX *mem_ctx)
2685 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2688 /*******************************************************************
2689 * fill a notify_info_data with the average ppm
2690 ********************************************************************/
2692 static void spoolss_notify_average_ppm(int snum,
2693 struct spoolss_Notify *data,
2694 print_queue_struct *queue,
2695 NT_PRINTER_INFO_LEVEL *printer,
2696 TALLOC_CTX *mem_ctx)
2698 /* always respond 8 pages per minutes */
2699 /* a little hard ! */
2700 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2703 /*******************************************************************
2704 * fill a notify_info_data with username
2705 ********************************************************************/
2707 static void spoolss_notify_username(int snum,
2708 struct spoolss_Notify *data,
2709 print_queue_struct *queue,
2710 NT_PRINTER_INFO_LEVEL *printer,
2711 TALLOC_CTX *mem_ctx)
2713 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2716 /*******************************************************************
2717 * fill a notify_info_data with job status
2718 ********************************************************************/
2720 static void spoolss_notify_job_status(int snum,
2721 struct spoolss_Notify *data,
2722 print_queue_struct *queue,
2723 NT_PRINTER_INFO_LEVEL *printer,
2724 TALLOC_CTX *mem_ctx)
2726 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2729 /*******************************************************************
2730 * fill a notify_info_data with job name
2731 ********************************************************************/
2733 static void spoolss_notify_job_name(int snum,
2734 struct spoolss_Notify *data,
2735 print_queue_struct *queue,
2736 NT_PRINTER_INFO_LEVEL *printer,
2737 TALLOC_CTX *mem_ctx)
2739 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2742 /*******************************************************************
2743 * fill a notify_info_data with job status
2744 ********************************************************************/
2746 static void spoolss_notify_job_status_string(int snum,
2747 struct spoolss_Notify *data,
2748 print_queue_struct *queue,
2749 NT_PRINTER_INFO_LEVEL *printer,
2750 TALLOC_CTX *mem_ctx)
2753 * Now we're returning job status codes we just return a "" here. JRA.
2756 const char *p = "";
2758 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2759 p = "unknown";
2761 switch (queue->status) {
2762 case LPQ_QUEUED:
2763 p = "Queued";
2764 break;
2765 case LPQ_PAUSED:
2766 p = ""; /* NT provides the paused string */
2767 break;
2768 case LPQ_SPOOLING:
2769 p = "Spooling";
2770 break;
2771 case LPQ_PRINTING:
2772 p = "Printing";
2773 break;
2775 #endif /* NO LONGER NEEDED. */
2777 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2780 /*******************************************************************
2781 * fill a notify_info_data with job time
2782 ********************************************************************/
2784 static void spoolss_notify_job_time(int snum,
2785 struct spoolss_Notify *data,
2786 print_queue_struct *queue,
2787 NT_PRINTER_INFO_LEVEL *printer,
2788 TALLOC_CTX *mem_ctx)
2790 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2793 /*******************************************************************
2794 * fill a notify_info_data with job size
2795 ********************************************************************/
2797 static void spoolss_notify_job_size(int snum,
2798 struct spoolss_Notify *data,
2799 print_queue_struct *queue,
2800 NT_PRINTER_INFO_LEVEL *printer,
2801 TALLOC_CTX *mem_ctx)
2803 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2806 /*******************************************************************
2807 * fill a notify_info_data with page info
2808 ********************************************************************/
2809 static void spoolss_notify_total_pages(int snum,
2810 struct spoolss_Notify *data,
2811 print_queue_struct *queue,
2812 NT_PRINTER_INFO_LEVEL *printer,
2813 TALLOC_CTX *mem_ctx)
2815 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2818 /*******************************************************************
2819 * fill a notify_info_data with pages printed info.
2820 ********************************************************************/
2821 static void spoolss_notify_pages_printed(int snum,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 NT_PRINTER_INFO_LEVEL *printer,
2825 TALLOC_CTX *mem_ctx)
2827 /* Add code when back-end tracks this */
2828 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2831 /*******************************************************************
2832 Fill a notify_info_data with job position.
2833 ********************************************************************/
2835 static void spoolss_notify_job_position(int snum,
2836 struct spoolss_Notify *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2841 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2844 /*******************************************************************
2845 Fill a notify_info_data with submitted time.
2846 ********************************************************************/
2848 static void spoolss_notify_submitted_time(int snum,
2849 struct spoolss_Notify *data,
2850 print_queue_struct *queue,
2851 NT_PRINTER_INFO_LEVEL *printer,
2852 TALLOC_CTX *mem_ctx)
2854 data->data.string.string = NULL;
2855 data->data.string.size = 0;
2857 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2858 &data->data.string.string,
2859 &data->data.string.size);
2863 struct s_notify_info_data_table
2865 enum spoolss_NotifyType type;
2866 uint16_t field;
2867 const char *name;
2868 enum spoolss_NotifyTable variable_type;
2869 void (*fn) (int snum, struct spoolss_Notify *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2874 /* A table describing the various print notification constants and
2875 whether the notification data is a pointer to a variable sized
2876 buffer, a one value uint32_t or a two value uint32_t. */
2878 static const struct s_notify_info_data_table notify_info_data_table[] =
2880 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2881 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2882 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2883 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2884 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2885 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2886 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2887 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2888 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2889 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2890 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2891 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2892 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2893 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2894 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2895 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2896 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2897 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2898 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2899 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2900 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
2901 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
2902 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
2903 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2904 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
2905 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2906 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2907 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2908 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2909 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2910 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2911 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2912 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2913 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2914 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2915 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2916 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
2917 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
2918 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
2919 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
2920 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2921 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
2922 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
2923 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2924 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2925 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
2926 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
2927 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
2928 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
2931 /*******************************************************************
2932 Return the variable_type of info_data structure.
2933 ********************************************************************/
2935 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
2936 uint16_t field)
2938 int i=0;
2940 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
2941 if ( (notify_info_data_table[i].type == type) &&
2942 (notify_info_data_table[i].field == field) ) {
2943 return notify_info_data_table[i].variable_type;
2947 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2949 return 0;
2952 /****************************************************************************
2953 ****************************************************************************/
2955 static bool search_notify(enum spoolss_NotifyType type,
2956 uint16_t field,
2957 int *value)
2959 int i;
2961 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
2962 if (notify_info_data_table[i].type == type &&
2963 notify_info_data_table[i].field == field &&
2964 notify_info_data_table[i].fn != NULL) {
2965 *value = i;
2966 return true;
2970 return false;
2973 /****************************************************************************
2974 ****************************************************************************/
2976 void construct_info_data(struct spoolss_Notify *info_data,
2977 enum spoolss_NotifyType type,
2978 uint16_t field,
2979 int id)
2981 info_data->type = type;
2982 info_data->field.field = field;
2983 info_data->variable_type = variable_type_of_notify_info_data(type, field);
2984 info_data->job_id = id;
2987 /*******************************************************************
2989 * fill a notify_info struct with info asked
2991 ********************************************************************/
2993 static bool construct_notify_printer_info(Printer_entry *print_hnd,
2994 struct spoolss_NotifyInfo *info,
2995 int snum,
2996 const struct spoolss_NotifyOptionType *option_type,
2997 uint32_t id,
2998 TALLOC_CTX *mem_ctx)
3000 int field_num,j;
3001 enum spoolss_NotifyType type;
3002 uint16_t field;
3004 struct spoolss_Notify *current_data;
3005 NT_PRINTER_INFO_LEVEL *printer = NULL;
3006 print_queue_struct *queue=NULL;
3008 type = option_type->type;
3010 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3011 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3012 option_type->count, lp_servicename(snum)));
3014 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3015 return false;
3017 for(field_num=0; field_num < option_type->count; field_num++) {
3018 field = option_type->fields[field_num].field;
3020 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3022 if (!search_notify(type, field, &j) )
3023 continue;
3025 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3026 struct spoolss_Notify,
3027 info->count + 1);
3028 if (info->notifies == NULL) {
3029 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3030 free_a_printer(&printer, 2);
3031 return false;
3034 current_data = &info->notifies[info->count];
3036 construct_info_data(current_data, type, field, id);
3038 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3039 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3041 notify_info_data_table[j].fn(snum, current_data, queue,
3042 printer, mem_ctx);
3044 info->count++;
3047 free_a_printer(&printer, 2);
3048 return true;
3051 /*******************************************************************
3053 * fill a notify_info struct with info asked
3055 ********************************************************************/
3057 static bool construct_notify_jobs_info(print_queue_struct *queue,
3058 struct spoolss_NotifyInfo *info,
3059 NT_PRINTER_INFO_LEVEL *printer,
3060 int snum,
3061 const struct spoolss_NotifyOptionType *option_type,
3062 uint32_t id,
3063 TALLOC_CTX *mem_ctx)
3065 int field_num,j;
3066 enum spoolss_NotifyType type;
3067 uint16_t field;
3068 struct spoolss_Notify *current_data;
3070 DEBUG(4,("construct_notify_jobs_info\n"));
3072 type = option_type->type;
3074 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3075 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3076 option_type->count));
3078 for(field_num=0; field_num<option_type->count; field_num++) {
3079 field = option_type->fields[field_num].field;
3081 if (!search_notify(type, field, &j) )
3082 continue;
3084 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3085 struct spoolss_Notify,
3086 info->count + 1);
3087 if (info->notifies == NULL) {
3088 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3089 return false;
3092 current_data=&(info->notifies[info->count]);
3094 construct_info_data(current_data, type, field, id);
3095 notify_info_data_table[j].fn(snum, current_data, queue,
3096 printer, mem_ctx);
3097 info->count++;
3100 return true;
3104 * JFM: The enumeration is not that simple, it's even non obvious.
3106 * let's take an example: I want to monitor the PRINTER SERVER for
3107 * the printer's name and the number of jobs currently queued.
3108 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3109 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3111 * I have 3 printers on the back of my server.
3113 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3114 * structures.
3115 * Number Data Id
3116 * 1 printer 1 name 1
3117 * 2 printer 1 cjob 1
3118 * 3 printer 2 name 2
3119 * 4 printer 2 cjob 2
3120 * 5 printer 3 name 3
3121 * 6 printer 3 name 3
3123 * that's the print server case, the printer case is even worse.
3126 /*******************************************************************
3128 * enumerate all printers on the printserver
3129 * fill a notify_info struct with info asked
3131 ********************************************************************/
3133 static WERROR printserver_notify_info(pipes_struct *p,
3134 struct policy_handle *hnd,
3135 struct spoolss_NotifyInfo *info,
3136 TALLOC_CTX *mem_ctx)
3138 int snum;
3139 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3140 int n_services=lp_numservices();
3141 int i;
3142 struct spoolss_NotifyOption *option;
3143 struct spoolss_NotifyOptionType option_type;
3145 DEBUG(4,("printserver_notify_info\n"));
3147 if (!Printer)
3148 return WERR_BADFID;
3150 option = Printer->notify.option;
3152 info->version = 2;
3153 info->notifies = NULL;
3154 info->count = 0;
3156 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3157 sending a ffpcn() request first */
3159 if ( !option )
3160 return WERR_BADFID;
3162 for (i=0; i<option->count; i++) {
3163 option_type = option->types[i];
3165 if (option_type.type != PRINTER_NOTIFY_TYPE)
3166 continue;
3168 for (snum=0; snum<n_services; snum++)
3170 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3171 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3175 #if 0
3177 * Debugging information, don't delete.
3180 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3181 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3182 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3184 for (i=0; i<info->count; i++) {
3185 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3186 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3187 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3189 #endif
3191 return WERR_OK;
3194 /*******************************************************************
3196 * fill a notify_info struct with info asked
3198 ********************************************************************/
3200 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3201 struct spoolss_NotifyInfo *info,
3202 TALLOC_CTX *mem_ctx)
3204 int snum;
3205 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3206 int i;
3207 uint32_t id;
3208 struct spoolss_NotifyOption *option;
3209 struct spoolss_NotifyOptionType option_type;
3210 int count,j;
3211 print_queue_struct *queue=NULL;
3212 print_status_struct status;
3214 DEBUG(4,("printer_notify_info\n"));
3216 if (!Printer)
3217 return WERR_BADFID;
3219 option = Printer->notify.option;
3220 id = 0x0;
3222 info->version = 2;
3223 info->notifies = NULL;
3224 info->count = 0;
3226 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3227 sending a ffpcn() request first */
3229 if ( !option )
3230 return WERR_BADFID;
3232 get_printer_snum(p, hnd, &snum, NULL);
3234 for (i=0; i<option->count; i++) {
3235 option_type = option->types[i];
3237 switch (option_type.type) {
3238 case PRINTER_NOTIFY_TYPE:
3239 if(construct_notify_printer_info(Printer, info, snum,
3240 &option_type, id,
3241 mem_ctx))
3242 id--;
3243 break;
3245 case JOB_NOTIFY_TYPE: {
3246 NT_PRINTER_INFO_LEVEL *printer = NULL;
3248 count = print_queue_status(snum, &queue, &status);
3250 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3251 goto done;
3253 for (j=0; j<count; j++) {
3254 construct_notify_jobs_info(&queue[j], info,
3255 printer, snum,
3256 &option_type,
3257 queue[j].job,
3258 mem_ctx);
3261 free_a_printer(&printer, 2);
3263 done:
3264 SAFE_FREE(queue);
3265 break;
3271 * Debugging information, don't delete.
3274 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3275 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3276 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3278 for (i=0; i<info->count; i++) {
3279 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3280 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3281 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3284 return WERR_OK;
3287 /****************************************************************
3288 _spoolss_RouterRefreshPrinterChangeNotify
3289 ****************************************************************/
3291 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3292 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3294 struct spoolss_NotifyInfo *info;
3296 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3297 WERROR result = WERR_BADFID;
3299 /* we always have a spoolss_NotifyInfo struct */
3300 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3301 if (!info) {
3302 result = WERR_NOMEM;
3303 goto done;
3306 *r->out.info = info;
3308 if (!Printer) {
3309 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3310 "Invalid handle (%s:%u:%u).\n",
3311 OUR_HANDLE(r->in.handle)));
3312 goto done;
3315 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3318 * We are now using the change value, and
3319 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3320 * I don't have a global notification system, I'm sending back all the
3321 * informations even when _NOTHING_ has changed.
3324 /* We need to keep track of the change value to send back in
3325 RRPCN replies otherwise our updates are ignored. */
3327 Printer->notify.fnpcn = true;
3329 if (Printer->notify.client_connected) {
3330 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3331 "Saving change value in request [%x]\n",
3332 r->in.change_low));
3333 Printer->notify.change = r->in.change_low;
3336 /* just ignore the spoolss_NotifyOption */
3338 switch (Printer->printer_type) {
3339 case SPLHND_SERVER:
3340 result = printserver_notify_info(p, r->in.handle,
3341 info, p->mem_ctx);
3342 break;
3344 case SPLHND_PRINTER:
3345 result = printer_notify_info(p, r->in.handle,
3346 info, p->mem_ctx);
3347 break;
3350 Printer->notify.fnpcn = false;
3352 done:
3353 return result;
3356 /********************************************************************
3357 * construct_printer_info_0
3358 * fill a printer_info_0 struct
3359 ********************************************************************/
3361 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3362 struct auth_serversupplied_info *server_info,
3363 struct spoolss_PrinterInfo2 *info2,
3364 struct spoolss_PrinterInfo0 *r,
3365 int snum)
3367 int count;
3368 counter_printer_0 *session_counter;
3369 struct timeval setuptime;
3370 print_status_struct status;
3372 r->printername = talloc_strdup(mem_ctx, info2->printername);
3373 W_ERROR_HAVE_NO_MEMORY(r->printername);
3375 r->servername = talloc_strdup(mem_ctx, info2->servername);
3376 W_ERROR_HAVE_NO_MEMORY(r->servername);
3378 count = print_queue_length(snum, &status);
3380 /* check if we already have a counter for this printer */
3381 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3382 if (session_counter->snum == snum)
3383 break;
3386 /* it's the first time, add it to the list */
3387 if (session_counter == NULL) {
3388 session_counter = SMB_MALLOC_P(counter_printer_0);
3389 W_ERROR_HAVE_NO_MEMORY(session_counter);
3390 ZERO_STRUCTP(session_counter);
3391 session_counter->snum = snum;
3392 session_counter->counter = 0;
3393 DLIST_ADD(counter_list, session_counter);
3396 /* increment it */
3397 session_counter->counter++;
3399 r->cjobs = count;
3400 r->total_jobs = 0;
3401 r->total_bytes = 0;
3403 get_startup_time(&setuptime);
3404 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3406 /* JFM:
3407 * the global_counter should be stored in a TDB as it's common to all the clients
3408 * and should be zeroed on samba startup
3410 r->global_counter = session_counter->counter;
3411 r->total_pages = 0;
3412 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3413 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3414 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3415 r->free_build = SPOOLSS_RELEASE_BUILD;
3416 r->spooling = 0;
3417 r->max_spooling = 0;
3418 r->session_counter = session_counter->counter;
3419 r->num_error_out_of_paper = 0x0;
3420 r->num_error_not_ready = 0x0; /* number of print failure */
3421 r->job_error = 0x0;
3422 r->number_of_processors = 0x1;
3423 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3424 r->high_part_total_bytes = 0x0;
3425 winreg_printer_get_changeid(mem_ctx, server_info, info2->sharename, &r->change_id); /* ChangeID in milliseconds*/
3426 r->last_error = WERR_OK;
3427 r->status = nt_printq_status(status.status);
3428 r->enumerate_network_printers = 0x0;
3429 r->c_setprinter = 0x0;
3430 r->processor_architecture = 0x0;
3431 r->processor_level = 0x6; /* 6 ???*/
3432 r->ref_ic = 0;
3433 r->reserved2 = 0;
3434 r->reserved3 = 0;
3436 return WERR_OK;
3440 /****************************************************************************
3441 Create a spoolss_DeviceMode struct. Returns talloced memory.
3442 ****************************************************************************/
3444 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3445 const char *servicename)
3447 NT_PRINTER_INFO_LEVEL *printer = NULL;
3448 struct spoolss_DeviceMode *devmode = NULL;
3450 DEBUG(7,("construct_dev_mode\n"));
3452 DEBUGADD(8,("getting printer characteristics\n"));
3454 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3455 return NULL;
3457 if (!printer->info_2->devmode) {
3458 DEBUG(5, ("BONG! There was no device mode!\n"));
3459 goto done;
3462 devmode = talloc_steal(mem_ctx, printer->info_2->devmode);
3464 done:
3465 free_a_printer(&printer,2);
3467 return devmode;
3470 /********************************************************************
3471 * construct_printer_info1
3472 * fill a spoolss_PrinterInfo1 struct
3473 ********************************************************************/
3475 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3476 const struct spoolss_PrinterInfo2 *info2,
3477 uint32_t flags,
3478 struct spoolss_PrinterInfo1 *r,
3479 int snum)
3481 r->flags = flags;
3483 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3484 info2->printername,
3485 info2->drivername,
3486 info2->location);
3487 W_ERROR_HAVE_NO_MEMORY(r->description);
3489 if (info2->comment == NULL || info2->comment[0] == '\0') {
3490 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3491 } else {
3492 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3494 W_ERROR_HAVE_NO_MEMORY(r->comment);
3496 r->name = talloc_strdup(mem_ctx, info2->printername);
3497 W_ERROR_HAVE_NO_MEMORY(r->name);
3499 return WERR_OK;
3502 /********************************************************************
3503 * construct_printer_info2
3504 * fill a spoolss_PrinterInfo2 struct
3505 ********************************************************************/
3507 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3508 const struct spoolss_PrinterInfo2 *info2,
3509 struct spoolss_PrinterInfo2 *r,
3510 int snum)
3512 int count;
3513 print_status_struct status;
3515 count = print_queue_length(snum, &status);
3517 r->servername = talloc_strdup(mem_ctx, info2->servername);
3518 W_ERROR_HAVE_NO_MEMORY(r->servername);
3519 r->printername = talloc_strdup(mem_ctx, info2->printername);
3520 W_ERROR_HAVE_NO_MEMORY(r->printername);
3521 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3522 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3523 r->portname = talloc_strdup(mem_ctx, info2->portname);
3524 W_ERROR_HAVE_NO_MEMORY(r->portname);
3525 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3526 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3528 if (info2->comment[0] == '\0') {
3529 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3530 } else {
3531 r->comment = talloc_strdup(mem_ctx, info2->comment);
3533 W_ERROR_HAVE_NO_MEMORY(r->comment);
3535 r->location = talloc_strdup(mem_ctx, info2->location);
3536 W_ERROR_HAVE_NO_MEMORY(r->location);
3537 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
3538 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3539 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
3540 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3541 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
3542 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3543 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
3544 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3546 r->attributes = info2->attributes;
3548 r->priority = info2->priority;
3549 r->defaultpriority = info2->defaultpriority;
3550 r->starttime = info2->starttime;
3551 r->untiltime = info2->untiltime;
3552 r->status = nt_printq_status(status.status);
3553 r->cjobs = count;
3554 r->averageppm = info2->averageppm;
3556 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3557 if (!r->devmode) {
3558 DEBUG(8,("Returning NULL Devicemode!\n"));
3561 r->secdesc = NULL;
3563 if (info2->secdesc != NULL) {
3564 /* don't use talloc_steal() here unless you do a deep steal of all
3565 the SEC_DESC members */
3567 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3570 return WERR_OK;
3573 /********************************************************************
3574 * construct_printer_info3
3575 * fill a spoolss_PrinterInfo3 struct
3576 ********************************************************************/
3578 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3579 const struct spoolss_PrinterInfo2 *info2,
3580 struct spoolss_PrinterInfo3 *r,
3581 int snum)
3583 /* These are the components of the SD we are returning. */
3585 if (info2->secdesc != NULL) {
3586 /* don't use talloc_steal() here unless you do a deep steal of all
3587 the SEC_DESC members */
3589 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3590 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3593 return WERR_OK;
3596 /********************************************************************
3597 * construct_printer_info4
3598 * fill a spoolss_PrinterInfo4 struct
3599 ********************************************************************/
3601 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3602 const struct spoolss_PrinterInfo2 *info2,
3603 struct spoolss_PrinterInfo4 *r,
3604 int snum)
3606 r->printername = talloc_strdup(mem_ctx, info2->printername);
3607 W_ERROR_HAVE_NO_MEMORY(r->printername);
3608 r->servername = talloc_strdup(mem_ctx, info2->servername);
3609 W_ERROR_HAVE_NO_MEMORY(r->servername);
3611 r->attributes = info2->attributes;
3613 return WERR_OK;
3616 /********************************************************************
3617 * construct_printer_info5
3618 * fill a spoolss_PrinterInfo5 struct
3619 ********************************************************************/
3621 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3622 const struct spoolss_PrinterInfo2 *info2,
3623 struct spoolss_PrinterInfo5 *r,
3624 int snum)
3626 r->printername = talloc_strdup(mem_ctx, info2->printername);
3627 W_ERROR_HAVE_NO_MEMORY(r->printername);
3628 r->portname = talloc_strdup(mem_ctx, info2->portname);
3629 W_ERROR_HAVE_NO_MEMORY(r->portname);
3631 r->attributes = info2->attributes;
3633 /* these two are not used by NT+ according to MSDN */
3634 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3635 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3637 return WERR_OK;
3640 /********************************************************************
3641 * construct_printer_info_6
3642 * fill a spoolss_PrinterInfo6 struct
3643 ********************************************************************/
3645 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3646 const struct spoolss_PrinterInfo2 *info2,
3647 struct spoolss_PrinterInfo6 *r,
3648 int snum)
3650 int count;
3651 print_status_struct status;
3653 count = print_queue_length(snum, &status);
3655 r->status = nt_printq_status(status.status);
3657 return WERR_OK;
3660 /********************************************************************
3661 * construct_printer_info7
3662 * fill a spoolss_PrinterInfo7 struct
3663 ********************************************************************/
3665 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3666 Printer_entry *print_hnd,
3667 struct spoolss_PrinterInfo7 *r,
3668 int snum)
3670 struct GUID guid;
3672 if (is_printer_published(print_hnd, snum, &guid)) {
3673 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3674 r->action = DSPRINT_PUBLISH;
3675 } else {
3676 r->guid = talloc_strdup(mem_ctx, "");
3677 r->action = DSPRINT_UNPUBLISH;
3679 W_ERROR_HAVE_NO_MEMORY(r->guid);
3681 return WERR_OK;
3684 /********************************************************************
3685 * construct_printer_info8
3686 * fill a spoolss_PrinterInfo8 struct
3687 ********************************************************************/
3689 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3690 const struct spoolss_PrinterInfo2 *info2,
3691 struct spoolss_DeviceModeInfo *r,
3692 int snum)
3694 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3695 if (!r->devmode) {
3696 DEBUG(8,("Returning NULL Devicemode!\n"));
3699 return WERR_OK;
3703 /********************************************************************
3704 ********************************************************************/
3706 static bool snum_is_shared_printer(int snum)
3708 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3711 /********************************************************************
3712 Spoolss_enumprinters.
3713 ********************************************************************/
3715 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3716 struct auth_serversupplied_info *server_info,
3717 uint32_t level,
3718 uint32_t flags,
3719 union spoolss_PrinterInfo **info_p,
3720 uint32_t *count_p)
3722 int snum;
3723 int n_services = lp_numservices();
3724 union spoolss_PrinterInfo *info = NULL;
3725 uint32_t count = 0;
3726 WERROR result = WERR_OK;
3728 *count_p = 0;
3729 *info_p = NULL;
3731 for (snum = 0; snum < n_services; snum++) {
3733 const char *printer;
3734 struct spoolss_PrinterInfo2 *info2;
3736 if (!snum_is_shared_printer(snum)) {
3737 continue;
3740 printer = lp_const_servicename(snum);
3742 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3743 printer, snum));
3745 result = winreg_create_printer(mem_ctx,
3746 server_info,
3747 NULL,
3748 printer);
3749 if (!W_ERROR_IS_OK(result)) {
3750 goto out;
3753 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3754 union spoolss_PrinterInfo,
3755 count + 1);
3756 if (!info) {
3757 result = WERR_NOMEM;
3758 goto out;
3761 result = winreg_get_printer(mem_ctx, server_info,
3762 NULL, printer, &info2);
3763 if (!W_ERROR_IS_OK(result)) {
3764 goto out;
3767 switch (level) {
3768 case 0:
3769 result = construct_printer_info0(info, server_info, info2,
3770 &info[count].info0, snum);
3771 break;
3772 case 1:
3773 result = construct_printer_info1(info, info2, flags,
3774 &info[count].info1, snum);
3775 break;
3776 case 2:
3777 result = construct_printer_info2(info, info2,
3778 &info[count].info2, snum);
3779 break;
3780 case 4:
3781 result = construct_printer_info4(info, info2,
3782 &info[count].info4, snum);
3783 break;
3784 case 5:
3785 result = construct_printer_info5(info, info2,
3786 &info[count].info5, snum);
3787 break;
3789 default:
3790 result = WERR_UNKNOWN_LEVEL;
3791 goto out;
3794 if (!W_ERROR_IS_OK(result)) {
3795 goto out;
3798 count++;
3801 *count_p = count;
3802 *info_p = info;
3804 out:
3805 if (!W_ERROR_IS_OK(result)) {
3806 TALLOC_FREE(info);
3807 return result;
3810 *info_p = info;
3812 return WERR_OK;
3815 /********************************************************************
3816 * handle enumeration of printers at level 0
3817 ********************************************************************/
3819 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3820 struct auth_serversupplied_info *server_info,
3821 uint32_t flags,
3822 const char *servername,
3823 union spoolss_PrinterInfo **info,
3824 uint32_t *count)
3826 DEBUG(4,("enum_all_printers_info_0\n"));
3828 return enum_all_printers_info_level(mem_ctx, server_info, 0, flags, info, count);
3832 /********************************************************************
3833 ********************************************************************/
3835 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3836 struct auth_serversupplied_info *server_info,
3837 uint32_t flags,
3838 union spoolss_PrinterInfo **info,
3839 uint32_t *count)
3841 DEBUG(4,("enum_all_printers_info_1\n"));
3843 return enum_all_printers_info_level(mem_ctx, server_info, 1, flags, info, count);
3846 /********************************************************************
3847 enum_all_printers_info_1_local.
3848 *********************************************************************/
3850 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3851 struct auth_serversupplied_info *server_info,
3852 union spoolss_PrinterInfo **info,
3853 uint32_t *count)
3855 DEBUG(4,("enum_all_printers_info_1_local\n"));
3857 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3860 /********************************************************************
3861 enum_all_printers_info_1_name.
3862 *********************************************************************/
3864 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3865 struct auth_serversupplied_info *server_info,
3866 const char *name,
3867 union spoolss_PrinterInfo **info,
3868 uint32_t *count)
3870 const char *s = name;
3872 DEBUG(4,("enum_all_printers_info_1_name\n"));
3874 if ((name[0] == '\\') && (name[1] == '\\')) {
3875 s = name + 2;
3878 if (!is_myname_or_ipaddr(s)) {
3879 return WERR_INVALID_NAME;
3882 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3885 /********************************************************************
3886 enum_all_printers_info_1_network.
3887 *********************************************************************/
3889 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3890 struct auth_serversupplied_info *server_info,
3891 const char *name,
3892 union spoolss_PrinterInfo **info,
3893 uint32_t *count)
3895 const char *s = name;
3897 DEBUG(4,("enum_all_printers_info_1_network\n"));
3899 /* If we respond to a enum_printers level 1 on our name with flags
3900 set to PRINTER_ENUM_REMOTE with a list of printers then these
3901 printers incorrectly appear in the APW browse list.
3902 Specifically the printers for the server appear at the workgroup
3903 level where all the other servers in the domain are
3904 listed. Windows responds to this call with a
3905 WERR_CAN_NOT_COMPLETE so we should do the same. */
3907 if (name[0] == '\\' && name[1] == '\\') {
3908 s = name + 2;
3911 if (is_myname_or_ipaddr(s)) {
3912 return WERR_CAN_NOT_COMPLETE;
3915 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_NAME, info, count);
3918 /********************************************************************
3919 * api_spoolss_enumprinters
3921 * called from api_spoolss_enumprinters (see this to understand)
3922 ********************************************************************/
3924 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3925 struct auth_serversupplied_info *server_info,
3926 union spoolss_PrinterInfo **info,
3927 uint32_t *count)
3929 DEBUG(4,("enum_all_printers_info_2\n"));
3931 return enum_all_printers_info_level(mem_ctx, server_info, 2, 0, info, count);
3934 /********************************************************************
3935 * handle enumeration of printers at level 1
3936 ********************************************************************/
3938 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3939 struct auth_serversupplied_info *server_info,
3940 uint32_t flags,
3941 const char *name,
3942 union spoolss_PrinterInfo **info,
3943 uint32_t *count)
3945 /* Not all the flags are equals */
3947 if (flags & PRINTER_ENUM_LOCAL) {
3948 return enum_all_printers_info_1_local(mem_ctx, server_info, info, count);
3951 if (flags & PRINTER_ENUM_NAME) {
3952 return enum_all_printers_info_1_name(mem_ctx, server_info, name, info, count);
3955 if (flags & PRINTER_ENUM_NETWORK) {
3956 return enum_all_printers_info_1_network(mem_ctx, server_info, name, info, count);
3959 return WERR_OK; /* NT4sp5 does that */
3962 /********************************************************************
3963 * handle enumeration of printers at level 2
3964 ********************************************************************/
3966 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
3967 struct auth_serversupplied_info *server_info,
3968 uint32_t flags,
3969 const char *servername,
3970 union spoolss_PrinterInfo **info,
3971 uint32_t *count)
3973 if (flags & PRINTER_ENUM_LOCAL) {
3974 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
3977 if (flags & PRINTER_ENUM_NAME) {
3978 if (!is_myname_or_ipaddr(canon_servername(servername))) {
3979 return WERR_INVALID_NAME;
3982 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
3985 if (flags & PRINTER_ENUM_REMOTE) {
3986 return WERR_UNKNOWN_LEVEL;
3989 return WERR_OK;
3992 /********************************************************************
3993 * handle enumeration of printers at level 4
3994 ********************************************************************/
3996 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
3997 struct auth_serversupplied_info *server_info,
3998 uint32_t flags,
3999 const char *servername,
4000 union spoolss_PrinterInfo **info,
4001 uint32_t *count)
4003 DEBUG(4,("enum_all_printers_info_4\n"));
4005 return enum_all_printers_info_level(mem_ctx, server_info, 4, flags, info, count);
4009 /********************************************************************
4010 * handle enumeration of printers at level 5
4011 ********************************************************************/
4013 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4014 struct auth_serversupplied_info *server_info,
4015 uint32_t flags,
4016 const char *servername,
4017 union spoolss_PrinterInfo **info,
4018 uint32_t *count)
4020 DEBUG(4,("enum_all_printers_info_5\n"));
4022 return enum_all_printers_info_level(mem_ctx, server_info, 5, flags, info, count);
4025 /****************************************************************
4026 _spoolss_EnumPrinters
4027 ****************************************************************/
4029 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4030 struct spoolss_EnumPrinters *r)
4032 const char *name = NULL;
4033 WERROR result;
4035 /* that's an [in out] buffer */
4037 if (!r->in.buffer && (r->in.offered != 0)) {
4038 return WERR_INVALID_PARAM;
4041 DEBUG(4,("_spoolss_EnumPrinters\n"));
4043 *r->out.needed = 0;
4044 *r->out.count = 0;
4045 *r->out.info = NULL;
4048 * Level 1:
4049 * flags==PRINTER_ENUM_NAME
4050 * if name=="" then enumerates all printers
4051 * if name!="" then enumerate the printer
4052 * flags==PRINTER_ENUM_REMOTE
4053 * name is NULL, enumerate printers
4054 * Level 2: name!="" enumerates printers, name can't be NULL
4055 * Level 3: doesn't exist
4056 * Level 4: does a local registry lookup
4057 * Level 5: same as Level 2
4060 if (r->in.server) {
4061 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4062 W_ERROR_HAVE_NO_MEMORY(name);
4065 switch (r->in.level) {
4066 case 0:
4067 result = enumprinters_level0(p->mem_ctx, p->server_info,
4068 r->in.flags, name,
4069 r->out.info, r->out.count);
4070 break;
4071 case 1:
4072 result = enumprinters_level1(p->mem_ctx, p->server_info,
4073 r->in.flags, name,
4074 r->out.info, r->out.count);
4075 break;
4076 case 2:
4077 result = enumprinters_level2(p->mem_ctx, p->server_info,
4078 r->in.flags, name,
4079 r->out.info, r->out.count);
4080 break;
4081 case 4:
4082 result = enumprinters_level4(p->mem_ctx, p->server_info,
4083 r->in.flags, name,
4084 r->out.info, r->out.count);
4085 break;
4086 case 5:
4087 result = enumprinters_level5(p->mem_ctx, p->server_info,
4088 r->in.flags, name,
4089 r->out.info, r->out.count);
4090 break;
4091 default:
4092 return WERR_UNKNOWN_LEVEL;
4095 if (!W_ERROR_IS_OK(result)) {
4096 return result;
4099 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4100 spoolss_EnumPrinters,
4101 *r->out.info, r->in.level,
4102 *r->out.count);
4103 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4104 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4106 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4109 /****************************************************************
4110 _spoolss_GetPrinter
4111 ****************************************************************/
4113 WERROR _spoolss_GetPrinter(pipes_struct *p,
4114 struct spoolss_GetPrinter *r)
4116 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4117 struct spoolss_PrinterInfo2 *info2 = NULL;
4118 WERROR result = WERR_OK;
4119 const char *servername = NULL;
4120 int snum;
4122 /* that's an [in out] buffer */
4124 if (!r->in.buffer && (r->in.offered != 0)) {
4125 return WERR_INVALID_PARAM;
4128 *r->out.needed = 0;
4130 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4131 return WERR_BADFID;
4134 if (Printer != NULL || Printer->servername != NULL) {
4135 servername = Printer->servername;
4138 result = winreg_get_printer(p->mem_ctx,
4139 p->server_info,
4140 servername,
4141 lp_const_servicename(snum),
4142 &info2);
4143 if (!W_ERROR_IS_OK(result)) {
4144 return result;
4147 switch (r->in.level) {
4148 case 0:
4149 result = construct_printer_info0(p->mem_ctx, p->server_info,
4150 info2,
4151 &r->out.info->info0, snum);
4152 break;
4153 case 1:
4154 result = construct_printer_info1(p->mem_ctx, info2,
4155 PRINTER_ENUM_ICON8,
4156 &r->out.info->info1, snum);
4157 break;
4158 case 2:
4159 result = construct_printer_info2(p->mem_ctx, info2,
4160 &r->out.info->info2, snum);
4161 break;
4162 case 3:
4163 result = construct_printer_info3(p->mem_ctx, info2,
4164 &r->out.info->info3, snum);
4165 break;
4166 case 4:
4167 result = construct_printer_info4(p->mem_ctx, info2,
4168 &r->out.info->info4, snum);
4169 break;
4170 case 5:
4171 result = construct_printer_info5(p->mem_ctx, info2,
4172 &r->out.info->info5, snum);
4173 break;
4174 case 6:
4175 result = construct_printer_info6(p->mem_ctx, info2,
4176 &r->out.info->info6, snum);
4177 break;
4178 case 7:
4179 result = construct_printer_info7(p->mem_ctx, Printer,
4180 &r->out.info->info7, snum);
4181 break;
4182 case 8:
4183 result = construct_printer_info8(p->mem_ctx, info2,
4184 &r->out.info->info8, snum);
4185 break;
4186 default:
4187 result = WERR_UNKNOWN_LEVEL;
4188 break;
4191 if (!W_ERROR_IS_OK(result)) {
4192 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4193 r->in.level, win_errstr(result)));
4194 TALLOC_FREE(r->out.info);
4195 return result;
4198 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4199 r->out.info, r->in.level);
4200 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4202 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4205 /********************************************************************
4206 ********************************************************************/
4208 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4209 const char **string_array,
4210 const char *cservername)
4212 int i, num_strings = 0;
4213 const char **array = NULL;
4215 if (!string_array) {
4216 return NULL;
4219 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4221 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4222 cservername, string_array[i]);
4223 if (!str) {
4224 TALLOC_FREE(array);
4225 return NULL;
4229 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4230 TALLOC_FREE(array);
4231 return NULL;
4235 if (i > 0) {
4236 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4237 &array, &num_strings);
4240 return array;
4243 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4244 do { \
4245 if (in && strlen(in)) { \
4246 out = talloc_strdup(mem_ctx, in); \
4247 W_ERROR_HAVE_NO_MEMORY(out); \
4248 } else { \
4249 out = NULL; \
4251 } while (0);
4253 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4254 do { \
4255 if (in && strlen(in)) { \
4256 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4257 } else { \
4258 out = talloc_strdup(mem_ctx, ""); \
4260 W_ERROR_HAVE_NO_MEMORY(out); \
4261 } while (0);
4263 /********************************************************************
4264 * fill a spoolss_DriverInfo1 struct
4265 ********************************************************************/
4267 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4268 struct spoolss_DriverInfo1 *r,
4269 const struct spoolss_DriverInfo8 *driver,
4270 const char *servername)
4272 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4273 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4275 return WERR_OK;
4278 /********************************************************************
4279 * fill a spoolss_DriverInfo2 struct
4280 ********************************************************************/
4282 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4283 struct spoolss_DriverInfo2 *r,
4284 const struct spoolss_DriverInfo8 *driver,
4285 const char *servername)
4288 const char *cservername = canon_servername(servername);
4290 r->version = driver->version;
4292 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4293 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4294 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4295 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4297 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4298 driver->driver_path,
4299 r->driver_path);
4301 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4302 driver->data_file,
4303 r->data_file);
4305 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4306 driver->config_file,
4307 r->config_file);
4309 return WERR_OK;
4312 /********************************************************************
4313 * fill a spoolss_DriverInfo3 struct
4314 ********************************************************************/
4316 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4317 struct spoolss_DriverInfo3 *r,
4318 const struct spoolss_DriverInfo8 *driver,
4319 const char *servername)
4321 const char *cservername = canon_servername(servername);
4323 r->version = driver->version;
4325 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4326 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4327 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4328 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4330 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4331 driver->driver_path,
4332 r->driver_path);
4334 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4335 driver->data_file,
4336 r->data_file);
4338 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4339 driver->config_file,
4340 r->config_file);
4342 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4343 driver->help_file,
4344 r->help_file);
4346 FILL_DRIVER_STRING(mem_ctx,
4347 driver->monitor_name,
4348 r->monitor_name);
4350 FILL_DRIVER_STRING(mem_ctx,
4351 driver->default_datatype,
4352 r->default_datatype);
4354 r->dependent_files = string_array_from_driver_info(mem_ctx,
4355 driver->dependent_files,
4356 cservername);
4357 return WERR_OK;
4360 /********************************************************************
4361 * fill a spoolss_DriverInfo4 struct
4362 ********************************************************************/
4364 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4365 struct spoolss_DriverInfo4 *r,
4366 const struct spoolss_DriverInfo8 *driver,
4367 const char *servername)
4369 const char *cservername = canon_servername(servername);
4371 r->version = driver->version;
4373 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4374 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4375 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4376 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4378 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4379 driver->driver_path,
4380 r->driver_path);
4382 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4383 driver->data_file,
4384 r->data_file);
4386 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4387 driver->config_file,
4388 r->config_file);
4390 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4391 driver->help_file,
4392 r->help_file);
4394 r->dependent_files = string_array_from_driver_info(mem_ctx,
4395 driver->dependent_files,
4396 cservername);
4398 FILL_DRIVER_STRING(mem_ctx,
4399 driver->monitor_name,
4400 r->monitor_name);
4402 FILL_DRIVER_STRING(mem_ctx,
4403 driver->default_datatype,
4404 r->default_datatype);
4406 r->previous_names = string_array_from_driver_info(mem_ctx,
4407 driver->previous_names,
4408 cservername);
4410 return WERR_OK;
4413 /********************************************************************
4414 * fill a spoolss_DriverInfo5 struct
4415 ********************************************************************/
4417 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4418 struct spoolss_DriverInfo5 *r,
4419 const struct spoolss_DriverInfo8 *driver,
4420 const char *servername)
4422 const char *cservername = canon_servername(servername);
4424 r->version = driver->version;
4426 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4427 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4428 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4429 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4431 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4432 driver->driver_path,
4433 r->driver_path);
4435 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4436 driver->data_file,
4437 r->data_file);
4439 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4440 driver->config_file,
4441 r->config_file);
4443 r->driver_attributes = 0;
4444 r->config_version = 0;
4445 r->driver_version = 0;
4447 return WERR_OK;
4449 /********************************************************************
4450 * fill a spoolss_DriverInfo6 struct
4451 ********************************************************************/
4453 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4454 struct spoolss_DriverInfo6 *r,
4455 const struct spoolss_DriverInfo8 *driver,
4456 const char *servername)
4458 const char *cservername = canon_servername(servername);
4460 r->version = driver->version;
4462 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4463 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4464 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4465 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4467 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4468 driver->driver_path,
4469 r->driver_path);
4471 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4472 driver->data_file,
4473 r->data_file);
4475 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4476 driver->config_file,
4477 r->config_file);
4479 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4480 driver->help_file,
4481 r->help_file);
4483 FILL_DRIVER_STRING(mem_ctx,
4484 driver->monitor_name,
4485 r->monitor_name);
4487 FILL_DRIVER_STRING(mem_ctx,
4488 driver->default_datatype,
4489 r->default_datatype);
4491 r->dependent_files = string_array_from_driver_info(mem_ctx,
4492 driver->dependent_files,
4493 cservername);
4494 r->previous_names = string_array_from_driver_info(mem_ctx,
4495 driver->previous_names,
4496 cservername);
4498 r->driver_date = driver->driver_date;
4499 r->driver_version = driver->driver_version;
4501 FILL_DRIVER_STRING(mem_ctx,
4502 driver->manufacturer_name,
4503 r->manufacturer_name);
4504 FILL_DRIVER_STRING(mem_ctx,
4505 driver->manufacturer_url,
4506 r->manufacturer_url);
4507 FILL_DRIVER_STRING(mem_ctx,
4508 driver->hardware_id,
4509 r->hardware_id);
4510 FILL_DRIVER_STRING(mem_ctx,
4511 driver->provider,
4512 r->provider);
4514 return WERR_OK;
4517 /********************************************************************
4518 * fill a spoolss_DriverInfo8 struct
4519 ********************************************************************/
4521 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4522 struct spoolss_DriverInfo8 *r,
4523 const struct spoolss_DriverInfo8 *driver,
4524 const char *servername)
4526 const char *cservername = canon_servername(servername);
4528 r->version = driver->version;
4530 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4531 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4532 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4533 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4535 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4536 driver->driver_path,
4537 r->driver_path);
4539 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4540 driver->data_file,
4541 r->data_file);
4543 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4544 driver->config_file,
4545 r->config_file);
4547 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4548 driver->help_file,
4549 r->help_file);
4551 FILL_DRIVER_STRING(mem_ctx,
4552 driver->monitor_name,
4553 r->monitor_name);
4555 FILL_DRIVER_STRING(mem_ctx,
4556 driver->default_datatype,
4557 r->default_datatype);
4559 r->dependent_files = string_array_from_driver_info(mem_ctx,
4560 driver->dependent_files,
4561 cservername);
4562 r->previous_names = string_array_from_driver_info(mem_ctx,
4563 driver->previous_names,
4564 cservername);
4566 r->driver_date = driver->driver_date;
4567 r->driver_version = driver->driver_version;
4569 FILL_DRIVER_STRING(mem_ctx,
4570 driver->manufacturer_name,
4571 r->manufacturer_name);
4572 FILL_DRIVER_STRING(mem_ctx,
4573 driver->manufacturer_url,
4574 r->manufacturer_url);
4575 FILL_DRIVER_STRING(mem_ctx,
4576 driver->hardware_id,
4577 r->hardware_id);
4578 FILL_DRIVER_STRING(mem_ctx,
4579 driver->provider,
4580 r->provider);
4582 FILL_DRIVER_STRING(mem_ctx,
4583 driver->print_processor,
4584 r->print_processor);
4585 FILL_DRIVER_STRING(mem_ctx,
4586 driver->vendor_setup,
4587 r->vendor_setup);
4589 r->color_profiles = string_array_from_driver_info(mem_ctx,
4590 driver->color_profiles,
4591 cservername);
4593 FILL_DRIVER_STRING(mem_ctx,
4594 driver->inf_path,
4595 r->inf_path);
4597 r->printer_driver_attributes = driver->printer_driver_attributes;
4599 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4600 driver->core_driver_dependencies,
4601 cservername);
4603 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4604 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4606 return WERR_OK;
4609 #if 0 /* disabled until marshalling issues are resolved - gd */
4610 /********************************************************************
4611 ********************************************************************/
4613 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4614 struct spoolss_DriverFileInfo *r,
4615 const char *cservername,
4616 const char *file_name,
4617 enum spoolss_DriverFileType file_type,
4618 uint32_t file_version)
4620 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4621 cservername, file_name);
4622 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4623 r->file_type = file_type;
4624 r->file_version = file_version;
4626 return WERR_OK;
4629 /********************************************************************
4630 ********************************************************************/
4632 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4633 const struct spoolss_DriverInfo8 *driver,
4634 const char *cservername,
4635 struct spoolss_DriverFileInfo **info_p,
4636 uint32_t *count_p)
4638 struct spoolss_DriverFileInfo *info = NULL;
4639 uint32_t count = 0;
4640 WERROR result;
4641 uint32_t i;
4643 *info_p = NULL;
4644 *count_p = 0;
4646 if (strlen(driver->driver_path)) {
4647 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4648 struct spoolss_DriverFileInfo,
4649 count + 1);
4650 W_ERROR_HAVE_NO_MEMORY(info);
4651 result = fill_spoolss_DriverFileInfo(info,
4652 &info[count],
4653 cservername,
4654 driver->driver_path,
4655 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4657 W_ERROR_NOT_OK_RETURN(result);
4658 count++;
4661 if (strlen(driver->config_file)) {
4662 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4663 struct spoolss_DriverFileInfo,
4664 count + 1);
4665 W_ERROR_HAVE_NO_MEMORY(info);
4666 result = fill_spoolss_DriverFileInfo(info,
4667 &info[count],
4668 cservername,
4669 driver->config_file,
4670 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4672 W_ERROR_NOT_OK_RETURN(result);
4673 count++;
4676 if (strlen(driver->data_file)) {
4677 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4678 struct spoolss_DriverFileInfo,
4679 count + 1);
4680 W_ERROR_HAVE_NO_MEMORY(info);
4681 result = fill_spoolss_DriverFileInfo(info,
4682 &info[count],
4683 cservername,
4684 driver->data_file,
4685 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4687 W_ERROR_NOT_OK_RETURN(result);
4688 count++;
4691 if (strlen(driver->help_file)) {
4692 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4693 struct spoolss_DriverFileInfo,
4694 count + 1);
4695 W_ERROR_HAVE_NO_MEMORY(info);
4696 result = fill_spoolss_DriverFileInfo(info,
4697 &info[count],
4698 cservername,
4699 driver->help_file,
4700 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4702 W_ERROR_NOT_OK_RETURN(result);
4703 count++;
4706 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4707 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4708 struct spoolss_DriverFileInfo,
4709 count + 1);
4710 W_ERROR_HAVE_NO_MEMORY(info);
4711 result = fill_spoolss_DriverFileInfo(info,
4712 &info[count],
4713 cservername,
4714 driver->dependent_files[i],
4715 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4717 W_ERROR_NOT_OK_RETURN(result);
4718 count++;
4721 *info_p = info;
4722 *count_p = count;
4724 return WERR_OK;
4727 /********************************************************************
4728 * fill a spoolss_DriverInfo101 struct
4729 ********************************************************************/
4731 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4732 struct spoolss_DriverInfo101 *r,
4733 const struct spoolss_DriverInfo8 *driver,
4734 const char *servername)
4736 const char *cservername = canon_servername(servername);
4737 WERROR result;
4739 r->version = driver->version;
4741 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4742 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4743 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4744 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4746 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4747 cservername,
4748 &r->file_info,
4749 &r->file_count);
4750 if (!W_ERROR_IS_OK(result)) {
4751 return result;
4754 FILL_DRIVER_STRING(mem_ctx,
4755 driver->monitor_name,
4756 r->monitor_name);
4758 FILL_DRIVER_STRING(mem_ctx,
4759 driver->default_datatype,
4760 r->default_datatype);
4762 r->previous_names = string_array_from_driver_info(mem_ctx,
4763 driver->previous_names,
4764 cservername);
4765 r->driver_date = driver->driver_date;
4766 r->driver_version = driver->driver_version;
4768 FILL_DRIVER_STRING(mem_ctx,
4769 driver->manufacturer_name,
4770 r->manufacturer_name);
4771 FILL_DRIVER_STRING(mem_ctx,
4772 driver->manufacturer_url,
4773 r->manufacturer_url);
4774 FILL_DRIVER_STRING(mem_ctx,
4775 driver->hardware_id,
4776 r->hardware_id);
4777 FILL_DRIVER_STRING(mem_ctx,
4778 driver->provider,
4779 r->provider);
4781 return WERR_OK;
4783 #endif
4784 /********************************************************************
4785 ********************************************************************/
4787 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4788 uint32_t level,
4789 union spoolss_DriverInfo *r,
4790 int snum,
4791 const char *servername,
4792 const char *architecture,
4793 uint32_t version)
4795 NT_PRINTER_INFO_LEVEL *printer = NULL;
4796 struct spoolss_DriverInfo8 *driver;
4797 WERROR result;
4799 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4801 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4802 win_errstr(result)));
4804 if (!W_ERROR_IS_OK(result)) {
4805 return WERR_INVALID_PRINTER_NAME;
4808 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4809 architecture, version);
4811 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4812 win_errstr(result)));
4814 if (!W_ERROR_IS_OK(result)) {
4816 * Is this a W2k client ?
4819 if (version < 3) {
4820 free_a_printer(&printer, 2);
4821 return WERR_UNKNOWN_PRINTER_DRIVER;
4824 /* Yes - try again with a WinNT driver. */
4825 version = 2;
4826 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4827 architecture, version);
4828 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4829 win_errstr(result)));
4830 if (!W_ERROR_IS_OK(result)) {
4831 free_a_printer(&printer, 2);
4832 return WERR_UNKNOWN_PRINTER_DRIVER;
4836 switch (level) {
4837 case 1:
4838 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4839 break;
4840 case 2:
4841 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4842 break;
4843 case 3:
4844 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4845 break;
4846 case 4:
4847 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4848 break;
4849 case 5:
4850 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4851 break;
4852 case 6:
4853 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4854 break;
4855 case 8:
4856 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
4857 break;
4858 #if 0 /* disabled until marshalling issues are resolved - gd */
4859 case 101:
4860 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
4861 break;
4862 #endif
4863 default:
4864 result = WERR_UNKNOWN_LEVEL;
4865 break;
4868 free_a_printer(&printer, 2);
4869 free_a_printer_driver(driver);
4871 return result;
4874 /****************************************************************
4875 _spoolss_GetPrinterDriver2
4876 ****************************************************************/
4878 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
4879 struct spoolss_GetPrinterDriver2 *r)
4881 Printer_entry *printer;
4882 WERROR result;
4884 const char *servername;
4885 int snum;
4887 /* that's an [in out] buffer */
4889 if (!r->in.buffer && (r->in.offered != 0)) {
4890 return WERR_INVALID_PARAM;
4893 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
4895 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
4896 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
4897 return WERR_INVALID_PRINTER_NAME;
4900 *r->out.needed = 0;
4901 *r->out.server_major_version = 0;
4902 *r->out.server_minor_version = 0;
4904 servername = get_server_name(printer);
4906 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4907 return WERR_BADFID;
4910 result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
4911 r->out.info, snum,
4912 servername,
4913 r->in.architecture,
4914 r->in.client_major_version);
4915 if (!W_ERROR_IS_OK(result)) {
4916 TALLOC_FREE(r->out.info);
4917 return result;
4920 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
4921 r->out.info, r->in.level);
4922 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4924 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4928 /****************************************************************
4929 _spoolss_StartPagePrinter
4930 ****************************************************************/
4932 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
4933 struct spoolss_StartPagePrinter *r)
4935 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4937 if (!Printer) {
4938 DEBUG(3,("_spoolss_StartPagePrinter: "
4939 "Error in startpageprinter printer handle\n"));
4940 return WERR_BADFID;
4943 Printer->page_started = true;
4944 return WERR_OK;
4947 /****************************************************************
4948 _spoolss_EndPagePrinter
4949 ****************************************************************/
4951 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
4952 struct spoolss_EndPagePrinter *r)
4954 int snum;
4956 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4958 if (!Printer) {
4959 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
4960 OUR_HANDLE(r->in.handle)));
4961 return WERR_BADFID;
4964 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
4965 return WERR_BADFID;
4967 Printer->page_started = false;
4968 print_job_endpage(snum, Printer->jobid);
4970 return WERR_OK;
4973 /****************************************************************
4974 _spoolss_StartDocPrinter
4975 ****************************************************************/
4977 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
4978 struct spoolss_StartDocPrinter *r)
4980 struct spoolss_DocumentInfo1 *info_1;
4981 int snum;
4982 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4984 if (!Printer) {
4985 DEBUG(2,("_spoolss_StartDocPrinter: "
4986 "Invalid handle (%s:%u:%u)\n",
4987 OUR_HANDLE(r->in.handle)));
4988 return WERR_BADFID;
4991 if (r->in.level != 1) {
4992 return WERR_UNKNOWN_LEVEL;
4995 info_1 = r->in.info.info1;
4998 * a nice thing with NT is it doesn't listen to what you tell it.
4999 * when asked to send _only_ RAW datas, it tries to send datas
5000 * in EMF format.
5002 * So I add checks like in NT Server ...
5005 if (info_1->datatype) {
5006 if (strcmp(info_1->datatype, "RAW") != 0) {
5007 *r->out.job_id = 0;
5008 return WERR_INVALID_DATATYPE;
5012 /* get the share number of the printer */
5013 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5014 return WERR_BADFID;
5017 Printer->jobid = print_job_start(p->server_info, snum,
5018 info_1->document_name,
5019 Printer->devmode);
5021 /* An error occured in print_job_start() so return an appropriate
5022 NT error code. */
5024 if (Printer->jobid == -1) {
5025 return map_werror_from_unix(errno);
5028 Printer->document_started = true;
5029 *r->out.job_id = Printer->jobid;
5031 return WERR_OK;
5034 /****************************************************************
5035 _spoolss_EndDocPrinter
5036 ****************************************************************/
5038 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5039 struct spoolss_EndDocPrinter *r)
5041 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5042 int snum;
5044 if (!Printer) {
5045 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5046 OUR_HANDLE(r->in.handle)));
5047 return WERR_BADFID;
5050 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5051 return WERR_BADFID;
5054 Printer->document_started = false;
5055 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5056 /* error codes unhandled so far ... */
5058 return WERR_OK;
5061 /****************************************************************
5062 _spoolss_WritePrinter
5063 ****************************************************************/
5065 WERROR _spoolss_WritePrinter(pipes_struct *p,
5066 struct spoolss_WritePrinter *r)
5068 ssize_t buffer_written;
5069 int snum;
5070 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5072 if (!Printer) {
5073 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5074 OUR_HANDLE(r->in.handle)));
5075 *r->out.num_written = r->in._data_size;
5076 return WERR_BADFID;
5079 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5080 return WERR_BADFID;
5082 buffer_written = print_job_write(snum, Printer->jobid,
5083 (const char *)r->in.data.data,
5084 (SMB_OFF_T)-1,
5085 (size_t)r->in._data_size);
5086 if (buffer_written == (ssize_t)-1) {
5087 *r->out.num_written = 0;
5088 if (errno == ENOSPC)
5089 return WERR_NO_SPOOL_SPACE;
5090 else
5091 return WERR_ACCESS_DENIED;
5094 *r->out.num_written = r->in._data_size;
5096 return WERR_OK;
5099 /********************************************************************
5100 * api_spoolss_getprinter
5101 * called from the spoolss dispatcher
5103 ********************************************************************/
5105 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5106 pipes_struct *p)
5108 int snum;
5109 WERROR errcode = WERR_BADFUNC;
5110 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5112 if (!Printer) {
5113 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5114 OUR_HANDLE(handle)));
5115 return WERR_BADFID;
5118 if (!get_printer_snum(p, handle, &snum, NULL))
5119 return WERR_BADFID;
5121 switch (command) {
5122 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5123 errcode = print_queue_pause(p->server_info, snum);
5124 break;
5125 case SPOOLSS_PRINTER_CONTROL_RESUME:
5126 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5127 errcode = print_queue_resume(p->server_info, snum);
5128 break;
5129 case SPOOLSS_PRINTER_CONTROL_PURGE:
5130 errcode = print_queue_purge(p->server_info, snum);
5131 break;
5132 default:
5133 return WERR_UNKNOWN_LEVEL;
5136 return errcode;
5140 /****************************************************************
5141 _spoolss_AbortPrinter
5142 * From MSDN: "Deletes printer's spool file if printer is configured
5143 * for spooling"
5144 ****************************************************************/
5146 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5147 struct spoolss_AbortPrinter *r)
5149 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5150 int snum;
5151 WERROR errcode = WERR_OK;
5153 if (!Printer) {
5154 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5155 OUR_HANDLE(r->in.handle)));
5156 return WERR_BADFID;
5159 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5160 return WERR_BADFID;
5162 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5164 return errcode;
5167 /********************************************************************
5168 * called by spoolss_api_setprinter
5169 * when updating a printer description
5170 ********************************************************************/
5172 static WERROR update_printer_sec(struct policy_handle *handle,
5173 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5175 struct spoolss_security_descriptor *new_secdesc = NULL;
5176 struct spoolss_security_descriptor *old_secdesc = NULL;
5177 const char *printer;
5178 WERROR result;
5179 int snum;
5181 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5183 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5184 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5185 OUR_HANDLE(handle)));
5187 result = WERR_BADFID;
5188 goto done;
5191 if (secdesc_ctr == NULL) {
5192 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5193 result = WERR_INVALID_PARAM;
5194 goto done;
5196 printer = lp_const_servicename(snum);
5198 /* Check the user has permissions to change the security
5199 descriptor. By experimentation with two NT machines, the user
5200 requires Full Access to the printer to change security
5201 information. */
5203 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5204 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5205 result = WERR_ACCESS_DENIED;
5206 goto done;
5209 /* NT seems to like setting the security descriptor even though
5210 nothing may have actually changed. */
5211 result = winreg_get_printer_secdesc(p->mem_ctx,
5212 p->server_info,
5213 printer,
5214 &old_secdesc);
5215 if (!W_ERROR_IS_OK(result)) {
5216 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5217 result = WERR_BADFID;
5218 goto done;
5221 if (DEBUGLEVEL >= 10) {
5222 struct security_acl *the_acl;
5223 int i;
5225 the_acl = secdesc_ctr->sd->dacl;
5226 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5227 printer, the_acl->num_aces));
5229 for (i = 0; i < the_acl->num_aces; i++) {
5230 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5231 &the_acl->aces[i].trustee),
5232 the_acl->aces[i].access_mask));
5235 the_acl = secdesc_ctr->sd->dacl;
5237 if (the_acl) {
5238 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5239 printer, the_acl->num_aces));
5241 for (i = 0; i < the_acl->num_aces; i++) {
5242 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5243 &the_acl->aces[i].trustee),
5244 the_acl->aces[i].access_mask));
5246 } else {
5247 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5251 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5252 if (new_secdesc == NULL) {
5253 result = WERR_NOMEM;
5254 goto done;
5257 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5258 result = WERR_OK;
5259 goto done;
5262 result = winreg_set_printer_secdesc(p->mem_ctx,
5263 p->server_info,
5264 printer,
5265 new_secdesc);
5267 done:
5268 return result;
5271 /********************************************************************
5272 Canonicalize printer info from a client
5274 ATTN: It does not matter what we set the servername to hear
5275 since we do the necessary work in get_a_printer() to set it to
5276 the correct value based on what the client sent in the
5277 _spoolss_open_printer_ex().
5278 ********************************************************************/
5280 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5281 struct spoolss_SetPrinterInfo2 *info2,
5282 int snum)
5284 fstring printername;
5285 const char *p;
5287 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5288 "portname=%s drivername=%s comment=%s location=%s\n",
5289 info2->servername, info2->printername, info2->sharename,
5290 info2->portname, info2->drivername, info2->comment,
5291 info2->location));
5293 /* we force some elements to "correct" values */
5294 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5295 if (info2->servername == NULL) {
5296 return false;
5298 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5299 if (info2->sharename == NULL) {
5300 return false;
5303 /* check to see if we allow printername != sharename */
5304 if (lp_force_printername(snum)) {
5305 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5306 global_myname(), info2->sharename);
5307 } else {
5308 /* make sure printername is in \\server\printername format */
5309 fstrcpy(printername, info2->printername);
5310 p = printername;
5311 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5312 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5313 p++;
5316 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5317 global_myname(), p);
5319 if (info2->printername == NULL) {
5320 return false;
5323 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5324 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5326 return true;
5329 /****************************************************************************
5330 ****************************************************************************/
5332 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5334 char *cmd = lp_addport_cmd();
5335 char *command = NULL;
5336 int ret;
5337 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5338 bool is_print_op = false;
5340 if ( !*cmd ) {
5341 return WERR_ACCESS_DENIED;
5344 command = talloc_asprintf(ctx,
5345 "%s \"%s\" \"%s\"", cmd, portname, uri );
5346 if (!command) {
5347 return WERR_NOMEM;
5350 if ( token )
5351 is_print_op = user_has_privileges( token, &se_printop );
5353 DEBUG(10,("Running [%s]\n", command));
5355 /********* BEGIN SePrintOperatorPrivilege **********/
5357 if ( is_print_op )
5358 become_root();
5360 ret = smbrun(command, NULL);
5362 if ( is_print_op )
5363 unbecome_root();
5365 /********* END SePrintOperatorPrivilege **********/
5367 DEBUGADD(10,("returned [%d]\n", ret));
5369 TALLOC_FREE(command);
5371 if ( ret != 0 ) {
5372 return WERR_ACCESS_DENIED;
5375 return WERR_OK;
5378 /****************************************************************************
5379 ****************************************************************************/
5381 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5382 struct spoolss_SetPrinterInfo2 *info2)
5384 char *cmd = lp_addprinter_cmd();
5385 char **qlines;
5386 char *command = NULL;
5387 int numlines;
5388 int ret;
5389 int fd;
5390 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5391 bool is_print_op = false;
5392 char *remote_machine = talloc_strdup(ctx, "%m");
5394 if (!remote_machine) {
5395 return false;
5397 remote_machine = talloc_sub_basic(ctx,
5398 current_user_info.smb_name,
5399 current_user_info.domain,
5400 remote_machine);
5401 if (!remote_machine) {
5402 return false;
5405 command = talloc_asprintf(ctx,
5406 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5407 cmd, info2->printername, info2->sharename,
5408 info2->portname, info2->drivername,
5409 info2->location, info2->comment, remote_machine);
5410 if (!command) {
5411 return false;
5414 if ( token )
5415 is_print_op = user_has_privileges( token, &se_printop );
5417 DEBUG(10,("Running [%s]\n", command));
5419 /********* BEGIN SePrintOperatorPrivilege **********/
5421 if ( is_print_op )
5422 become_root();
5424 if ( (ret = smbrun(command, &fd)) == 0 ) {
5425 /* Tell everyone we updated smb.conf. */
5426 message_send_all(smbd_messaging_context(),
5427 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5430 if ( is_print_op )
5431 unbecome_root();
5433 /********* END SePrintOperatorPrivilege **********/
5435 DEBUGADD(10,("returned [%d]\n", ret));
5437 TALLOC_FREE(command);
5438 TALLOC_FREE(remote_machine);
5440 if ( ret != 0 ) {
5441 if (fd != -1)
5442 close(fd);
5443 return false;
5446 /* reload our services immediately */
5447 become_root();
5448 reload_services(false);
5449 unbecome_root();
5451 numlines = 0;
5452 /* Get lines and convert them back to dos-codepage */
5453 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5454 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5455 close(fd);
5457 /* Set the portname to what the script says the portname should be. */
5458 /* but don't require anything to be return from the script exit a good error code */
5460 if (numlines) {
5461 /* Set the portname to what the script says the portname should be. */
5462 info2->portname = talloc_strdup(ctx, qlines[0]);
5463 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5466 TALLOC_FREE(qlines);
5467 return true;
5471 /********************************************************************
5472 * Called by spoolss_api_setprinter
5473 * when updating a printer description.
5474 ********************************************************************/
5476 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5477 struct spoolss_SetPrinterInfoCtr *info_ctr,
5478 struct spoolss_DeviceMode *devmode)
5480 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5481 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5482 struct spoolss_PrinterInfo2 *old_printer;
5483 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5484 const char *servername = NULL;
5485 int snum;
5486 WERROR result;
5487 DATA_BLOB buffer;
5488 fstring asc_buffer;
5490 DEBUG(8,("update_printer\n"));
5492 result = WERR_OK;
5494 if (!Printer) {
5495 result = WERR_BADFID;
5496 goto done;
5499 if (!get_printer_snum(p, handle, &snum, NULL)) {
5500 result = WERR_BADFID;
5501 goto done;
5504 if (Printer != NULL || Printer->servername != NULL) {
5505 servername = Printer->servername;
5508 result = winreg_get_printer(p->mem_ctx,
5509 p->server_info,
5510 servername,
5511 lp_const_servicename(snum),
5512 &old_printer);
5513 if (!W_ERROR_IS_OK(result)) {
5514 result = WERR_BADFID;
5515 goto done;
5518 /* Do sanity check on the requested changes for Samba */
5519 if (!check_printer_ok(p->mem_ctx, printer, snum)) {
5520 result = WERR_INVALID_PARAM;
5521 goto done;
5524 /* FIXME!!! If the driver has changed we really should verify that
5525 it is installed before doing much else --jerry */
5527 /* Check calling user has permission to update printer description */
5528 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5529 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5530 result = WERR_ACCESS_DENIED;
5531 goto done;
5534 /* Call addprinter hook */
5535 /* Check changes to see if this is really needed */
5537 if (*lp_addprinter_cmd() &&
5538 (!strequal(printer->drivername, old_printer->drivername) ||
5539 !strequal(printer->comment, old_printer->comment) ||
5540 !strequal(printer->portname, old_printer->portname) ||
5541 !strequal(printer->location, old_printer->location)) )
5543 /* add_printer_hook() will call reload_services() */
5544 if (!add_printer_hook(p->mem_ctx, p->server_info->ptok,
5545 printer) ) {
5546 result = WERR_ACCESS_DENIED;
5547 goto done;
5552 * When a *new* driver is bound to a printer, the drivername is used to
5553 * lookup previously saved driver initialization info, which is then
5554 * bound to the printer, simulating what happens in the Windows arch.
5556 if (!strequal(printer->drivername, old_printer->drivername)) {
5557 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5558 printer->drivername));
5560 notify_printer_driver(snum, printer->drivername);
5564 * flag which changes actually occured. This is a small subset of
5565 * all the possible changes. We also have to update things in the
5566 * DsSpooler key.
5568 if (!strequal(printer->comment, old_printer->comment)) {
5569 push_reg_sz(talloc_tos(), &buffer, printer->comment);
5570 winreg_set_printer_dataex(p->mem_ctx,
5571 p->server_info,
5572 printer->sharename,
5573 SPOOL_DSSPOOLER_KEY,
5574 "description",
5575 REG_SZ,
5576 buffer.data,
5577 buffer.length);
5579 notify_printer_comment(snum, printer->comment);
5582 if (!strequal(printer->sharename, old_printer->sharename)) {
5583 push_reg_sz(talloc_tos(), &buffer, printer->sharename);
5584 winreg_set_printer_dataex(p->mem_ctx,
5585 p->server_info,
5586 printer->sharename,
5587 SPOOL_DSSPOOLER_KEY,
5588 "shareName",
5589 REG_SZ,
5590 buffer.data,
5591 buffer.length);
5593 notify_printer_sharename(snum, printer->sharename);
5596 if (!strequal(printer->printername, old_printer->printername)) {
5597 const char *pname;
5599 if ( (pname = strchr_m( printer->printername+2, '\\' )) != NULL )
5600 pname++;
5601 else
5602 pname = printer->printername;
5604 push_reg_sz(talloc_tos(), &buffer, pname);
5605 winreg_set_printer_dataex(p->mem_ctx,
5606 p->server_info,
5607 printer->sharename,
5608 SPOOL_DSSPOOLER_KEY,
5609 "printerName",
5610 REG_SZ,
5611 buffer.data,
5612 buffer.length);
5614 notify_printer_printername( snum, pname );
5617 if (!strequal(printer->portname, old_printer->portname)) {
5618 push_reg_sz(talloc_tos(), &buffer, printer->portname);
5619 winreg_set_printer_dataex(p->mem_ctx,
5620 p->server_info,
5621 printer->sharename,
5622 SPOOL_DSSPOOLER_KEY,
5623 "portName",
5624 REG_SZ,
5625 buffer.data,
5626 buffer.length);
5628 notify_printer_port(snum, printer->portname);
5631 if (!strequal(printer->location, old_printer->location)) {
5632 push_reg_sz(talloc_tos(), &buffer, printer->location);
5633 winreg_set_printer_dataex(p->mem_ctx,
5634 p->server_info,
5635 printer->sharename,
5636 SPOOL_DSSPOOLER_KEY,
5637 "location",
5638 REG_SZ,
5639 buffer.data,
5640 buffer.length);
5642 notify_printer_location(snum, printer->location);
5645 /* here we need to update some more DsSpooler keys */
5646 /* uNCName, serverName, shortServerName */
5648 push_reg_sz(talloc_tos(), &buffer, global_myname());
5649 winreg_set_printer_dataex(p->mem_ctx,
5650 p->server_info,
5651 printer->sharename,
5652 SPOOL_DSSPOOLER_KEY,
5653 "serverName",
5654 REG_SZ,
5655 buffer.data,
5656 buffer.length);
5657 winreg_set_printer_dataex(p->mem_ctx,
5658 p->server_info,
5659 printer->sharename,
5660 SPOOL_DSSPOOLER_KEY,
5661 "shortServerName",
5662 REG_SZ,
5663 buffer.data,
5664 buffer.length);
5666 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5667 global_myname(), printer->sharename );
5668 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5669 winreg_set_printer_dataex(p->mem_ctx,
5670 p->server_info,
5671 printer->sharename,
5672 SPOOL_DSSPOOLER_KEY,
5673 "uNCName",
5674 REG_SZ,
5675 buffer.data,
5676 buffer.length);
5678 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
5680 if (devmode == NULL) {
5681 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
5683 result = winreg_update_printer(p->mem_ctx,
5684 p->server_info,
5685 printer->sharename,
5686 printer_mask,
5687 printer,
5688 devmode,
5689 NULL);
5691 done:
5692 talloc_free(old_printer);
5694 return result;
5697 /****************************************************************************
5698 ****************************************************************************/
5699 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5700 struct policy_handle *handle,
5701 struct spoolss_SetPrinterInfo7 *info7)
5703 #ifdef HAVE_ADS
5704 int snum;
5705 Printer_entry *Printer;
5707 if ( lp_security() != SEC_ADS ) {
5708 return WERR_UNKNOWN_LEVEL;
5711 Printer = find_printer_index_by_hnd(p, handle);
5713 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5715 if (!Printer)
5716 return WERR_BADFID;
5718 if (!get_printer_snum(p, handle, &snum, NULL))
5719 return WERR_BADFID;
5721 nt_printer_publish(Printer, snum, info7->action);
5723 return WERR_OK;
5724 #else
5725 return WERR_UNKNOWN_LEVEL;
5726 #endif
5729 /********************************************************************
5730 ********************************************************************/
5732 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5733 struct spoolss_DeviceMode *devmode)
5735 int snum;
5736 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5737 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
5739 DEBUG(8,("update_printer_devmode\n"));
5741 if (!Printer) {
5742 return WERR_BADFID;
5745 if (!get_printer_snum(p, handle, &snum, NULL)) {
5746 return WERR_BADFID;
5749 /* Check calling user has permission to update printer description */
5750 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5751 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5752 return WERR_ACCESS_DENIED;
5755 return winreg_update_printer(p->mem_ctx,
5756 p->server_info,
5757 lp_const_servicename(snum),
5758 info2_mask,
5759 NULL,
5760 devmode,
5761 NULL);
5765 /****************************************************************
5766 _spoolss_SetPrinter
5767 ****************************************************************/
5769 WERROR _spoolss_SetPrinter(pipes_struct *p,
5770 struct spoolss_SetPrinter *r)
5772 WERROR result;
5774 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5776 if (!Printer) {
5777 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5778 OUR_HANDLE(r->in.handle)));
5779 return WERR_BADFID;
5782 /* check the level */
5783 switch (r->in.info_ctr->level) {
5784 case 0:
5785 return control_printer(r->in.handle, r->in.command, p);
5786 case 2:
5787 result = update_printer(p, r->in.handle,
5788 r->in.info_ctr,
5789 r->in.devmode_ctr->devmode);
5790 if (!W_ERROR_IS_OK(result))
5791 return result;
5792 if (r->in.secdesc_ctr->sd)
5793 result = update_printer_sec(r->in.handle, p,
5794 r->in.secdesc_ctr);
5795 return result;
5796 case 3:
5797 return update_printer_sec(r->in.handle, p,
5798 r->in.secdesc_ctr);
5799 case 7:
5800 return publish_or_unpublish_printer(p, r->in.handle,
5801 r->in.info_ctr->info.info7);
5802 case 8:
5803 return update_printer_devmode(p, r->in.handle,
5804 r->in.devmode_ctr->devmode);
5805 default:
5806 return WERR_UNKNOWN_LEVEL;
5810 /****************************************************************
5811 _spoolss_FindClosePrinterNotify
5812 ****************************************************************/
5814 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5815 struct spoolss_FindClosePrinterNotify *r)
5817 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5819 if (!Printer) {
5820 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5821 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5822 return WERR_BADFID;
5825 if (Printer->notify.client_connected == true) {
5826 int snum = -1;
5828 if ( Printer->printer_type == SPLHND_SERVER)
5829 snum = -1;
5830 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5831 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5832 return WERR_BADFID;
5834 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5837 Printer->notify.flags=0;
5838 Printer->notify.options=0;
5839 Printer->notify.localmachine[0]='\0';
5840 Printer->notify.printerlocal=0;
5841 TALLOC_FREE(Printer->notify.option);
5842 Printer->notify.client_connected = false;
5844 return WERR_OK;
5847 /****************************************************************
5848 _spoolss_AddJob
5849 ****************************************************************/
5851 WERROR _spoolss_AddJob(pipes_struct *p,
5852 struct spoolss_AddJob *r)
5854 if (!r->in.buffer && (r->in.offered != 0)) {
5855 return WERR_INVALID_PARAM;
5858 /* this is what a NT server returns for AddJob. AddJob must fail on
5859 * non-local printers */
5861 if (r->in.level != 1) {
5862 return WERR_UNKNOWN_LEVEL;
5865 return WERR_INVALID_PARAM;
5868 /****************************************************************************
5869 fill_job_info1
5870 ****************************************************************************/
5872 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5873 struct spoolss_JobInfo1 *r,
5874 const print_queue_struct *queue,
5875 int position, int snum,
5876 const NT_PRINTER_INFO_LEVEL *ntprinter)
5878 struct tm *t;
5880 t = gmtime(&queue->time);
5882 r->job_id = queue->job;
5884 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5885 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5886 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
5887 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5888 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5889 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5890 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5891 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5892 r->data_type = talloc_strdup(mem_ctx, "RAW");
5893 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5894 r->text_status = talloc_strdup(mem_ctx, "");
5895 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5897 r->status = nt_printj_status(queue->status);
5898 r->priority = queue->priority;
5899 r->position = position;
5900 r->total_pages = queue->page_count;
5901 r->pages_printed = 0; /* ??? */
5903 init_systemtime(&r->submitted, t);
5905 return WERR_OK;
5908 /****************************************************************************
5909 fill_job_info2
5910 ****************************************************************************/
5912 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
5913 struct spoolss_JobInfo2 *r,
5914 const print_queue_struct *queue,
5915 int position, int snum,
5916 const NT_PRINTER_INFO_LEVEL *ntprinter,
5917 struct spoolss_DeviceMode *devmode)
5919 struct tm *t;
5921 t = gmtime(&queue->time);
5923 r->job_id = queue->job;
5925 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5926 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5927 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
5928 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5929 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5930 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5931 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5932 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5933 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
5934 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
5935 r->data_type = talloc_strdup(mem_ctx, "RAW");
5936 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5937 r->print_processor = talloc_strdup(mem_ctx, "winprint");
5938 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
5939 r->parameters = talloc_strdup(mem_ctx, "");
5940 W_ERROR_HAVE_NO_MEMORY(r->parameters);
5941 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
5942 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5944 r->devmode = devmode;
5946 r->text_status = talloc_strdup(mem_ctx, "");
5947 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5949 r->secdesc = NULL;
5951 r->status = nt_printj_status(queue->status);
5952 r->priority = queue->priority;
5953 r->position = position;
5954 r->start_time = 0;
5955 r->until_time = 0;
5956 r->total_pages = queue->page_count;
5957 r->size = queue->size;
5958 init_systemtime(&r->submitted, t);
5959 r->time = 0;
5960 r->pages_printed = 0; /* ??? */
5962 return WERR_OK;
5965 /****************************************************************************
5966 fill_job_info3
5967 ****************************************************************************/
5969 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
5970 struct spoolss_JobInfo3 *r,
5971 const print_queue_struct *queue,
5972 const print_queue_struct *next_queue,
5973 int position, int snum,
5974 const NT_PRINTER_INFO_LEVEL *ntprinter)
5976 r->job_id = queue->job;
5977 r->next_job_id = 0;
5978 if (next_queue) {
5979 r->next_job_id = next_queue->job;
5981 r->reserved = 0;
5983 return WERR_OK;
5986 /****************************************************************************
5987 Enumjobs at level 1.
5988 ****************************************************************************/
5990 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
5991 const print_queue_struct *queue,
5992 uint32_t num_queues, int snum,
5993 const NT_PRINTER_INFO_LEVEL *ntprinter,
5994 union spoolss_JobInfo **info_p,
5995 uint32_t *count)
5997 union spoolss_JobInfo *info;
5998 int i;
5999 WERROR result = WERR_OK;
6001 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6002 W_ERROR_HAVE_NO_MEMORY(info);
6004 *count = num_queues;
6006 for (i=0; i<*count; i++) {
6007 result = fill_job_info1(info,
6008 &info[i].info1,
6009 &queue[i],
6011 snum,
6012 ntprinter);
6013 if (!W_ERROR_IS_OK(result)) {
6014 goto out;
6018 out:
6019 if (!W_ERROR_IS_OK(result)) {
6020 TALLOC_FREE(info);
6021 *count = 0;
6022 return result;
6025 *info_p = info;
6027 return WERR_OK;
6030 /****************************************************************************
6031 Enumjobs at level 2.
6032 ****************************************************************************/
6034 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6035 const print_queue_struct *queue,
6036 uint32_t num_queues, int snum,
6037 const NT_PRINTER_INFO_LEVEL *ntprinter,
6038 union spoolss_JobInfo **info_p,
6039 uint32_t *count)
6041 union spoolss_JobInfo *info;
6042 int i;
6043 WERROR result = WERR_OK;
6045 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6046 W_ERROR_HAVE_NO_MEMORY(info);
6048 *count = num_queues;
6050 for (i=0; i<*count; i++) {
6052 struct spoolss_DeviceMode *devmode;
6054 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6055 if (!devmode) {
6056 result = WERR_NOMEM;
6057 goto out;
6060 result = fill_job_info2(info,
6061 &info[i].info2,
6062 &queue[i],
6064 snum,
6065 ntprinter,
6066 devmode);
6067 if (!W_ERROR_IS_OK(result)) {
6068 goto out;
6072 out:
6073 if (!W_ERROR_IS_OK(result)) {
6074 TALLOC_FREE(info);
6075 *count = 0;
6076 return result;
6079 *info_p = info;
6081 return WERR_OK;
6084 /****************************************************************************
6085 Enumjobs at level 3.
6086 ****************************************************************************/
6088 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6089 const print_queue_struct *queue,
6090 uint32_t num_queues, int snum,
6091 const NT_PRINTER_INFO_LEVEL *ntprinter,
6092 union spoolss_JobInfo **info_p,
6093 uint32_t *count)
6095 union spoolss_JobInfo *info;
6096 int i;
6097 WERROR result = WERR_OK;
6099 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6100 W_ERROR_HAVE_NO_MEMORY(info);
6102 *count = num_queues;
6104 for (i=0; i<*count; i++) {
6105 const print_queue_struct *next_queue = NULL;
6107 if (i+1 < *count) {
6108 next_queue = &queue[i+1];
6111 result = fill_job_info3(info,
6112 &info[i].info3,
6113 &queue[i],
6114 next_queue,
6116 snum,
6117 ntprinter);
6118 if (!W_ERROR_IS_OK(result)) {
6119 goto out;
6123 out:
6124 if (!W_ERROR_IS_OK(result)) {
6125 TALLOC_FREE(info);
6126 *count = 0;
6127 return result;
6130 *info_p = info;
6132 return WERR_OK;
6135 /****************************************************************
6136 _spoolss_EnumJobs
6137 ****************************************************************/
6139 WERROR _spoolss_EnumJobs(pipes_struct *p,
6140 struct spoolss_EnumJobs *r)
6142 WERROR result;
6143 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6144 int snum;
6145 print_status_struct prt_status;
6146 print_queue_struct *queue = NULL;
6147 uint32_t count;
6149 /* that's an [in out] buffer */
6151 if (!r->in.buffer && (r->in.offered != 0)) {
6152 return WERR_INVALID_PARAM;
6155 DEBUG(4,("_spoolss_EnumJobs\n"));
6157 *r->out.needed = 0;
6158 *r->out.count = 0;
6159 *r->out.info = NULL;
6161 /* lookup the printer snum and tdb entry */
6163 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6164 return WERR_BADFID;
6167 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6168 if (!W_ERROR_IS_OK(result)) {
6169 return result;
6172 count = print_queue_status(snum, &queue, &prt_status);
6173 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6174 count, prt_status.status, prt_status.message));
6176 if (count == 0) {
6177 SAFE_FREE(queue);
6178 free_a_printer(&ntprinter, 2);
6179 return WERR_OK;
6182 switch (r->in.level) {
6183 case 1:
6184 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6185 ntprinter, r->out.info, r->out.count);
6186 break;
6187 case 2:
6188 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6189 ntprinter, r->out.info, r->out.count);
6190 break;
6191 case 3:
6192 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6193 ntprinter, r->out.info, r->out.count);
6194 break;
6195 default:
6196 result = WERR_UNKNOWN_LEVEL;
6197 break;
6200 SAFE_FREE(queue);
6201 free_a_printer(&ntprinter, 2);
6203 if (!W_ERROR_IS_OK(result)) {
6204 return result;
6207 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6208 spoolss_EnumJobs,
6209 *r->out.info, r->in.level,
6210 *r->out.count);
6211 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6212 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6214 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6217 /****************************************************************
6218 _spoolss_ScheduleJob
6219 ****************************************************************/
6221 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6222 struct spoolss_ScheduleJob *r)
6224 return WERR_OK;
6227 /****************************************************************
6228 ****************************************************************/
6230 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6231 const char *printer_name,
6232 uint32_t job_id,
6233 struct spoolss_SetJobInfo1 *r)
6235 char *old_doc_name;
6237 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6238 return WERR_BADFID;
6241 if (strequal(old_doc_name, r->document_name)) {
6242 return WERR_OK;
6245 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6246 return WERR_BADFID;
6249 return WERR_OK;
6252 /****************************************************************
6253 _spoolss_SetJob
6254 ****************************************************************/
6256 WERROR _spoolss_SetJob(pipes_struct *p,
6257 struct spoolss_SetJob *r)
6259 int snum;
6260 WERROR errcode = WERR_BADFUNC;
6262 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6263 return WERR_BADFID;
6266 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6267 return WERR_INVALID_PRINTER_NAME;
6270 switch (r->in.command) {
6271 case SPOOLSS_JOB_CONTROL_CANCEL:
6272 case SPOOLSS_JOB_CONTROL_DELETE:
6273 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6274 errcode = WERR_OK;
6276 break;
6277 case SPOOLSS_JOB_CONTROL_PAUSE:
6278 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6279 errcode = WERR_OK;
6281 break;
6282 case SPOOLSS_JOB_CONTROL_RESTART:
6283 case SPOOLSS_JOB_CONTROL_RESUME:
6284 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6285 errcode = WERR_OK;
6287 break;
6288 case 0:
6289 errcode = WERR_OK;
6290 break;
6291 default:
6292 return WERR_UNKNOWN_LEVEL;
6295 if (!W_ERROR_IS_OK(errcode)) {
6296 return errcode;
6299 if (r->in.ctr == NULL) {
6300 return errcode;
6303 switch (r->in.ctr->level) {
6304 case 1:
6305 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6306 r->in.job_id,
6307 r->in.ctr->info.info1);
6308 break;
6309 case 2:
6310 case 3:
6311 case 4:
6312 default:
6313 return WERR_UNKNOWN_LEVEL;
6316 return errcode;
6319 /****************************************************************************
6320 Enumerates all printer drivers by level and architecture.
6321 ****************************************************************************/
6323 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6324 const char *servername,
6325 const char *architecture,
6326 uint32_t level,
6327 union spoolss_DriverInfo **info_p,
6328 uint32_t *count_p)
6330 int i;
6331 int ndrivers;
6332 uint32_t version;
6333 fstring *list = NULL;
6334 struct spoolss_DriverInfo8 *driver;
6335 union spoolss_DriverInfo *info = NULL;
6336 uint32_t count = 0;
6337 WERROR result = WERR_OK;
6339 *count_p = 0;
6340 *info_p = NULL;
6342 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6343 list = NULL;
6344 ndrivers = get_ntdrivers(&list, architecture, version);
6345 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6346 ndrivers, architecture, version));
6348 if (ndrivers == -1) {
6349 result = WERR_NOMEM;
6350 goto out;
6353 if (ndrivers != 0) {
6354 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6355 union spoolss_DriverInfo,
6356 count + ndrivers);
6357 if (!info) {
6358 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6359 "failed to enlarge driver info buffer!\n"));
6360 result = WERR_NOMEM;
6361 goto out;
6365 for (i=0; i<ndrivers; i++) {
6366 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6367 ZERO_STRUCT(driver);
6368 result = get_a_printer_driver(mem_ctx, &driver, list[i],
6369 architecture, version);
6370 if (!W_ERROR_IS_OK(result)) {
6371 goto out;
6374 switch (level) {
6375 case 1:
6376 result = fill_printer_driver_info1(info, &info[count+i].info1,
6377 driver, servername);
6378 break;
6379 case 2:
6380 result = fill_printer_driver_info2(info, &info[count+i].info2,
6381 driver, servername);
6382 break;
6383 case 3:
6384 result = fill_printer_driver_info3(info, &info[count+i].info3,
6385 driver, servername);
6386 break;
6387 case 4:
6388 result = fill_printer_driver_info4(info, &info[count+i].info4,
6389 driver, servername);
6390 break;
6391 case 5:
6392 result = fill_printer_driver_info5(info, &info[count+i].info5,
6393 driver, servername);
6394 break;
6395 case 6:
6396 result = fill_printer_driver_info6(info, &info[count+i].info6,
6397 driver, servername);
6398 break;
6399 case 8:
6400 result = fill_printer_driver_info8(info, &info[count+i].info8,
6401 driver, servername);
6402 break;
6403 default:
6404 result = WERR_UNKNOWN_LEVEL;
6405 break;
6408 free_a_printer_driver(driver);
6410 if (!W_ERROR_IS_OK(result)) {
6411 goto out;
6415 count += ndrivers;
6416 SAFE_FREE(list);
6419 out:
6420 SAFE_FREE(list);
6422 if (!W_ERROR_IS_OK(result)) {
6423 TALLOC_FREE(info);
6424 return result;
6427 *info_p = info;
6428 *count_p = count;
6430 return WERR_OK;
6433 /****************************************************************************
6434 Enumerates all printer drivers by level.
6435 ****************************************************************************/
6437 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6438 const char *servername,
6439 const char *architecture,
6440 uint32_t level,
6441 union spoolss_DriverInfo **info_p,
6442 uint32_t *count_p)
6444 uint32_t a,i;
6445 WERROR result = WERR_OK;
6447 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6449 for (a=0; archi_table[a].long_archi != NULL; a++) {
6451 union spoolss_DriverInfo *info = NULL;
6452 uint32_t count = 0;
6454 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6455 servername,
6456 archi_table[a].long_archi,
6457 level,
6458 &info,
6459 &count);
6460 if (!W_ERROR_IS_OK(result)) {
6461 continue;
6464 for (i=0; i < count; i++) {
6465 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6466 info[i], info_p, count_p);
6470 return result;
6473 return enumprinterdrivers_level_by_architecture(mem_ctx,
6474 servername,
6475 architecture,
6476 level,
6477 info_p,
6478 count_p);
6481 /****************************************************************
6482 _spoolss_EnumPrinterDrivers
6483 ****************************************************************/
6485 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6486 struct spoolss_EnumPrinterDrivers *r)
6488 const char *cservername;
6489 WERROR result;
6491 /* that's an [in out] buffer */
6493 if (!r->in.buffer && (r->in.offered != 0)) {
6494 return WERR_INVALID_PARAM;
6497 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6499 *r->out.needed = 0;
6500 *r->out.count = 0;
6501 *r->out.info = NULL;
6503 cservername = canon_servername(r->in.server);
6505 if (!is_myname_or_ipaddr(cservername)) {
6506 return WERR_UNKNOWN_PRINTER_DRIVER;
6509 result = enumprinterdrivers_level(p->mem_ctx, cservername,
6510 r->in.environment,
6511 r->in.level,
6512 r->out.info,
6513 r->out.count);
6514 if (!W_ERROR_IS_OK(result)) {
6515 return result;
6518 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6519 spoolss_EnumPrinterDrivers,
6520 *r->out.info, r->in.level,
6521 *r->out.count);
6522 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6523 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6525 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6528 /****************************************************************
6529 _spoolss_EnumForms
6530 ****************************************************************/
6532 WERROR _spoolss_EnumForms(pipes_struct *p,
6533 struct spoolss_EnumForms *r)
6535 WERROR result;
6537 *r->out.count = 0;
6538 *r->out.needed = 0;
6539 *r->out.info = NULL;
6541 /* that's an [in out] buffer */
6543 if (!r->in.buffer && (r->in.offered != 0) ) {
6544 return WERR_INVALID_PARAM;
6547 DEBUG(4,("_spoolss_EnumForms\n"));
6548 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6549 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6551 switch (r->in.level) {
6552 case 1:
6553 result = winreg_printer_enumforms1(p->mem_ctx,
6554 p->server_info,
6555 r->out.count,
6556 r->out.info);
6557 break;
6558 default:
6559 result = WERR_UNKNOWN_LEVEL;
6560 break;
6563 if (!W_ERROR_IS_OK(result)) {
6564 return result;
6567 if (*r->out.count == 0) {
6568 return WERR_NO_MORE_ITEMS;
6571 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6572 spoolss_EnumForms,
6573 *r->out.info, r->in.level,
6574 *r->out.count);
6575 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6576 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6578 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6581 /****************************************************************
6582 _spoolss_GetForm
6583 ****************************************************************/
6585 WERROR _spoolss_GetForm(pipes_struct *p,
6586 struct spoolss_GetForm *r)
6588 WERROR result;
6590 /* that's an [in out] buffer */
6592 if (!r->in.buffer && (r->in.offered != 0)) {
6593 return WERR_INVALID_PARAM;
6596 DEBUG(4,("_spoolss_GetForm\n"));
6597 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6598 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6600 switch (r->in.level) {
6601 case 1:
6602 result = winreg_printer_getform1(p->mem_ctx,
6603 p->server_info,
6604 r->in.form_name,
6605 &r->out.info->info1);
6606 break;
6607 default:
6608 result = WERR_UNKNOWN_LEVEL;
6609 break;
6612 if (!W_ERROR_IS_OK(result)) {
6613 TALLOC_FREE(r->out.info);
6614 return result;
6617 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6618 r->out.info, r->in.level);
6619 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6621 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6624 /****************************************************************************
6625 ****************************************************************************/
6627 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6628 struct spoolss_PortInfo1 *r,
6629 const char *name)
6631 r->port_name = talloc_strdup(mem_ctx, name);
6632 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6634 return WERR_OK;
6637 /****************************************************************************
6638 TODO: This probably needs distinguish between TCP/IP and Local ports
6639 somehow.
6640 ****************************************************************************/
6642 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6643 struct spoolss_PortInfo2 *r,
6644 const char *name)
6646 r->port_name = talloc_strdup(mem_ctx, name);
6647 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6649 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6650 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6652 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6653 W_ERROR_HAVE_NO_MEMORY(r->description);
6655 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6656 r->reserved = 0;
6658 return WERR_OK;
6662 /****************************************************************************
6663 wrapper around the enumer ports command
6664 ****************************************************************************/
6666 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6668 char *cmd = lp_enumports_cmd();
6669 char **qlines = NULL;
6670 char *command = NULL;
6671 int numlines;
6672 int ret;
6673 int fd;
6675 *count = 0;
6676 *lines = NULL;
6678 /* if no hook then just fill in the default port */
6680 if ( !*cmd ) {
6681 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6682 return WERR_NOMEM;
6684 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6685 TALLOC_FREE(qlines);
6686 return WERR_NOMEM;
6688 qlines[1] = NULL;
6689 numlines = 1;
6691 else {
6692 /* we have a valid enumport command */
6694 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6695 if (!command) {
6696 return WERR_NOMEM;
6699 DEBUG(10,("Running [%s]\n", command));
6700 ret = smbrun(command, &fd);
6701 DEBUG(10,("Returned [%d]\n", ret));
6702 TALLOC_FREE(command);
6703 if (ret != 0) {
6704 if (fd != -1) {
6705 close(fd);
6707 return WERR_ACCESS_DENIED;
6710 numlines = 0;
6711 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6712 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6713 close(fd);
6716 *count = numlines;
6717 *lines = qlines;
6719 return WERR_OK;
6722 /****************************************************************************
6723 enumports level 1.
6724 ****************************************************************************/
6726 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6727 union spoolss_PortInfo **info_p,
6728 uint32_t *count)
6730 union spoolss_PortInfo *info = NULL;
6731 int i=0;
6732 WERROR result = WERR_OK;
6733 char **qlines = NULL;
6734 int numlines = 0;
6736 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6737 if (!W_ERROR_IS_OK(result)) {
6738 goto out;
6741 if (numlines) {
6742 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6743 if (!info) {
6744 DEBUG(10,("Returning WERR_NOMEM\n"));
6745 result = WERR_NOMEM;
6746 goto out;
6749 for (i=0; i<numlines; i++) {
6750 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6751 result = fill_port_1(info, &info[i].info1, qlines[i]);
6752 if (!W_ERROR_IS_OK(result)) {
6753 goto out;
6757 TALLOC_FREE(qlines);
6759 out:
6760 if (!W_ERROR_IS_OK(result)) {
6761 TALLOC_FREE(info);
6762 TALLOC_FREE(qlines);
6763 *count = 0;
6764 *info_p = NULL;
6765 return result;
6768 *info_p = info;
6769 *count = numlines;
6771 return WERR_OK;
6774 /****************************************************************************
6775 enumports level 2.
6776 ****************************************************************************/
6778 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6779 union spoolss_PortInfo **info_p,
6780 uint32_t *count)
6782 union spoolss_PortInfo *info = NULL;
6783 int i=0;
6784 WERROR result = WERR_OK;
6785 char **qlines = NULL;
6786 int numlines = 0;
6788 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6789 if (!W_ERROR_IS_OK(result)) {
6790 goto out;
6793 if (numlines) {
6794 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6795 if (!info) {
6796 DEBUG(10,("Returning WERR_NOMEM\n"));
6797 result = WERR_NOMEM;
6798 goto out;
6801 for (i=0; i<numlines; i++) {
6802 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6803 result = fill_port_2(info, &info[i].info2, qlines[i]);
6804 if (!W_ERROR_IS_OK(result)) {
6805 goto out;
6809 TALLOC_FREE(qlines);
6811 out:
6812 if (!W_ERROR_IS_OK(result)) {
6813 TALLOC_FREE(info);
6814 TALLOC_FREE(qlines);
6815 *count = 0;
6816 *info_p = NULL;
6817 return result;
6820 *info_p = info;
6821 *count = numlines;
6823 return WERR_OK;
6826 /****************************************************************
6827 _spoolss_EnumPorts
6828 ****************************************************************/
6830 WERROR _spoolss_EnumPorts(pipes_struct *p,
6831 struct spoolss_EnumPorts *r)
6833 WERROR result;
6835 /* that's an [in out] buffer */
6837 if (!r->in.buffer && (r->in.offered != 0)) {
6838 return WERR_INVALID_PARAM;
6841 DEBUG(4,("_spoolss_EnumPorts\n"));
6843 *r->out.count = 0;
6844 *r->out.needed = 0;
6845 *r->out.info = NULL;
6847 switch (r->in.level) {
6848 case 1:
6849 result = enumports_level_1(p->mem_ctx, r->out.info,
6850 r->out.count);
6851 break;
6852 case 2:
6853 result = enumports_level_2(p->mem_ctx, r->out.info,
6854 r->out.count);
6855 break;
6856 default:
6857 return WERR_UNKNOWN_LEVEL;
6860 if (!W_ERROR_IS_OK(result)) {
6861 return result;
6864 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6865 spoolss_EnumPorts,
6866 *r->out.info, r->in.level,
6867 *r->out.count);
6868 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6869 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6871 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6874 /****************************************************************************
6875 ****************************************************************************/
6877 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
6878 const char *server,
6879 struct spoolss_SetPrinterInfoCtr *info_ctr,
6880 struct spoolss_DeviceMode *devmode,
6881 struct security_descriptor *secdesc,
6882 struct spoolss_UserLevelCtr *user_ctr,
6883 struct policy_handle *handle)
6885 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
6886 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
6887 int snum;
6888 WERROR err = WERR_OK;
6890 /* samba does not have a concept of local, non-shared printers yet, so
6891 * make sure we always setup sharename - gd */
6892 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
6893 (info2->printername != NULL && info2->printername[0] != '\0')) {
6894 DEBUG(5, ("spoolss_addprinterex_level_2: "
6895 "no sharename has been set, setting printername %s as sharename\n",
6896 info2->printername));
6897 info2->sharename = info2->printername;
6900 /* check to see if the printer already exists */
6901 if ((snum = print_queue_snum(info2->sharename)) != -1) {
6902 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
6903 info2->sharename));
6904 return WERR_PRINTER_ALREADY_EXISTS;
6907 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
6908 if ((snum = print_queue_snum(info2->printername)) != -1) {
6909 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
6910 info2->printername));
6911 return WERR_PRINTER_ALREADY_EXISTS;
6915 /* validate printer info struct */
6916 if (!info2->printername || strlen(info2->printername) == 0) {
6917 return WERR_INVALID_PRINTER_NAME;
6919 if (!info2->portname || strlen(info2->portname) == 0) {
6920 return WERR_UNKNOWN_PORT;
6922 if (!info2->drivername || strlen(info2->drivername) == 0) {
6923 return WERR_UNKNOWN_PRINTER_DRIVER;
6925 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
6926 return WERR_UNKNOWN_PRINTPROCESSOR;
6929 /* FIXME!!! smbd should check to see if the driver is installed before
6930 trying to add a printer like this --jerry */
6932 if (*lp_addprinter_cmd() ) {
6933 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6934 info2) ) {
6935 return WERR_ACCESS_DENIED;
6937 } else {
6938 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
6939 "smb.conf parameter \"addprinter command\" is defined. This"
6940 "parameter must exist for this call to succeed\n",
6941 info2->sharename ));
6944 if ((snum = print_queue_snum(info2->sharename)) == -1) {
6945 return WERR_ACCESS_DENIED;
6948 /* you must be a printer admin to add a new printer */
6949 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
6950 return WERR_ACCESS_DENIED;
6954 * Do sanity check on the requested changes for Samba.
6957 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
6958 return WERR_INVALID_PARAM;
6961 if (devmode == NULL) {
6962 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
6965 err = winreg_update_printer(p->mem_ctx,
6966 p->server_info,
6967 info2->sharename,
6968 info2_mask,
6969 info2,
6970 devmode,
6971 secdesc);
6972 if (!W_ERROR_IS_OK(err)) {
6973 return err;
6976 if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
6977 /* Handle open failed - remove addition. */
6978 ZERO_STRUCTP(handle);
6979 return WERR_ACCESS_DENIED;
6982 return WERR_OK;
6985 /****************************************************************
6986 _spoolss_AddPrinterEx
6987 ****************************************************************/
6989 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
6990 struct spoolss_AddPrinterEx *r)
6992 switch (r->in.info_ctr->level) {
6993 case 1:
6994 /* we don't handle yet */
6995 /* but I know what to do ... */
6996 return WERR_UNKNOWN_LEVEL;
6997 case 2:
6998 return spoolss_addprinterex_level_2(p, r->in.server,
6999 r->in.info_ctr,
7000 r->in.devmode_ctr->devmode,
7001 r->in.secdesc_ctr->sd,
7002 r->in.userlevel_ctr,
7003 r->out.handle);
7004 default:
7005 return WERR_UNKNOWN_LEVEL;
7009 /****************************************************************
7010 _spoolss_AddPrinter
7011 ****************************************************************/
7013 WERROR _spoolss_AddPrinter(pipes_struct *p,
7014 struct spoolss_AddPrinter *r)
7016 struct spoolss_AddPrinterEx a;
7017 struct spoolss_UserLevelCtr userlevel_ctr;
7019 ZERO_STRUCT(userlevel_ctr);
7021 userlevel_ctr.level = 1;
7023 a.in.server = r->in.server;
7024 a.in.info_ctr = r->in.info_ctr;
7025 a.in.devmode_ctr = r->in.devmode_ctr;
7026 a.in.secdesc_ctr = r->in.secdesc_ctr;
7027 a.in.userlevel_ctr = &userlevel_ctr;
7028 a.out.handle = r->out.handle;
7030 return _spoolss_AddPrinterEx(p, &a);
7033 /****************************************************************
7034 _spoolss_AddPrinterDriverEx
7035 ****************************************************************/
7037 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7038 struct spoolss_AddPrinterDriverEx *r)
7040 WERROR err = WERR_OK;
7041 char *driver_name = NULL;
7042 uint32_t version;
7043 const char *fn;
7045 switch (p->opnum) {
7046 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7047 fn = "_spoolss_AddPrinterDriver";
7048 break;
7049 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7050 fn = "_spoolss_AddPrinterDriverEx";
7051 break;
7052 default:
7053 return WERR_INVALID_PARAM;
7057 * we only support the semantics of AddPrinterDriver()
7058 * i.e. only copy files that are newer than existing ones
7061 if (r->in.flags == 0) {
7062 return WERR_INVALID_PARAM;
7065 if (r->in.flags != APD_COPY_NEW_FILES) {
7066 return WERR_ACCESS_DENIED;
7069 /* FIXME */
7070 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7071 /* Clever hack from Martin Zielinski <mz@seh.de>
7072 * to allow downgrade from level 8 (Vista).
7074 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7075 r->in.info_ctr->level));
7076 return WERR_UNKNOWN_LEVEL;
7079 DEBUG(5,("Cleaning driver's information\n"));
7080 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7081 if (!W_ERROR_IS_OK(err))
7082 goto done;
7084 DEBUG(5,("Moving driver to final destination\n"));
7085 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7086 &err)) ) {
7087 goto done;
7090 if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7091 err = WERR_ACCESS_DENIED;
7092 goto done;
7096 * I think this is where he DrvUpgradePrinter() hook would be
7097 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7098 * server. Right now, we just need to send ourselves a message
7099 * to update each printer bound to this driver. --jerry
7102 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7103 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7104 fn, driver_name));
7107 done:
7108 return err;
7111 /****************************************************************
7112 _spoolss_AddPrinterDriver
7113 ****************************************************************/
7115 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7116 struct spoolss_AddPrinterDriver *r)
7118 struct spoolss_AddPrinterDriverEx a;
7120 switch (r->in.info_ctr->level) {
7121 case 2:
7122 case 3:
7123 case 4:
7124 case 5:
7125 break;
7126 default:
7127 return WERR_UNKNOWN_LEVEL;
7130 a.in.servername = r->in.servername;
7131 a.in.info_ctr = r->in.info_ctr;
7132 a.in.flags = APD_COPY_NEW_FILES;
7134 return _spoolss_AddPrinterDriverEx(p, &a);
7137 /****************************************************************************
7138 ****************************************************************************/
7140 struct _spoolss_paths {
7141 int type;
7142 const char *share;
7143 const char *dir;
7146 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7148 static const struct _spoolss_paths spoolss_paths[]= {
7149 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7150 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7153 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7154 const char *servername,
7155 const char *environment,
7156 int component,
7157 char **path)
7159 const char *pservername = NULL;
7160 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7161 const char *short_archi;
7163 *path = NULL;
7165 /* environment may be empty */
7166 if (environment && strlen(environment)) {
7167 long_archi = environment;
7170 /* servername may be empty */
7171 if (servername && strlen(servername)) {
7172 pservername = canon_servername(servername);
7174 if (!is_myname_or_ipaddr(pservername)) {
7175 return WERR_INVALID_PARAM;
7179 if (!(short_archi = get_short_archi(long_archi))) {
7180 return WERR_INVALID_ENVIRONMENT;
7183 switch (component) {
7184 case SPOOLSS_PRTPROCS_PATH:
7185 case SPOOLSS_DRIVER_PATH:
7186 if (pservername) {
7187 *path = talloc_asprintf(mem_ctx,
7188 "\\\\%s\\%s\\%s",
7189 pservername,
7190 spoolss_paths[component].share,
7191 short_archi);
7192 } else {
7193 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7194 SPOOLSS_DEFAULT_SERVER_PATH,
7195 spoolss_paths[component].dir,
7196 short_archi);
7198 break;
7199 default:
7200 return WERR_INVALID_PARAM;
7203 if (!*path) {
7204 return WERR_NOMEM;
7207 return WERR_OK;
7210 /****************************************************************************
7211 ****************************************************************************/
7213 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7214 const char *servername,
7215 const char *environment,
7216 struct spoolss_DriverDirectoryInfo1 *r)
7218 WERROR werr;
7219 char *path = NULL;
7221 werr = compose_spoolss_server_path(mem_ctx,
7222 servername,
7223 environment,
7224 SPOOLSS_DRIVER_PATH,
7225 &path);
7226 if (!W_ERROR_IS_OK(werr)) {
7227 return werr;
7230 DEBUG(4,("printer driver directory: [%s]\n", path));
7232 r->directory_name = path;
7234 return WERR_OK;
7237 /****************************************************************
7238 _spoolss_GetPrinterDriverDirectory
7239 ****************************************************************/
7241 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7242 struct spoolss_GetPrinterDriverDirectory *r)
7244 WERROR werror;
7246 /* that's an [in out] buffer */
7248 if (!r->in.buffer && (r->in.offered != 0)) {
7249 return WERR_INVALID_PARAM;
7252 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7253 r->in.level));
7255 *r->out.needed = 0;
7257 /* r->in.level is ignored */
7259 werror = getprinterdriverdir_level_1(p->mem_ctx,
7260 r->in.server,
7261 r->in.environment,
7262 &r->out.info->info1);
7263 if (!W_ERROR_IS_OK(werror)) {
7264 TALLOC_FREE(r->out.info);
7265 return werror;
7268 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7269 r->out.info, r->in.level);
7270 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7272 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7275 /****************************************************************
7276 _spoolss_EnumPrinterData
7277 ****************************************************************/
7279 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7280 struct spoolss_EnumPrinterData *r)
7282 WERROR result;
7283 struct spoolss_EnumPrinterDataEx r2;
7284 uint32_t count;
7285 struct spoolss_PrinterEnumValues *info, *val = NULL;
7286 uint32_t needed;
7288 r2.in.handle = r->in.handle;
7289 r2.in.key_name = "PrinterDriverData";
7290 r2.in.offered = 0;
7291 r2.out.count = &count;
7292 r2.out.info = &info;
7293 r2.out.needed = &needed;
7295 result = _spoolss_EnumPrinterDataEx(p, &r2);
7296 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7297 r2.in.offered = needed;
7298 result = _spoolss_EnumPrinterDataEx(p, &r2);
7300 if (!W_ERROR_IS_OK(result)) {
7301 return result;
7305 * The NT machine wants to know the biggest size of value and data
7307 * cf: MSDN EnumPrinterData remark section
7310 if (!r->in.value_offered && !r->in.data_offered) {
7311 uint32_t biggest_valuesize = 0;
7312 uint32_t biggest_datasize = 0;
7313 int i, name_length;
7315 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7317 for (i=0; i<count; i++) {
7319 name_length = strlen(info[i].value_name);
7320 if (strlen(info[i].value_name) > biggest_valuesize) {
7321 biggest_valuesize = name_length;
7324 if (info[i].data_length > biggest_datasize) {
7325 biggest_datasize = info[i].data_length;
7328 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7329 biggest_datasize));
7332 /* the value is an UNICODE string but real_value_size is the length
7333 in bytes including the trailing 0 */
7335 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7336 *r->out.data_needed = biggest_datasize;
7338 DEBUG(6,("final values: [%d], [%d]\n",
7339 *r->out.value_needed, *r->out.data_needed));
7341 return WERR_OK;
7344 if (r->in.enum_index < count) {
7345 val = &info[r->in.enum_index];
7348 if (val == NULL) {
7349 /* out_value should default to "" or else NT4 has
7350 problems unmarshalling the response */
7352 if (r->in.value_offered) {
7353 *r->out.value_needed = 1;
7354 r->out.value_name = talloc_strdup(r, "");
7355 if (!r->out.value_name) {
7356 return WERR_NOMEM;
7358 } else {
7359 r->out.value_name = NULL;
7360 *r->out.value_needed = 0;
7363 /* the data is counted in bytes */
7365 *r->out.data_needed = r->in.data_offered;
7367 result = WERR_NO_MORE_ITEMS;
7368 } else {
7370 * the value is:
7371 * - counted in bytes in the request
7372 * - counted in UNICODE chars in the max reply
7373 * - counted in bytes in the real size
7375 * take a pause *before* coding not *during* coding
7378 /* name */
7379 if (r->in.value_offered) {
7380 r->out.value_name = talloc_strdup(r, val->value_name);
7381 if (!r->out.value_name) {
7382 return WERR_NOMEM;
7384 *r->out.value_needed = val->value_name_len;
7385 } else {
7386 r->out.value_name = NULL;
7387 *r->out.value_needed = 0;
7390 /* type */
7392 *r->out.type = val->type;
7394 /* data - counted in bytes */
7397 * See the section "Dynamically Typed Query Parameters"
7398 * in MS-RPRN.
7401 if (r->out.data && val->data && val->data->data &&
7402 val->data_length && r->in.data_offered) {
7403 memcpy(r->out.data, val->data->data,
7404 MIN(val->data_length,r->in.data_offered));
7407 *r->out.data_needed = val->data_length;
7409 result = WERR_OK;
7412 return result;
7415 /****************************************************************
7416 _spoolss_SetPrinterData
7417 ****************************************************************/
7419 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7420 struct spoolss_SetPrinterData *r)
7422 struct spoolss_SetPrinterDataEx r2;
7424 r2.in.handle = r->in.handle;
7425 r2.in.key_name = "PrinterDriverData";
7426 r2.in.value_name = r->in.value_name;
7427 r2.in.type = r->in.type;
7428 r2.in.data = r->in.data;
7429 r2.in.offered = r->in.offered;
7431 return _spoolss_SetPrinterDataEx(p, &r2);
7434 /****************************************************************
7435 _spoolss_ResetPrinter
7436 ****************************************************************/
7438 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7439 struct spoolss_ResetPrinter *r)
7441 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7442 int snum;
7444 DEBUG(5,("_spoolss_ResetPrinter\n"));
7447 * All we do is to check to see if the handle and queue is valid.
7448 * This call really doesn't mean anything to us because we only
7449 * support RAW printing. --jerry
7452 if (!Printer) {
7453 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7454 OUR_HANDLE(r->in.handle)));
7455 return WERR_BADFID;
7458 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7459 return WERR_BADFID;
7462 /* blindly return success */
7463 return WERR_OK;
7466 /****************************************************************
7467 _spoolss_DeletePrinterData
7468 ****************************************************************/
7470 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7471 struct spoolss_DeletePrinterData *r)
7473 struct spoolss_DeletePrinterDataEx r2;
7475 r2.in.handle = r->in.handle;
7476 r2.in.key_name = "PrinterDriverData";
7477 r2.in.value_name = r->in.value_name;
7479 return _spoolss_DeletePrinterDataEx(p, &r2);
7482 /****************************************************************
7483 _spoolss_AddForm
7484 ****************************************************************/
7486 WERROR _spoolss_AddForm(pipes_struct *p,
7487 struct spoolss_AddForm *r)
7489 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7490 int snum = -1;
7491 WERROR status = WERR_OK;
7492 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7494 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7496 DEBUG(5,("_spoolss_AddForm\n"));
7498 if (!Printer) {
7499 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7500 OUR_HANDLE(r->in.handle)));
7501 return WERR_BADFID;
7504 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7505 and not a printer admin, then fail */
7507 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7508 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7509 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7510 p->server_info->info3->base.domain.string,
7511 NULL,
7512 p->server_info->ptok,
7513 lp_printer_admin(snum))) {
7514 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7515 return WERR_ACCESS_DENIED;
7518 switch (form->flags) {
7519 case SPOOLSS_FORM_USER:
7520 case SPOOLSS_FORM_BUILTIN:
7521 case SPOOLSS_FORM_PRINTER:
7522 break;
7523 default:
7524 return WERR_INVALID_PARAM;
7527 status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7528 if (!W_ERROR_IS_OK(status)) {
7529 return status;
7533 * ChangeID must always be set if this is a printer
7535 if (Printer->printer_type == SPLHND_PRINTER) {
7536 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7537 return WERR_BADFID;
7540 status = winreg_printer_update_changeid(p->mem_ctx,
7541 p->server_info,
7542 lp_const_servicename(snum));
7543 if (!W_ERROR_IS_OK(status)) {
7544 return status;
7548 return status;
7551 /****************************************************************
7552 _spoolss_DeleteForm
7553 ****************************************************************/
7555 WERROR _spoolss_DeleteForm(pipes_struct *p,
7556 struct spoolss_DeleteForm *r)
7558 const char *form_name = r->in.form_name;
7559 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7560 int snum = -1;
7561 WERROR status = WERR_OK;
7562 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7564 DEBUG(5,("_spoolss_DeleteForm\n"));
7566 if (!Printer) {
7567 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7568 OUR_HANDLE(r->in.handle)));
7569 return WERR_BADFID;
7572 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7573 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7574 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7575 p->server_info->info3->base.domain.string,
7576 NULL,
7577 p->server_info->ptok,
7578 lp_printer_admin(snum))) {
7579 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7580 return WERR_ACCESS_DENIED;
7583 status = winreg_printer_deleteform1(p->mem_ctx,
7584 p->server_info,
7585 form_name);
7586 if (!W_ERROR_IS_OK(status)) {
7587 return status;
7591 * ChangeID must always be set if this is a printer
7593 if (Printer->printer_type == SPLHND_PRINTER) {
7594 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7595 return WERR_BADFID;
7598 status = winreg_printer_update_changeid(p->mem_ctx,
7599 p->server_info,
7600 lp_const_servicename(snum));
7601 if (!W_ERROR_IS_OK(status)) {
7602 return status;
7606 return status;
7609 /****************************************************************
7610 _spoolss_SetForm
7611 ****************************************************************/
7613 WERROR _spoolss_SetForm(pipes_struct *p,
7614 struct spoolss_SetForm *r)
7616 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7617 const char *form_name = r->in.form_name;
7618 int snum = -1;
7619 WERROR status = WERR_OK;
7620 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7622 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7624 DEBUG(5,("_spoolss_SetForm\n"));
7626 if (!Printer) {
7627 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7628 OUR_HANDLE(r->in.handle)));
7629 return WERR_BADFID;
7632 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7633 and not a printer admin, then fail */
7635 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7636 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7637 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7638 p->server_info->info3->base.domain.string,
7639 NULL,
7640 p->server_info->ptok,
7641 lp_printer_admin(snum))) {
7642 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7643 return WERR_ACCESS_DENIED;
7646 status = winreg_printer_setform1(p->mem_ctx,
7647 p->server_info,
7648 form_name,
7649 form);
7650 if (!W_ERROR_IS_OK(status)) {
7651 return status;
7655 * ChangeID must always be set if this is a printer
7657 if (Printer->printer_type == SPLHND_PRINTER) {
7658 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7659 return WERR_BADFID;
7662 status = winreg_printer_update_changeid(p->mem_ctx,
7663 p->server_info,
7664 lp_const_servicename(snum));
7665 if (!W_ERROR_IS_OK(status)) {
7666 return status;
7670 return status;
7673 /****************************************************************************
7674 fill_print_processor1
7675 ****************************************************************************/
7677 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7678 struct spoolss_PrintProcessorInfo1 *r,
7679 const char *print_processor_name)
7681 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7682 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7684 return WERR_OK;
7687 /****************************************************************************
7688 enumprintprocessors level 1.
7689 ****************************************************************************/
7691 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7692 union spoolss_PrintProcessorInfo **info_p,
7693 uint32_t *count)
7695 union spoolss_PrintProcessorInfo *info;
7696 WERROR result;
7698 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7699 W_ERROR_HAVE_NO_MEMORY(info);
7701 *count = 1;
7703 result = fill_print_processor1(info, &info[0].info1, "winprint");
7704 if (!W_ERROR_IS_OK(result)) {
7705 goto out;
7708 out:
7709 if (!W_ERROR_IS_OK(result)) {
7710 TALLOC_FREE(info);
7711 *count = 0;
7712 return result;
7715 *info_p = info;
7717 return WERR_OK;
7720 /****************************************************************
7721 _spoolss_EnumPrintProcessors
7722 ****************************************************************/
7724 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7725 struct spoolss_EnumPrintProcessors *r)
7727 WERROR result;
7729 /* that's an [in out] buffer */
7731 if (!r->in.buffer && (r->in.offered != 0)) {
7732 return WERR_INVALID_PARAM;
7735 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
7738 * Enumerate the print processors ...
7740 * Just reply with "winprint", to keep NT happy
7741 * and I can use my nice printer checker.
7744 *r->out.count = 0;
7745 *r->out.needed = 0;
7746 *r->out.info = NULL;
7748 switch (r->in.level) {
7749 case 1:
7750 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
7751 r->out.count);
7752 break;
7753 default:
7754 return WERR_UNKNOWN_LEVEL;
7757 if (!W_ERROR_IS_OK(result)) {
7758 return result;
7761 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7762 spoolss_EnumPrintProcessors,
7763 *r->out.info, r->in.level,
7764 *r->out.count);
7765 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7766 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7768 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7771 /****************************************************************************
7772 fill_printprocdatatype1
7773 ****************************************************************************/
7775 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
7776 struct spoolss_PrintProcDataTypesInfo1 *r,
7777 const char *name_array)
7779 r->name_array = talloc_strdup(mem_ctx, name_array);
7780 W_ERROR_HAVE_NO_MEMORY(r->name_array);
7782 return WERR_OK;
7785 /****************************************************************************
7786 enumprintprocdatatypes level 1.
7787 ****************************************************************************/
7789 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
7790 union spoolss_PrintProcDataTypesInfo **info_p,
7791 uint32_t *count)
7793 WERROR result;
7794 union spoolss_PrintProcDataTypesInfo *info;
7796 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
7797 W_ERROR_HAVE_NO_MEMORY(info);
7799 *count = 1;
7801 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
7802 if (!W_ERROR_IS_OK(result)) {
7803 goto out;
7806 out:
7807 if (!W_ERROR_IS_OK(result)) {
7808 TALLOC_FREE(info);
7809 *count = 0;
7810 return result;
7813 *info_p = info;
7815 return WERR_OK;
7818 /****************************************************************
7819 _spoolss_EnumPrintProcDataTypes
7820 ****************************************************************/
7822 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
7823 struct spoolss_EnumPrintProcDataTypes *r)
7825 WERROR result;
7827 /* that's an [in out] buffer */
7829 if (!r->in.buffer && (r->in.offered != 0)) {
7830 return WERR_INVALID_PARAM;
7833 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
7835 *r->out.count = 0;
7836 *r->out.needed = 0;
7837 *r->out.info = NULL;
7839 switch (r->in.level) {
7840 case 1:
7841 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
7842 r->out.count);
7843 break;
7844 default:
7845 return WERR_UNKNOWN_LEVEL;
7848 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7849 spoolss_EnumPrintProcDataTypes,
7850 *r->out.info, r->in.level,
7851 *r->out.count);
7852 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7853 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7855 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7858 /****************************************************************************
7859 fill_monitor_1
7860 ****************************************************************************/
7862 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
7863 struct spoolss_MonitorInfo1 *r,
7864 const char *monitor_name)
7866 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
7867 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7869 return WERR_OK;
7872 /****************************************************************************
7873 fill_monitor_2
7874 ****************************************************************************/
7876 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
7877 struct spoolss_MonitorInfo2 *r,
7878 const char *monitor_name,
7879 const char *environment,
7880 const char *dll_name)
7882 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
7883 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7884 r->environment = talloc_strdup(mem_ctx, environment);
7885 W_ERROR_HAVE_NO_MEMORY(r->environment);
7886 r->dll_name = talloc_strdup(mem_ctx, dll_name);
7887 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
7889 return WERR_OK;
7892 /****************************************************************************
7893 enumprintmonitors level 1.
7894 ****************************************************************************/
7896 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
7897 union spoolss_MonitorInfo **info_p,
7898 uint32_t *count)
7900 union spoolss_MonitorInfo *info;
7901 WERROR result = WERR_OK;
7903 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
7904 W_ERROR_HAVE_NO_MEMORY(info);
7906 *count = 2;
7908 result = fill_monitor_1(info, &info[0].info1,
7909 SPL_LOCAL_PORT);
7910 if (!W_ERROR_IS_OK(result)) {
7911 goto out;
7914 result = fill_monitor_1(info, &info[1].info1,
7915 SPL_TCPIP_PORT);
7916 if (!W_ERROR_IS_OK(result)) {
7917 goto out;
7920 out:
7921 if (!W_ERROR_IS_OK(result)) {
7922 TALLOC_FREE(info);
7923 *count = 0;
7924 return result;
7927 *info_p = info;
7929 return WERR_OK;
7932 /****************************************************************************
7933 enumprintmonitors level 2.
7934 ****************************************************************************/
7936 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
7937 union spoolss_MonitorInfo **info_p,
7938 uint32_t *count)
7940 union spoolss_MonitorInfo *info;
7941 WERROR result = WERR_OK;
7943 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
7944 W_ERROR_HAVE_NO_MEMORY(info);
7946 *count = 2;
7948 result = fill_monitor_2(info, &info[0].info2,
7949 SPL_LOCAL_PORT,
7950 "Windows NT X86", /* FIXME */
7951 "localmon.dll");
7952 if (!W_ERROR_IS_OK(result)) {
7953 goto out;
7956 result = fill_monitor_2(info, &info[1].info2,
7957 SPL_TCPIP_PORT,
7958 "Windows NT X86", /* FIXME */
7959 "tcpmon.dll");
7960 if (!W_ERROR_IS_OK(result)) {
7961 goto out;
7964 out:
7965 if (!W_ERROR_IS_OK(result)) {
7966 TALLOC_FREE(info);
7967 *count = 0;
7968 return result;
7971 *info_p = info;
7973 return WERR_OK;
7976 /****************************************************************
7977 _spoolss_EnumMonitors
7978 ****************************************************************/
7980 WERROR _spoolss_EnumMonitors(pipes_struct *p,
7981 struct spoolss_EnumMonitors *r)
7983 WERROR result;
7985 /* that's an [in out] buffer */
7987 if (!r->in.buffer && (r->in.offered != 0)) {
7988 return WERR_INVALID_PARAM;
7991 DEBUG(5,("_spoolss_EnumMonitors\n"));
7994 * Enumerate the print monitors ...
7996 * Just reply with "Local Port", to keep NT happy
7997 * and I can use my nice printer checker.
8000 *r->out.count = 0;
8001 *r->out.needed = 0;
8002 *r->out.info = NULL;
8004 switch (r->in.level) {
8005 case 1:
8006 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8007 r->out.count);
8008 break;
8009 case 2:
8010 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8011 r->out.count);
8012 break;
8013 default:
8014 return WERR_UNKNOWN_LEVEL;
8017 if (!W_ERROR_IS_OK(result)) {
8018 return result;
8021 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8022 spoolss_EnumMonitors,
8023 *r->out.info, r->in.level,
8024 *r->out.count);
8025 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8026 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8028 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8031 /****************************************************************************
8032 ****************************************************************************/
8034 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8035 const print_queue_struct *queue,
8036 int count, int snum,
8037 const NT_PRINTER_INFO_LEVEL *ntprinter,
8038 uint32_t jobid,
8039 struct spoolss_JobInfo1 *r)
8041 int i = 0;
8042 bool found = false;
8044 for (i=0; i<count; i++) {
8045 if (queue[i].job == (int)jobid) {
8046 found = true;
8047 break;
8051 if (found == false) {
8052 /* NT treats not found as bad param... yet another bad choice */
8053 return WERR_INVALID_PARAM;
8056 return fill_job_info1(mem_ctx,
8058 &queue[i],
8060 snum,
8061 ntprinter);
8064 /****************************************************************************
8065 ****************************************************************************/
8067 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8068 const print_queue_struct *queue,
8069 int count, int snum,
8070 const NT_PRINTER_INFO_LEVEL *ntprinter,
8071 uint32_t jobid,
8072 struct spoolss_JobInfo2 *r)
8074 int i = 0;
8075 bool found = false;
8076 struct spoolss_DeviceMode *devmode;
8078 for (i=0; i<count; i++) {
8079 if (queue[i].job == (int)jobid) {
8080 found = true;
8081 break;
8085 if (found == false) {
8086 /* NT treats not found as bad param... yet another bad
8087 choice */
8088 return WERR_INVALID_PARAM;
8092 * if the print job does not have a DEVMODE associated with it,
8093 * just use the one for the printer. A NULL devicemode is not
8094 * a failure condition
8097 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8098 if (!devmode) {
8099 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8100 W_ERROR_HAVE_NO_MEMORY(devmode);
8103 return fill_job_info2(mem_ctx,
8105 &queue[i],
8107 snum,
8108 ntprinter,
8109 devmode);
8112 /****************************************************************
8113 _spoolss_GetJob
8114 ****************************************************************/
8116 WERROR _spoolss_GetJob(pipes_struct *p,
8117 struct spoolss_GetJob *r)
8119 WERROR result = WERR_OK;
8120 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8121 int snum;
8122 int count;
8123 print_queue_struct *queue = NULL;
8124 print_status_struct prt_status;
8126 /* that's an [in out] buffer */
8128 if (!r->in.buffer && (r->in.offered != 0)) {
8129 return WERR_INVALID_PARAM;
8132 DEBUG(5,("_spoolss_GetJob\n"));
8134 *r->out.needed = 0;
8136 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8137 return WERR_BADFID;
8140 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8141 if (!W_ERROR_IS_OK(result)) {
8142 return result;
8145 count = print_queue_status(snum, &queue, &prt_status);
8147 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8148 count, prt_status.status, prt_status.message));
8150 switch (r->in.level) {
8151 case 1:
8152 result = getjob_level_1(p->mem_ctx,
8153 queue, count, snum, ntprinter,
8154 r->in.job_id, &r->out.info->info1);
8155 break;
8156 case 2:
8157 result = getjob_level_2(p->mem_ctx,
8158 queue, count, snum, ntprinter,
8159 r->in.job_id, &r->out.info->info2);
8160 break;
8161 default:
8162 result = WERR_UNKNOWN_LEVEL;
8163 break;
8166 SAFE_FREE(queue);
8167 free_a_printer(&ntprinter, 2);
8169 if (!W_ERROR_IS_OK(result)) {
8170 TALLOC_FREE(r->out.info);
8171 return result;
8174 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8175 r->in.level);
8176 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8178 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8181 /****************************************************************
8182 _spoolss_GetPrinterDataEx
8183 ****************************************************************/
8185 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8186 struct spoolss_GetPrinterDataEx *r)
8189 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8190 const char *printer;
8191 int snum = 0;
8192 WERROR result = WERR_OK;
8193 DATA_BLOB blob;
8194 enum winreg_Type val_type;
8195 uint8_t *val_data;
8196 uint32_t val_size;
8199 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8201 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8202 r->in.key_name, r->in.value_name));
8204 /* in case of problem, return some default values */
8206 *r->out.needed = 0;
8207 *r->out.type = REG_NONE;
8209 if (!Printer) {
8210 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8211 OUR_HANDLE(r->in.handle)));
8212 result = WERR_BADFID;
8213 goto done;
8216 /* Is the handle to a printer or to the server? */
8218 if (Printer->printer_type == SPLHND_SERVER) {
8220 union spoolss_PrinterData data;
8222 result = getprinterdata_printer_server(p->mem_ctx,
8223 r->in.value_name,
8224 r->out.type,
8225 &data);
8226 if (!W_ERROR_IS_OK(result)) {
8227 return result;
8230 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8231 *r->out.type, &data);
8232 if (!W_ERROR_IS_OK(result)) {
8233 return result;
8236 *r->out.needed = blob.length;
8238 if (r->in.offered >= *r->out.needed) {
8239 memcpy(r->out.data, blob.data, blob.length);
8242 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8245 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8246 return WERR_BADFID;
8248 printer = lp_const_servicename(snum);
8250 /* check to see if the keyname is valid */
8251 if (!strlen(r->in.key_name)) {
8252 return WERR_INVALID_PARAM;
8255 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8256 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8257 strequal(r->in.value_name, "ChangeId")) {
8258 *r->out.type = REG_DWORD;
8259 *r->out.needed = 4;
8260 if (r->in.offered >= *r->out.needed) {
8261 uint32_t changeid = 0;
8263 result = winreg_printer_get_changeid(p->mem_ctx,
8264 p->server_info,
8265 printer,
8266 &changeid);
8267 if (!W_ERROR_IS_OK(result)) {
8268 return result;
8271 SIVAL(r->out.data, 0, changeid);
8272 result = WERR_OK;
8274 goto done;
8277 result = winreg_get_printer_dataex(p->mem_ctx,
8278 p->server_info,
8279 printer,
8280 r->in.key_name,
8281 r->in.value_name,
8282 &val_type,
8283 &val_data,
8284 &val_size);
8285 if (!W_ERROR_IS_OK(result)) {
8286 return result;
8289 *r->out.needed = val_size;
8290 *r->out.type = val_type;
8292 if (r->in.offered >= *r->out.needed) {
8293 memcpy(r->out.data, val_data, val_size);
8296 done:
8297 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8298 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8300 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8303 /****************************************************************
8304 _spoolss_SetPrinterDataEx
8305 ****************************************************************/
8307 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8308 struct spoolss_SetPrinterDataEx *r)
8310 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8311 int snum = 0;
8312 WERROR result = WERR_OK;
8313 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8314 char *oid_string;
8316 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8318 /* From MSDN documentation of SetPrinterDataEx: pass request to
8319 SetPrinterData if key is "PrinterDriverData" */
8321 if (!Printer) {
8322 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8323 OUR_HANDLE(r->in.handle)));
8324 return WERR_BADFID;
8327 if (Printer->printer_type == SPLHND_SERVER) {
8328 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8329 "Not implemented for server handles yet\n"));
8330 return WERR_INVALID_PARAM;
8333 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8334 return WERR_BADFID;
8338 * Access check : NT returns "access denied" if you make a
8339 * SetPrinterData call without the necessary privildge.
8340 * we were originally returning OK if nothing changed
8341 * which made Win2k issue **a lot** of SetPrinterData
8342 * when connecting to a printer --jerry
8345 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8346 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8347 "change denied by handle access permissions\n"));
8348 return WERR_ACCESS_DENIED;
8351 result = winreg_get_printer(Printer, p->server_info,
8352 Printer->servername,
8353 lp_servicename(snum),
8354 &pinfo2);
8355 if (!W_ERROR_IS_OK(result)) {
8356 return result;
8359 /* check for OID in valuename */
8361 oid_string = strchr(r->in.value_name, ',');
8362 if (oid_string) {
8363 *oid_string = '\0';
8364 oid_string++;
8367 /* save the registry data */
8369 result = winreg_set_printer_dataex(p->mem_ctx,
8370 p->server_info,
8371 pinfo2->sharename,
8372 r->in.key_name,
8373 r->in.value_name,
8374 r->in.type,
8375 r->in.data,
8376 r->in.offered);
8378 if (W_ERROR_IS_OK(result)) {
8379 /* save the OID if one was specified */
8380 if (oid_string) {
8381 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8382 r->in.key_name, SPOOL_OID_KEY);
8383 if (!str) {
8384 result = WERR_NOMEM;
8385 goto done;
8389 * I'm not checking the status here on purpose. Don't know
8390 * if this is right, but I'm returning the status from the
8391 * previous set_printer_dataex() call. I have no idea if
8392 * this is right. --jerry
8394 winreg_set_printer_dataex(p->mem_ctx,
8395 p->server_info,
8396 pinfo2->sharename,
8397 str,
8398 r->in.value_name,
8399 REG_SZ,
8400 (uint8_t *) oid_string,
8401 strlen(oid_string) + 1);
8404 result = winreg_printer_update_changeid(p->mem_ctx,
8405 p->server_info,
8406 lp_const_servicename(snum));
8410 done:
8411 talloc_free(pinfo2);
8412 return result;
8415 /****************************************************************
8416 _spoolss_DeletePrinterDataEx
8417 ****************************************************************/
8419 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8420 struct spoolss_DeletePrinterDataEx *r)
8422 const char *printer;
8423 int snum=0;
8424 WERROR status = WERR_OK;
8425 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8427 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8429 if (!Printer) {
8430 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8431 "Invalid handle (%s:%u:%u).\n",
8432 OUR_HANDLE(r->in.handle)));
8433 return WERR_BADFID;
8436 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8437 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8438 "printer properties change denied by handle\n"));
8439 return WERR_ACCESS_DENIED;
8442 if (!r->in.value_name || !r->in.key_name) {
8443 return WERR_NOMEM;
8446 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8447 return WERR_BADFID;
8449 printer = lp_const_servicename(snum);
8451 status = winreg_delete_printer_dataex(p->mem_ctx,
8452 p->server_info,
8453 printer,
8454 r->in.key_name,
8455 r->in.value_name);
8456 if (W_ERROR_IS_OK(status)) {
8457 status = winreg_printer_update_changeid(p->mem_ctx,
8458 p->server_info,
8459 printer);
8462 return status;
8465 /****************************************************************
8466 _spoolss_EnumPrinterKey
8467 ****************************************************************/
8469 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8470 struct spoolss_EnumPrinterKey *r)
8472 uint32_t num_keys;
8473 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8474 int snum = 0;
8475 WERROR result = WERR_BADFILE;
8476 const char **array = NULL;
8477 DATA_BLOB blob;
8479 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8481 if (!Printer) {
8482 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8483 OUR_HANDLE(r->in.handle)));
8484 return WERR_BADFID;
8487 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8488 return WERR_BADFID;
8491 result = winreg_enum_printer_key(p->mem_ctx,
8492 p->server_info,
8493 lp_const_servicename(snum),
8494 r->in.key_name,
8495 &num_keys,
8496 &array);
8497 if (!W_ERROR_IS_OK(result)) {
8498 goto done;
8501 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8502 result = WERR_NOMEM;
8503 goto done;
8506 *r->out._ndr_size = r->in.offered / 2;
8507 *r->out.needed = blob.length;
8509 if (r->in.offered < *r->out.needed) {
8510 result = WERR_MORE_DATA;
8511 } else {
8512 result = WERR_OK;
8513 r->out.key_buffer->string_array = array;
8516 done:
8517 if (!W_ERROR_IS_OK(result)) {
8518 TALLOC_FREE(array);
8519 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8520 *r->out.needed = 0;
8524 return result;
8527 /****************************************************************
8528 _spoolss_DeletePrinterKey
8529 ****************************************************************/
8531 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8532 struct spoolss_DeletePrinterKey *r)
8534 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8535 int snum=0;
8536 WERROR status;
8537 const char *printer;
8539 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8541 if (!Printer) {
8542 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8543 OUR_HANDLE(r->in.handle)));
8544 return WERR_BADFID;
8547 /* if keyname == NULL, return error */
8548 if ( !r->in.key_name )
8549 return WERR_INVALID_PARAM;
8551 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8552 return WERR_BADFID;
8555 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8556 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8557 "printer properties change denied by handle\n"));
8558 return WERR_ACCESS_DENIED;
8561 printer = lp_const_servicename(snum);
8563 /* delete the key and all subkeys */
8564 status = winreg_delete_printer_key(p->mem_ctx,
8565 p->server_info,
8566 printer,
8567 r->in.key_name);
8568 if (W_ERROR_IS_OK(status)) {
8569 status = winreg_printer_update_changeid(p->mem_ctx,
8570 p->server_info,
8571 printer);
8574 return status;
8577 /****************************************************************
8578 _spoolss_EnumPrinterDataEx
8579 ****************************************************************/
8581 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8582 struct spoolss_EnumPrinterDataEx *r)
8584 uint32_t count = 0;
8585 struct spoolss_PrinterEnumValues *info = NULL;
8586 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8587 int snum;
8588 WERROR result;
8590 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8592 *r->out.count = 0;
8593 *r->out.needed = 0;
8594 *r->out.info = NULL;
8596 if (!Printer) {
8597 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8598 OUR_HANDLE(r->in.handle)));
8599 return WERR_BADFID;
8603 * first check for a keyname of NULL or "". Win2k seems to send
8604 * this a lot and we should send back WERR_INVALID_PARAM
8605 * no need to spend time looking up the printer in this case.
8606 * --jerry
8609 if (!strlen(r->in.key_name)) {
8610 result = WERR_INVALID_PARAM;
8611 goto done;
8614 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8615 return WERR_BADFID;
8618 /* now look for a match on the key name */
8619 result = winreg_enum_printer_dataex(p->mem_ctx,
8620 p->server_info,
8621 lp_const_servicename(snum),
8622 r->in.key_name,
8623 &count,
8624 &info);
8625 if (!W_ERROR_IS_OK(result)) {
8626 goto done;
8629 #if 0 /* FIXME - gd */
8630 /* housekeeping information in the reply */
8632 /* Fix from Martin Zielinski <mz@seh.de> - ensure
8633 * the hand marshalled container size is a multiple
8634 * of 4 bytes for RPC alignment.
8637 if (needed % 4) {
8638 needed += 4-(needed % 4);
8640 #endif
8641 *r->out.count = count;
8642 *r->out.info = info;
8644 done:
8645 if (!W_ERROR_IS_OK(result)) {
8646 return result;
8649 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8650 spoolss_EnumPrinterDataEx,
8651 *r->out.info,
8652 *r->out.count);
8653 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8654 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8656 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8659 /****************************************************************************
8660 ****************************************************************************/
8662 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8663 const char *servername,
8664 const char *environment,
8665 struct spoolss_PrintProcessorDirectoryInfo1 *r)
8667 WERROR werr;
8668 char *path = NULL;
8670 werr = compose_spoolss_server_path(mem_ctx,
8671 servername,
8672 environment,
8673 SPOOLSS_PRTPROCS_PATH,
8674 &path);
8675 if (!W_ERROR_IS_OK(werr)) {
8676 return werr;
8679 DEBUG(4,("print processor directory: [%s]\n", path));
8681 r->directory_name = path;
8683 return WERR_OK;
8686 /****************************************************************
8687 _spoolss_GetPrintProcessorDirectory
8688 ****************************************************************/
8690 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
8691 struct spoolss_GetPrintProcessorDirectory *r)
8693 WERROR result;
8695 /* that's an [in out] buffer */
8697 if (!r->in.buffer && (r->in.offered != 0)) {
8698 return WERR_INVALID_PARAM;
8701 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
8702 r->in.level));
8704 *r->out.needed = 0;
8706 /* r->in.level is ignored */
8708 /* We always should reply with a local print processor directory so that
8709 * users are not forced to have a [prnproc$] share on the Samba spoolss
8710 * server - Guenther */
8712 result = getprintprocessordirectory_level_1(p->mem_ctx,
8713 NULL, /* r->in.server */
8714 r->in.environment,
8715 &r->out.info->info1);
8716 if (!W_ERROR_IS_OK(result)) {
8717 TALLOC_FREE(r->out.info);
8718 return result;
8721 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
8722 r->out.info, r->in.level);
8723 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8725 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8728 /*******************************************************************
8729 ********************************************************************/
8731 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
8732 const char *dllname)
8734 enum ndr_err_code ndr_err;
8735 struct spoolss_MonitorUi ui;
8737 ui.dll_name = dllname;
8739 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
8740 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
8741 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8742 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
8744 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8747 /*******************************************************************
8748 Streams the monitor UI DLL name in UNICODE
8749 *******************************************************************/
8751 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
8752 NT_USER_TOKEN *token, DATA_BLOB *in,
8753 DATA_BLOB *out, uint32_t *needed)
8755 const char *dllname = "tcpmonui.dll";
8757 *needed = (strlen(dllname)+1) * 2;
8759 if (out->length < *needed) {
8760 return WERR_INSUFFICIENT_BUFFER;
8763 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8764 return WERR_NOMEM;
8767 return WERR_OK;
8770 /*******************************************************************
8771 ********************************************************************/
8773 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
8774 struct spoolss_PortData1 *port1,
8775 const DATA_BLOB *buf)
8777 enum ndr_err_code ndr_err;
8778 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
8779 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
8780 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8781 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
8783 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8786 /*******************************************************************
8787 ********************************************************************/
8789 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
8790 struct spoolss_PortData2 *port2,
8791 const DATA_BLOB *buf)
8793 enum ndr_err_code ndr_err;
8794 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
8795 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
8796 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8797 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
8799 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8802 /*******************************************************************
8803 Create a new TCP/IP port
8804 *******************************************************************/
8806 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
8807 NT_USER_TOKEN *token, DATA_BLOB *in,
8808 DATA_BLOB *out, uint32_t *needed)
8810 struct spoolss_PortData1 port1;
8811 struct spoolss_PortData2 port2;
8812 char *device_uri = NULL;
8813 uint32_t version;
8815 const char *portname;
8816 const char *hostaddress;
8817 const char *queue;
8818 uint32_t port_number;
8819 uint32_t protocol;
8821 /* peek for spoolss_PortData version */
8823 if (!in || (in->length < (128 + 4))) {
8824 return WERR_GENERAL_FAILURE;
8827 version = IVAL(in->data, 128);
8829 switch (version) {
8830 case 1:
8831 ZERO_STRUCT(port1);
8833 if (!pull_port_data_1(mem_ctx, &port1, in)) {
8834 return WERR_NOMEM;
8837 portname = port1.portname;
8838 hostaddress = port1.hostaddress;
8839 queue = port1.queue;
8840 protocol = port1.protocol;
8841 port_number = port1.port_number;
8843 break;
8844 case 2:
8845 ZERO_STRUCT(port2);
8847 if (!pull_port_data_2(mem_ctx, &port2, in)) {
8848 return WERR_NOMEM;
8851 portname = port2.portname;
8852 hostaddress = port2.hostaddress;
8853 queue = port2.queue;
8854 protocol = port2.protocol;
8855 port_number = port2.port_number;
8857 break;
8858 default:
8859 DEBUG(1,("xcvtcp_addport: "
8860 "unknown version of port_data: %d\n", version));
8861 return WERR_UNKNOWN_PORT;
8864 /* create the device URI and call the add_port_hook() */
8866 switch (protocol) {
8867 case PROTOCOL_RAWTCP_TYPE:
8868 device_uri = talloc_asprintf(mem_ctx,
8869 "socket://%s:%d/", hostaddress,
8870 port_number);
8871 break;
8873 case PROTOCOL_LPR_TYPE:
8874 device_uri = talloc_asprintf(mem_ctx,
8875 "lpr://%s/%s", hostaddress, queue );
8876 break;
8878 default:
8879 return WERR_UNKNOWN_PORT;
8882 if (!device_uri) {
8883 return WERR_NOMEM;
8886 return add_port_hook(mem_ctx, token, portname, device_uri);
8889 /*******************************************************************
8890 *******************************************************************/
8892 struct xcv_api_table xcvtcp_cmds[] = {
8893 { "MonitorUI", xcvtcp_monitorui },
8894 { "AddPort", xcvtcp_addport},
8895 { NULL, NULL }
8898 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
8899 NT_USER_TOKEN *token, const char *command,
8900 DATA_BLOB *inbuf,
8901 DATA_BLOB *outbuf,
8902 uint32_t *needed )
8904 int i;
8906 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
8908 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
8909 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
8910 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
8913 return WERR_BADFUNC;
8916 /*******************************************************************
8917 *******************************************************************/
8918 #if 0 /* don't support management using the "Local Port" monitor */
8920 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
8921 NT_USER_TOKEN *token, DATA_BLOB *in,
8922 DATA_BLOB *out, uint32_t *needed)
8924 const char *dllname = "localui.dll";
8926 *needed = (strlen(dllname)+1) * 2;
8928 if (out->length < *needed) {
8929 return WERR_INSUFFICIENT_BUFFER;
8932 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8933 return WERR_NOMEM;
8936 return WERR_OK;
8939 /*******************************************************************
8940 *******************************************************************/
8942 struct xcv_api_table xcvlocal_cmds[] = {
8943 { "MonitorUI", xcvlocal_monitorui },
8944 { NULL, NULL }
8946 #else
8947 struct xcv_api_table xcvlocal_cmds[] = {
8948 { NULL, NULL }
8950 #endif
8954 /*******************************************************************
8955 *******************************************************************/
8957 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
8958 NT_USER_TOKEN *token, const char *command,
8959 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
8960 uint32_t *needed)
8962 int i;
8964 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
8966 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
8967 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
8968 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
8970 return WERR_BADFUNC;
8973 /****************************************************************
8974 _spoolss_XcvData
8975 ****************************************************************/
8977 WERROR _spoolss_XcvData(pipes_struct *p,
8978 struct spoolss_XcvData *r)
8980 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8981 DATA_BLOB out_data = data_blob_null;
8982 WERROR werror;
8984 if (!Printer) {
8985 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
8986 OUR_HANDLE(r->in.handle)));
8987 return WERR_BADFID;
8990 /* Has to be a handle to the TCP/IP port monitor */
8992 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
8993 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
8994 return WERR_BADFID;
8997 /* requires administrative access to the server */
8999 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9000 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9001 return WERR_ACCESS_DENIED;
9004 /* Allocate the outgoing buffer */
9006 if (r->in.out_data_size) {
9007 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9008 if (out_data.data == NULL) {
9009 return WERR_NOMEM;
9013 switch ( Printer->printer_type ) {
9014 case SPLHND_PORTMON_TCP:
9015 werror = process_xcvtcp_command(p->mem_ctx,
9016 p->server_info->ptok,
9017 r->in.function_name,
9018 &r->in.in_data, &out_data,
9019 r->out.needed);
9020 break;
9021 case SPLHND_PORTMON_LOCAL:
9022 werror = process_xcvlocal_command(p->mem_ctx,
9023 p->server_info->ptok,
9024 r->in.function_name,
9025 &r->in.in_data, &out_data,
9026 r->out.needed);
9027 break;
9028 default:
9029 werror = WERR_INVALID_PRINT_MONITOR;
9032 if (!W_ERROR_IS_OK(werror)) {
9033 return werror;
9036 *r->out.status_code = 0;
9038 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9039 memcpy(r->out.out_data, out_data.data,
9040 MIN(r->in.out_data_size, out_data.length));
9043 return WERR_OK;
9046 /****************************************************************
9047 _spoolss_AddPrintProcessor
9048 ****************************************************************/
9050 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9051 struct spoolss_AddPrintProcessor *r)
9053 /* for now, just indicate success and ignore the add. We'll
9054 automatically set the winprint processor for printer
9055 entries later. Used to debug the LexMark Optra S 1855 PCL
9056 driver --jerry */
9058 return WERR_OK;
9061 /****************************************************************
9062 _spoolss_AddPort
9063 ****************************************************************/
9065 WERROR _spoolss_AddPort(pipes_struct *p,
9066 struct spoolss_AddPort *r)
9068 /* do what w2k3 does */
9070 return WERR_NOT_SUPPORTED;
9073 /****************************************************************
9074 _spoolss_GetPrinterDriver
9075 ****************************************************************/
9077 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9078 struct spoolss_GetPrinterDriver *r)
9080 p->rng_fault_state = true;
9081 return WERR_NOT_SUPPORTED;
9084 /****************************************************************
9085 _spoolss_ReadPrinter
9086 ****************************************************************/
9088 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9089 struct spoolss_ReadPrinter *r)
9091 p->rng_fault_state = true;
9092 return WERR_NOT_SUPPORTED;
9095 /****************************************************************
9096 _spoolss_WaitForPrinterChange
9097 ****************************************************************/
9099 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9100 struct spoolss_WaitForPrinterChange *r)
9102 p->rng_fault_state = true;
9103 return WERR_NOT_SUPPORTED;
9106 /****************************************************************
9107 _spoolss_ConfigurePort
9108 ****************************************************************/
9110 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9111 struct spoolss_ConfigurePort *r)
9113 p->rng_fault_state = true;
9114 return WERR_NOT_SUPPORTED;
9117 /****************************************************************
9118 _spoolss_DeletePort
9119 ****************************************************************/
9121 WERROR _spoolss_DeletePort(pipes_struct *p,
9122 struct spoolss_DeletePort *r)
9124 p->rng_fault_state = true;
9125 return WERR_NOT_SUPPORTED;
9128 /****************************************************************
9129 _spoolss_CreatePrinterIC
9130 ****************************************************************/
9132 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9133 struct spoolss_CreatePrinterIC *r)
9135 p->rng_fault_state = true;
9136 return WERR_NOT_SUPPORTED;
9139 /****************************************************************
9140 _spoolss_PlayGDIScriptOnPrinterIC
9141 ****************************************************************/
9143 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9144 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9146 p->rng_fault_state = true;
9147 return WERR_NOT_SUPPORTED;
9150 /****************************************************************
9151 _spoolss_DeletePrinterIC
9152 ****************************************************************/
9154 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9155 struct spoolss_DeletePrinterIC *r)
9157 p->rng_fault_state = true;
9158 return WERR_NOT_SUPPORTED;
9161 /****************************************************************
9162 _spoolss_AddPrinterConnection
9163 ****************************************************************/
9165 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9166 struct spoolss_AddPrinterConnection *r)
9168 p->rng_fault_state = true;
9169 return WERR_NOT_SUPPORTED;
9172 /****************************************************************
9173 _spoolss_DeletePrinterConnection
9174 ****************************************************************/
9176 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9177 struct spoolss_DeletePrinterConnection *r)
9179 p->rng_fault_state = true;
9180 return WERR_NOT_SUPPORTED;
9183 /****************************************************************
9184 _spoolss_PrinterMessageBox
9185 ****************************************************************/
9187 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9188 struct spoolss_PrinterMessageBox *r)
9190 p->rng_fault_state = true;
9191 return WERR_NOT_SUPPORTED;
9194 /****************************************************************
9195 _spoolss_AddMonitor
9196 ****************************************************************/
9198 WERROR _spoolss_AddMonitor(pipes_struct *p,
9199 struct spoolss_AddMonitor *r)
9201 p->rng_fault_state = true;
9202 return WERR_NOT_SUPPORTED;
9205 /****************************************************************
9206 _spoolss_DeleteMonitor
9207 ****************************************************************/
9209 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9210 struct spoolss_DeleteMonitor *r)
9212 p->rng_fault_state = true;
9213 return WERR_NOT_SUPPORTED;
9216 /****************************************************************
9217 _spoolss_DeletePrintProcessor
9218 ****************************************************************/
9220 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9221 struct spoolss_DeletePrintProcessor *r)
9223 p->rng_fault_state = true;
9224 return WERR_NOT_SUPPORTED;
9227 /****************************************************************
9228 _spoolss_AddPrintProvidor
9229 ****************************************************************/
9231 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9232 struct spoolss_AddPrintProvidor *r)
9234 p->rng_fault_state = true;
9235 return WERR_NOT_SUPPORTED;
9238 /****************************************************************
9239 _spoolss_DeletePrintProvidor
9240 ****************************************************************/
9242 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9243 struct spoolss_DeletePrintProvidor *r)
9245 p->rng_fault_state = true;
9246 return WERR_NOT_SUPPORTED;
9249 /****************************************************************
9250 _spoolss_FindFirstPrinterChangeNotification
9251 ****************************************************************/
9253 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9254 struct spoolss_FindFirstPrinterChangeNotification *r)
9256 p->rng_fault_state = true;
9257 return WERR_NOT_SUPPORTED;
9260 /****************************************************************
9261 _spoolss_FindNextPrinterChangeNotification
9262 ****************************************************************/
9264 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9265 struct spoolss_FindNextPrinterChangeNotification *r)
9267 p->rng_fault_state = true;
9268 return WERR_NOT_SUPPORTED;
9271 /****************************************************************
9272 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9273 ****************************************************************/
9275 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9276 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9278 p->rng_fault_state = true;
9279 return WERR_NOT_SUPPORTED;
9282 /****************************************************************
9283 _spoolss_ReplyOpenPrinter
9284 ****************************************************************/
9286 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9287 struct spoolss_ReplyOpenPrinter *r)
9289 p->rng_fault_state = true;
9290 return WERR_NOT_SUPPORTED;
9293 /****************************************************************
9294 _spoolss_RouterReplyPrinter
9295 ****************************************************************/
9297 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9298 struct spoolss_RouterReplyPrinter *r)
9300 p->rng_fault_state = true;
9301 return WERR_NOT_SUPPORTED;
9304 /****************************************************************
9305 _spoolss_ReplyClosePrinter
9306 ****************************************************************/
9308 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9309 struct spoolss_ReplyClosePrinter *r)
9311 p->rng_fault_state = true;
9312 return WERR_NOT_SUPPORTED;
9315 /****************************************************************
9316 _spoolss_AddPortEx
9317 ****************************************************************/
9319 WERROR _spoolss_AddPortEx(pipes_struct *p,
9320 struct spoolss_AddPortEx *r)
9322 p->rng_fault_state = true;
9323 return WERR_NOT_SUPPORTED;
9326 /****************************************************************
9327 _spoolss_RouterFindFirstPrinterChangeNotification
9328 ****************************************************************/
9330 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9331 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9333 p->rng_fault_state = true;
9334 return WERR_NOT_SUPPORTED;
9337 /****************************************************************
9338 _spoolss_SpoolerInit
9339 ****************************************************************/
9341 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9342 struct spoolss_SpoolerInit *r)
9344 p->rng_fault_state = true;
9345 return WERR_NOT_SUPPORTED;
9348 /****************************************************************
9349 _spoolss_ResetPrinterEx
9350 ****************************************************************/
9352 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9353 struct spoolss_ResetPrinterEx *r)
9355 p->rng_fault_state = true;
9356 return WERR_NOT_SUPPORTED;
9359 /****************************************************************
9360 _spoolss_RouterReplyPrinterEx
9361 ****************************************************************/
9363 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9364 struct spoolss_RouterReplyPrinterEx *r)
9366 p->rng_fault_state = true;
9367 return WERR_NOT_SUPPORTED;
9370 /****************************************************************
9371 _spoolss_44
9372 ****************************************************************/
9374 WERROR _spoolss_44(pipes_struct *p,
9375 struct spoolss_44 *r)
9377 p->rng_fault_state = true;
9378 return WERR_NOT_SUPPORTED;
9381 /****************************************************************
9382 _spoolss_47
9383 ****************************************************************/
9385 WERROR _spoolss_47(pipes_struct *p,
9386 struct spoolss_47 *r)
9388 p->rng_fault_state = true;
9389 return WERR_NOT_SUPPORTED;
9392 /****************************************************************
9393 _spoolss_4a
9394 ****************************************************************/
9396 WERROR _spoolss_4a(pipes_struct *p,
9397 struct spoolss_4a *r)
9399 p->rng_fault_state = true;
9400 return WERR_NOT_SUPPORTED;
9403 /****************************************************************
9404 _spoolss_4b
9405 ****************************************************************/
9407 WERROR _spoolss_4b(pipes_struct *p,
9408 struct spoolss_4b *r)
9410 p->rng_fault_state = true;
9411 return WERR_NOT_SUPPORTED;
9414 /****************************************************************
9415 _spoolss_4c
9416 ****************************************************************/
9418 WERROR _spoolss_4c(pipes_struct *p,
9419 struct spoolss_4c *r)
9421 p->rng_fault_state = true;
9422 return WERR_NOT_SUPPORTED;
9425 /****************************************************************
9426 _spoolss_53
9427 ****************************************************************/
9429 WERROR _spoolss_53(pipes_struct *p,
9430 struct spoolss_53 *r)
9432 p->rng_fault_state = true;
9433 return WERR_NOT_SUPPORTED;
9436 /****************************************************************
9437 _spoolss_55
9438 ****************************************************************/
9440 WERROR _spoolss_55(pipes_struct *p,
9441 struct spoolss_55 *r)
9443 p->rng_fault_state = true;
9444 return WERR_NOT_SUPPORTED;
9447 /****************************************************************
9448 _spoolss_56
9449 ****************************************************************/
9451 WERROR _spoolss_56(pipes_struct *p,
9452 struct spoolss_56 *r)
9454 p->rng_fault_state = true;
9455 return WERR_NOT_SUPPORTED;
9458 /****************************************************************
9459 _spoolss_57
9460 ****************************************************************/
9462 WERROR _spoolss_57(pipes_struct *p,
9463 struct spoolss_57 *r)
9465 p->rng_fault_state = true;
9466 return WERR_NOT_SUPPORTED;
9469 /****************************************************************
9470 _spoolss_5a
9471 ****************************************************************/
9473 WERROR _spoolss_5a(pipes_struct *p,
9474 struct spoolss_5a *r)
9476 p->rng_fault_state = true;
9477 return WERR_NOT_SUPPORTED;
9480 /****************************************************************
9481 _spoolss_5b
9482 ****************************************************************/
9484 WERROR _spoolss_5b(pipes_struct *p,
9485 struct spoolss_5b *r)
9487 p->rng_fault_state = true;
9488 return WERR_NOT_SUPPORTED;
9491 /****************************************************************
9492 _spoolss_5c
9493 ****************************************************************/
9495 WERROR _spoolss_5c(pipes_struct *p,
9496 struct spoolss_5c *r)
9498 p->rng_fault_state = true;
9499 return WERR_NOT_SUPPORTED;
9502 /****************************************************************
9503 _spoolss_5d
9504 ****************************************************************/
9506 WERROR _spoolss_5d(pipes_struct *p,
9507 struct spoolss_5d *r)
9509 p->rng_fault_state = true;
9510 return WERR_NOT_SUPPORTED;
9513 /****************************************************************
9514 _spoolss_5e
9515 ****************************************************************/
9517 WERROR _spoolss_5e(pipes_struct *p,
9518 struct spoolss_5e *r)
9520 p->rng_fault_state = true;
9521 return WERR_NOT_SUPPORTED;
9524 /****************************************************************
9525 _spoolss_5f
9526 ****************************************************************/
9528 WERROR _spoolss_5f(pipes_struct *p,
9529 struct spoolss_5f *r)
9531 p->rng_fault_state = true;
9532 return WERR_NOT_SUPPORTED;
9535 /****************************************************************
9536 _spoolss_60
9537 ****************************************************************/
9539 WERROR _spoolss_60(pipes_struct *p,
9540 struct spoolss_60 *r)
9542 p->rng_fault_state = true;
9543 return WERR_NOT_SUPPORTED;
9546 /****************************************************************
9547 _spoolss_61
9548 ****************************************************************/
9550 WERROR _spoolss_61(pipes_struct *p,
9551 struct spoolss_61 *r)
9553 p->rng_fault_state = true;
9554 return WERR_NOT_SUPPORTED;
9557 /****************************************************************
9558 _spoolss_62
9559 ****************************************************************/
9561 WERROR _spoolss_62(pipes_struct *p,
9562 struct spoolss_62 *r)
9564 p->rng_fault_state = true;
9565 return WERR_NOT_SUPPORTED;
9568 /****************************************************************
9569 _spoolss_63
9570 ****************************************************************/
9572 WERROR _spoolss_63(pipes_struct *p,
9573 struct spoolss_63 *r)
9575 p->rng_fault_state = true;
9576 return WERR_NOT_SUPPORTED;
9579 /****************************************************************
9580 _spoolss_64
9581 ****************************************************************/
9583 WERROR _spoolss_64(pipes_struct *p,
9584 struct spoolss_64 *r)
9586 p->rng_fault_state = true;
9587 return WERR_NOT_SUPPORTED;
9590 /****************************************************************
9591 _spoolss_65
9592 ****************************************************************/
9594 WERROR _spoolss_65(pipes_struct *p,
9595 struct spoolss_65 *r)
9597 p->rng_fault_state = true;
9598 return WERR_NOT_SUPPORTED;
9601 /****************************************************************
9602 _spoolss_GetCorePrinterDrivers
9603 ****************************************************************/
9605 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9606 struct spoolss_GetCorePrinterDrivers *r)
9608 p->rng_fault_state = true;
9609 return WERR_NOT_SUPPORTED;
9612 /****************************************************************
9613 _spoolss_67
9614 ****************************************************************/
9616 WERROR _spoolss_67(pipes_struct *p,
9617 struct spoolss_67 *r)
9619 p->rng_fault_state = true;
9620 return WERR_NOT_SUPPORTED;
9623 /****************************************************************
9624 _spoolss_GetPrinterDriverPackagePath
9625 ****************************************************************/
9627 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9628 struct spoolss_GetPrinterDriverPackagePath *r)
9630 p->rng_fault_state = true;
9631 return WERR_NOT_SUPPORTED;
9634 /****************************************************************
9635 _spoolss_69
9636 ****************************************************************/
9638 WERROR _spoolss_69(pipes_struct *p,
9639 struct spoolss_69 *r)
9641 p->rng_fault_state = true;
9642 return WERR_NOT_SUPPORTED;
9645 /****************************************************************
9646 _spoolss_6a
9647 ****************************************************************/
9649 WERROR _spoolss_6a(pipes_struct *p,
9650 struct spoolss_6a *r)
9652 p->rng_fault_state = true;
9653 return WERR_NOT_SUPPORTED;
9656 /****************************************************************
9657 _spoolss_6b
9658 ****************************************************************/
9660 WERROR _spoolss_6b(pipes_struct *p,
9661 struct spoolss_6b *r)
9663 p->rng_fault_state = true;
9664 return WERR_NOT_SUPPORTED;
9667 /****************************************************************
9668 _spoolss_6c
9669 ****************************************************************/
9671 WERROR _spoolss_6c(pipes_struct *p,
9672 struct spoolss_6c *r)
9674 p->rng_fault_state = true;
9675 return WERR_NOT_SUPPORTED;
9678 /****************************************************************
9679 _spoolss_6d
9680 ****************************************************************/
9682 WERROR _spoolss_6d(pipes_struct *p,
9683 struct spoolss_6d *r)
9685 p->rng_fault_state = true;
9686 return WERR_NOT_SUPPORTED;