s3-spoolss: Create and update DsSpooler values.
[Samba/bjacke.git] / source3 / rpc_server / srv_spoolss_nt.c
bloba3d72586c7e940cf89e7e7c6c48f713a8ef9e5de
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 "librpc/gen_ndr/ndr_security.h"
37 #include "registry.h"
38 #include "registry/reg_objects.h"
40 /* macros stolen from s4 spoolss server */
41 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
42 ((info)?ndr_size_##fn(info, level, 0):0)
44 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
45 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
47 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
48 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
50 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
53 extern userdom_struct current_user_info;
55 #undef DBGC_CLASS
56 #define DBGC_CLASS DBGC_RPC_SRV
58 #ifndef MAX_OPEN_PRINTER_EXS
59 #define MAX_OPEN_PRINTER_EXS 50
60 #endif
62 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
67 struct _counter_printer_0 *next;
68 struct _counter_printer_0 *prev;
70 int snum;
71 uint32_t counter;
72 } counter_printer_0;
74 static counter_printer_0 *counter_list;
76 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
77 static uint32_t smb_connections = 0;
80 /* in printing/nt_printing.c */
82 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
84 /* API table for Xcv Monitor functions */
86 struct xcv_api_table {
87 const char *name;
88 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
91 /********************************************************************
92 * Canonicalize servername.
93 ********************************************************************/
95 static const char *canon_servername(const char *servername)
97 const char *pservername = servername;
98 while (*pservername == '\\') {
99 pservername++;
101 return pservername;
104 /* translate between internal status numbers and NT status numbers */
105 static int nt_printj_status(int v)
107 switch (v) {
108 case LPQ_QUEUED:
109 return 0;
110 case LPQ_PAUSED:
111 return JOB_STATUS_PAUSED;
112 case LPQ_SPOOLING:
113 return JOB_STATUS_SPOOLING;
114 case LPQ_PRINTING:
115 return JOB_STATUS_PRINTING;
116 case LPQ_ERROR:
117 return JOB_STATUS_ERROR;
118 case LPQ_DELETING:
119 return JOB_STATUS_DELETING;
120 case LPQ_OFFLINE:
121 return JOB_STATUS_OFFLINE;
122 case LPQ_PAPEROUT:
123 return JOB_STATUS_PAPEROUT;
124 case LPQ_PRINTED:
125 return JOB_STATUS_PRINTED;
126 case LPQ_DELETED:
127 return JOB_STATUS_DELETED;
128 case LPQ_BLOCKED:
129 return JOB_STATUS_BLOCKED_DEVQ;
130 case LPQ_USER_INTERVENTION:
131 return JOB_STATUS_USER_INTERVENTION;
133 return 0;
136 static int nt_printq_status(int v)
138 switch (v) {
139 case LPQ_PAUSED:
140 return PRINTER_STATUS_PAUSED;
141 case LPQ_QUEUED:
142 case LPQ_SPOOLING:
143 case LPQ_PRINTING:
144 return 0;
146 return 0;
149 /***************************************************************************
150 Disconnect from the client
151 ****************************************************************************/
153 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
155 WERROR result;
156 NTSTATUS status;
159 * Tell the specific printing tdb we no longer want messages for this printer
160 * by deregistering our PID.
163 if (!print_notify_deregister_pid(snum))
164 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
166 /* weird if the test succeds !!! */
167 if (smb_connections==0) {
168 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 return;
172 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
173 handle,
174 &result);
175 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
176 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
177 win_errstr(result)));
179 /* if it's the last connection, deconnect the IPC$ share */
180 if (smb_connections==1) {
182 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
183 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
185 messaging_deregister(smbd_messaging_context(),
186 MSG_PRINTER_NOTIFY2, NULL);
188 /* Tell the connections db we're no longer interested in
189 * printer notify messages. */
191 serverid_register_msg_flags(
192 messaging_server_id(smbd_messaging_context()),
193 false, FLAG_MSG_PRINT_NOTIFY);
196 smb_connections--;
199 /****************************************************************************
200 Functions to free a printer entry datastruct.
201 ****************************************************************************/
203 static int printer_entry_destructor(Printer_entry *Printer)
205 if (Printer->notify.client_connected == true) {
206 int snum = -1;
208 if ( Printer->printer_type == SPLHND_SERVER) {
209 snum = -1;
210 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
211 } else if (Printer->printer_type == SPLHND_PRINTER) {
212 snum = print_queue_snum(Printer->sharename);
213 if (snum != -1)
214 srv_spoolss_replycloseprinter(snum,
215 &Printer->notify.client_hnd);
219 Printer->notify.flags=0;
220 Printer->notify.options=0;
221 Printer->notify.localmachine[0]='\0';
222 Printer->notify.printerlocal=0;
223 TALLOC_FREE(Printer->notify.option);
224 Printer->notify.client_connected = false;
226 TALLOC_FREE(Printer->devmode);
227 free_a_printer( &Printer->printer_info, 2 );
229 /* Remove from the internal list. */
230 DLIST_REMOVE(printers_list, Printer);
231 return 0;
234 /****************************************************************************
235 find printer index by handle
236 ****************************************************************************/
238 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
239 struct policy_handle *hnd)
241 Printer_entry *find_printer = NULL;
243 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
244 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
245 return NULL;
248 return find_printer;
251 /****************************************************************************
252 Close printer index by handle.
253 ****************************************************************************/
255 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
257 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
259 if (!Printer) {
260 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
261 OUR_HANDLE(hnd)));
262 return false;
265 close_policy_hnd(p, hnd);
267 return true;
270 /****************************************************************************
271 Delete a printer given a handle.
272 ****************************************************************************/
274 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
276 char *cmd = lp_deleteprinter_cmd();
277 char *command = NULL;
278 int ret;
279 SE_PRIV se_printop = SE_PRINT_OPERATOR;
280 bool is_print_op = false;
282 /* can't fail if we don't try */
284 if ( !*cmd )
285 return WERR_OK;
287 command = talloc_asprintf(ctx,
288 "%s \"%s\"",
289 cmd, sharename);
290 if (!command) {
291 return WERR_NOMEM;
293 if ( token )
294 is_print_op = user_has_privileges( token, &se_printop );
296 DEBUG(10,("Running [%s]\n", command));
298 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
300 if ( is_print_op )
301 become_root();
303 if ( (ret = smbrun(command, NULL)) == 0 ) {
304 /* Tell everyone we updated smb.conf. */
305 message_send_all(smbd_messaging_context(),
306 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
309 if ( is_print_op )
310 unbecome_root();
312 /********** END SePrintOperatorPrivlege BLOCK **********/
314 DEBUGADD(10,("returned [%d]\n", ret));
316 TALLOC_FREE(command);
318 if (ret != 0)
319 return WERR_BADFID; /* What to return here? */
321 /* go ahead and re-read the services immediately */
322 become_root();
323 reload_services(false);
324 unbecome_root();
326 if ( lp_servicenumber( sharename ) > 0 )
327 return WERR_ACCESS_DENIED;
329 return WERR_OK;
332 /****************************************************************************
333 Delete a printer given a handle.
334 ****************************************************************************/
336 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
338 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
339 WERROR result;
341 if (!Printer) {
342 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
343 OUR_HANDLE(hnd)));
344 return WERR_BADFID;
348 * It turns out that Windows allows delete printer on a handle
349 * opened by an admin user, then used on a pipe handle created
350 * by an anonymous user..... but they're working on security.... riiight !
351 * JRA.
354 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
355 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
356 return WERR_ACCESS_DENIED;
359 /* this does not need a become root since the access check has been
360 done on the handle already */
362 result = winreg_delete_printer_key(p->mem_ctx, p->server_info,
363 Printer->sharename, "");
364 if (!W_ERROR_IS_OK(result)) {
365 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
366 return WERR_BADFID;
369 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
370 Printer->sharename );
373 /****************************************************************************
374 Return the snum of a printer corresponding to an handle.
375 ****************************************************************************/
377 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
378 int *number, struct share_params **params)
380 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
382 if (!Printer) {
383 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
384 OUR_HANDLE(hnd)));
385 return false;
388 switch (Printer->printer_type) {
389 case SPLHND_PRINTER:
390 DEBUG(4,("short name:%s\n", Printer->sharename));
391 *number = print_queue_snum(Printer->sharename);
392 return (*number != -1);
393 case SPLHND_SERVER:
394 return false;
395 default:
396 return false;
400 /****************************************************************************
401 Set printer handle type.
402 Check if it's \\server or \\server\printer
403 ****************************************************************************/
405 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
407 DEBUG(3,("Setting printer type=%s\n", handlename));
409 if ( strlen(handlename) < 3 ) {
410 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
411 return false;
414 /* it's a print server */
415 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
416 DEBUGADD(4,("Printer is a print server\n"));
417 Printer->printer_type = SPLHND_SERVER;
419 /* it's a printer (set_printer_hnd_name() will handle port monitors */
420 else {
421 DEBUGADD(4,("Printer is a printer\n"));
422 Printer->printer_type = SPLHND_PRINTER;
425 return true;
428 /****************************************************************************
429 Set printer handle name.. Accept names like \\server, \\server\printer,
430 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
431 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
432 XcvDataPort() interface.
433 ****************************************************************************/
435 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
436 struct auth_serversupplied_info *server_info,
437 Printer_entry *Printer,
438 const char *handlename)
440 int snum;
441 int n_services=lp_numservices();
442 char *aprinter;
443 const char *printername;
444 const char *servername;
445 fstring sname;
446 bool found = false;
447 struct spoolss_PrinterInfo2 *info2 = NULL;
448 WERROR result;
450 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
451 (unsigned long)strlen(handlename)));
453 aprinter = CONST_DISCARD(char *, handlename);
454 if ( *handlename == '\\' ) {
455 servername = canon_servername(handlename);
456 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
457 *aprinter = '\0';
458 aprinter++;
460 if (!is_myname_or_ipaddr(servername)) {
461 return false;
464 fstrcpy(Printer->servername, servername);
467 if (Printer->printer_type == SPLHND_SERVER) {
468 return true;
471 if (Printer->printer_type != SPLHND_PRINTER) {
472 return false;
475 DEBUGADD(5, ("searching for [%s]\n", aprinter));
477 /* check for the Port Monitor Interface */
478 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
479 Printer->printer_type = SPLHND_PORTMON_TCP;
480 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
481 found = true;
483 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
484 Printer->printer_type = SPLHND_PORTMON_LOCAL;
485 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
486 found = true;
489 /* Search all sharenames first as this is easier than pulling
490 the printer_info_2 off of disk. Don't use find_service() since
491 that calls out to map_username() */
493 /* do another loop to look for printernames */
494 for (snum = 0; !found && snum < n_services; snum++) {
495 const char *printer = lp_const_servicename(snum);
497 /* no point going on if this is not a printer */
498 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
499 continue;
502 /* ignore [printers] share */
503 if (strequal(printer, "printers")) {
504 continue;
507 fstrcpy(sname, printer);
508 if (strequal(aprinter, printer)) {
509 found = true;
510 break;
513 /* no point looking up the printer object if
514 we aren't allowing printername != sharename */
515 if (lp_force_printername(snum)) {
516 continue;
519 result = winreg_get_printer(mem_ctx,
520 server_info,
521 servername,
522 sname,
523 &info2);
524 if ( !W_ERROR_IS_OK(result) ) {
525 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
526 sname, win_errstr(result)));
527 continue;
530 printername = strrchr(info2->printername, '\\');
531 if (printername == NULL) {
532 printername = info2->printername;
533 } else {
534 printername++;
537 if (strequal(printername, aprinter)) {
538 found = true;
539 break;
542 DEBUGADD(10, ("printername: %s\n", printername));
544 TALLOC_FREE(info2);
547 if ( !found ) {
548 DEBUGADD(4,("Printer not found\n"));
549 return false;
552 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
554 fstrcpy(Printer->sharename, sname);
556 return true;
559 /****************************************************************************
560 Find first available printer slot. creates a printer handle for you.
561 ****************************************************************************/
563 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
564 const char *name, uint32_t access_granted)
566 Printer_entry *new_printer;
568 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
570 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
571 if (new_printer == NULL) {
572 return false;
574 talloc_set_destructor(new_printer, printer_entry_destructor);
576 if (!create_policy_hnd(p, hnd, new_printer)) {
577 TALLOC_FREE(new_printer);
578 return false;
581 /* Add to the internal list. */
582 DLIST_ADD(printers_list, new_printer);
584 new_printer->notify.option=NULL;
586 if (!set_printer_hnd_printertype(new_printer, name)) {
587 close_printer_handle(p, hnd);
588 return false;
591 if (!set_printer_hnd_name(p->mem_ctx, p->server_info, new_printer, name)) {
592 close_printer_handle(p, hnd);
593 return false;
596 new_printer->access_granted = access_granted;
598 DEBUG(5, ("%d printer handles active\n",
599 (int)num_pipe_handles(p)));
601 return true;
604 /***************************************************************************
605 check to see if the client motify handle is monitoring the notification
606 given by (notify_type, notify_field).
607 **************************************************************************/
609 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
610 uint16_t notify_field)
612 return true;
615 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
616 uint16_t notify_field)
618 struct spoolss_NotifyOption *option = p->notify.option;
619 uint32_t i, j;
622 * Flags should always be zero when the change notify
623 * is registered by the client's spooler. A user Win32 app
624 * might use the flags though instead of the NOTIFY_OPTION_INFO
625 * --jerry
628 if (!option) {
629 return false;
632 if (p->notify.flags)
633 return is_monitoring_event_flags(
634 p->notify.flags, notify_type, notify_field);
636 for (i = 0; i < option->count; i++) {
638 /* Check match for notify_type */
640 if (option->types[i].type != notify_type)
641 continue;
643 /* Check match for field */
645 for (j = 0; j < option->types[i].count; j++) {
646 if (option->types[i].fields[j].field == notify_field) {
647 return true;
652 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
653 p->servername, p->sharename, notify_type, notify_field));
655 return false;
658 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
659 _data->data.integer[0] = _integer; \
660 _data->data.integer[1] = 0;
663 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
664 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
665 if (!_data->data.string.string) {\
666 _data->data.string.size = 0; \
668 _data->data.string.size = strlen_m_term(_p) * 2;
670 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
671 _data->data.devmode.devmode = _devmode;
673 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
674 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
675 if (!_data->data.sd.sd) { \
676 _data->data.sd.sd_size = 0; \
678 _data->data.sd.sd_size = \
679 ndr_size_security_descriptor(_data->data.sd.sd, 0);
681 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
682 struct tm *t,
683 const char **pp,
684 uint32_t *plen)
686 struct spoolss_Time st;
687 uint32_t len = 16;
688 char *p;
690 if (!init_systemtime(&st, t)) {
691 return;
694 p = talloc_array(mem_ctx, char, len);
695 if (!p) {
696 return;
700 * Systemtime must be linearized as a set of UINT16's.
701 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
704 SSVAL(p, 0, st.year);
705 SSVAL(p, 2, st.month);
706 SSVAL(p, 4, st.day_of_week);
707 SSVAL(p, 6, st.day);
708 SSVAL(p, 8, st.hour);
709 SSVAL(p, 10, st.minute);
710 SSVAL(p, 12, st.second);
711 SSVAL(p, 14, st.millisecond);
713 *pp = p;
714 *plen = len;
717 /* Convert a notification message to a struct spoolss_Notify */
719 static void notify_one_value(struct spoolss_notify_msg *msg,
720 struct spoolss_Notify *data,
721 TALLOC_CTX *mem_ctx)
723 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
726 static void notify_string(struct spoolss_notify_msg *msg,
727 struct spoolss_Notify *data,
728 TALLOC_CTX *mem_ctx)
730 /* The length of the message includes the trailing \0 */
732 data->data.string.size = msg->len * 2;
733 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
734 if (!data->data.string.string) {
735 data->data.string.size = 0;
736 return;
740 static void notify_system_time(struct spoolss_notify_msg *msg,
741 struct spoolss_Notify *data,
742 TALLOC_CTX *mem_ctx)
744 data->data.string.string = NULL;
745 data->data.string.size = 0;
747 if (msg->len != sizeof(time_t)) {
748 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
749 msg->len));
750 return;
753 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
754 &data->data.string.string,
755 &data->data.string.size);
758 struct notify2_message_table {
759 const char *name;
760 void (*fn)(struct spoolss_notify_msg *msg,
761 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
764 static struct notify2_message_table printer_notify_table[] = {
765 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
766 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
767 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
768 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
769 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
770 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
771 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
772 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
773 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
774 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
775 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
776 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
777 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
778 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
779 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
780 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
781 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
782 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
783 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
786 static struct notify2_message_table job_notify_table[] = {
787 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
788 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
789 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
790 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
791 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
792 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
793 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
794 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
795 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
796 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
797 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
798 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
799 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
800 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
801 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
802 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
803 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
804 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
805 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
806 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
807 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
808 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
809 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
810 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
814 /***********************************************************************
815 Allocate talloc context for container object
816 **********************************************************************/
818 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
820 if ( !ctr )
821 return;
823 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
825 return;
828 /***********************************************************************
829 release all allocated memory and zero out structure
830 **********************************************************************/
832 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
834 if ( !ctr )
835 return;
837 if ( ctr->ctx )
838 talloc_destroy(ctr->ctx);
840 ZERO_STRUCTP(ctr);
842 return;
845 /***********************************************************************
846 **********************************************************************/
848 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
850 if ( !ctr )
851 return NULL;
853 return ctr->ctx;
856 /***********************************************************************
857 **********************************************************************/
859 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
861 if ( !ctr || !ctr->msg_groups )
862 return NULL;
864 if ( idx >= ctr->num_groups )
865 return NULL;
867 return &ctr->msg_groups[idx];
871 /***********************************************************************
872 How many groups of change messages do we have ?
873 **********************************************************************/
875 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
877 if ( !ctr )
878 return 0;
880 return ctr->num_groups;
883 /***********************************************************************
884 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
885 **********************************************************************/
887 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
889 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
890 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
891 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
892 int i, new_slot;
894 if ( !ctr || !msg )
895 return 0;
897 /* loop over all groups looking for a matching printer name */
899 for ( i=0; i<ctr->num_groups; i++ ) {
900 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
901 break;
904 /* add a new group? */
906 if ( i == ctr->num_groups ) {
907 ctr->num_groups++;
909 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
911 return 0;
913 ctr->msg_groups = groups;
915 /* clear the new entry and set the printer name */
917 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
918 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
921 /* add the change messages; 'i' is the correct index now regardless */
923 msg_grp = &ctr->msg_groups[i];
925 msg_grp->num_msgs++;
927 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
928 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
929 return 0;
931 msg_grp->msgs = msg_list;
933 new_slot = msg_grp->num_msgs-1;
934 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
936 /* need to allocate own copy of data */
938 if ( msg->len != 0 )
939 msg_grp->msgs[new_slot].notify.data = (char *)
940 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
942 return ctr->num_groups;
945 static void construct_info_data(struct spoolss_Notify *info_data,
946 enum spoolss_NotifyType type,
947 uint16_t field, int id);
949 /***********************************************************************
950 Send a change notication message on all handles which have a call
951 back registered
952 **********************************************************************/
954 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
956 Printer_entry *p;
957 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
958 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
959 SPOOLSS_NOTIFY_MSG *messages;
960 int sending_msg_count;
962 if ( !msg_group ) {
963 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
964 return;
967 messages = msg_group->msgs;
969 if ( !messages ) {
970 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
971 return;
974 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
976 /* loop over all printers */
978 for (p = printers_list; p; p = p->next) {
979 struct spoolss_Notify *notifies;
980 uint32_t count = 0;
981 uint32_t id;
982 int i;
984 /* Is there notification on this handle? */
986 if ( !p->notify.client_connected )
987 continue;
989 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
991 /* For this printer? Print servers always receive
992 notifications. */
994 if ( ( p->printer_type == SPLHND_PRINTER ) &&
995 ( !strequal(msg_group->printername, p->sharename) ) )
996 continue;
998 DEBUG(10,("Our printer\n"));
1000 /* allocate the max entries possible */
1002 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1003 if (!notifies) {
1004 return;
1007 /* build the array of change notifications */
1009 sending_msg_count = 0;
1011 for ( i=0; i<msg_group->num_msgs; i++ ) {
1012 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1014 /* Are we monitoring this event? */
1016 if (!is_monitoring_event(p, msg->type, msg->field))
1017 continue;
1019 sending_msg_count++;
1022 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1023 msg->type, msg->field, p->sharename));
1026 * if the is a printer notification handle and not a job notification
1027 * type, then set the id to 0. Other wise just use what was specified
1028 * in the message.
1030 * When registering change notification on a print server handle
1031 * we always need to send back the id (snum) matching the printer
1032 * for which the change took place. For change notify registered
1033 * on a printer handle, this does not matter and the id should be 0.
1035 * --jerry
1038 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1039 id = 0;
1040 else
1041 id = msg->id;
1044 /* Convert unix jobid to smb jobid */
1046 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1047 id = sysjob_to_jobid(msg->id);
1049 if (id == -1) {
1050 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1051 goto done;
1055 construct_info_data( &notifies[count], msg->type, msg->field, id );
1057 switch(msg->type) {
1058 case PRINTER_NOTIFY_TYPE:
1059 if ( printer_notify_table[msg->field].fn )
1060 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1061 break;
1063 case JOB_NOTIFY_TYPE:
1064 if ( job_notify_table[msg->field].fn )
1065 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1066 break;
1068 default:
1069 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1070 goto done;
1073 count++;
1076 if ( sending_msg_count ) {
1077 NTSTATUS status;
1078 WERROR werr;
1079 union spoolss_ReplyPrinterInfo info;
1080 struct spoolss_NotifyInfo info0;
1081 uint32_t reply_result;
1083 info0.version = 0x2;
1084 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1085 info0.count = count;
1086 info0.notifies = notifies;
1088 info.info0 = &info0;
1090 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1091 &p->notify.client_hnd,
1092 p->notify.change, /* color */
1093 p->notify.flags,
1094 &reply_result,
1095 0, /* reply_type, must be 0 */
1096 info,
1097 &werr);
1098 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1099 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1100 notify_cli_pipe->srv_name_slash,
1101 win_errstr(werr)));
1103 switch (reply_result) {
1104 case 0:
1105 break;
1106 case PRINTER_NOTIFY_INFO_DISCARDED:
1107 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1108 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1109 break;
1110 default:
1111 break;
1116 done:
1117 DEBUG(8,("send_notify2_changes: Exit...\n"));
1118 return;
1121 /***********************************************************************
1122 **********************************************************************/
1124 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1127 uint32_t tv_sec, tv_usec;
1128 size_t offset = 0;
1130 /* Unpack message */
1132 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1133 msg->printer);
1135 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1136 &tv_sec, &tv_usec,
1137 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1139 if (msg->len == 0)
1140 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1141 &msg->notify.value[0], &msg->notify.value[1]);
1142 else
1143 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1144 &msg->len, &msg->notify.data);
1146 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1147 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1149 tv->tv_sec = tv_sec;
1150 tv->tv_usec = tv_usec;
1152 if (msg->len == 0)
1153 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1154 msg->notify.value[1]));
1155 else
1156 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1158 return true;
1161 /********************************************************************
1162 Receive a notify2 message list
1163 ********************************************************************/
1165 static void receive_notify2_message_list(struct messaging_context *msg,
1166 void *private_data,
1167 uint32_t msg_type,
1168 struct server_id server_id,
1169 DATA_BLOB *data)
1171 size_t msg_count, i;
1172 char *buf = (char *)data->data;
1173 char *msg_ptr;
1174 size_t msg_len;
1175 SPOOLSS_NOTIFY_MSG notify;
1176 SPOOLSS_NOTIFY_MSG_CTR messages;
1177 int num_groups;
1179 if (data->length < 4) {
1180 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1181 return;
1184 msg_count = IVAL(buf, 0);
1185 msg_ptr = buf + 4;
1187 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1189 if (msg_count == 0) {
1190 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1191 return;
1194 /* initialize the container */
1196 ZERO_STRUCT( messages );
1197 notify_msg_ctr_init( &messages );
1200 * build message groups for each printer identified
1201 * in a change_notify msg. Remember that a PCN message
1202 * includes the handle returned for the srv_spoolss_replyopenprinter()
1203 * call. Therefore messages are grouped according to printer handle.
1206 for ( i=0; i<msg_count; i++ ) {
1207 struct timeval msg_tv;
1209 if (msg_ptr + 4 - buf > data->length) {
1210 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1211 return;
1214 msg_len = IVAL(msg_ptr,0);
1215 msg_ptr += 4;
1217 if (msg_ptr + msg_len - buf > data->length) {
1218 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1219 return;
1222 /* unpack messages */
1224 ZERO_STRUCT( notify );
1225 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1226 msg_ptr += msg_len;
1228 /* add to correct list in container */
1230 notify_msg_ctr_addmsg( &messages, &notify );
1232 /* free memory that might have been allocated by notify2_unpack_msg() */
1234 if ( notify.len != 0 )
1235 SAFE_FREE( notify.notify.data );
1238 /* process each group of messages */
1240 num_groups = notify_msg_ctr_numgroups( &messages );
1241 for ( i=0; i<num_groups; i++ )
1242 send_notify2_changes( &messages, i );
1245 /* cleanup */
1247 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1248 (uint32_t)msg_count ));
1250 notify_msg_ctr_destroy( &messages );
1252 return;
1255 /********************************************************************
1256 Send a message to ourself about new driver being installed
1257 so we can upgrade the information for each printer bound to this
1258 driver
1259 ********************************************************************/
1261 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1263 int len = strlen(drivername);
1265 if (!len)
1266 return false;
1268 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1269 drivername));
1271 messaging_send_buf(smbd_messaging_context(),
1272 messaging_server_id(smbd_messaging_context()),
1273 MSG_PRINTER_DRVUPGRADE,
1274 (uint8_t *)drivername, len+1);
1276 return true;
1279 /**********************************************************************
1280 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1281 over all printers, upgrading ones as necessary
1282 **********************************************************************/
1284 void do_drv_upgrade_printer(struct messaging_context *msg,
1285 void *private_data,
1286 uint32_t msg_type,
1287 struct server_id server_id,
1288 DATA_BLOB *data)
1290 TALLOC_CTX *tmp_ctx;
1291 struct auth_serversupplied_info *server_info = NULL;
1292 struct spoolss_PrinterInfo2 *pinfo2;
1293 NTSTATUS status;
1294 WERROR result;
1295 const char *drivername;
1296 int snum;
1297 int n_services = lp_numservices();
1298 size_t len;
1300 tmp_ctx = talloc_new(NULL);
1301 if (!tmp_ctx) return;
1303 status = make_server_info_system(tmp_ctx, &server_info);
1304 if (!NT_STATUS_IS_OK(status)) {
1305 DEBUG(0, ("do_drv_upgrade_printer: "
1306 "Could not create system server_info\n"));
1307 goto done;
1310 len = MIN(data->length,sizeof(drivername)-1);
1311 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1312 if (!drivername) {
1313 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1314 goto done;
1317 DEBUG(10, ("do_drv_upgrade_printer: "
1318 "Got message for new driver [%s]\n", drivername));
1320 /* Iterate the printer list */
1322 for (snum = 0; snum < n_services; snum++) {
1323 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1324 continue;
1327 result = winreg_get_printer(tmp_ctx, server_info, NULL,
1328 lp_const_servicename(snum),
1329 &pinfo2);
1331 if (!W_ERROR_IS_OK(result)) {
1332 continue;
1335 if (strcmp(drivername, pinfo2->drivername) != 0) {
1336 continue;
1339 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1341 /* all we care about currently is the change_id */
1342 result = winreg_printer_update_changeid(tmp_ctx,
1343 server_info,
1344 pinfo2->printername);
1346 if (!W_ERROR_IS_OK(result)) {
1347 DEBUG(3, ("do_drv_upgrade_printer: "
1348 "Failed to update changeid [%s]\n",
1349 win_errstr(result)));
1353 /* all done */
1354 done:
1355 talloc_free(tmp_ctx);
1358 /********************************************************************
1359 Update the cache for all printq's with a registered client
1360 connection
1361 ********************************************************************/
1363 void update_monitored_printq_cache( void )
1365 Printer_entry *printer = printers_list;
1366 int snum;
1368 /* loop through all printers and update the cache where
1369 client_connected == true */
1370 while ( printer )
1372 if ( (printer->printer_type == SPLHND_PRINTER)
1373 && printer->notify.client_connected )
1375 snum = print_queue_snum(printer->sharename);
1376 print_queue_status( snum, NULL, NULL );
1379 printer = printer->next;
1382 return;
1385 /****************************************************************
1386 _spoolss_OpenPrinter
1387 ****************************************************************/
1389 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1390 struct spoolss_OpenPrinter *r)
1392 struct spoolss_OpenPrinterEx e;
1393 WERROR werr;
1395 ZERO_STRUCT(e.in.userlevel);
1397 e.in.printername = r->in.printername;
1398 e.in.datatype = r->in.datatype;
1399 e.in.devmode_ctr = r->in.devmode_ctr;
1400 e.in.access_mask = r->in.access_mask;
1401 e.in.level = 0;
1403 e.out.handle = r->out.handle;
1405 werr = _spoolss_OpenPrinterEx(p, &e);
1407 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1408 /* OpenPrinterEx returns this for a bad
1409 * printer name. We must return WERR_INVALID_PRINTER_NAME
1410 * instead.
1412 werr = WERR_INVALID_PRINTER_NAME;
1415 return werr;
1418 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1419 struct spoolss_DeviceMode *orig,
1420 struct spoolss_DeviceMode **dest)
1422 struct spoolss_DeviceMode *dm;
1424 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1425 if (!dm) {
1426 return WERR_NOMEM;
1429 /* copy all values, then duplicate strings and structs */
1430 *dm = *orig;
1432 dm->devicename = talloc_strdup(dm, orig->devicename);
1433 if (!dm->devicename) {
1434 return WERR_NOMEM;
1436 dm->formname = talloc_strdup(dm, orig->formname);
1437 if (!dm->formname) {
1438 return WERR_NOMEM;
1440 if (orig->driverextra_data.data) {
1441 dm->driverextra_data.data =
1442 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1443 orig->driverextra_data.length);
1444 if (!dm->driverextra_data.data) {
1445 return WERR_NOMEM;
1449 *dest = dm;
1450 return WERR_OK;
1453 /****************************************************************
1454 _spoolss_OpenPrinterEx
1455 ****************************************************************/
1457 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1458 struct spoolss_OpenPrinterEx *r)
1460 int snum;
1461 Printer_entry *Printer=NULL;
1463 if (!r->in.printername) {
1464 return WERR_INVALID_PARAM;
1467 /* some sanity check because you can open a printer or a print server */
1468 /* aka: \\server\printer or \\server */
1470 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1472 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1473 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1474 " for printer %s\n", r->in.printername));
1475 ZERO_STRUCTP(r->out.handle);
1476 return WERR_INVALID_PARAM;
1479 Printer = find_printer_index_by_hnd(p, r->out.handle);
1480 if ( !Printer ) {
1481 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1482 "handle we created for printer %s\n", r->in.printername));
1483 close_printer_handle(p, r->out.handle);
1484 ZERO_STRUCTP(r->out.handle);
1485 return WERR_INVALID_PARAM;
1489 * First case: the user is opening the print server:
1491 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1492 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1494 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1495 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1496 * or if the user is listed in the smb.conf printer admin parameter.
1498 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1499 * client view printer folder, but does not show the MSAPW.
1501 * Note: this test needs code to check access rights here too. Jeremy
1502 * could you look at this?
1504 * Second case: the user is opening a printer:
1505 * NT doesn't let us connect to a printer if the connecting user
1506 * doesn't have print permission.
1508 * Third case: user is opening a Port Monitor
1509 * access checks same as opening a handle to the print server.
1512 switch (Printer->printer_type )
1514 case SPLHND_SERVER:
1515 case SPLHND_PORTMON_TCP:
1516 case SPLHND_PORTMON_LOCAL:
1517 /* Printserver handles use global struct... */
1519 snum = -1;
1521 /* Map standard access rights to object specific access rights */
1523 se_map_standard(&r->in.access_mask,
1524 &printserver_std_mapping);
1526 /* Deny any object specific bits that don't apply to print
1527 servers (i.e printer and job specific bits) */
1529 r->in.access_mask &= SEC_MASK_SPECIFIC;
1531 if (r->in.access_mask &
1532 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1533 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1534 close_printer_handle(p, r->out.handle);
1535 ZERO_STRUCTP(r->out.handle);
1536 return WERR_ACCESS_DENIED;
1539 /* Allow admin access */
1541 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1543 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1545 if (!lp_ms_add_printer_wizard()) {
1546 close_printer_handle(p, r->out.handle);
1547 ZERO_STRUCTP(r->out.handle);
1548 return WERR_ACCESS_DENIED;
1551 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1552 and not a printer admin, then fail */
1554 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1555 !user_has_privileges(p->server_info->ptok,
1556 &se_printop ) &&
1557 !token_contains_name_in_list(
1558 uidtoname(p->server_info->utok.uid),
1559 p->server_info->info3->base.domain.string,
1560 NULL,
1561 p->server_info->ptok,
1562 lp_printer_admin(snum))) {
1563 close_printer_handle(p, r->out.handle);
1564 ZERO_STRUCTP(r->out.handle);
1565 return WERR_ACCESS_DENIED;
1568 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1570 else
1572 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1575 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1576 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1578 /* We fall through to return WERR_OK */
1579 break;
1581 case SPLHND_PRINTER:
1582 /* NT doesn't let us connect to a printer if the connecting user
1583 doesn't have print permission. */
1585 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1586 close_printer_handle(p, r->out.handle);
1587 ZERO_STRUCTP(r->out.handle);
1588 return WERR_BADFID;
1591 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1592 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1595 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1597 /* map an empty access mask to the minimum access mask */
1598 if (r->in.access_mask == 0x0)
1599 r->in.access_mask = PRINTER_ACCESS_USE;
1602 * If we are not serving the printer driver for this printer,
1603 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1604 * will keep NT clients happy --jerry
1607 if (lp_use_client_driver(snum)
1608 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1610 r->in.access_mask = PRINTER_ACCESS_USE;
1613 /* check smb.conf parameters and the the sec_desc */
1615 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1616 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1617 ZERO_STRUCTP(r->out.handle);
1618 return WERR_ACCESS_DENIED;
1621 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1622 p->server_info->ptok, snum) ||
1623 !print_access_check(p->server_info, snum,
1624 r->in.access_mask)) {
1625 DEBUG(3, ("access DENIED for printer open\n"));
1626 close_printer_handle(p, r->out.handle);
1627 ZERO_STRUCTP(r->out.handle);
1628 return WERR_ACCESS_DENIED;
1631 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1632 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1633 close_printer_handle(p, r->out.handle);
1634 ZERO_STRUCTP(r->out.handle);
1635 return WERR_ACCESS_DENIED;
1638 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1639 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1640 else
1641 r->in.access_mask = PRINTER_ACCESS_USE;
1643 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1644 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1646 winreg_create_printer(p->mem_ctx,
1647 p->server_info,
1648 Printer->servername,
1649 lp_const_servicename(snum));
1651 break;
1653 default:
1654 /* sanity check to prevent programmer error */
1655 ZERO_STRUCTP(r->out.handle);
1656 return WERR_BADFID;
1659 Printer->access_granted = r->in.access_mask;
1662 * If the client sent a devmode in the OpenPrinter() call, then
1663 * save it here in case we get a job submission on this handle
1666 if ((Printer->printer_type != SPLHND_SERVER) &&
1667 r->in.devmode_ctr.devmode) {
1668 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1669 &Printer->devmode);
1672 #if 0 /* JERRY -- I'm doubtful this is really effective */
1673 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1674 optimization in Windows 2000 clients --jerry */
1676 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1677 && (RA_WIN2K == get_remote_arch()) )
1679 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1680 sys_usleep( 500000 );
1682 #endif
1684 return WERR_OK;
1687 /****************************************************************
1688 _spoolss_ClosePrinter
1689 ****************************************************************/
1691 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1692 struct spoolss_ClosePrinter *r)
1694 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1696 if (Printer && Printer->document_started) {
1697 struct spoolss_EndDocPrinter e;
1699 e.in.handle = r->in.handle;
1701 _spoolss_EndDocPrinter(p, &e);
1704 if (!close_printer_handle(p, r->in.handle))
1705 return WERR_BADFID;
1707 /* clear the returned printer handle. Observed behavior
1708 from Win2k server. Don't think this really matters.
1709 Previous code just copied the value of the closed
1710 handle. --jerry */
1712 ZERO_STRUCTP(r->out.handle);
1714 return WERR_OK;
1717 /****************************************************************
1718 _spoolss_DeletePrinter
1719 ****************************************************************/
1721 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1722 struct spoolss_DeletePrinter *r)
1724 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1725 WERROR result;
1726 int snum;
1728 if (Printer && Printer->document_started) {
1729 struct spoolss_EndDocPrinter e;
1731 e.in.handle = r->in.handle;
1733 _spoolss_EndDocPrinter(p, &e);
1736 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1737 winreg_delete_printer_key(p->mem_ctx,
1738 p->server_info,
1739 lp_const_servicename(snum),
1740 "");
1743 result = delete_printer_handle(p, r->in.handle);
1745 return result;
1748 /*******************************************************************
1749 * static function to lookup the version id corresponding to an
1750 * long architecture string
1751 ******************************************************************/
1753 static const struct print_architecture_table_node archi_table[]= {
1755 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1756 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1757 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1758 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1759 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1760 {"Windows IA64", SPL_ARCH_IA64, 3 },
1761 {"Windows x64", SPL_ARCH_X64, 3 },
1762 {NULL, "", -1 }
1765 static int get_version_id(const char *arch)
1767 int i;
1769 for (i=0; archi_table[i].long_archi != NULL; i++)
1771 if (strcmp(arch, archi_table[i].long_archi) == 0)
1772 return (archi_table[i].version);
1775 return -1;
1778 /****************************************************************
1779 _spoolss_DeletePrinterDriver
1780 ****************************************************************/
1782 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1783 struct spoolss_DeletePrinterDriver *r)
1786 struct spoolss_DriverInfo8 *info = NULL;
1787 struct spoolss_DriverInfo8 *info_win2k = NULL;
1788 int version;
1789 WERROR status;
1790 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1792 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1793 and not a printer admin, then fail */
1795 if ( (p->server_info->utok.uid != sec_initial_uid())
1796 && !user_has_privileges(p->server_info->ptok, &se_printop )
1797 && !token_contains_name_in_list(
1798 uidtoname(p->server_info->utok.uid),
1799 p->server_info->info3->base.domain.string,
1800 NULL,
1801 p->server_info->ptok,
1802 lp_printer_admin(-1)) )
1804 return WERR_ACCESS_DENIED;
1807 /* check that we have a valid driver name first */
1809 if ((version = get_version_id(r->in.architecture)) == -1)
1810 return WERR_INVALID_ENVIRONMENT;
1812 status = winreg_get_driver(p->mem_ctx, p->server_info,
1813 r->in.architecture, r->in.driver,
1814 version, &info);
1815 if (!W_ERROR_IS_OK(status)) {
1816 /* try for Win2k driver if "Windows NT x86" */
1818 if ( version == 2 ) {
1819 version = 3;
1821 status = winreg_get_driver(p->mem_ctx, p->server_info,
1822 r->in.architecture,
1823 r->in.driver,
1824 version, &info);
1825 if (!W_ERROR_IS_OK(status)) {
1826 status = WERR_UNKNOWN_PRINTER_DRIVER;
1827 goto done;
1830 /* otherwise it was a failure */
1831 else {
1832 status = WERR_UNKNOWN_PRINTER_DRIVER;
1833 goto done;
1838 if (printer_driver_in_use(p->mem_ctx, p->server_info, info)) {
1839 status = WERR_PRINTER_DRIVER_IN_USE;
1840 goto done;
1843 if (version == 2) {
1844 status = winreg_get_driver(p->mem_ctx, p->server_info,
1845 r->in.architecture,
1846 r->in.driver, 3, &info_win2k);
1847 if (W_ERROR_IS_OK(status)) {
1848 /* if we get to here, we now have 2 driver info structures to remove */
1849 /* remove the Win2k driver first*/
1851 status = winreg_del_driver(p->mem_ctx,
1852 p->server_info,
1853 info_win2k, 3);
1854 talloc_free(info_win2k);
1856 /* this should not have failed---if it did, report to client */
1857 if (!W_ERROR_IS_OK(status)) {
1858 goto done;
1863 status = winreg_del_driver(p->mem_ctx, p->server_info, info, version);
1865 done:
1866 talloc_free(info);
1868 return status;
1871 /****************************************************************
1872 _spoolss_DeletePrinterDriverEx
1873 ****************************************************************/
1875 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1876 struct spoolss_DeletePrinterDriverEx *r)
1878 struct spoolss_DriverInfo8 *info = NULL;
1879 struct spoolss_DriverInfo8 *info_win2k = NULL;
1880 int version;
1881 bool delete_files;
1882 WERROR status;
1883 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1885 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1886 and not a printer admin, then fail */
1888 if ( (p->server_info->utok.uid != sec_initial_uid())
1889 && !user_has_privileges(p->server_info->ptok, &se_printop )
1890 && !token_contains_name_in_list(
1891 uidtoname(p->server_info->utok.uid),
1892 p->server_info->info3->base.domain.string,
1893 NULL,
1894 p->server_info->ptok, lp_printer_admin(-1)) )
1896 return WERR_ACCESS_DENIED;
1899 /* check that we have a valid driver name first */
1900 if ((version = get_version_id(r->in.architecture)) == -1) {
1901 /* this is what NT returns */
1902 return WERR_INVALID_ENVIRONMENT;
1905 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1906 version = r->in.version;
1908 status = winreg_get_driver(p->mem_ctx, p->server_info,
1909 r->in.architecture, r->in.driver,
1910 version, &info);
1911 if (!W_ERROR_IS_OK(status)) {
1912 status = WERR_UNKNOWN_PRINTER_DRIVER;
1915 * if the client asked for a specific version,
1916 * or this is something other than Windows NT x86,
1917 * then we've failed
1920 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1921 goto done;
1923 /* try for Win2k driver if "Windows NT x86" */
1925 version = 3;
1926 status = winreg_get_driver(info, p->server_info,
1927 r->in.architecture,
1928 r->in.driver,
1929 version, &info);
1930 if (!W_ERROR_IS_OK(status)) {
1931 status = WERR_UNKNOWN_PRINTER_DRIVER;
1932 goto done;
1936 if (printer_driver_in_use(info, p->server_info, info)) {
1937 status = WERR_PRINTER_DRIVER_IN_USE;
1938 goto done;
1942 * we have a couple of cases to consider.
1943 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1944 * then the delete should fail if **any** files overlap with
1945 * other drivers
1946 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1947 * non-overlapping files
1948 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1949 * is set, the do not delete any files
1950 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1953 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1955 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1957 if (delete_files &&
1958 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1959 printer_driver_files_in_use(info, p->server_info, info)) {
1960 /* no idea of the correct error here */
1961 status = WERR_ACCESS_DENIED;
1962 goto done;
1966 /* also check for W32X86/3 if necessary; maybe we already have? */
1968 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
1969 status = winreg_get_driver(info, p->server_info,
1970 r->in.architecture,
1971 r->in.driver, 3, &info_win2k);
1972 if (W_ERROR_IS_OK(status)) {
1974 if (delete_files &&
1975 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1976 printer_driver_files_in_use(info, p->server_info,
1977 info_win2k)) {
1978 /* no idea of the correct error here */
1979 talloc_free(info_win2k);
1980 status = WERR_ACCESS_DENIED;
1981 goto done;
1984 /* if we get to here, we now have 2 driver info structures to remove */
1985 /* remove the Win2k driver first*/
1987 status = winreg_del_driver(info, p->server_info,
1988 info_win2k, 3);
1990 /* this should not have failed---if it did, report to client */
1992 if (!W_ERROR_IS_OK(status)) {
1993 goto done;
1997 * now delete any associated files if delete_files is
1998 * true. Even if this part failes, we return succes
1999 * because the driver doesn not exist any more
2001 if (delete_files) {
2002 delete_driver_files(p->server_info,
2003 info_win2k);
2008 status = winreg_del_driver(info, p->server_info, info, version);
2009 if (!W_ERROR_IS_OK(status)) {
2010 goto done;
2014 * now delete any associated files if delete_files is
2015 * true. Even if this part failes, we return succes
2016 * because the driver doesn not exist any more
2018 if (delete_files) {
2019 delete_driver_files(p->server_info, info);
2022 done:
2023 talloc_free(info);
2024 return status;
2028 /****************************************************************************
2029 Internal routine for storing printerdata
2030 ***************************************************************************/
2032 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2033 const char *key, const char *value,
2034 uint32_t type, uint8_t *data, int real_len)
2036 /* the registry objects enforce uniqueness based on value name */
2038 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2041 /********************************************************************
2042 GetPrinterData on a printer server Handle.
2043 ********************************************************************/
2045 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2046 const char *value,
2047 enum winreg_Type *type,
2048 union spoolss_PrinterData *data)
2050 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2052 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2053 *type = REG_DWORD;
2054 data->value = 0x00;
2055 return WERR_OK;
2058 if (!StrCaseCmp(value, "BeepEnabled")) {
2059 *type = REG_DWORD;
2060 data->value = 0x00;
2061 return WERR_OK;
2064 if (!StrCaseCmp(value, "EventLog")) {
2065 *type = REG_DWORD;
2066 /* formally was 0x1b */
2067 data->value = 0x00;
2068 return WERR_OK;
2071 if (!StrCaseCmp(value, "NetPopup")) {
2072 *type = REG_DWORD;
2073 data->value = 0x00;
2074 return WERR_OK;
2077 if (!StrCaseCmp(value, "MajorVersion")) {
2078 *type = REG_DWORD;
2080 /* Windows NT 4.0 seems to not allow uploading of drivers
2081 to a server that reports 0x3 as the MajorVersion.
2082 need to investigate more how Win2k gets around this .
2083 -- jerry */
2085 if (RA_WINNT == get_remote_arch()) {
2086 data->value = 0x02;
2087 } else {
2088 data->value = 0x03;
2091 return WERR_OK;
2094 if (!StrCaseCmp(value, "MinorVersion")) {
2095 *type = REG_DWORD;
2096 data->value = 0x00;
2097 return WERR_OK;
2100 /* REG_BINARY
2101 * uint32_t size = 0x114
2102 * uint32_t major = 5
2103 * uint32_t minor = [0|1]
2104 * uint32_t build = [2195|2600]
2105 * extra unicode string = e.g. "Service Pack 3"
2107 if (!StrCaseCmp(value, "OSVersion")) {
2108 DATA_BLOB blob;
2109 enum ndr_err_code ndr_err;
2110 struct spoolss_OSVersion os;
2112 os.major = 5; /* Windows 2000 == 5.0 */
2113 os.minor = 0;
2114 os.build = 2195; /* build */
2115 os.extra_string = ""; /* leave extra string empty */
2117 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2118 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2119 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2120 return WERR_GENERAL_FAILURE;
2123 *type = REG_BINARY;
2124 data->binary = blob;
2126 return WERR_OK;
2130 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2131 *type = REG_SZ;
2133 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2134 W_ERROR_HAVE_NO_MEMORY(data->string);
2136 return WERR_OK;
2139 if (!StrCaseCmp(value, "Architecture")) {
2140 *type = REG_SZ;
2141 data->string = talloc_strdup(mem_ctx,
2142 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2143 W_ERROR_HAVE_NO_MEMORY(data->string);
2145 return WERR_OK;
2148 if (!StrCaseCmp(value, "DsPresent")) {
2149 *type = REG_DWORD;
2151 /* only show the publish check box if we are a
2152 member of a AD domain */
2154 if (lp_security() == SEC_ADS) {
2155 data->value = 0x01;
2156 } else {
2157 data->value = 0x00;
2159 return WERR_OK;
2162 if (!StrCaseCmp(value, "DNSMachineName")) {
2163 const char *hostname = get_mydnsfullname();
2165 if (!hostname) {
2166 return WERR_BADFILE;
2169 *type = REG_SZ;
2170 data->string = talloc_strdup(mem_ctx, hostname);
2171 W_ERROR_HAVE_NO_MEMORY(data->string);
2173 return WERR_OK;
2176 *type = REG_NONE;
2178 return WERR_INVALID_PARAM;
2181 /****************************************************************
2182 _spoolss_GetPrinterData
2183 ****************************************************************/
2185 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2186 struct spoolss_GetPrinterData *r)
2188 struct spoolss_GetPrinterDataEx r2;
2190 r2.in.handle = r->in.handle;
2191 r2.in.key_name = "PrinterDriverData";
2192 r2.in.value_name = r->in.value_name;
2193 r2.in.offered = r->in.offered;
2194 r2.out.type = r->out.type;
2195 r2.out.data = r->out.data;
2196 r2.out.needed = r->out.needed;
2198 return _spoolss_GetPrinterDataEx(p, &r2);
2201 /*********************************************************
2202 Connect to the client machine.
2203 **********************************************************/
2205 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2206 struct sockaddr_storage *client_ss, const char *remote_machine)
2208 NTSTATUS ret;
2209 struct cli_state *the_cli;
2210 struct sockaddr_storage rm_addr;
2211 char addr[INET6_ADDRSTRLEN];
2213 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2214 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2215 remote_machine));
2216 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2217 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2218 return false;
2220 print_sockaddr(addr, sizeof(addr), &rm_addr);
2221 } else {
2222 rm_addr = *client_ss;
2223 print_sockaddr(addr, sizeof(addr), &rm_addr);
2224 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2225 addr));
2228 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2229 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2230 addr));
2231 return false;
2234 /* setup the connection */
2235 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2236 &rm_addr, 0, "IPC$", "IPC",
2237 "", /* username */
2238 "", /* domain */
2239 "", /* password */
2240 0, lp_client_signing(), NULL );
2242 if ( !NT_STATUS_IS_OK( ret ) ) {
2243 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2244 remote_machine ));
2245 return false;
2248 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2249 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2250 cli_shutdown(the_cli);
2251 return false;
2255 * Ok - we have an anonymous connection to the IPC$ share.
2256 * Now start the NT Domain stuff :-).
2259 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2260 if (!NT_STATUS_IS_OK(ret)) {
2261 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2262 remote_machine, nt_errstr(ret)));
2263 cli_shutdown(the_cli);
2264 return false;
2267 return true;
2270 /***************************************************************************
2271 Connect to the client.
2272 ****************************************************************************/
2274 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2275 uint32_t localprinter, uint32_t type,
2276 struct policy_handle *handle,
2277 struct sockaddr_storage *client_ss)
2279 WERROR result;
2280 NTSTATUS status;
2283 * If it's the first connection, contact the client
2284 * and connect to the IPC$ share anonymously
2286 if (smb_connections==0) {
2287 fstring unix_printer;
2289 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2291 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2292 return false;
2294 messaging_register(smbd_messaging_context(), NULL,
2295 MSG_PRINTER_NOTIFY2,
2296 receive_notify2_message_list);
2297 /* Tell the connections db we're now interested in printer
2298 * notify messages. */
2299 serverid_register_msg_flags(
2300 messaging_server_id(smbd_messaging_context()),
2301 true, FLAG_MSG_PRINT_NOTIFY);
2305 * Tell the specific printing tdb we want messages for this printer
2306 * by registering our PID.
2309 if (!print_notify_register_pid(snum))
2310 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2312 smb_connections++;
2314 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2315 printer,
2316 localprinter,
2317 type,
2319 NULL,
2320 handle,
2321 &result);
2322 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2323 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2324 win_errstr(result)));
2326 return (W_ERROR_IS_OK(result));
2329 /****************************************************************
2330 ****************************************************************/
2332 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2333 const struct spoolss_NotifyOption *r)
2335 struct spoolss_NotifyOption *option;
2336 uint32_t i,k;
2338 if (!r) {
2339 return NULL;
2342 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2343 if (!option) {
2344 return NULL;
2347 *option = *r;
2349 if (!option->count) {
2350 return option;
2353 option->types = talloc_zero_array(option,
2354 struct spoolss_NotifyOptionType, option->count);
2355 if (!option->types) {
2356 talloc_free(option);
2357 return NULL;
2360 for (i=0; i < option->count; i++) {
2361 option->types[i] = r->types[i];
2363 if (option->types[i].count) {
2364 option->types[i].fields = talloc_zero_array(option,
2365 union spoolss_Field, option->types[i].count);
2366 if (!option->types[i].fields) {
2367 talloc_free(option);
2368 return NULL;
2370 for (k=0; k<option->types[i].count; k++) {
2371 option->types[i].fields[k] =
2372 r->types[i].fields[k];
2377 return option;
2380 /****************************************************************
2381 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2383 * before replying OK: status=0 a rpc call is made to the workstation
2384 * asking ReplyOpenPrinter
2386 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2387 * called from api_spoolss_rffpcnex
2388 ****************************************************************/
2390 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2391 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2393 int snum = -1;
2394 struct spoolss_NotifyOption *option = r->in.notify_options;
2395 struct sockaddr_storage client_ss;
2397 /* store the notify value in the printer struct */
2399 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2401 if (!Printer) {
2402 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2403 "Invalid handle (%s:%u:%u).\n",
2404 OUR_HANDLE(r->in.handle)));
2405 return WERR_BADFID;
2408 Printer->notify.flags = r->in.flags;
2409 Printer->notify.options = r->in.options;
2410 Printer->notify.printerlocal = r->in.printer_local;
2412 TALLOC_FREE(Printer->notify.option);
2413 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2415 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2417 /* Connect to the client machine and send a ReplyOpenPrinter */
2419 if ( Printer->printer_type == SPLHND_SERVER)
2420 snum = -1;
2421 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2422 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2423 return WERR_BADFID;
2425 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2426 "client_address is %s\n", p->client_address));
2428 if (!interpret_string_addr(&client_ss, p->client_address,
2429 AI_NUMERICHOST)) {
2430 return WERR_SERVER_UNAVAILABLE;
2433 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2434 Printer->notify.printerlocal, 1,
2435 &Printer->notify.client_hnd, &client_ss))
2436 return WERR_SERVER_UNAVAILABLE;
2438 Printer->notify.client_connected = true;
2440 return WERR_OK;
2443 /*******************************************************************
2444 * fill a notify_info_data with the servername
2445 ********************************************************************/
2447 static void spoolss_notify_server_name(int snum,
2448 struct spoolss_Notify *data,
2449 print_queue_struct *queue,
2450 struct spoolss_PrinterInfo2 *pinfo2,
2451 TALLOC_CTX *mem_ctx)
2453 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2456 /*******************************************************************
2457 * fill a notify_info_data with the printername (not including the servername).
2458 ********************************************************************/
2460 static void spoolss_notify_printer_name(int snum,
2461 struct spoolss_Notify *data,
2462 print_queue_struct *queue,
2463 struct spoolss_PrinterInfo2 *pinfo2,
2464 TALLOC_CTX *mem_ctx)
2466 /* the notify name should not contain the \\server\ part */
2467 const char *p = strrchr(pinfo2->printername, '\\');
2469 if (!p) {
2470 p = pinfo2->printername;
2471 } else {
2472 p++;
2475 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2478 /*******************************************************************
2479 * fill a notify_info_data with the servicename
2480 ********************************************************************/
2482 static void spoolss_notify_share_name(int snum,
2483 struct spoolss_Notify *data,
2484 print_queue_struct *queue,
2485 struct spoolss_PrinterInfo2 *pinfo2,
2486 TALLOC_CTX *mem_ctx)
2488 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2491 /*******************************************************************
2492 * fill a notify_info_data with the port name
2493 ********************************************************************/
2495 static void spoolss_notify_port_name(int snum,
2496 struct spoolss_Notify *data,
2497 print_queue_struct *queue,
2498 struct spoolss_PrinterInfo2 *pinfo2,
2499 TALLOC_CTX *mem_ctx)
2501 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2504 /*******************************************************************
2505 * fill a notify_info_data with the printername
2506 * but it doesn't exist, have to see what to do
2507 ********************************************************************/
2509 static void spoolss_notify_driver_name(int snum,
2510 struct spoolss_Notify *data,
2511 print_queue_struct *queue,
2512 struct spoolss_PrinterInfo2 *pinfo2,
2513 TALLOC_CTX *mem_ctx)
2515 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2518 /*******************************************************************
2519 * fill a notify_info_data with the comment
2520 ********************************************************************/
2522 static void spoolss_notify_comment(int snum,
2523 struct spoolss_Notify *data,
2524 print_queue_struct *queue,
2525 struct spoolss_PrinterInfo2 *pinfo2,
2526 TALLOC_CTX *mem_ctx)
2528 const char *p;
2530 if (*pinfo2->comment == '\0') {
2531 p = lp_comment(snum);
2532 } else {
2533 p = pinfo2->comment;
2536 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2539 /*******************************************************************
2540 * fill a notify_info_data with the comment
2541 * location = "Room 1, floor 2, building 3"
2542 ********************************************************************/
2544 static void spoolss_notify_location(int snum,
2545 struct spoolss_Notify *data,
2546 print_queue_struct *queue,
2547 struct spoolss_PrinterInfo2 *pinfo2,
2548 TALLOC_CTX *mem_ctx)
2550 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2553 /*******************************************************************
2554 * fill a notify_info_data with the device mode
2555 * jfm:xxxx don't to it for know but that's a real problem !!!
2556 ********************************************************************/
2558 static void spoolss_notify_devmode(int snum,
2559 struct spoolss_Notify *data,
2560 print_queue_struct *queue,
2561 struct spoolss_PrinterInfo2 *pinfo2,
2562 TALLOC_CTX *mem_ctx)
2564 /* for a dummy implementation we have to zero the fields */
2565 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2568 /*******************************************************************
2569 * fill a notify_info_data with the separator file name
2570 ********************************************************************/
2572 static void spoolss_notify_sepfile(int snum,
2573 struct spoolss_Notify *data,
2574 print_queue_struct *queue,
2575 struct spoolss_PrinterInfo2 *pinfo2,
2576 TALLOC_CTX *mem_ctx)
2578 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2581 /*******************************************************************
2582 * fill a notify_info_data with the print processor
2583 * jfm:xxxx return always winprint to indicate we don't do anything to it
2584 ********************************************************************/
2586 static void spoolss_notify_print_processor(int snum,
2587 struct spoolss_Notify *data,
2588 print_queue_struct *queue,
2589 struct spoolss_PrinterInfo2 *pinfo2,
2590 TALLOC_CTX *mem_ctx)
2592 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2595 /*******************************************************************
2596 * fill a notify_info_data with the print processor options
2597 * jfm:xxxx send an empty string
2598 ********************************************************************/
2600 static void spoolss_notify_parameters(int snum,
2601 struct spoolss_Notify *data,
2602 print_queue_struct *queue,
2603 struct spoolss_PrinterInfo2 *pinfo2,
2604 TALLOC_CTX *mem_ctx)
2606 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2609 /*******************************************************************
2610 * fill a notify_info_data with the data type
2611 * jfm:xxxx always send RAW as data type
2612 ********************************************************************/
2614 static void spoolss_notify_datatype(int snum,
2615 struct spoolss_Notify *data,
2616 print_queue_struct *queue,
2617 struct spoolss_PrinterInfo2 *pinfo2,
2618 TALLOC_CTX *mem_ctx)
2620 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2623 /*******************************************************************
2624 * fill a notify_info_data with the security descriptor
2625 * jfm:xxxx send an null pointer to say no security desc
2626 * have to implement security before !
2627 ********************************************************************/
2629 static void spoolss_notify_security_desc(int snum,
2630 struct spoolss_Notify *data,
2631 print_queue_struct *queue,
2632 struct spoolss_PrinterInfo2 *pinfo2,
2633 TALLOC_CTX *mem_ctx)
2635 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2638 /*******************************************************************
2639 * fill a notify_info_data with the attributes
2640 * jfm:xxxx a samba printer is always shared
2641 ********************************************************************/
2643 static void spoolss_notify_attributes(int snum,
2644 struct spoolss_Notify *data,
2645 print_queue_struct *queue,
2646 struct spoolss_PrinterInfo2 *pinfo2,
2647 TALLOC_CTX *mem_ctx)
2649 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2652 /*******************************************************************
2653 * fill a notify_info_data with the priority
2654 ********************************************************************/
2656 static void spoolss_notify_priority(int snum,
2657 struct spoolss_Notify *data,
2658 print_queue_struct *queue,
2659 struct spoolss_PrinterInfo2 *pinfo2,
2660 TALLOC_CTX *mem_ctx)
2662 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2665 /*******************************************************************
2666 * fill a notify_info_data with the default priority
2667 ********************************************************************/
2669 static void spoolss_notify_default_priority(int snum,
2670 struct spoolss_Notify *data,
2671 print_queue_struct *queue,
2672 struct spoolss_PrinterInfo2 *pinfo2,
2673 TALLOC_CTX *mem_ctx)
2675 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2678 /*******************************************************************
2679 * fill a notify_info_data with the start time
2680 ********************************************************************/
2682 static void spoolss_notify_start_time(int snum,
2683 struct spoolss_Notify *data,
2684 print_queue_struct *queue,
2685 struct spoolss_PrinterInfo2 *pinfo2,
2686 TALLOC_CTX *mem_ctx)
2688 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2691 /*******************************************************************
2692 * fill a notify_info_data with the until time
2693 ********************************************************************/
2695 static void spoolss_notify_until_time(int snum,
2696 struct spoolss_Notify *data,
2697 print_queue_struct *queue,
2698 struct spoolss_PrinterInfo2 *pinfo2,
2699 TALLOC_CTX *mem_ctx)
2701 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2704 /*******************************************************************
2705 * fill a notify_info_data with the status
2706 ********************************************************************/
2708 static void spoolss_notify_status(int snum,
2709 struct spoolss_Notify *data,
2710 print_queue_struct *queue,
2711 struct spoolss_PrinterInfo2 *pinfo2,
2712 TALLOC_CTX *mem_ctx)
2714 print_status_struct status;
2716 print_queue_length(snum, &status);
2717 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2720 /*******************************************************************
2721 * fill a notify_info_data with the number of jobs queued
2722 ********************************************************************/
2724 static void spoolss_notify_cjobs(int snum,
2725 struct spoolss_Notify *data,
2726 print_queue_struct *queue,
2727 struct spoolss_PrinterInfo2 *pinfo2,
2728 TALLOC_CTX *mem_ctx)
2730 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2733 /*******************************************************************
2734 * fill a notify_info_data with the average ppm
2735 ********************************************************************/
2737 static void spoolss_notify_average_ppm(int snum,
2738 struct spoolss_Notify *data,
2739 print_queue_struct *queue,
2740 struct spoolss_PrinterInfo2 *pinfo2,
2741 TALLOC_CTX *mem_ctx)
2743 /* always respond 8 pages per minutes */
2744 /* a little hard ! */
2745 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
2748 /*******************************************************************
2749 * fill a notify_info_data with username
2750 ********************************************************************/
2752 static void spoolss_notify_username(int snum,
2753 struct spoolss_Notify *data,
2754 print_queue_struct *queue,
2755 struct spoolss_PrinterInfo2 *pinfo2,
2756 TALLOC_CTX *mem_ctx)
2758 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2761 /*******************************************************************
2762 * fill a notify_info_data with job status
2763 ********************************************************************/
2765 static void spoolss_notify_job_status(int snum,
2766 struct spoolss_Notify *data,
2767 print_queue_struct *queue,
2768 struct spoolss_PrinterInfo2 *pinfo2,
2769 TALLOC_CTX *mem_ctx)
2771 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2774 /*******************************************************************
2775 * fill a notify_info_data with job name
2776 ********************************************************************/
2778 static void spoolss_notify_job_name(int snum,
2779 struct spoolss_Notify *data,
2780 print_queue_struct *queue,
2781 struct spoolss_PrinterInfo2 *pinfo2,
2782 TALLOC_CTX *mem_ctx)
2784 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2787 /*******************************************************************
2788 * fill a notify_info_data with job status
2789 ********************************************************************/
2791 static void spoolss_notify_job_status_string(int snum,
2792 struct spoolss_Notify *data,
2793 print_queue_struct *queue,
2794 struct spoolss_PrinterInfo2 *pinfo2,
2795 TALLOC_CTX *mem_ctx)
2798 * Now we're returning job status codes we just return a "" here. JRA.
2801 const char *p = "";
2803 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2804 p = "unknown";
2806 switch (queue->status) {
2807 case LPQ_QUEUED:
2808 p = "Queued";
2809 break;
2810 case LPQ_PAUSED:
2811 p = ""; /* NT provides the paused string */
2812 break;
2813 case LPQ_SPOOLING:
2814 p = "Spooling";
2815 break;
2816 case LPQ_PRINTING:
2817 p = "Printing";
2818 break;
2820 #endif /* NO LONGER NEEDED. */
2822 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2825 /*******************************************************************
2826 * fill a notify_info_data with job time
2827 ********************************************************************/
2829 static void spoolss_notify_job_time(int snum,
2830 struct spoolss_Notify *data,
2831 print_queue_struct *queue,
2832 struct spoolss_PrinterInfo2 *pinfo2,
2833 TALLOC_CTX *mem_ctx)
2835 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2838 /*******************************************************************
2839 * fill a notify_info_data with job size
2840 ********************************************************************/
2842 static void spoolss_notify_job_size(int snum,
2843 struct spoolss_Notify *data,
2844 print_queue_struct *queue,
2845 struct spoolss_PrinterInfo2 *pinfo2,
2846 TALLOC_CTX *mem_ctx)
2848 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2851 /*******************************************************************
2852 * fill a notify_info_data with page info
2853 ********************************************************************/
2854 static void spoolss_notify_total_pages(int snum,
2855 struct spoolss_Notify *data,
2856 print_queue_struct *queue,
2857 struct spoolss_PrinterInfo2 *pinfo2,
2858 TALLOC_CTX *mem_ctx)
2860 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2863 /*******************************************************************
2864 * fill a notify_info_data with pages printed info.
2865 ********************************************************************/
2866 static void spoolss_notify_pages_printed(int snum,
2867 struct spoolss_Notify *data,
2868 print_queue_struct *queue,
2869 struct spoolss_PrinterInfo2 *pinfo2,
2870 TALLOC_CTX *mem_ctx)
2872 /* Add code when back-end tracks this */
2873 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2876 /*******************************************************************
2877 Fill a notify_info_data with job position.
2878 ********************************************************************/
2880 static void spoolss_notify_job_position(int snum,
2881 struct spoolss_Notify *data,
2882 print_queue_struct *queue,
2883 struct spoolss_PrinterInfo2 *pinfo2,
2884 TALLOC_CTX *mem_ctx)
2886 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2889 /*******************************************************************
2890 Fill a notify_info_data with submitted time.
2891 ********************************************************************/
2893 static void spoolss_notify_submitted_time(int snum,
2894 struct spoolss_Notify *data,
2895 print_queue_struct *queue,
2896 struct spoolss_PrinterInfo2 *pinfo2,
2897 TALLOC_CTX *mem_ctx)
2899 data->data.string.string = NULL;
2900 data->data.string.size = 0;
2902 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2903 &data->data.string.string,
2904 &data->data.string.size);
2908 struct s_notify_info_data_table
2910 enum spoolss_NotifyType type;
2911 uint16_t field;
2912 const char *name;
2913 enum spoolss_NotifyTable variable_type;
2914 void (*fn) (int snum, struct spoolss_Notify *data,
2915 print_queue_struct *queue,
2916 struct spoolss_PrinterInfo2 *pinfo2,
2917 TALLOC_CTX *mem_ctx);
2920 /* A table describing the various print notification constants and
2921 whether the notification data is a pointer to a variable sized
2922 buffer, a one value uint32_t or a two value uint32_t. */
2924 static const struct s_notify_info_data_table notify_info_data_table[] =
2926 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2927 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2928 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2929 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2930 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2931 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2932 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2933 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2934 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2935 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2936 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2937 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2938 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2939 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2940 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2941 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2942 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2943 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2944 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2945 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2946 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
2947 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
2948 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
2949 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2950 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
2951 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2952 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2953 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2954 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2955 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2956 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2957 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2958 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2959 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2960 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2961 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2962 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
2963 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
2964 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
2965 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
2966 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2967 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
2968 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
2969 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2970 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2971 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
2972 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
2973 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
2974 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
2977 /*******************************************************************
2978 Return the variable_type of info_data structure.
2979 ********************************************************************/
2981 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
2982 uint16_t field)
2984 int i=0;
2986 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
2987 if ( (notify_info_data_table[i].type == type) &&
2988 (notify_info_data_table[i].field == field) ) {
2989 return notify_info_data_table[i].variable_type;
2993 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2995 return 0;
2998 /****************************************************************************
2999 ****************************************************************************/
3001 static bool search_notify(enum spoolss_NotifyType type,
3002 uint16_t field,
3003 int *value)
3005 int i;
3007 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3008 if (notify_info_data_table[i].type == type &&
3009 notify_info_data_table[i].field == field &&
3010 notify_info_data_table[i].fn != NULL) {
3011 *value = i;
3012 return true;
3016 return false;
3019 /****************************************************************************
3020 ****************************************************************************/
3022 static void construct_info_data(struct spoolss_Notify *info_data,
3023 enum spoolss_NotifyType type,
3024 uint16_t field, int id)
3026 info_data->type = type;
3027 info_data->field.field = field;
3028 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3029 info_data->job_id = id;
3032 /*******************************************************************
3034 * fill a notify_info struct with info asked
3036 ********************************************************************/
3038 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3039 struct spoolss_NotifyInfo *info,
3040 struct spoolss_PrinterInfo2 *pinfo2,
3041 int snum,
3042 const struct spoolss_NotifyOptionType *option_type,
3043 uint32_t id,
3044 TALLOC_CTX *mem_ctx)
3046 int field_num,j;
3047 enum spoolss_NotifyType type;
3048 uint16_t field;
3050 struct spoolss_Notify *current_data;
3051 print_queue_struct *queue=NULL;
3053 type = option_type->type;
3055 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3056 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3057 option_type->count, lp_servicename(snum)));
3059 for(field_num=0; field_num < option_type->count; field_num++) {
3060 field = option_type->fields[field_num].field;
3062 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3064 if (!search_notify(type, field, &j) )
3065 continue;
3067 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3068 struct spoolss_Notify,
3069 info->count + 1);
3070 if (info->notifies == NULL) {
3071 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3072 return false;
3075 current_data = &info->notifies[info->count];
3077 construct_info_data(current_data, type, field, id);
3079 DEBUG(10, ("construct_notify_printer_info: "
3080 "calling [%s] snum=%d printername=[%s])\n",
3081 notify_info_data_table[j].name, snum,
3082 pinfo2->printername));
3084 notify_info_data_table[j].fn(snum, current_data, queue,
3085 pinfo2, mem_ctx);
3087 info->count++;
3090 return true;
3093 /*******************************************************************
3095 * fill a notify_info struct with info asked
3097 ********************************************************************/
3099 static bool construct_notify_jobs_info(print_queue_struct *queue,
3100 struct spoolss_NotifyInfo *info,
3101 struct spoolss_PrinterInfo2 *pinfo2,
3102 int snum,
3103 const struct spoolss_NotifyOptionType *option_type,
3104 uint32_t id,
3105 TALLOC_CTX *mem_ctx)
3107 int field_num,j;
3108 enum spoolss_NotifyType type;
3109 uint16_t field;
3110 struct spoolss_Notify *current_data;
3112 DEBUG(4,("construct_notify_jobs_info\n"));
3114 type = option_type->type;
3116 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3117 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3118 option_type->count));
3120 for(field_num=0; field_num<option_type->count; field_num++) {
3121 field = option_type->fields[field_num].field;
3123 if (!search_notify(type, field, &j) )
3124 continue;
3126 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3127 struct spoolss_Notify,
3128 info->count + 1);
3129 if (info->notifies == NULL) {
3130 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3131 return false;
3134 current_data=&(info->notifies[info->count]);
3136 construct_info_data(current_data, type, field, id);
3137 notify_info_data_table[j].fn(snum, current_data, queue,
3138 pinfo2, mem_ctx);
3139 info->count++;
3142 return true;
3146 * JFM: The enumeration is not that simple, it's even non obvious.
3148 * let's take an example: I want to monitor the PRINTER SERVER for
3149 * the printer's name and the number of jobs currently queued.
3150 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3151 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3153 * I have 3 printers on the back of my server.
3155 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3156 * structures.
3157 * Number Data Id
3158 * 1 printer 1 name 1
3159 * 2 printer 1 cjob 1
3160 * 3 printer 2 name 2
3161 * 4 printer 2 cjob 2
3162 * 5 printer 3 name 3
3163 * 6 printer 3 name 3
3165 * that's the print server case, the printer case is even worse.
3168 /*******************************************************************
3170 * enumerate all printers on the printserver
3171 * fill a notify_info struct with info asked
3173 ********************************************************************/
3175 static WERROR printserver_notify_info(pipes_struct *p,
3176 struct policy_handle *hnd,
3177 struct spoolss_NotifyInfo *info,
3178 TALLOC_CTX *mem_ctx)
3180 int snum;
3181 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3182 int n_services=lp_numservices();
3183 int i;
3184 struct spoolss_NotifyOption *option;
3185 struct spoolss_NotifyOptionType option_type;
3186 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3187 WERROR result;
3189 DEBUG(4,("printserver_notify_info\n"));
3191 if (!Printer)
3192 return WERR_BADFID;
3194 option = Printer->notify.option;
3196 info->version = 2;
3197 info->notifies = NULL;
3198 info->count = 0;
3200 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3201 sending a ffpcn() request first */
3203 if ( !option )
3204 return WERR_BADFID;
3206 for (i=0; i<option->count; i++) {
3207 option_type = option->types[i];
3209 if (option_type.type != PRINTER_NOTIFY_TYPE)
3210 continue;
3212 for (snum = 0; snum < n_services; snum++) {
3213 if (!lp_browseable(snum) ||
3214 !lp_snum_ok(snum) ||
3215 !lp_print_ok(snum)) {
3216 continue; /* skip */
3219 /* FIXME: should we use a SYSTEM server_info here? */
3220 result = winreg_get_printer(mem_ctx, p->server_info,
3221 Printer->servername,
3222 lp_servicename(snum),
3223 &pinfo2);
3224 if (!W_ERROR_IS_OK(result)) {
3225 DEBUG(4, ("printserver_notify_info: "
3226 "Failed to get printer [%s]\n",
3227 lp_servicename(snum)));
3228 continue;
3232 construct_notify_printer_info(Printer, info,
3233 pinfo2, snum,
3234 &option_type, snum,
3235 mem_ctx);
3237 TALLOC_FREE(pinfo2);
3241 #if 0
3243 * Debugging information, don't delete.
3246 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3247 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3248 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3250 for (i=0; i<info->count; i++) {
3251 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3252 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3253 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3255 #endif
3257 return WERR_OK;
3260 /*******************************************************************
3262 * fill a notify_info struct with info asked
3264 ********************************************************************/
3266 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3267 struct spoolss_NotifyInfo *info,
3268 TALLOC_CTX *mem_ctx)
3270 int snum;
3271 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3272 int i;
3273 uint32_t id;
3274 struct spoolss_NotifyOption *option;
3275 struct spoolss_NotifyOptionType option_type;
3276 int count,j;
3277 print_queue_struct *queue=NULL;
3278 print_status_struct status;
3279 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3280 WERROR result;
3282 DEBUG(4,("printer_notify_info\n"));
3284 if (!Printer)
3285 return WERR_BADFID;
3287 option = Printer->notify.option;
3288 id = 0x0;
3290 info->version = 2;
3291 info->notifies = NULL;
3292 info->count = 0;
3294 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3295 sending a ffpcn() request first */
3297 if ( !option )
3298 return WERR_BADFID;
3300 get_printer_snum(p, hnd, &snum, NULL);
3302 /* FIXME: should we use a SYSTEM server_info here ? */
3303 result = winreg_get_printer(mem_ctx, p->server_info,
3304 Printer->servername,
3305 lp_servicename(snum), &pinfo2);
3306 if (!W_ERROR_IS_OK(result)) {
3307 return WERR_BADFID;
3310 for (i=0; i<option->count; i++) {
3311 option_type = option->types[i];
3313 switch (option_type.type) {
3314 case PRINTER_NOTIFY_TYPE:
3315 if (construct_notify_printer_info(Printer, info,
3316 pinfo2, snum,
3317 &option_type, id,
3318 mem_ctx)) {
3319 id--;
3321 break;
3323 case JOB_NOTIFY_TYPE:
3325 count = print_queue_status(snum, &queue, &status);
3327 for (j=0; j<count; j++) {
3328 construct_notify_jobs_info(&queue[j], info,
3329 pinfo2, snum,
3330 &option_type,
3331 queue[j].job,
3332 mem_ctx);
3335 SAFE_FREE(queue);
3336 break;
3341 * Debugging information, don't delete.
3344 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3345 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3346 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3348 for (i=0; i<info->count; i++) {
3349 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3350 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3351 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3355 talloc_free(pinfo2);
3356 return WERR_OK;
3359 /****************************************************************
3360 _spoolss_RouterRefreshPrinterChangeNotify
3361 ****************************************************************/
3363 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3364 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3366 struct spoolss_NotifyInfo *info;
3368 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3369 WERROR result = WERR_BADFID;
3371 /* we always have a spoolss_NotifyInfo struct */
3372 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3373 if (!info) {
3374 result = WERR_NOMEM;
3375 goto done;
3378 *r->out.info = info;
3380 if (!Printer) {
3381 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3382 "Invalid handle (%s:%u:%u).\n",
3383 OUR_HANDLE(r->in.handle)));
3384 goto done;
3387 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3390 * We are now using the change value, and
3391 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3392 * I don't have a global notification system, I'm sending back all the
3393 * informations even when _NOTHING_ has changed.
3396 /* We need to keep track of the change value to send back in
3397 RRPCN replies otherwise our updates are ignored. */
3399 Printer->notify.fnpcn = true;
3401 if (Printer->notify.client_connected) {
3402 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3403 "Saving change value in request [%x]\n",
3404 r->in.change_low));
3405 Printer->notify.change = r->in.change_low;
3408 /* just ignore the spoolss_NotifyOption */
3410 switch (Printer->printer_type) {
3411 case SPLHND_SERVER:
3412 result = printserver_notify_info(p, r->in.handle,
3413 info, p->mem_ctx);
3414 break;
3416 case SPLHND_PRINTER:
3417 result = printer_notify_info(p, r->in.handle,
3418 info, p->mem_ctx);
3419 break;
3422 Printer->notify.fnpcn = false;
3424 done:
3425 return result;
3428 /********************************************************************
3429 * construct_printer_info_0
3430 * fill a printer_info_0 struct
3431 ********************************************************************/
3433 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3434 struct auth_serversupplied_info *server_info,
3435 struct spoolss_PrinterInfo2 *info2,
3436 struct spoolss_PrinterInfo0 *r,
3437 int snum)
3439 int count;
3440 counter_printer_0 *session_counter;
3441 struct timeval setuptime;
3442 print_status_struct status;
3444 r->printername = talloc_strdup(mem_ctx, info2->printername);
3445 W_ERROR_HAVE_NO_MEMORY(r->printername);
3447 r->servername = talloc_strdup(mem_ctx, info2->servername);
3448 W_ERROR_HAVE_NO_MEMORY(r->servername);
3450 count = print_queue_length(snum, &status);
3452 /* check if we already have a counter for this printer */
3453 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3454 if (session_counter->snum == snum)
3455 break;
3458 /* it's the first time, add it to the list */
3459 if (session_counter == NULL) {
3460 session_counter = SMB_MALLOC_P(counter_printer_0);
3461 W_ERROR_HAVE_NO_MEMORY(session_counter);
3462 ZERO_STRUCTP(session_counter);
3463 session_counter->snum = snum;
3464 session_counter->counter = 0;
3465 DLIST_ADD(counter_list, session_counter);
3468 /* increment it */
3469 session_counter->counter++;
3471 r->cjobs = count;
3472 r->total_jobs = 0;
3473 r->total_bytes = 0;
3475 get_startup_time(&setuptime);
3476 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3478 /* JFM:
3479 * the global_counter should be stored in a TDB as it's common to all the clients
3480 * and should be zeroed on samba startup
3482 r->global_counter = session_counter->counter;
3483 r->total_pages = 0;
3484 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3485 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3486 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3487 r->free_build = SPOOLSS_RELEASE_BUILD;
3488 r->spooling = 0;
3489 r->max_spooling = 0;
3490 r->session_counter = session_counter->counter;
3491 r->num_error_out_of_paper = 0x0;
3492 r->num_error_not_ready = 0x0; /* number of print failure */
3493 r->job_error = 0x0;
3494 r->number_of_processors = 0x1;
3495 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3496 r->high_part_total_bytes = 0x0;
3497 winreg_printer_get_changeid(mem_ctx, server_info, info2->sharename, &r->change_id); /* ChangeID in milliseconds*/
3498 r->last_error = WERR_OK;
3499 r->status = nt_printq_status(status.status);
3500 r->enumerate_network_printers = 0x0;
3501 r->c_setprinter = 0x0;
3502 r->processor_architecture = 0x0;
3503 r->processor_level = 0x6; /* 6 ???*/
3504 r->ref_ic = 0;
3505 r->reserved2 = 0;
3506 r->reserved3 = 0;
3508 return WERR_OK;
3512 /********************************************************************
3513 * construct_printer_info1
3514 * fill a spoolss_PrinterInfo1 struct
3515 ********************************************************************/
3517 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3518 const struct spoolss_PrinterInfo2 *info2,
3519 uint32_t flags,
3520 struct spoolss_PrinterInfo1 *r,
3521 int snum)
3523 r->flags = flags;
3525 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3526 info2->printername,
3527 info2->drivername,
3528 info2->location);
3529 W_ERROR_HAVE_NO_MEMORY(r->description);
3531 if (info2->comment == NULL || info2->comment[0] == '\0') {
3532 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3533 } else {
3534 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3536 W_ERROR_HAVE_NO_MEMORY(r->comment);
3538 r->name = talloc_strdup(mem_ctx, info2->printername);
3539 W_ERROR_HAVE_NO_MEMORY(r->name);
3541 return WERR_OK;
3544 /********************************************************************
3545 * construct_printer_info2
3546 * fill a spoolss_PrinterInfo2 struct
3547 ********************************************************************/
3549 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3550 const struct spoolss_PrinterInfo2 *info2,
3551 struct spoolss_PrinterInfo2 *r,
3552 int snum)
3554 int count;
3555 print_status_struct status;
3557 count = print_queue_length(snum, &status);
3559 r->servername = talloc_strdup(mem_ctx, info2->servername);
3560 W_ERROR_HAVE_NO_MEMORY(r->servername);
3561 r->printername = talloc_strdup(mem_ctx, info2->printername);
3562 W_ERROR_HAVE_NO_MEMORY(r->printername);
3563 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3564 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3565 r->portname = talloc_strdup(mem_ctx, info2->portname);
3566 W_ERROR_HAVE_NO_MEMORY(r->portname);
3567 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3568 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3570 if (info2->comment[0] == '\0') {
3571 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3572 } else {
3573 r->comment = talloc_strdup(mem_ctx, info2->comment);
3575 W_ERROR_HAVE_NO_MEMORY(r->comment);
3577 r->location = talloc_strdup(mem_ctx, info2->location);
3578 W_ERROR_HAVE_NO_MEMORY(r->location);
3579 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
3580 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3581 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
3582 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3583 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
3584 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3585 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
3586 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3588 r->attributes = info2->attributes;
3590 r->priority = info2->priority;
3591 r->defaultpriority = info2->defaultpriority;
3592 r->starttime = info2->starttime;
3593 r->untiltime = info2->untiltime;
3594 r->status = nt_printq_status(status.status);
3595 r->cjobs = count;
3596 r->averageppm = info2->averageppm;
3598 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3599 if (!r->devmode) {
3600 DEBUG(8,("Returning NULL Devicemode!\n"));
3603 r->secdesc = NULL;
3605 if (info2->secdesc != NULL) {
3606 /* don't use talloc_steal() here unless you do a deep steal of all
3607 the SEC_DESC members */
3609 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3612 return WERR_OK;
3615 /********************************************************************
3616 * construct_printer_info3
3617 * fill a spoolss_PrinterInfo3 struct
3618 ********************************************************************/
3620 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3621 const struct spoolss_PrinterInfo2 *info2,
3622 struct spoolss_PrinterInfo3 *r,
3623 int snum)
3625 /* These are the components of the SD we are returning. */
3627 if (info2->secdesc != NULL) {
3628 /* don't use talloc_steal() here unless you do a deep steal of all
3629 the SEC_DESC members */
3631 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3632 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3635 return WERR_OK;
3638 /********************************************************************
3639 * construct_printer_info4
3640 * fill a spoolss_PrinterInfo4 struct
3641 ********************************************************************/
3643 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3644 const struct spoolss_PrinterInfo2 *info2,
3645 struct spoolss_PrinterInfo4 *r,
3646 int snum)
3648 r->printername = talloc_strdup(mem_ctx, info2->printername);
3649 W_ERROR_HAVE_NO_MEMORY(r->printername);
3650 r->servername = talloc_strdup(mem_ctx, info2->servername);
3651 W_ERROR_HAVE_NO_MEMORY(r->servername);
3653 r->attributes = info2->attributes;
3655 return WERR_OK;
3658 /********************************************************************
3659 * construct_printer_info5
3660 * fill a spoolss_PrinterInfo5 struct
3661 ********************************************************************/
3663 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3664 const struct spoolss_PrinterInfo2 *info2,
3665 struct spoolss_PrinterInfo5 *r,
3666 int snum)
3668 r->printername = talloc_strdup(mem_ctx, info2->printername);
3669 W_ERROR_HAVE_NO_MEMORY(r->printername);
3670 r->portname = talloc_strdup(mem_ctx, info2->portname);
3671 W_ERROR_HAVE_NO_MEMORY(r->portname);
3673 r->attributes = info2->attributes;
3675 /* these two are not used by NT+ according to MSDN */
3676 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3677 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3679 return WERR_OK;
3682 /********************************************************************
3683 * construct_printer_info_6
3684 * fill a spoolss_PrinterInfo6 struct
3685 ********************************************************************/
3687 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3688 const struct spoolss_PrinterInfo2 *info2,
3689 struct spoolss_PrinterInfo6 *r,
3690 int snum)
3692 int count;
3693 print_status_struct status;
3695 count = print_queue_length(snum, &status);
3697 r->status = nt_printq_status(status.status);
3699 return WERR_OK;
3702 /********************************************************************
3703 * construct_printer_info7
3704 * fill a spoolss_PrinterInfo7 struct
3705 ********************************************************************/
3707 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3708 Printer_entry *print_hnd,
3709 struct spoolss_PrinterInfo7 *r,
3710 int snum)
3712 struct auth_serversupplied_info *server_info;
3713 struct GUID guid;
3714 NTSTATUS status;
3716 status = make_server_info_system(mem_ctx, &server_info);
3717 if (!NT_STATUS_IS_OK(status)) {
3718 DEBUG(0, ("construct_printer_info7: "
3719 "Could not create system server_info\n"));
3720 return WERR_NOMEM;
3723 if (is_printer_published(mem_ctx, server_info, print_hnd->servername,
3724 lp_servicename(snum), &guid, NULL)) {
3725 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3726 r->action = DSPRINT_PUBLISH;
3727 } else {
3728 r->guid = talloc_strdup(mem_ctx, "");
3729 r->action = DSPRINT_UNPUBLISH;
3731 W_ERROR_HAVE_NO_MEMORY(r->guid);
3733 TALLOC_FREE(server_info);
3734 return WERR_OK;
3737 /********************************************************************
3738 * construct_printer_info8
3739 * fill a spoolss_PrinterInfo8 struct
3740 ********************************************************************/
3742 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3743 const struct spoolss_PrinterInfo2 *info2,
3744 struct spoolss_DeviceModeInfo *r,
3745 int snum)
3747 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3748 if (!r->devmode) {
3749 DEBUG(8,("Returning NULL Devicemode!\n"));
3752 return WERR_OK;
3756 /********************************************************************
3757 ********************************************************************/
3759 static bool snum_is_shared_printer(int snum)
3761 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3764 /********************************************************************
3765 Spoolss_enumprinters.
3766 ********************************************************************/
3768 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3769 struct auth_serversupplied_info *server_info,
3770 uint32_t level,
3771 uint32_t flags,
3772 union spoolss_PrinterInfo **info_p,
3773 uint32_t *count_p)
3775 int snum;
3776 int n_services = lp_numservices();
3777 union spoolss_PrinterInfo *info = NULL;
3778 uint32_t count = 0;
3779 WERROR result = WERR_OK;
3781 *count_p = 0;
3782 *info_p = NULL;
3784 for (snum = 0; snum < n_services; snum++) {
3786 const char *printer;
3787 struct spoolss_PrinterInfo2 *info2;
3789 if (!snum_is_shared_printer(snum)) {
3790 continue;
3793 printer = lp_const_servicename(snum);
3795 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3796 printer, snum));
3798 result = winreg_create_printer(mem_ctx,
3799 server_info,
3800 NULL,
3801 printer);
3802 if (!W_ERROR_IS_OK(result)) {
3803 goto out;
3806 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3807 union spoolss_PrinterInfo,
3808 count + 1);
3809 if (!info) {
3810 result = WERR_NOMEM;
3811 goto out;
3814 result = winreg_get_printer(mem_ctx, server_info,
3815 NULL, printer, &info2);
3816 if (!W_ERROR_IS_OK(result)) {
3817 goto out;
3820 switch (level) {
3821 case 0:
3822 result = construct_printer_info0(info, server_info, info2,
3823 &info[count].info0, snum);
3824 break;
3825 case 1:
3826 result = construct_printer_info1(info, info2, flags,
3827 &info[count].info1, snum);
3828 break;
3829 case 2:
3830 result = construct_printer_info2(info, info2,
3831 &info[count].info2, snum);
3832 break;
3833 case 4:
3834 result = construct_printer_info4(info, info2,
3835 &info[count].info4, snum);
3836 break;
3837 case 5:
3838 result = construct_printer_info5(info, info2,
3839 &info[count].info5, snum);
3840 break;
3842 default:
3843 result = WERR_UNKNOWN_LEVEL;
3844 goto out;
3847 if (!W_ERROR_IS_OK(result)) {
3848 goto out;
3851 count++;
3854 *count_p = count;
3855 *info_p = info;
3857 out:
3858 if (!W_ERROR_IS_OK(result)) {
3859 TALLOC_FREE(info);
3860 return result;
3863 *info_p = info;
3865 return WERR_OK;
3868 /********************************************************************
3869 * handle enumeration of printers at level 0
3870 ********************************************************************/
3872 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3873 struct auth_serversupplied_info *server_info,
3874 uint32_t flags,
3875 const char *servername,
3876 union spoolss_PrinterInfo **info,
3877 uint32_t *count)
3879 DEBUG(4,("enum_all_printers_info_0\n"));
3881 return enum_all_printers_info_level(mem_ctx, server_info, 0, flags, info, count);
3885 /********************************************************************
3886 ********************************************************************/
3888 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3889 struct auth_serversupplied_info *server_info,
3890 uint32_t flags,
3891 union spoolss_PrinterInfo **info,
3892 uint32_t *count)
3894 DEBUG(4,("enum_all_printers_info_1\n"));
3896 return enum_all_printers_info_level(mem_ctx, server_info, 1, flags, info, count);
3899 /********************************************************************
3900 enum_all_printers_info_1_local.
3901 *********************************************************************/
3903 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3904 struct auth_serversupplied_info *server_info,
3905 union spoolss_PrinterInfo **info,
3906 uint32_t *count)
3908 DEBUG(4,("enum_all_printers_info_1_local\n"));
3910 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3913 /********************************************************************
3914 enum_all_printers_info_1_name.
3915 *********************************************************************/
3917 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3918 struct auth_serversupplied_info *server_info,
3919 const char *name,
3920 union spoolss_PrinterInfo **info,
3921 uint32_t *count)
3923 const char *s = name;
3925 DEBUG(4,("enum_all_printers_info_1_name\n"));
3927 if ((name[0] == '\\') && (name[1] == '\\')) {
3928 s = name + 2;
3931 if (!is_myname_or_ipaddr(s)) {
3932 return WERR_INVALID_NAME;
3935 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3938 /********************************************************************
3939 enum_all_printers_info_1_network.
3940 *********************************************************************/
3942 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3943 struct auth_serversupplied_info *server_info,
3944 const char *name,
3945 union spoolss_PrinterInfo **info,
3946 uint32_t *count)
3948 const char *s = name;
3950 DEBUG(4,("enum_all_printers_info_1_network\n"));
3952 /* If we respond to a enum_printers level 1 on our name with flags
3953 set to PRINTER_ENUM_REMOTE with a list of printers then these
3954 printers incorrectly appear in the APW browse list.
3955 Specifically the printers for the server appear at the workgroup
3956 level where all the other servers in the domain are
3957 listed. Windows responds to this call with a
3958 WERR_CAN_NOT_COMPLETE so we should do the same. */
3960 if (name[0] == '\\' && name[1] == '\\') {
3961 s = name + 2;
3964 if (is_myname_or_ipaddr(s)) {
3965 return WERR_CAN_NOT_COMPLETE;
3968 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_NAME, info, count);
3971 /********************************************************************
3972 * api_spoolss_enumprinters
3974 * called from api_spoolss_enumprinters (see this to understand)
3975 ********************************************************************/
3977 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3978 struct auth_serversupplied_info *server_info,
3979 union spoolss_PrinterInfo **info,
3980 uint32_t *count)
3982 DEBUG(4,("enum_all_printers_info_2\n"));
3984 return enum_all_printers_info_level(mem_ctx, server_info, 2, 0, info, count);
3987 /********************************************************************
3988 * handle enumeration of printers at level 1
3989 ********************************************************************/
3991 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3992 struct auth_serversupplied_info *server_info,
3993 uint32_t flags,
3994 const char *name,
3995 union spoolss_PrinterInfo **info,
3996 uint32_t *count)
3998 /* Not all the flags are equals */
4000 if (flags & PRINTER_ENUM_LOCAL) {
4001 return enum_all_printers_info_1_local(mem_ctx, server_info, info, count);
4004 if (flags & PRINTER_ENUM_NAME) {
4005 return enum_all_printers_info_1_name(mem_ctx, server_info, name, info, count);
4008 if (flags & PRINTER_ENUM_NETWORK) {
4009 return enum_all_printers_info_1_network(mem_ctx, server_info, name, info, count);
4012 return WERR_OK; /* NT4sp5 does that */
4015 /********************************************************************
4016 * handle enumeration of printers at level 2
4017 ********************************************************************/
4019 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4020 struct auth_serversupplied_info *server_info,
4021 uint32_t flags,
4022 const char *servername,
4023 union spoolss_PrinterInfo **info,
4024 uint32_t *count)
4026 if (flags & PRINTER_ENUM_LOCAL) {
4027 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4030 if (flags & PRINTER_ENUM_NAME) {
4031 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4032 return WERR_INVALID_NAME;
4035 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4038 if (flags & PRINTER_ENUM_REMOTE) {
4039 return WERR_UNKNOWN_LEVEL;
4042 return WERR_OK;
4045 /********************************************************************
4046 * handle enumeration of printers at level 4
4047 ********************************************************************/
4049 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4050 struct auth_serversupplied_info *server_info,
4051 uint32_t flags,
4052 const char *servername,
4053 union spoolss_PrinterInfo **info,
4054 uint32_t *count)
4056 DEBUG(4,("enum_all_printers_info_4\n"));
4058 return enum_all_printers_info_level(mem_ctx, server_info, 4, flags, info, count);
4062 /********************************************************************
4063 * handle enumeration of printers at level 5
4064 ********************************************************************/
4066 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4067 struct auth_serversupplied_info *server_info,
4068 uint32_t flags,
4069 const char *servername,
4070 union spoolss_PrinterInfo **info,
4071 uint32_t *count)
4073 DEBUG(4,("enum_all_printers_info_5\n"));
4075 return enum_all_printers_info_level(mem_ctx, server_info, 5, flags, info, count);
4078 /****************************************************************
4079 _spoolss_EnumPrinters
4080 ****************************************************************/
4082 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4083 struct spoolss_EnumPrinters *r)
4085 const char *name = NULL;
4086 WERROR result;
4088 /* that's an [in out] buffer */
4090 if (!r->in.buffer && (r->in.offered != 0)) {
4091 return WERR_INVALID_PARAM;
4094 DEBUG(4,("_spoolss_EnumPrinters\n"));
4096 *r->out.needed = 0;
4097 *r->out.count = 0;
4098 *r->out.info = NULL;
4101 * Level 1:
4102 * flags==PRINTER_ENUM_NAME
4103 * if name=="" then enumerates all printers
4104 * if name!="" then enumerate the printer
4105 * flags==PRINTER_ENUM_REMOTE
4106 * name is NULL, enumerate printers
4107 * Level 2: name!="" enumerates printers, name can't be NULL
4108 * Level 3: doesn't exist
4109 * Level 4: does a local registry lookup
4110 * Level 5: same as Level 2
4113 if (r->in.server) {
4114 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4115 W_ERROR_HAVE_NO_MEMORY(name);
4118 switch (r->in.level) {
4119 case 0:
4120 result = enumprinters_level0(p->mem_ctx, p->server_info,
4121 r->in.flags, name,
4122 r->out.info, r->out.count);
4123 break;
4124 case 1:
4125 result = enumprinters_level1(p->mem_ctx, p->server_info,
4126 r->in.flags, name,
4127 r->out.info, r->out.count);
4128 break;
4129 case 2:
4130 result = enumprinters_level2(p->mem_ctx, p->server_info,
4131 r->in.flags, name,
4132 r->out.info, r->out.count);
4133 break;
4134 case 4:
4135 result = enumprinters_level4(p->mem_ctx, p->server_info,
4136 r->in.flags, name,
4137 r->out.info, r->out.count);
4138 break;
4139 case 5:
4140 result = enumprinters_level5(p->mem_ctx, p->server_info,
4141 r->in.flags, name,
4142 r->out.info, r->out.count);
4143 break;
4144 default:
4145 return WERR_UNKNOWN_LEVEL;
4148 if (!W_ERROR_IS_OK(result)) {
4149 return result;
4152 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4153 spoolss_EnumPrinters,
4154 *r->out.info, r->in.level,
4155 *r->out.count);
4156 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4157 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4159 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4162 /****************************************************************
4163 _spoolss_GetPrinter
4164 ****************************************************************/
4166 WERROR _spoolss_GetPrinter(pipes_struct *p,
4167 struct spoolss_GetPrinter *r)
4169 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4170 struct spoolss_PrinterInfo2 *info2 = NULL;
4171 WERROR result = WERR_OK;
4172 const char *servername = NULL;
4173 int snum;
4175 /* that's an [in out] buffer */
4177 if (!r->in.buffer && (r->in.offered != 0)) {
4178 return WERR_INVALID_PARAM;
4181 *r->out.needed = 0;
4183 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4184 return WERR_BADFID;
4187 if (Printer != NULL || Printer->servername != NULL) {
4188 servername = Printer->servername;
4191 result = winreg_get_printer(p->mem_ctx,
4192 p->server_info,
4193 servername,
4194 lp_const_servicename(snum),
4195 &info2);
4196 if (!W_ERROR_IS_OK(result)) {
4197 return result;
4200 switch (r->in.level) {
4201 case 0:
4202 result = construct_printer_info0(p->mem_ctx, p->server_info,
4203 info2,
4204 &r->out.info->info0, snum);
4205 break;
4206 case 1:
4207 result = construct_printer_info1(p->mem_ctx, info2,
4208 PRINTER_ENUM_ICON8,
4209 &r->out.info->info1, snum);
4210 break;
4211 case 2:
4212 result = construct_printer_info2(p->mem_ctx, info2,
4213 &r->out.info->info2, snum);
4214 break;
4215 case 3:
4216 result = construct_printer_info3(p->mem_ctx, info2,
4217 &r->out.info->info3, snum);
4218 break;
4219 case 4:
4220 result = construct_printer_info4(p->mem_ctx, info2,
4221 &r->out.info->info4, snum);
4222 break;
4223 case 5:
4224 result = construct_printer_info5(p->mem_ctx, info2,
4225 &r->out.info->info5, snum);
4226 break;
4227 case 6:
4228 result = construct_printer_info6(p->mem_ctx, info2,
4229 &r->out.info->info6, snum);
4230 break;
4231 case 7:
4232 result = construct_printer_info7(p->mem_ctx, Printer,
4233 &r->out.info->info7, snum);
4234 break;
4235 case 8:
4236 result = construct_printer_info8(p->mem_ctx, info2,
4237 &r->out.info->info8, snum);
4238 break;
4239 default:
4240 result = WERR_UNKNOWN_LEVEL;
4241 break;
4244 if (!W_ERROR_IS_OK(result)) {
4245 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4246 r->in.level, win_errstr(result)));
4247 TALLOC_FREE(r->out.info);
4248 return result;
4251 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4252 r->out.info, r->in.level);
4253 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4255 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4258 /********************************************************************
4259 ********************************************************************/
4261 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4262 do { \
4263 if (in && strlen(in)) { \
4264 out = talloc_strdup(mem_ctx, in); \
4265 W_ERROR_HAVE_NO_MEMORY(out); \
4266 } else { \
4267 out = NULL; \
4269 } while (0);
4271 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4272 do { \
4273 if (in && strlen(in)) { \
4274 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4275 } else { \
4276 out = talloc_strdup(mem_ctx, ""); \
4278 W_ERROR_HAVE_NO_MEMORY(out); \
4279 } while (0);
4281 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4282 const char **string_array,
4283 const char ***presult,
4284 const char *cservername,
4285 const char *arch,
4286 int version)
4288 int i, num_strings = 0;
4289 const char **array = NULL;
4291 if (string_array == NULL) {
4292 return WERR_INVALID_PARAMETER;;
4295 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4296 const char *str = NULL;
4298 if (cservername == NULL || arch == NULL) {
4299 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4300 } else {
4301 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4304 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4305 TALLOC_FREE(array);
4306 return WERR_NOMEM;
4310 if (i > 0) {
4311 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4312 &array, &num_strings);
4315 if (presult) {
4316 *presult = array;
4319 return WERR_OK;
4322 /********************************************************************
4323 * fill a spoolss_DriverInfo1 struct
4324 ********************************************************************/
4326 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4327 struct spoolss_DriverInfo1 *r,
4328 const struct spoolss_DriverInfo8 *driver,
4329 const char *servername)
4331 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4332 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4334 return WERR_OK;
4337 /********************************************************************
4338 * fill a spoolss_DriverInfo2 struct
4339 ********************************************************************/
4341 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4342 struct spoolss_DriverInfo2 *r,
4343 const struct spoolss_DriverInfo8 *driver,
4344 const char *servername)
4347 const char *cservername = canon_servername(servername);
4349 r->version = driver->version;
4351 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4352 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4353 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4354 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4356 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4357 driver->architecture,
4358 driver->version,
4359 driver->driver_path,
4360 r->driver_path);
4362 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4363 driver->architecture,
4364 driver->version,
4365 driver->data_file,
4366 r->data_file);
4368 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4369 driver->architecture,
4370 driver->version,
4371 driver->config_file,
4372 r->config_file);
4374 return WERR_OK;
4377 /********************************************************************
4378 * fill a spoolss_DriverInfo3 struct
4379 ********************************************************************/
4381 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4382 struct spoolss_DriverInfo3 *r,
4383 const struct spoolss_DriverInfo8 *driver,
4384 const char *servername)
4386 const char *cservername = canon_servername(servername);
4388 r->version = driver->version;
4390 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4391 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4392 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4393 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4395 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4396 driver->architecture,
4397 driver->version,
4398 driver->driver_path,
4399 r->driver_path);
4401 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4402 driver->architecture,
4403 driver->version,
4404 driver->data_file,
4405 r->data_file);
4407 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4408 driver->architecture,
4409 driver->version,
4410 driver->config_file,
4411 r->config_file);
4413 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4414 driver->architecture,
4415 driver->version,
4416 driver->help_file,
4417 r->help_file);
4419 FILL_DRIVER_STRING(mem_ctx,
4420 driver->monitor_name,
4421 r->monitor_name);
4423 FILL_DRIVER_STRING(mem_ctx,
4424 driver->default_datatype,
4425 r->default_datatype);
4427 return string_array_from_driver_info(mem_ctx,
4428 driver->dependent_files,
4429 &r->dependent_files,
4430 cservername,
4431 driver->architecture,
4432 driver->version);
4435 /********************************************************************
4436 * fill a spoolss_DriverInfo4 struct
4437 ********************************************************************/
4439 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4440 struct spoolss_DriverInfo4 *r,
4441 const struct spoolss_DriverInfo8 *driver,
4442 const char *servername)
4444 const char *cservername = canon_servername(servername);
4445 WERROR result;
4447 r->version = driver->version;
4449 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4450 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4451 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4452 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4454 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4455 driver->architecture,
4456 driver->version,
4457 driver->driver_path,
4458 r->driver_path);
4460 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4461 driver->architecture,
4462 driver->version,
4463 driver->data_file,
4464 r->data_file);
4466 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4467 driver->architecture,
4468 driver->version,
4469 driver->config_file,
4470 r->config_file);
4472 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4473 driver->architecture,
4474 driver->version,
4475 driver->help_file,
4476 r->help_file);
4478 result = string_array_from_driver_info(mem_ctx,
4479 driver->dependent_files,
4480 &r->dependent_files,
4481 cservername,
4482 driver->architecture,
4483 driver->version);
4484 if (!W_ERROR_IS_OK(result)) {
4485 return result;
4488 FILL_DRIVER_STRING(mem_ctx,
4489 driver->monitor_name,
4490 r->monitor_name);
4492 FILL_DRIVER_STRING(mem_ctx,
4493 driver->default_datatype,
4494 r->default_datatype);
4497 result = string_array_from_driver_info(mem_ctx,
4498 driver->previous_names,
4499 &r->previous_names,
4500 NULL, NULL, 0);
4502 return result;
4505 /********************************************************************
4506 * fill a spoolss_DriverInfo5 struct
4507 ********************************************************************/
4509 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4510 struct spoolss_DriverInfo5 *r,
4511 const struct spoolss_DriverInfo8 *driver,
4512 const char *servername)
4514 const char *cservername = canon_servername(servername);
4516 r->version = driver->version;
4518 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4519 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4520 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4521 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4523 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4524 driver->architecture,
4525 driver->version,
4526 driver->driver_path,
4527 r->driver_path);
4529 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4530 driver->architecture,
4531 driver->version,
4532 driver->data_file,
4533 r->data_file);
4535 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4536 driver->architecture,
4537 driver->version,
4538 driver->config_file,
4539 r->config_file);
4541 r->driver_attributes = 0;
4542 r->config_version = 0;
4543 r->driver_version = 0;
4545 return WERR_OK;
4547 /********************************************************************
4548 * fill a spoolss_DriverInfo6 struct
4549 ********************************************************************/
4551 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4552 struct spoolss_DriverInfo6 *r,
4553 const struct spoolss_DriverInfo8 *driver,
4554 const char *servername)
4556 const char *cservername = canon_servername(servername);
4557 WERROR result;
4559 r->version = driver->version;
4561 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4562 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4563 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4564 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4566 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4567 driver->architecture,
4568 driver->version,
4569 driver->driver_path,
4570 r->driver_path);
4572 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4573 driver->architecture,
4574 driver->version,
4575 driver->data_file,
4576 r->data_file);
4578 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4579 driver->architecture,
4580 driver->version,
4581 driver->config_file,
4582 r->config_file);
4584 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4585 driver->architecture,
4586 driver->version,
4587 driver->help_file,
4588 r->help_file);
4590 FILL_DRIVER_STRING(mem_ctx,
4591 driver->monitor_name,
4592 r->monitor_name);
4594 FILL_DRIVER_STRING(mem_ctx,
4595 driver->default_datatype,
4596 r->default_datatype);
4598 result = string_array_from_driver_info(mem_ctx,
4599 driver->dependent_files,
4600 &r->dependent_files,
4601 cservername,
4602 driver->architecture,
4603 driver->version);
4604 if (!W_ERROR_IS_OK(result)) {
4605 return result;
4608 result = string_array_from_driver_info(mem_ctx,
4609 driver->previous_names,
4610 &r->previous_names,
4611 NULL, NULL, 0);
4612 if (!W_ERROR_IS_OK(result)) {
4613 return result;
4616 r->driver_date = driver->driver_date;
4617 r->driver_version = driver->driver_version;
4619 FILL_DRIVER_STRING(mem_ctx,
4620 driver->manufacturer_name,
4621 r->manufacturer_name);
4622 FILL_DRIVER_STRING(mem_ctx,
4623 driver->manufacturer_url,
4624 r->manufacturer_url);
4625 FILL_DRIVER_STRING(mem_ctx,
4626 driver->hardware_id,
4627 r->hardware_id);
4628 FILL_DRIVER_STRING(mem_ctx,
4629 driver->provider,
4630 r->provider);
4632 return WERR_OK;
4635 /********************************************************************
4636 * fill a spoolss_DriverInfo8 struct
4637 ********************************************************************/
4639 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4640 struct spoolss_DriverInfo8 *r,
4641 const struct spoolss_DriverInfo8 *driver,
4642 const char *servername)
4644 const char *cservername = canon_servername(servername);
4645 WERROR result;
4647 r->version = driver->version;
4649 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4650 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4651 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4652 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4654 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4655 driver->architecture,
4656 driver->version,
4657 driver->driver_path,
4658 r->driver_path);
4660 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4661 driver->architecture,
4662 driver->version,
4663 driver->data_file,
4664 r->data_file);
4666 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4667 driver->architecture,
4668 driver->version,
4669 driver->config_file,
4670 r->config_file);
4672 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4673 driver->architecture,
4674 driver->version,
4675 driver->help_file,
4676 r->help_file);
4678 FILL_DRIVER_STRING(mem_ctx,
4679 driver->monitor_name,
4680 r->monitor_name);
4682 FILL_DRIVER_STRING(mem_ctx,
4683 driver->default_datatype,
4684 r->default_datatype);
4686 result = string_array_from_driver_info(mem_ctx,
4687 driver->dependent_files,
4688 &r->dependent_files,
4689 cservername,
4690 driver->architecture,
4691 driver->version);
4692 if (!W_ERROR_IS_OK(result)) {
4693 return result;
4696 result = string_array_from_driver_info(mem_ctx,
4697 driver->previous_names,
4698 &r->previous_names,
4699 NULL, NULL, 0);
4700 if (!W_ERROR_IS_OK(result)) {
4701 return result;
4704 r->driver_date = driver->driver_date;
4705 r->driver_version = driver->driver_version;
4707 FILL_DRIVER_STRING(mem_ctx,
4708 driver->manufacturer_name,
4709 r->manufacturer_name);
4710 FILL_DRIVER_STRING(mem_ctx,
4711 driver->manufacturer_url,
4712 r->manufacturer_url);
4713 FILL_DRIVER_STRING(mem_ctx,
4714 driver->hardware_id,
4715 r->hardware_id);
4716 FILL_DRIVER_STRING(mem_ctx,
4717 driver->provider,
4718 r->provider);
4720 FILL_DRIVER_STRING(mem_ctx,
4721 driver->print_processor,
4722 r->print_processor);
4723 FILL_DRIVER_STRING(mem_ctx,
4724 driver->vendor_setup,
4725 r->vendor_setup);
4727 result = string_array_from_driver_info(mem_ctx,
4728 driver->color_profiles,
4729 &r->color_profiles,
4730 NULL, NULL, 0);
4731 if (!W_ERROR_IS_OK(result)) {
4732 return result;
4735 FILL_DRIVER_STRING(mem_ctx,
4736 driver->inf_path,
4737 r->inf_path);
4739 r->printer_driver_attributes = driver->printer_driver_attributes;
4741 result = string_array_from_driver_info(mem_ctx,
4742 driver->core_driver_dependencies,
4743 &r->core_driver_dependencies,
4744 NULL, NULL, 0);
4745 if (!W_ERROR_IS_OK(result)) {
4746 return result;
4749 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4750 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4752 return WERR_OK;
4755 #if 0 /* disabled until marshalling issues are resolved - gd */
4756 /********************************************************************
4757 ********************************************************************/
4759 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4760 struct spoolss_DriverFileInfo *r,
4761 const char *cservername,
4762 const char *file_name,
4763 enum spoolss_DriverFileType file_type,
4764 uint32_t file_version)
4766 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4767 cservername, file_name);
4768 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4769 r->file_type = file_type;
4770 r->file_version = file_version;
4772 return WERR_OK;
4775 /********************************************************************
4776 ********************************************************************/
4778 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4779 const struct spoolss_DriverInfo8 *driver,
4780 const char *cservername,
4781 struct spoolss_DriverFileInfo **info_p,
4782 uint32_t *count_p)
4784 struct spoolss_DriverFileInfo *info = NULL;
4785 uint32_t count = 0;
4786 WERROR result;
4787 uint32_t i;
4789 *info_p = NULL;
4790 *count_p = 0;
4792 if (strlen(driver->driver_path)) {
4793 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4794 struct spoolss_DriverFileInfo,
4795 count + 1);
4796 W_ERROR_HAVE_NO_MEMORY(info);
4797 result = fill_spoolss_DriverFileInfo(info,
4798 &info[count],
4799 cservername,
4800 driver->driver_path,
4801 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4803 W_ERROR_NOT_OK_RETURN(result);
4804 count++;
4807 if (strlen(driver->config_file)) {
4808 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4809 struct spoolss_DriverFileInfo,
4810 count + 1);
4811 W_ERROR_HAVE_NO_MEMORY(info);
4812 result = fill_spoolss_DriverFileInfo(info,
4813 &info[count],
4814 cservername,
4815 driver->config_file,
4816 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4818 W_ERROR_NOT_OK_RETURN(result);
4819 count++;
4822 if (strlen(driver->data_file)) {
4823 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4824 struct spoolss_DriverFileInfo,
4825 count + 1);
4826 W_ERROR_HAVE_NO_MEMORY(info);
4827 result = fill_spoolss_DriverFileInfo(info,
4828 &info[count],
4829 cservername,
4830 driver->data_file,
4831 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4833 W_ERROR_NOT_OK_RETURN(result);
4834 count++;
4837 if (strlen(driver->help_file)) {
4838 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4839 struct spoolss_DriverFileInfo,
4840 count + 1);
4841 W_ERROR_HAVE_NO_MEMORY(info);
4842 result = fill_spoolss_DriverFileInfo(info,
4843 &info[count],
4844 cservername,
4845 driver->help_file,
4846 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4848 W_ERROR_NOT_OK_RETURN(result);
4849 count++;
4852 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4853 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4854 struct spoolss_DriverFileInfo,
4855 count + 1);
4856 W_ERROR_HAVE_NO_MEMORY(info);
4857 result = fill_spoolss_DriverFileInfo(info,
4858 &info[count],
4859 cservername,
4860 driver->dependent_files[i],
4861 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4863 W_ERROR_NOT_OK_RETURN(result);
4864 count++;
4867 *info_p = info;
4868 *count_p = count;
4870 return WERR_OK;
4873 /********************************************************************
4874 * fill a spoolss_DriverInfo101 struct
4875 ********************************************************************/
4877 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4878 struct spoolss_DriverInfo101 *r,
4879 const struct spoolss_DriverInfo8 *driver,
4880 const char *servername)
4882 const char *cservername = canon_servername(servername);
4883 WERROR result;
4885 r->version = driver->version;
4887 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4888 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4889 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4890 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4892 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4893 cservername,
4894 &r->file_info,
4895 &r->file_count);
4896 if (!W_ERROR_IS_OK(result)) {
4897 return result;
4900 FILL_DRIVER_STRING(mem_ctx,
4901 driver->monitor_name,
4902 r->monitor_name);
4904 FILL_DRIVER_STRING(mem_ctx,
4905 driver->default_datatype,
4906 r->default_datatype);
4908 result = string_array_from_driver_info(mem_ctx,
4909 driver->previous_names,
4910 &r->previous_names,
4911 NULL, NULL, 0);
4912 if (!W_ERROR_IS_OK(result)) {
4913 return result;
4916 r->driver_date = driver->driver_date;
4917 r->driver_version = driver->driver_version;
4919 FILL_DRIVER_STRING(mem_ctx,
4920 driver->manufacturer_name,
4921 r->manufacturer_name);
4922 FILL_DRIVER_STRING(mem_ctx,
4923 driver->manufacturer_url,
4924 r->manufacturer_url);
4925 FILL_DRIVER_STRING(mem_ctx,
4926 driver->hardware_id,
4927 r->hardware_id);
4928 FILL_DRIVER_STRING(mem_ctx,
4929 driver->provider,
4930 r->provider);
4932 return WERR_OK;
4934 #endif
4935 /********************************************************************
4936 ********************************************************************/
4938 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4939 struct auth_serversupplied_info *server_info,
4940 uint32_t level,
4941 union spoolss_DriverInfo *r,
4942 int snum,
4943 const char *servername,
4944 const char *architecture,
4945 uint32_t version)
4947 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4948 struct spoolss_DriverInfo8 *driver;
4949 WERROR result;
4951 result = winreg_get_printer(mem_ctx,
4952 server_info,
4953 servername,
4954 lp_const_servicename(snum),
4955 &pinfo2);
4957 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4958 win_errstr(result)));
4960 if (!W_ERROR_IS_OK(result)) {
4961 return WERR_INVALID_PRINTER_NAME;
4964 result = winreg_get_driver(mem_ctx, server_info, architecture,
4965 pinfo2->drivername, version, &driver);
4967 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4968 win_errstr(result)));
4970 if (!W_ERROR_IS_OK(result)) {
4972 * Is this a W2k client ?
4975 if (version < 3) {
4976 talloc_free(pinfo2);
4977 return WERR_UNKNOWN_PRINTER_DRIVER;
4980 /* Yes - try again with a WinNT driver. */
4981 version = 2;
4982 result = winreg_get_driver(mem_ctx, server_info, architecture,
4983 pinfo2->drivername,
4984 version, &driver);
4985 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4986 win_errstr(result)));
4987 if (!W_ERROR_IS_OK(result)) {
4988 talloc_free(pinfo2);
4989 return WERR_UNKNOWN_PRINTER_DRIVER;
4993 switch (level) {
4994 case 1:
4995 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4996 break;
4997 case 2:
4998 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4999 break;
5000 case 3:
5001 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5002 break;
5003 case 4:
5004 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5005 break;
5006 case 5:
5007 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5008 break;
5009 case 6:
5010 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5011 break;
5012 case 8:
5013 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5014 break;
5015 #if 0 /* disabled until marshalling issues are resolved - gd */
5016 case 101:
5017 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5018 break;
5019 #endif
5020 default:
5021 result = WERR_UNKNOWN_LEVEL;
5022 break;
5025 talloc_free(pinfo2);
5026 talloc_free(driver);
5028 return result;
5031 /****************************************************************
5032 _spoolss_GetPrinterDriver2
5033 ****************************************************************/
5035 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5036 struct spoolss_GetPrinterDriver2 *r)
5038 Printer_entry *printer;
5039 WERROR result;
5041 int snum;
5043 /* that's an [in out] buffer */
5045 if (!r->in.buffer && (r->in.offered != 0)) {
5046 return WERR_INVALID_PARAM;
5049 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5051 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5052 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5053 return WERR_INVALID_PRINTER_NAME;
5056 *r->out.needed = 0;
5057 *r->out.server_major_version = 0;
5058 *r->out.server_minor_version = 0;
5060 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5061 return WERR_BADFID;
5064 result = construct_printer_driver_info_level(p->mem_ctx, p->server_info,
5065 r->in.level, r->out.info,
5066 snum, printer->servername,
5067 r->in.architecture,
5068 r->in.client_major_version);
5069 if (!W_ERROR_IS_OK(result)) {
5070 TALLOC_FREE(r->out.info);
5071 return result;
5074 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5075 r->out.info, r->in.level);
5076 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5078 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5082 /****************************************************************
5083 _spoolss_StartPagePrinter
5084 ****************************************************************/
5086 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5087 struct spoolss_StartPagePrinter *r)
5089 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5091 if (!Printer) {
5092 DEBUG(3,("_spoolss_StartPagePrinter: "
5093 "Error in startpageprinter printer handle\n"));
5094 return WERR_BADFID;
5097 Printer->page_started = true;
5098 return WERR_OK;
5101 /****************************************************************
5102 _spoolss_EndPagePrinter
5103 ****************************************************************/
5105 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5106 struct spoolss_EndPagePrinter *r)
5108 int snum;
5110 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5112 if (!Printer) {
5113 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5114 OUR_HANDLE(r->in.handle)));
5115 return WERR_BADFID;
5118 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5119 return WERR_BADFID;
5121 Printer->page_started = false;
5122 print_job_endpage(snum, Printer->jobid);
5124 return WERR_OK;
5127 /****************************************************************
5128 _spoolss_StartDocPrinter
5129 ****************************************************************/
5131 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5132 struct spoolss_StartDocPrinter *r)
5134 struct spoolss_DocumentInfo1 *info_1;
5135 int snum;
5136 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5138 if (!Printer) {
5139 DEBUG(2,("_spoolss_StartDocPrinter: "
5140 "Invalid handle (%s:%u:%u)\n",
5141 OUR_HANDLE(r->in.handle)));
5142 return WERR_BADFID;
5145 if (r->in.level != 1) {
5146 return WERR_UNKNOWN_LEVEL;
5149 info_1 = r->in.info.info1;
5152 * a nice thing with NT is it doesn't listen to what you tell it.
5153 * when asked to send _only_ RAW datas, it tries to send datas
5154 * in EMF format.
5156 * So I add checks like in NT Server ...
5159 if (info_1->datatype) {
5160 if (strcmp(info_1->datatype, "RAW") != 0) {
5161 *r->out.job_id = 0;
5162 return WERR_INVALID_DATATYPE;
5166 /* get the share number of the printer */
5167 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5168 return WERR_BADFID;
5171 Printer->jobid = print_job_start(p->server_info, snum,
5172 info_1->document_name,
5173 Printer->devmode);
5175 /* An error occured in print_job_start() so return an appropriate
5176 NT error code. */
5178 if (Printer->jobid == -1) {
5179 return map_werror_from_unix(errno);
5182 Printer->document_started = true;
5183 *r->out.job_id = Printer->jobid;
5185 return WERR_OK;
5188 /****************************************************************
5189 _spoolss_EndDocPrinter
5190 ****************************************************************/
5192 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5193 struct spoolss_EndDocPrinter *r)
5195 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5196 int snum;
5198 if (!Printer) {
5199 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5200 OUR_HANDLE(r->in.handle)));
5201 return WERR_BADFID;
5204 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5205 return WERR_BADFID;
5208 Printer->document_started = false;
5209 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5210 /* error codes unhandled so far ... */
5212 return WERR_OK;
5215 /****************************************************************
5216 _spoolss_WritePrinter
5217 ****************************************************************/
5219 WERROR _spoolss_WritePrinter(pipes_struct *p,
5220 struct spoolss_WritePrinter *r)
5222 ssize_t buffer_written;
5223 int snum;
5224 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5226 if (!Printer) {
5227 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5228 OUR_HANDLE(r->in.handle)));
5229 *r->out.num_written = r->in._data_size;
5230 return WERR_BADFID;
5233 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5234 return WERR_BADFID;
5236 buffer_written = print_job_write(snum, Printer->jobid,
5237 (const char *)r->in.data.data,
5238 (SMB_OFF_T)-1,
5239 (size_t)r->in._data_size);
5240 if (buffer_written == (ssize_t)-1) {
5241 *r->out.num_written = 0;
5242 if (errno == ENOSPC)
5243 return WERR_NO_SPOOL_SPACE;
5244 else
5245 return WERR_ACCESS_DENIED;
5248 *r->out.num_written = r->in._data_size;
5250 return WERR_OK;
5253 /********************************************************************
5254 * api_spoolss_getprinter
5255 * called from the spoolss dispatcher
5257 ********************************************************************/
5259 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5260 pipes_struct *p)
5262 int snum;
5263 WERROR errcode = WERR_BADFUNC;
5264 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5266 if (!Printer) {
5267 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5268 OUR_HANDLE(handle)));
5269 return WERR_BADFID;
5272 if (!get_printer_snum(p, handle, &snum, NULL))
5273 return WERR_BADFID;
5275 switch (command) {
5276 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5277 errcode = print_queue_pause(p->server_info, snum);
5278 break;
5279 case SPOOLSS_PRINTER_CONTROL_RESUME:
5280 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5281 errcode = print_queue_resume(p->server_info, snum);
5282 break;
5283 case SPOOLSS_PRINTER_CONTROL_PURGE:
5284 errcode = print_queue_purge(p->server_info, snum);
5285 break;
5286 default:
5287 return WERR_UNKNOWN_LEVEL;
5290 return errcode;
5294 /****************************************************************
5295 _spoolss_AbortPrinter
5296 * From MSDN: "Deletes printer's spool file if printer is configured
5297 * for spooling"
5298 ****************************************************************/
5300 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5301 struct spoolss_AbortPrinter *r)
5303 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5304 int snum;
5305 WERROR errcode = WERR_OK;
5307 if (!Printer) {
5308 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5309 OUR_HANDLE(r->in.handle)));
5310 return WERR_BADFID;
5313 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5314 return WERR_BADFID;
5316 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5318 return errcode;
5321 /********************************************************************
5322 * called by spoolss_api_setprinter
5323 * when updating a printer description
5324 ********************************************************************/
5326 static WERROR update_printer_sec(struct policy_handle *handle,
5327 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5329 struct spoolss_security_descriptor *new_secdesc = NULL;
5330 struct spoolss_security_descriptor *old_secdesc = NULL;
5331 const char *printer;
5332 WERROR result;
5333 int snum;
5335 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5337 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5338 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5339 OUR_HANDLE(handle)));
5341 result = WERR_BADFID;
5342 goto done;
5345 if (secdesc_ctr == NULL) {
5346 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5347 result = WERR_INVALID_PARAM;
5348 goto done;
5350 printer = lp_const_servicename(snum);
5352 /* Check the user has permissions to change the security
5353 descriptor. By experimentation with two NT machines, the user
5354 requires Full Access to the printer to change security
5355 information. */
5357 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5358 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5359 result = WERR_ACCESS_DENIED;
5360 goto done;
5363 /* NT seems to like setting the security descriptor even though
5364 nothing may have actually changed. */
5365 result = winreg_get_printer_secdesc(p->mem_ctx,
5366 p->server_info,
5367 printer,
5368 &old_secdesc);
5369 if (!W_ERROR_IS_OK(result)) {
5370 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5371 result = WERR_BADFID;
5372 goto done;
5375 if (DEBUGLEVEL >= 10) {
5376 struct security_acl *the_acl;
5377 int i;
5379 the_acl = secdesc_ctr->sd->dacl;
5380 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5381 printer, the_acl->num_aces));
5383 for (i = 0; i < the_acl->num_aces; i++) {
5384 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5385 &the_acl->aces[i].trustee),
5386 the_acl->aces[i].access_mask));
5389 the_acl = secdesc_ctr->sd->dacl;
5391 if (the_acl) {
5392 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5393 printer, the_acl->num_aces));
5395 for (i = 0; i < the_acl->num_aces; i++) {
5396 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5397 &the_acl->aces[i].trustee),
5398 the_acl->aces[i].access_mask));
5400 } else {
5401 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5405 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5406 if (new_secdesc == NULL) {
5407 result = WERR_NOMEM;
5408 goto done;
5411 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5412 result = WERR_OK;
5413 goto done;
5416 result = winreg_set_printer_secdesc(p->mem_ctx,
5417 p->server_info,
5418 printer,
5419 new_secdesc);
5421 done:
5422 return result;
5425 /********************************************************************
5426 Canonicalize printer info from a client
5428 ATTN: It does not matter what we set the servername to hear
5429 since we do the necessary work in get_a_printer() to set it to
5430 the correct value based on what the client sent in the
5431 _spoolss_open_printer_ex().
5432 ********************************************************************/
5434 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5435 struct spoolss_SetPrinterInfo2 *info2,
5436 int snum)
5438 fstring printername;
5439 const char *p;
5441 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5442 "portname=%s drivername=%s comment=%s location=%s\n",
5443 info2->servername, info2->printername, info2->sharename,
5444 info2->portname, info2->drivername, info2->comment,
5445 info2->location));
5447 /* we force some elements to "correct" values */
5448 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5449 if (info2->servername == NULL) {
5450 return false;
5452 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5453 if (info2->sharename == NULL) {
5454 return false;
5457 /* check to see if we allow printername != sharename */
5458 if (lp_force_printername(snum)) {
5459 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5460 global_myname(), info2->sharename);
5461 } else {
5462 /* make sure printername is in \\server\printername format */
5463 fstrcpy(printername, info2->printername);
5464 p = printername;
5465 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5466 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5467 p++;
5470 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5471 global_myname(), p);
5473 if (info2->printername == NULL) {
5474 return false;
5477 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5478 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5480 return true;
5483 /****************************************************************************
5484 ****************************************************************************/
5486 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5488 char *cmd = lp_addport_cmd();
5489 char *command = NULL;
5490 int ret;
5491 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5492 bool is_print_op = false;
5494 if ( !*cmd ) {
5495 return WERR_ACCESS_DENIED;
5498 command = talloc_asprintf(ctx,
5499 "%s \"%s\" \"%s\"", cmd, portname, uri );
5500 if (!command) {
5501 return WERR_NOMEM;
5504 if ( token )
5505 is_print_op = user_has_privileges( token, &se_printop );
5507 DEBUG(10,("Running [%s]\n", command));
5509 /********* BEGIN SePrintOperatorPrivilege **********/
5511 if ( is_print_op )
5512 become_root();
5514 ret = smbrun(command, NULL);
5516 if ( is_print_op )
5517 unbecome_root();
5519 /********* END SePrintOperatorPrivilege **********/
5521 DEBUGADD(10,("returned [%d]\n", ret));
5523 TALLOC_FREE(command);
5525 if ( ret != 0 ) {
5526 return WERR_ACCESS_DENIED;
5529 return WERR_OK;
5532 /****************************************************************************
5533 ****************************************************************************/
5535 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5536 struct spoolss_SetPrinterInfo2 *info2)
5538 char *cmd = lp_addprinter_cmd();
5539 char **qlines;
5540 char *command = NULL;
5541 int numlines;
5542 int ret;
5543 int fd;
5544 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5545 bool is_print_op = false;
5546 char *remote_machine = talloc_strdup(ctx, "%m");
5548 if (!remote_machine) {
5549 return false;
5551 remote_machine = talloc_sub_basic(ctx,
5552 current_user_info.smb_name,
5553 current_user_info.domain,
5554 remote_machine);
5555 if (!remote_machine) {
5556 return false;
5559 command = talloc_asprintf(ctx,
5560 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5561 cmd, info2->printername, info2->sharename,
5562 info2->portname, info2->drivername,
5563 info2->location, info2->comment, remote_machine);
5564 if (!command) {
5565 return false;
5568 if ( token )
5569 is_print_op = user_has_privileges( token, &se_printop );
5571 DEBUG(10,("Running [%s]\n", command));
5573 /********* BEGIN SePrintOperatorPrivilege **********/
5575 if ( is_print_op )
5576 become_root();
5578 if ( (ret = smbrun(command, &fd)) == 0 ) {
5579 /* Tell everyone we updated smb.conf. */
5580 message_send_all(smbd_messaging_context(),
5581 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5584 if ( is_print_op )
5585 unbecome_root();
5587 /********* END SePrintOperatorPrivilege **********/
5589 DEBUGADD(10,("returned [%d]\n", ret));
5591 TALLOC_FREE(command);
5592 TALLOC_FREE(remote_machine);
5594 if ( ret != 0 ) {
5595 if (fd != -1)
5596 close(fd);
5597 return false;
5600 /* reload our services immediately */
5601 become_root();
5602 reload_services(false);
5603 unbecome_root();
5605 numlines = 0;
5606 /* Get lines and convert them back to dos-codepage */
5607 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5608 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5609 close(fd);
5611 /* Set the portname to what the script says the portname should be. */
5612 /* but don't require anything to be return from the script exit a good error code */
5614 if (numlines) {
5615 /* Set the portname to what the script says the portname should be. */
5616 info2->portname = talloc_strdup(ctx, qlines[0]);
5617 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5620 TALLOC_FREE(qlines);
5621 return true;
5624 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5625 struct auth_serversupplied_info *server_info,
5626 int snum,
5627 struct spoolss_SetPrinterInfo2 *printer,
5628 struct spoolss_PrinterInfo2 *old_printer)
5630 bool force_update = (old_printer == NULL);
5631 const char *dnsdomname;
5632 const char *longname;
5633 const char *uncname;
5634 const char *spooling;
5635 DATA_BLOB buffer;
5636 WERROR result = WERR_OK;
5638 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
5639 push_reg_sz(mem_ctx, &buffer, printer->drivername);
5640 winreg_set_printer_dataex(mem_ctx,
5641 server_info,
5642 printer->sharename,
5643 SPOOL_DSSPOOLER_KEY,
5644 SPOOL_REG_DRIVERNAME,
5645 REG_SZ,
5646 buffer.data,
5647 buffer.length);
5649 if (!force_update) {
5650 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5651 printer->drivername));
5653 notify_printer_driver(snum, printer->drivername);
5657 if (force_update || !strequal(printer->comment, old_printer->comment)) {
5658 push_reg_sz(mem_ctx, &buffer, printer->comment);
5659 winreg_set_printer_dataex(mem_ctx,
5660 server_info,
5661 printer->sharename,
5662 SPOOL_DSSPOOLER_KEY,
5663 SPOOL_REG_DESCRIPTION,
5664 REG_SZ,
5665 buffer.data,
5666 buffer.length);
5668 if (!force_update) {
5669 notify_printer_comment(snum, printer->comment);
5673 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
5674 push_reg_sz(mem_ctx, &buffer, printer->sharename);
5675 winreg_set_printer_dataex(mem_ctx,
5676 server_info,
5677 printer->sharename,
5678 SPOOL_DSSPOOLER_KEY,
5679 SPOOL_REG_PRINTSHARENAME,
5680 REG_SZ,
5681 buffer.data,
5682 buffer.length);
5684 if (!force_update) {
5685 notify_printer_sharename(snum, printer->sharename);
5689 if (force_update || !strequal(printer->printername, old_printer->printername)) {
5690 const char *p;
5692 p = strrchr(printer->printername, '\\' );
5693 if (p != NULL) {
5694 p++;
5695 } else {
5696 p = printer->printername;
5699 push_reg_sz(mem_ctx, &buffer, p);
5700 winreg_set_printer_dataex(mem_ctx,
5701 server_info,
5702 printer->sharename,
5703 SPOOL_DSSPOOLER_KEY,
5704 SPOOL_REG_PRINTERNAME,
5705 REG_SZ,
5706 buffer.data,
5707 buffer.length);
5709 if (!force_update) {
5710 notify_printer_printername(snum, p);
5714 if (force_update || !strequal(printer->portname, old_printer->portname)) {
5715 push_reg_sz(mem_ctx, &buffer, printer->portname);
5716 winreg_set_printer_dataex(mem_ctx,
5717 server_info,
5718 printer->sharename,
5719 SPOOL_DSSPOOLER_KEY,
5720 SPOOL_REG_PORTNAME,
5721 REG_SZ,
5722 buffer.data,
5723 buffer.length);
5725 if (!force_update) {
5726 notify_printer_port(snum, printer->portname);
5730 if (force_update || !strequal(printer->location, old_printer->location)) {
5731 push_reg_sz(mem_ctx, &buffer, printer->location);
5732 winreg_set_printer_dataex(mem_ctx,
5733 server_info,
5734 printer->sharename,
5735 SPOOL_DSSPOOLER_KEY,
5736 SPOOL_REG_LOCATION,
5737 REG_SZ,
5738 buffer.data,
5739 buffer.length);
5741 if (!force_update) {
5742 notify_printer_location(snum, printer->location);
5746 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
5747 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
5748 winreg_set_printer_dataex(mem_ctx,
5749 server_info,
5750 printer->sharename,
5751 SPOOL_DSSPOOLER_KEY,
5752 SPOOL_REG_PRINTSEPARATORFILE,
5753 REG_SZ,
5754 buffer.data,
5755 buffer.length);
5757 if (!force_update) {
5758 notify_printer_location(snum, printer->location);
5762 if (force_update || printer->starttime != old_printer->starttime) {
5763 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5764 SIVAL(buffer.data, 0, printer->starttime);
5765 winreg_set_printer_dataex(mem_ctx,
5766 server_info,
5767 printer->sharename,
5768 SPOOL_DSSPOOLER_KEY,
5769 SPOOL_REG_PRINTSTARTTIME,
5770 REG_DWORD,
5771 buffer.data,
5772 buffer.length);
5775 if (force_update || printer->untiltime != old_printer->untiltime) {
5776 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5777 SIVAL(buffer.data, 0, printer->untiltime);
5778 winreg_set_printer_dataex(mem_ctx,
5779 server_info,
5780 printer->sharename,
5781 SPOOL_DSSPOOLER_KEY,
5782 SPOOL_REG_PRINTENDTIME,
5783 REG_DWORD,
5784 buffer.data,
5785 buffer.length);
5788 if (force_update || printer->priority != old_printer->priority) {
5789 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5790 SIVAL(buffer.data, 0, printer->priority);
5791 winreg_set_printer_dataex(mem_ctx,
5792 server_info,
5793 printer->sharename,
5794 SPOOL_DSSPOOLER_KEY,
5795 SPOOL_REG_PRIORITY,
5796 REG_DWORD,
5797 buffer.data,
5798 buffer.length);
5801 if (force_update || printer->attributes != old_printer->attributes) {
5802 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5803 SIVAL(buffer.data, 0, (printer->attributes &
5804 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
5805 winreg_set_printer_dataex(mem_ctx,
5806 server_info,
5807 printer->sharename,
5808 SPOOL_DSSPOOLER_KEY,
5809 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
5810 REG_DWORD,
5811 buffer.data,
5812 buffer.length);
5814 switch (printer->attributes & 0x3) {
5815 case 0:
5816 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
5817 break;
5818 case 1:
5819 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
5820 break;
5821 case 2:
5822 spooling = SPOOL_REGVAL_PRINTDIRECT;
5823 break;
5824 default:
5825 spooling = "unknown";
5827 push_reg_sz(mem_ctx, &buffer, spooling);
5828 winreg_set_printer_dataex(mem_ctx,
5829 server_info,
5830 printer->sharename,
5831 SPOOL_DSSPOOLER_KEY,
5832 SPOOL_REG_PRINTSPOOLING,
5833 REG_SZ,
5834 buffer.data,
5835 buffer.length);
5838 push_reg_sz(mem_ctx, &buffer, global_myname());
5839 winreg_set_printer_dataex(mem_ctx,
5840 server_info,
5841 printer->sharename,
5842 SPOOL_DSSPOOLER_KEY,
5843 SPOOL_REG_SHORTSERVERNAME,
5844 REG_SZ,
5845 buffer.data,
5846 buffer.length);
5848 dnsdomname = get_mydnsfullname();
5849 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
5850 longname = talloc_strdup(mem_ctx, dnsdomname);
5851 } else {
5852 longname = talloc_strdup(mem_ctx, global_myname());
5854 if (longname == NULL) {
5855 result = WERR_NOMEM;
5856 goto done;
5859 push_reg_sz(mem_ctx, &buffer, longname);
5860 winreg_set_printer_dataex(mem_ctx,
5861 server_info,
5862 printer->sharename,
5863 SPOOL_DSSPOOLER_KEY,
5864 SPOOL_REG_SERVERNAME,
5865 REG_SZ,
5866 buffer.data,
5867 buffer.length);
5869 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5870 global_myname(), printer->sharename);
5871 push_reg_sz(mem_ctx, &buffer, uncname);
5872 winreg_set_printer_dataex(mem_ctx,
5873 server_info,
5874 printer->sharename,
5875 SPOOL_DSSPOOLER_KEY,
5876 SPOOL_REG_UNCNAME,
5877 REG_SZ,
5878 buffer.data,
5879 buffer.length);
5881 done:
5882 return result;
5885 /********************************************************************
5886 * Called by spoolss_api_setprinter
5887 * when updating a printer description.
5888 ********************************************************************/
5890 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5891 struct spoolss_SetPrinterInfoCtr *info_ctr,
5892 struct spoolss_DeviceMode *devmode)
5894 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5895 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5896 struct spoolss_PrinterInfo2 *old_printer;
5897 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5898 const char *servername = NULL;
5899 int snum;
5900 WERROR result = WERR_OK;
5901 TALLOC_CTX *tmp_ctx;
5903 DEBUG(8,("update_printer\n"));
5905 tmp_ctx = talloc_new(p->mem_ctx);
5906 if (tmp_ctx == NULL) {
5907 return WERR_NOMEM;
5910 if (!Printer) {
5911 result = WERR_BADFID;
5912 goto done;
5915 if (!get_printer_snum(p, handle, &snum, NULL)) {
5916 result = WERR_BADFID;
5917 goto done;
5920 if (Printer != NULL || Printer->servername != NULL) {
5921 servername = Printer->servername;
5924 result = winreg_get_printer(tmp_ctx,
5925 p->server_info,
5926 servername,
5927 lp_const_servicename(snum),
5928 &old_printer);
5929 if (!W_ERROR_IS_OK(result)) {
5930 result = WERR_BADFID;
5931 goto done;
5934 /* Do sanity check on the requested changes for Samba */
5935 if (!check_printer_ok(tmp_ctx, printer, snum)) {
5936 result = WERR_INVALID_PARAM;
5937 goto done;
5940 /* FIXME!!! If the driver has changed we really should verify that
5941 it is installed before doing much else --jerry */
5943 /* Check calling user has permission to update printer description */
5944 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5945 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5946 result = WERR_ACCESS_DENIED;
5947 goto done;
5950 /* Call addprinter hook */
5951 /* Check changes to see if this is really needed */
5953 if (*lp_addprinter_cmd() &&
5954 (!strequal(printer->drivername, old_printer->drivername) ||
5955 !strequal(printer->comment, old_printer->comment) ||
5956 !strequal(printer->portname, old_printer->portname) ||
5957 !strequal(printer->location, old_printer->location)) )
5959 /* add_printer_hook() will call reload_services() */
5960 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
5961 printer) ) {
5962 result = WERR_ACCESS_DENIED;
5963 goto done;
5967 update_dsspooler(tmp_ctx,
5968 p->server_info,
5969 snum,
5970 printer,
5971 old_printer);
5973 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
5975 if (devmode == NULL) {
5976 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
5978 result = winreg_update_printer(tmp_ctx,
5979 p->server_info,
5980 printer->sharename,
5981 printer_mask,
5982 printer,
5983 devmode,
5984 NULL);
5986 done:
5987 talloc_free(tmp_ctx);
5989 return result;
5992 /****************************************************************************
5993 ****************************************************************************/
5994 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5995 struct policy_handle *handle,
5996 struct spoolss_SetPrinterInfo7 *info7)
5998 #ifdef HAVE_ADS
5999 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6000 WERROR result;
6001 int snum;
6002 Printer_entry *Printer;
6004 if ( lp_security() != SEC_ADS ) {
6005 return WERR_UNKNOWN_LEVEL;
6008 Printer = find_printer_index_by_hnd(p, handle);
6010 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6012 if (!Printer)
6013 return WERR_BADFID;
6015 if (!get_printer_snum(p, handle, &snum, NULL))
6016 return WERR_BADFID;
6018 result = winreg_get_printer(p->mem_ctx, p->server_info,
6019 Printer->servername,
6020 lp_servicename(snum), &pinfo2);
6021 if (!W_ERROR_IS_OK(result)) {
6022 return WERR_BADFID;
6025 nt_printer_publish(pinfo2, p->server_info, pinfo2, info7->action);
6027 TALLOC_FREE(pinfo2);
6028 return WERR_OK;
6029 #else
6030 return WERR_UNKNOWN_LEVEL;
6031 #endif
6034 /********************************************************************
6035 ********************************************************************/
6037 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
6038 struct spoolss_DeviceMode *devmode)
6040 int snum;
6041 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6042 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6044 DEBUG(8,("update_printer_devmode\n"));
6046 if (!Printer) {
6047 return WERR_BADFID;
6050 if (!get_printer_snum(p, handle, &snum, NULL)) {
6051 return WERR_BADFID;
6054 /* Check calling user has permission to update printer description */
6055 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6056 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6057 return WERR_ACCESS_DENIED;
6060 return winreg_update_printer(p->mem_ctx,
6061 p->server_info,
6062 lp_const_servicename(snum),
6063 info2_mask,
6064 NULL,
6065 devmode,
6066 NULL);
6070 /****************************************************************
6071 _spoolss_SetPrinter
6072 ****************************************************************/
6074 WERROR _spoolss_SetPrinter(pipes_struct *p,
6075 struct spoolss_SetPrinter *r)
6077 WERROR result;
6079 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6081 if (!Printer) {
6082 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6083 OUR_HANDLE(r->in.handle)));
6084 return WERR_BADFID;
6087 /* check the level */
6088 switch (r->in.info_ctr->level) {
6089 case 0:
6090 return control_printer(r->in.handle, r->in.command, p);
6091 case 2:
6092 result = update_printer(p, r->in.handle,
6093 r->in.info_ctr,
6094 r->in.devmode_ctr->devmode);
6095 if (!W_ERROR_IS_OK(result))
6096 return result;
6097 if (r->in.secdesc_ctr->sd)
6098 result = update_printer_sec(r->in.handle, p,
6099 r->in.secdesc_ctr);
6100 return result;
6101 case 3:
6102 return update_printer_sec(r->in.handle, p,
6103 r->in.secdesc_ctr);
6104 case 7:
6105 return publish_or_unpublish_printer(p, r->in.handle,
6106 r->in.info_ctr->info.info7);
6107 case 8:
6108 return update_printer_devmode(p, r->in.handle,
6109 r->in.devmode_ctr->devmode);
6110 default:
6111 return WERR_UNKNOWN_LEVEL;
6115 /****************************************************************
6116 _spoolss_FindClosePrinterNotify
6117 ****************************************************************/
6119 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6120 struct spoolss_FindClosePrinterNotify *r)
6122 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6124 if (!Printer) {
6125 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6126 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6127 return WERR_BADFID;
6130 if (Printer->notify.client_connected == true) {
6131 int snum = -1;
6133 if ( Printer->printer_type == SPLHND_SERVER)
6134 snum = -1;
6135 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6136 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6137 return WERR_BADFID;
6139 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6142 Printer->notify.flags=0;
6143 Printer->notify.options=0;
6144 Printer->notify.localmachine[0]='\0';
6145 Printer->notify.printerlocal=0;
6146 TALLOC_FREE(Printer->notify.option);
6147 Printer->notify.client_connected = false;
6149 return WERR_OK;
6152 /****************************************************************
6153 _spoolss_AddJob
6154 ****************************************************************/
6156 WERROR _spoolss_AddJob(pipes_struct *p,
6157 struct spoolss_AddJob *r)
6159 if (!r->in.buffer && (r->in.offered != 0)) {
6160 return WERR_INVALID_PARAM;
6163 /* this is what a NT server returns for AddJob. AddJob must fail on
6164 * non-local printers */
6166 if (r->in.level != 1) {
6167 return WERR_UNKNOWN_LEVEL;
6170 return WERR_INVALID_PARAM;
6173 /****************************************************************************
6174 fill_job_info1
6175 ****************************************************************************/
6177 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6178 struct spoolss_JobInfo1 *r,
6179 const print_queue_struct *queue,
6180 int position, int snum,
6181 struct spoolss_PrinterInfo2 *pinfo2)
6183 struct tm *t;
6185 t = gmtime(&queue->time);
6187 r->job_id = queue->job;
6189 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6190 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6191 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6192 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6193 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6194 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6195 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6196 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6197 r->data_type = talloc_strdup(mem_ctx, "RAW");
6198 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6199 r->text_status = talloc_strdup(mem_ctx, "");
6200 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6202 r->status = nt_printj_status(queue->status);
6203 r->priority = queue->priority;
6204 r->position = position;
6205 r->total_pages = queue->page_count;
6206 r->pages_printed = 0; /* ??? */
6208 init_systemtime(&r->submitted, t);
6210 return WERR_OK;
6213 /****************************************************************************
6214 fill_job_info2
6215 ****************************************************************************/
6217 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6218 struct spoolss_JobInfo2 *r,
6219 const print_queue_struct *queue,
6220 int position, int snum,
6221 struct spoolss_PrinterInfo2 *pinfo2,
6222 struct spoolss_DeviceMode *devmode)
6224 struct tm *t;
6226 t = gmtime(&queue->time);
6228 r->job_id = queue->job;
6230 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6231 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6232 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6233 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6234 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6235 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6236 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6237 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6238 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6239 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6240 r->data_type = talloc_strdup(mem_ctx, "RAW");
6241 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6242 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6243 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6244 r->parameters = talloc_strdup(mem_ctx, "");
6245 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6246 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6247 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6249 r->devmode = devmode;
6251 r->text_status = talloc_strdup(mem_ctx, "");
6252 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6254 r->secdesc = NULL;
6256 r->status = nt_printj_status(queue->status);
6257 r->priority = queue->priority;
6258 r->position = position;
6259 r->start_time = 0;
6260 r->until_time = 0;
6261 r->total_pages = queue->page_count;
6262 r->size = queue->size;
6263 init_systemtime(&r->submitted, t);
6264 r->time = 0;
6265 r->pages_printed = 0; /* ??? */
6267 return WERR_OK;
6270 /****************************************************************************
6271 fill_job_info3
6272 ****************************************************************************/
6274 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6275 struct spoolss_JobInfo3 *r,
6276 const print_queue_struct *queue,
6277 const print_queue_struct *next_queue,
6278 int position, int snum,
6279 struct spoolss_PrinterInfo2 *pinfo2)
6281 r->job_id = queue->job;
6282 r->next_job_id = 0;
6283 if (next_queue) {
6284 r->next_job_id = next_queue->job;
6286 r->reserved = 0;
6288 return WERR_OK;
6291 /****************************************************************************
6292 Enumjobs at level 1.
6293 ****************************************************************************/
6295 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6296 const print_queue_struct *queue,
6297 uint32_t num_queues, int snum,
6298 struct spoolss_PrinterInfo2 *pinfo2,
6299 union spoolss_JobInfo **info_p,
6300 uint32_t *count)
6302 union spoolss_JobInfo *info;
6303 int i;
6304 WERROR result = WERR_OK;
6306 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6307 W_ERROR_HAVE_NO_MEMORY(info);
6309 *count = num_queues;
6311 for (i=0; i<*count; i++) {
6312 result = fill_job_info1(info,
6313 &info[i].info1,
6314 &queue[i],
6316 snum,
6317 pinfo2);
6318 if (!W_ERROR_IS_OK(result)) {
6319 goto out;
6323 out:
6324 if (!W_ERROR_IS_OK(result)) {
6325 TALLOC_FREE(info);
6326 *count = 0;
6327 return result;
6330 *info_p = info;
6332 return WERR_OK;
6335 /****************************************************************************
6336 Enumjobs at level 2.
6337 ****************************************************************************/
6339 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6340 const print_queue_struct *queue,
6341 uint32_t num_queues, int snum,
6342 struct spoolss_PrinterInfo2 *pinfo2,
6343 union spoolss_JobInfo **info_p,
6344 uint32_t *count)
6346 union spoolss_JobInfo *info;
6347 int i;
6348 WERROR result = WERR_OK;
6350 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6351 W_ERROR_HAVE_NO_MEMORY(info);
6353 *count = num_queues;
6355 for (i=0; i<*count; i++) {
6356 struct spoolss_DeviceMode *devmode;
6358 result = spoolss_create_default_devmode(info,
6359 pinfo2->printername,
6360 &devmode);
6361 if (!W_ERROR_IS_OK(result)) {
6362 DEBUG(3, ("Can't proceed w/o a devmode!"));
6363 goto out;
6366 result = fill_job_info2(info,
6367 &info[i].info2,
6368 &queue[i],
6370 snum,
6371 pinfo2,
6372 devmode);
6373 if (!W_ERROR_IS_OK(result)) {
6374 goto out;
6378 out:
6379 if (!W_ERROR_IS_OK(result)) {
6380 TALLOC_FREE(info);
6381 *count = 0;
6382 return result;
6385 *info_p = info;
6387 return WERR_OK;
6390 /****************************************************************************
6391 Enumjobs at level 3.
6392 ****************************************************************************/
6394 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6395 const print_queue_struct *queue,
6396 uint32_t num_queues, int snum,
6397 struct spoolss_PrinterInfo2 *pinfo2,
6398 union spoolss_JobInfo **info_p,
6399 uint32_t *count)
6401 union spoolss_JobInfo *info;
6402 int i;
6403 WERROR result = WERR_OK;
6405 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6406 W_ERROR_HAVE_NO_MEMORY(info);
6408 *count = num_queues;
6410 for (i=0; i<*count; i++) {
6411 const print_queue_struct *next_queue = NULL;
6413 if (i+1 < *count) {
6414 next_queue = &queue[i+1];
6417 result = fill_job_info3(info,
6418 &info[i].info3,
6419 &queue[i],
6420 next_queue,
6422 snum,
6423 pinfo2);
6424 if (!W_ERROR_IS_OK(result)) {
6425 goto out;
6429 out:
6430 if (!W_ERROR_IS_OK(result)) {
6431 TALLOC_FREE(info);
6432 *count = 0;
6433 return result;
6436 *info_p = info;
6438 return WERR_OK;
6441 /****************************************************************
6442 _spoolss_EnumJobs
6443 ****************************************************************/
6445 WERROR _spoolss_EnumJobs(pipes_struct *p,
6446 struct spoolss_EnumJobs *r)
6448 WERROR result;
6449 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6450 int snum;
6451 print_status_struct prt_status;
6452 print_queue_struct *queue = NULL;
6453 uint32_t count;
6455 /* that's an [in out] buffer */
6457 if (!r->in.buffer && (r->in.offered != 0)) {
6458 return WERR_INVALID_PARAM;
6461 DEBUG(4,("_spoolss_EnumJobs\n"));
6463 *r->out.needed = 0;
6464 *r->out.count = 0;
6465 *r->out.info = NULL;
6467 /* lookup the printer snum and tdb entry */
6469 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6470 return WERR_BADFID;
6473 result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
6474 lp_servicename(snum), &pinfo2);
6475 if (!W_ERROR_IS_OK(result)) {
6476 return result;
6479 count = print_queue_status(snum, &queue, &prt_status);
6480 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6481 count, prt_status.status, prt_status.message));
6483 if (count == 0) {
6484 SAFE_FREE(queue);
6485 TALLOC_FREE(pinfo2);
6486 return WERR_OK;
6489 switch (r->in.level) {
6490 case 1:
6491 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6492 pinfo2, r->out.info, r->out.count);
6493 break;
6494 case 2:
6495 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6496 pinfo2, r->out.info, r->out.count);
6497 break;
6498 case 3:
6499 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6500 pinfo2, r->out.info, r->out.count);
6501 break;
6502 default:
6503 result = WERR_UNKNOWN_LEVEL;
6504 break;
6507 SAFE_FREE(queue);
6508 TALLOC_FREE(pinfo2);
6510 if (!W_ERROR_IS_OK(result)) {
6511 return result;
6514 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6515 spoolss_EnumJobs,
6516 *r->out.info, r->in.level,
6517 *r->out.count);
6518 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6519 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6521 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6524 /****************************************************************
6525 _spoolss_ScheduleJob
6526 ****************************************************************/
6528 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6529 struct spoolss_ScheduleJob *r)
6531 return WERR_OK;
6534 /****************************************************************
6535 ****************************************************************/
6537 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6538 const char *printer_name,
6539 uint32_t job_id,
6540 struct spoolss_SetJobInfo1 *r)
6542 char *old_doc_name;
6544 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6545 return WERR_BADFID;
6548 if (strequal(old_doc_name, r->document_name)) {
6549 return WERR_OK;
6552 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6553 return WERR_BADFID;
6556 return WERR_OK;
6559 /****************************************************************
6560 _spoolss_SetJob
6561 ****************************************************************/
6563 WERROR _spoolss_SetJob(pipes_struct *p,
6564 struct spoolss_SetJob *r)
6566 int snum;
6567 WERROR errcode = WERR_BADFUNC;
6569 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6570 return WERR_BADFID;
6573 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6574 return WERR_INVALID_PRINTER_NAME;
6577 switch (r->in.command) {
6578 case SPOOLSS_JOB_CONTROL_CANCEL:
6579 case SPOOLSS_JOB_CONTROL_DELETE:
6580 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6581 errcode = WERR_OK;
6583 break;
6584 case SPOOLSS_JOB_CONTROL_PAUSE:
6585 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6586 errcode = WERR_OK;
6588 break;
6589 case SPOOLSS_JOB_CONTROL_RESTART:
6590 case SPOOLSS_JOB_CONTROL_RESUME:
6591 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6592 errcode = WERR_OK;
6594 break;
6595 case 0:
6596 errcode = WERR_OK;
6597 break;
6598 default:
6599 return WERR_UNKNOWN_LEVEL;
6602 if (!W_ERROR_IS_OK(errcode)) {
6603 return errcode;
6606 if (r->in.ctr == NULL) {
6607 return errcode;
6610 switch (r->in.ctr->level) {
6611 case 1:
6612 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6613 r->in.job_id,
6614 r->in.ctr->info.info1);
6615 break;
6616 case 2:
6617 case 3:
6618 case 4:
6619 default:
6620 return WERR_UNKNOWN_LEVEL;
6623 return errcode;
6626 /****************************************************************************
6627 Enumerates all printer drivers by level and architecture.
6628 ****************************************************************************/
6630 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6631 struct auth_serversupplied_info *server_info,
6632 const char *servername,
6633 const char *architecture,
6634 uint32_t level,
6635 union spoolss_DriverInfo **info_p,
6636 uint32_t *count_p)
6638 int i;
6639 uint32_t version;
6640 struct spoolss_DriverInfo8 *driver;
6641 union spoolss_DriverInfo *info = NULL;
6642 uint32_t count = 0;
6643 WERROR result = WERR_OK;
6644 uint32_t num_drivers;
6645 const char **drivers;
6647 *count_p = 0;
6648 *info_p = NULL;
6650 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6651 result = winreg_get_driver_list(mem_ctx, server_info,
6652 architecture, version,
6653 &num_drivers, &drivers);
6654 if (!W_ERROR_IS_OK(result)) {
6655 goto out;
6657 DEBUG(4, ("we have:[%d] drivers in environment"
6658 " [%s] and version [%d]\n",
6659 num_drivers, architecture, version));
6661 if (num_drivers != 0) {
6662 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6663 union spoolss_DriverInfo,
6664 count + num_drivers);
6665 if (!info) {
6666 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6667 "failed to enlarge driver info buffer!\n"));
6668 result = WERR_NOMEM;
6669 goto out;
6673 for (i = 0; i < num_drivers; i++) {
6674 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6676 result = winreg_get_driver(mem_ctx, server_info,
6677 architecture, drivers[i],
6678 version, &driver);
6679 if (!W_ERROR_IS_OK(result)) {
6680 goto out;
6683 switch (level) {
6684 case 1:
6685 result = fill_printer_driver_info1(info, &info[count+i].info1,
6686 driver, servername);
6687 break;
6688 case 2:
6689 result = fill_printer_driver_info2(info, &info[count+i].info2,
6690 driver, servername);
6691 break;
6692 case 3:
6693 result = fill_printer_driver_info3(info, &info[count+i].info3,
6694 driver, servername);
6695 break;
6696 case 4:
6697 result = fill_printer_driver_info4(info, &info[count+i].info4,
6698 driver, servername);
6699 break;
6700 case 5:
6701 result = fill_printer_driver_info5(info, &info[count+i].info5,
6702 driver, servername);
6703 break;
6704 case 6:
6705 result = fill_printer_driver_info6(info, &info[count+i].info6,
6706 driver, servername);
6707 break;
6708 case 8:
6709 result = fill_printer_driver_info8(info, &info[count+i].info8,
6710 driver, servername);
6711 break;
6712 default:
6713 result = WERR_UNKNOWN_LEVEL;
6714 break;
6717 TALLOC_FREE(driver);
6719 if (!W_ERROR_IS_OK(result)) {
6720 goto out;
6724 count += num_drivers;
6725 TALLOC_FREE(drivers);
6728 out:
6729 TALLOC_FREE(drivers);
6731 if (!W_ERROR_IS_OK(result)) {
6732 TALLOC_FREE(info);
6733 return result;
6736 *info_p = info;
6737 *count_p = count;
6739 return WERR_OK;
6742 /****************************************************************************
6743 Enumerates all printer drivers by level.
6744 ****************************************************************************/
6746 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6747 struct auth_serversupplied_info *server_info,
6748 const char *servername,
6749 const char *architecture,
6750 uint32_t level,
6751 union spoolss_DriverInfo **info_p,
6752 uint32_t *count_p)
6754 uint32_t a,i;
6755 WERROR result = WERR_OK;
6757 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6759 for (a=0; archi_table[a].long_archi != NULL; a++) {
6761 union spoolss_DriverInfo *info = NULL;
6762 uint32_t count = 0;
6764 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6765 server_info,
6766 servername,
6767 archi_table[a].long_archi,
6768 level,
6769 &info,
6770 &count);
6771 if (!W_ERROR_IS_OK(result)) {
6772 continue;
6775 for (i=0; i < count; i++) {
6776 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6777 info[i], info_p, count_p);
6781 return result;
6784 return enumprinterdrivers_level_by_architecture(mem_ctx,
6785 server_info,
6786 servername,
6787 architecture,
6788 level,
6789 info_p,
6790 count_p);
6793 /****************************************************************
6794 _spoolss_EnumPrinterDrivers
6795 ****************************************************************/
6797 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6798 struct spoolss_EnumPrinterDrivers *r)
6800 const char *cservername;
6801 WERROR result;
6803 /* that's an [in out] buffer */
6805 if (!r->in.buffer && (r->in.offered != 0)) {
6806 return WERR_INVALID_PARAM;
6809 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6811 *r->out.needed = 0;
6812 *r->out.count = 0;
6813 *r->out.info = NULL;
6815 cservername = canon_servername(r->in.server);
6817 if (!is_myname_or_ipaddr(cservername)) {
6818 return WERR_UNKNOWN_PRINTER_DRIVER;
6821 result = enumprinterdrivers_level(p->mem_ctx,
6822 p->server_info,
6823 cservername,
6824 r->in.environment,
6825 r->in.level,
6826 r->out.info,
6827 r->out.count);
6828 if (!W_ERROR_IS_OK(result)) {
6829 return result;
6832 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6833 spoolss_EnumPrinterDrivers,
6834 *r->out.info, r->in.level,
6835 *r->out.count);
6836 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6837 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6839 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6842 /****************************************************************
6843 _spoolss_EnumForms
6844 ****************************************************************/
6846 WERROR _spoolss_EnumForms(pipes_struct *p,
6847 struct spoolss_EnumForms *r)
6849 WERROR result;
6851 *r->out.count = 0;
6852 *r->out.needed = 0;
6853 *r->out.info = NULL;
6855 /* that's an [in out] buffer */
6857 if (!r->in.buffer && (r->in.offered != 0) ) {
6858 return WERR_INVALID_PARAM;
6861 DEBUG(4,("_spoolss_EnumForms\n"));
6862 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6863 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6865 switch (r->in.level) {
6866 case 1:
6867 result = winreg_printer_enumforms1(p->mem_ctx,
6868 p->server_info,
6869 r->out.count,
6870 r->out.info);
6871 break;
6872 default:
6873 result = WERR_UNKNOWN_LEVEL;
6874 break;
6877 if (!W_ERROR_IS_OK(result)) {
6878 return result;
6881 if (*r->out.count == 0) {
6882 return WERR_NO_MORE_ITEMS;
6885 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6886 spoolss_EnumForms,
6887 *r->out.info, r->in.level,
6888 *r->out.count);
6889 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6890 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6892 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6895 /****************************************************************
6896 _spoolss_GetForm
6897 ****************************************************************/
6899 WERROR _spoolss_GetForm(pipes_struct *p,
6900 struct spoolss_GetForm *r)
6902 WERROR result;
6904 /* that's an [in out] buffer */
6906 if (!r->in.buffer && (r->in.offered != 0)) {
6907 return WERR_INVALID_PARAM;
6910 DEBUG(4,("_spoolss_GetForm\n"));
6911 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6912 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6914 switch (r->in.level) {
6915 case 1:
6916 result = winreg_printer_getform1(p->mem_ctx,
6917 p->server_info,
6918 r->in.form_name,
6919 &r->out.info->info1);
6920 break;
6921 default:
6922 result = WERR_UNKNOWN_LEVEL;
6923 break;
6926 if (!W_ERROR_IS_OK(result)) {
6927 TALLOC_FREE(r->out.info);
6928 return result;
6931 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6932 r->out.info, r->in.level);
6933 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6935 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6938 /****************************************************************************
6939 ****************************************************************************/
6941 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6942 struct spoolss_PortInfo1 *r,
6943 const char *name)
6945 r->port_name = talloc_strdup(mem_ctx, name);
6946 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6948 return WERR_OK;
6951 /****************************************************************************
6952 TODO: This probably needs distinguish between TCP/IP and Local ports
6953 somehow.
6954 ****************************************************************************/
6956 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6957 struct spoolss_PortInfo2 *r,
6958 const char *name)
6960 r->port_name = talloc_strdup(mem_ctx, name);
6961 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6963 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6964 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6966 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6967 W_ERROR_HAVE_NO_MEMORY(r->description);
6969 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6970 r->reserved = 0;
6972 return WERR_OK;
6976 /****************************************************************************
6977 wrapper around the enumer ports command
6978 ****************************************************************************/
6980 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6982 char *cmd = lp_enumports_cmd();
6983 char **qlines = NULL;
6984 char *command = NULL;
6985 int numlines;
6986 int ret;
6987 int fd;
6989 *count = 0;
6990 *lines = NULL;
6992 /* if no hook then just fill in the default port */
6994 if ( !*cmd ) {
6995 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6996 return WERR_NOMEM;
6998 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6999 TALLOC_FREE(qlines);
7000 return WERR_NOMEM;
7002 qlines[1] = NULL;
7003 numlines = 1;
7005 else {
7006 /* we have a valid enumport command */
7008 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7009 if (!command) {
7010 return WERR_NOMEM;
7013 DEBUG(10,("Running [%s]\n", command));
7014 ret = smbrun(command, &fd);
7015 DEBUG(10,("Returned [%d]\n", ret));
7016 TALLOC_FREE(command);
7017 if (ret != 0) {
7018 if (fd != -1) {
7019 close(fd);
7021 return WERR_ACCESS_DENIED;
7024 numlines = 0;
7025 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7026 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7027 close(fd);
7030 *count = numlines;
7031 *lines = qlines;
7033 return WERR_OK;
7036 /****************************************************************************
7037 enumports level 1.
7038 ****************************************************************************/
7040 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7041 union spoolss_PortInfo **info_p,
7042 uint32_t *count)
7044 union spoolss_PortInfo *info = NULL;
7045 int i=0;
7046 WERROR result = WERR_OK;
7047 char **qlines = NULL;
7048 int numlines = 0;
7050 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7051 if (!W_ERROR_IS_OK(result)) {
7052 goto out;
7055 if (numlines) {
7056 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7057 if (!info) {
7058 DEBUG(10,("Returning WERR_NOMEM\n"));
7059 result = WERR_NOMEM;
7060 goto out;
7063 for (i=0; i<numlines; i++) {
7064 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7065 result = fill_port_1(info, &info[i].info1, qlines[i]);
7066 if (!W_ERROR_IS_OK(result)) {
7067 goto out;
7071 TALLOC_FREE(qlines);
7073 out:
7074 if (!W_ERROR_IS_OK(result)) {
7075 TALLOC_FREE(info);
7076 TALLOC_FREE(qlines);
7077 *count = 0;
7078 *info_p = NULL;
7079 return result;
7082 *info_p = info;
7083 *count = numlines;
7085 return WERR_OK;
7088 /****************************************************************************
7089 enumports level 2.
7090 ****************************************************************************/
7092 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7093 union spoolss_PortInfo **info_p,
7094 uint32_t *count)
7096 union spoolss_PortInfo *info = NULL;
7097 int i=0;
7098 WERROR result = WERR_OK;
7099 char **qlines = NULL;
7100 int numlines = 0;
7102 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7103 if (!W_ERROR_IS_OK(result)) {
7104 goto out;
7107 if (numlines) {
7108 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7109 if (!info) {
7110 DEBUG(10,("Returning WERR_NOMEM\n"));
7111 result = WERR_NOMEM;
7112 goto out;
7115 for (i=0; i<numlines; i++) {
7116 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7117 result = fill_port_2(info, &info[i].info2, qlines[i]);
7118 if (!W_ERROR_IS_OK(result)) {
7119 goto out;
7123 TALLOC_FREE(qlines);
7125 out:
7126 if (!W_ERROR_IS_OK(result)) {
7127 TALLOC_FREE(info);
7128 TALLOC_FREE(qlines);
7129 *count = 0;
7130 *info_p = NULL;
7131 return result;
7134 *info_p = info;
7135 *count = numlines;
7137 return WERR_OK;
7140 /****************************************************************
7141 _spoolss_EnumPorts
7142 ****************************************************************/
7144 WERROR _spoolss_EnumPorts(pipes_struct *p,
7145 struct spoolss_EnumPorts *r)
7147 WERROR result;
7149 /* that's an [in out] buffer */
7151 if (!r->in.buffer && (r->in.offered != 0)) {
7152 return WERR_INVALID_PARAM;
7155 DEBUG(4,("_spoolss_EnumPorts\n"));
7157 *r->out.count = 0;
7158 *r->out.needed = 0;
7159 *r->out.info = NULL;
7161 switch (r->in.level) {
7162 case 1:
7163 result = enumports_level_1(p->mem_ctx, r->out.info,
7164 r->out.count);
7165 break;
7166 case 2:
7167 result = enumports_level_2(p->mem_ctx, r->out.info,
7168 r->out.count);
7169 break;
7170 default:
7171 return WERR_UNKNOWN_LEVEL;
7174 if (!W_ERROR_IS_OK(result)) {
7175 return result;
7178 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7179 spoolss_EnumPorts,
7180 *r->out.info, r->in.level,
7181 *r->out.count);
7182 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7183 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7185 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7188 /****************************************************************************
7189 ****************************************************************************/
7191 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7192 const char *server,
7193 struct spoolss_SetPrinterInfoCtr *info_ctr,
7194 struct spoolss_DeviceMode *devmode,
7195 struct security_descriptor *secdesc,
7196 struct spoolss_UserLevelCtr *user_ctr,
7197 struct policy_handle *handle)
7199 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7200 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7201 int snum;
7202 WERROR err = WERR_OK;
7204 /* samba does not have a concept of local, non-shared printers yet, so
7205 * make sure we always setup sharename - gd */
7206 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7207 (info2->printername != NULL && info2->printername[0] != '\0')) {
7208 DEBUG(5, ("spoolss_addprinterex_level_2: "
7209 "no sharename has been set, setting printername %s as sharename\n",
7210 info2->printername));
7211 info2->sharename = info2->printername;
7214 /* check to see if the printer already exists */
7215 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7216 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7217 info2->sharename));
7218 return WERR_PRINTER_ALREADY_EXISTS;
7221 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7222 if ((snum = print_queue_snum(info2->printername)) != -1) {
7223 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7224 info2->printername));
7225 return WERR_PRINTER_ALREADY_EXISTS;
7229 /* validate printer info struct */
7230 if (!info2->printername || strlen(info2->printername) == 0) {
7231 return WERR_INVALID_PRINTER_NAME;
7233 if (!info2->portname || strlen(info2->portname) == 0) {
7234 return WERR_UNKNOWN_PORT;
7236 if (!info2->drivername || strlen(info2->drivername) == 0) {
7237 return WERR_UNKNOWN_PRINTER_DRIVER;
7239 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7240 return WERR_UNKNOWN_PRINTPROCESSOR;
7243 /* FIXME!!! smbd should check to see if the driver is installed before
7244 trying to add a printer like this --jerry */
7246 if (*lp_addprinter_cmd() ) {
7247 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7248 info2) ) {
7249 return WERR_ACCESS_DENIED;
7251 } else {
7252 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7253 "smb.conf parameter \"addprinter command\" is defined. This"
7254 "parameter must exist for this call to succeed\n",
7255 info2->sharename ));
7258 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7259 return WERR_ACCESS_DENIED;
7262 /* you must be a printer admin to add a new printer */
7263 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7264 return WERR_ACCESS_DENIED;
7268 * Do sanity check on the requested changes for Samba.
7271 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7272 return WERR_INVALID_PARAM;
7275 if (devmode == NULL) {
7276 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7279 update_dsspooler(p->mem_ctx,
7280 p->server_info,
7282 info2,
7283 NULL);
7285 err = winreg_update_printer(p->mem_ctx,
7286 p->server_info,
7287 info2->sharename,
7288 info2_mask,
7289 info2,
7290 devmode,
7291 secdesc);
7292 if (!W_ERROR_IS_OK(err)) {
7293 return err;
7296 if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7297 /* Handle open failed - remove addition. */
7298 ZERO_STRUCTP(handle);
7299 return WERR_ACCESS_DENIED;
7302 return WERR_OK;
7305 /****************************************************************
7306 _spoolss_AddPrinterEx
7307 ****************************************************************/
7309 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7310 struct spoolss_AddPrinterEx *r)
7312 switch (r->in.info_ctr->level) {
7313 case 1:
7314 /* we don't handle yet */
7315 /* but I know what to do ... */
7316 return WERR_UNKNOWN_LEVEL;
7317 case 2:
7318 return spoolss_addprinterex_level_2(p, r->in.server,
7319 r->in.info_ctr,
7320 r->in.devmode_ctr->devmode,
7321 r->in.secdesc_ctr->sd,
7322 r->in.userlevel_ctr,
7323 r->out.handle);
7324 default:
7325 return WERR_UNKNOWN_LEVEL;
7329 /****************************************************************
7330 _spoolss_AddPrinter
7331 ****************************************************************/
7333 WERROR _spoolss_AddPrinter(pipes_struct *p,
7334 struct spoolss_AddPrinter *r)
7336 struct spoolss_AddPrinterEx a;
7337 struct spoolss_UserLevelCtr userlevel_ctr;
7339 ZERO_STRUCT(userlevel_ctr);
7341 userlevel_ctr.level = 1;
7343 a.in.server = r->in.server;
7344 a.in.info_ctr = r->in.info_ctr;
7345 a.in.devmode_ctr = r->in.devmode_ctr;
7346 a.in.secdesc_ctr = r->in.secdesc_ctr;
7347 a.in.userlevel_ctr = &userlevel_ctr;
7348 a.out.handle = r->out.handle;
7350 return _spoolss_AddPrinterEx(p, &a);
7353 /****************************************************************
7354 _spoolss_AddPrinterDriverEx
7355 ****************************************************************/
7357 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7358 struct spoolss_AddPrinterDriverEx *r)
7360 WERROR err = WERR_OK;
7361 const char *driver_name = NULL;
7362 uint32_t version;
7363 const char *fn;
7365 switch (p->opnum) {
7366 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7367 fn = "_spoolss_AddPrinterDriver";
7368 break;
7369 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7370 fn = "_spoolss_AddPrinterDriverEx";
7371 break;
7372 default:
7373 return WERR_INVALID_PARAM;
7377 * we only support the semantics of AddPrinterDriver()
7378 * i.e. only copy files that are newer than existing ones
7381 if (r->in.flags == 0) {
7382 return WERR_INVALID_PARAM;
7385 if (r->in.flags != APD_COPY_NEW_FILES) {
7386 return WERR_ACCESS_DENIED;
7389 /* FIXME */
7390 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7391 /* Clever hack from Martin Zielinski <mz@seh.de>
7392 * to allow downgrade from level 8 (Vista).
7394 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7395 r->in.info_ctr->level));
7396 return WERR_UNKNOWN_LEVEL;
7399 DEBUG(5,("Cleaning driver's information\n"));
7400 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7401 if (!W_ERROR_IS_OK(err))
7402 goto done;
7404 DEBUG(5,("Moving driver to final destination\n"));
7405 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7406 &err)) ) {
7407 goto done;
7410 err = winreg_add_driver(p->mem_ctx, p->server_info,
7411 r->in.info_ctr, &driver_name, &version);
7412 if (!W_ERROR_IS_OK(err)) {
7413 goto done;
7417 * I think this is where he DrvUpgradePrinter() hook would be
7418 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7419 * server. Right now, we just need to send ourselves a message
7420 * to update each printer bound to this driver. --jerry
7423 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7424 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7425 fn, driver_name));
7428 done:
7429 return err;
7432 /****************************************************************
7433 _spoolss_AddPrinterDriver
7434 ****************************************************************/
7436 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7437 struct spoolss_AddPrinterDriver *r)
7439 struct spoolss_AddPrinterDriverEx a;
7441 switch (r->in.info_ctr->level) {
7442 case 2:
7443 case 3:
7444 case 4:
7445 case 5:
7446 break;
7447 default:
7448 return WERR_UNKNOWN_LEVEL;
7451 a.in.servername = r->in.servername;
7452 a.in.info_ctr = r->in.info_ctr;
7453 a.in.flags = APD_COPY_NEW_FILES;
7455 return _spoolss_AddPrinterDriverEx(p, &a);
7458 /****************************************************************************
7459 ****************************************************************************/
7461 struct _spoolss_paths {
7462 int type;
7463 const char *share;
7464 const char *dir;
7467 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7469 static const struct _spoolss_paths spoolss_paths[]= {
7470 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7471 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7474 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7475 const char *servername,
7476 const char *environment,
7477 int component,
7478 char **path)
7480 const char *pservername = NULL;
7481 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7482 const char *short_archi;
7484 *path = NULL;
7486 /* environment may be empty */
7487 if (environment && strlen(environment)) {
7488 long_archi = environment;
7491 /* servername may be empty */
7492 if (servername && strlen(servername)) {
7493 pservername = canon_servername(servername);
7495 if (!is_myname_or_ipaddr(pservername)) {
7496 return WERR_INVALID_PARAM;
7500 if (!(short_archi = get_short_archi(long_archi))) {
7501 return WERR_INVALID_ENVIRONMENT;
7504 switch (component) {
7505 case SPOOLSS_PRTPROCS_PATH:
7506 case SPOOLSS_DRIVER_PATH:
7507 if (pservername) {
7508 *path = talloc_asprintf(mem_ctx,
7509 "\\\\%s\\%s\\%s",
7510 pservername,
7511 spoolss_paths[component].share,
7512 short_archi);
7513 } else {
7514 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7515 SPOOLSS_DEFAULT_SERVER_PATH,
7516 spoolss_paths[component].dir,
7517 short_archi);
7519 break;
7520 default:
7521 return WERR_INVALID_PARAM;
7524 if (!*path) {
7525 return WERR_NOMEM;
7528 return WERR_OK;
7531 /****************************************************************************
7532 ****************************************************************************/
7534 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7535 const char *servername,
7536 const char *environment,
7537 struct spoolss_DriverDirectoryInfo1 *r)
7539 WERROR werr;
7540 char *path = NULL;
7542 werr = compose_spoolss_server_path(mem_ctx,
7543 servername,
7544 environment,
7545 SPOOLSS_DRIVER_PATH,
7546 &path);
7547 if (!W_ERROR_IS_OK(werr)) {
7548 return werr;
7551 DEBUG(4,("printer driver directory: [%s]\n", path));
7553 r->directory_name = path;
7555 return WERR_OK;
7558 /****************************************************************
7559 _spoolss_GetPrinterDriverDirectory
7560 ****************************************************************/
7562 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7563 struct spoolss_GetPrinterDriverDirectory *r)
7565 WERROR werror;
7567 /* that's an [in out] buffer */
7569 if (!r->in.buffer && (r->in.offered != 0)) {
7570 return WERR_INVALID_PARAM;
7573 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7574 r->in.level));
7576 *r->out.needed = 0;
7578 /* r->in.level is ignored */
7580 werror = getprinterdriverdir_level_1(p->mem_ctx,
7581 r->in.server,
7582 r->in.environment,
7583 &r->out.info->info1);
7584 if (!W_ERROR_IS_OK(werror)) {
7585 TALLOC_FREE(r->out.info);
7586 return werror;
7589 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7590 r->out.info, r->in.level);
7591 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7593 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7596 /****************************************************************
7597 _spoolss_EnumPrinterData
7598 ****************************************************************/
7600 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7601 struct spoolss_EnumPrinterData *r)
7603 WERROR result;
7604 struct spoolss_EnumPrinterDataEx r2;
7605 uint32_t count;
7606 struct spoolss_PrinterEnumValues *info, *val = NULL;
7607 uint32_t needed;
7609 r2.in.handle = r->in.handle;
7610 r2.in.key_name = "PrinterDriverData";
7611 r2.in.offered = 0;
7612 r2.out.count = &count;
7613 r2.out.info = &info;
7614 r2.out.needed = &needed;
7616 result = _spoolss_EnumPrinterDataEx(p, &r2);
7617 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7618 r2.in.offered = needed;
7619 result = _spoolss_EnumPrinterDataEx(p, &r2);
7621 if (!W_ERROR_IS_OK(result)) {
7622 return result;
7626 * The NT machine wants to know the biggest size of value and data
7628 * cf: MSDN EnumPrinterData remark section
7631 if (!r->in.value_offered && !r->in.data_offered) {
7632 uint32_t biggest_valuesize = 0;
7633 uint32_t biggest_datasize = 0;
7634 int i, name_length;
7636 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7638 for (i=0; i<count; i++) {
7640 name_length = strlen(info[i].value_name);
7641 if (strlen(info[i].value_name) > biggest_valuesize) {
7642 biggest_valuesize = name_length;
7645 if (info[i].data_length > biggest_datasize) {
7646 biggest_datasize = info[i].data_length;
7649 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7650 biggest_datasize));
7653 /* the value is an UNICODE string but real_value_size is the length
7654 in bytes including the trailing 0 */
7656 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7657 *r->out.data_needed = biggest_datasize;
7659 DEBUG(6,("final values: [%d], [%d]\n",
7660 *r->out.value_needed, *r->out.data_needed));
7662 return WERR_OK;
7665 if (r->in.enum_index < count) {
7666 val = &info[r->in.enum_index];
7669 if (val == NULL) {
7670 /* out_value should default to "" or else NT4 has
7671 problems unmarshalling the response */
7673 if (r->in.value_offered) {
7674 *r->out.value_needed = 1;
7675 r->out.value_name = talloc_strdup(r, "");
7676 if (!r->out.value_name) {
7677 return WERR_NOMEM;
7679 } else {
7680 r->out.value_name = NULL;
7681 *r->out.value_needed = 0;
7684 /* the data is counted in bytes */
7686 *r->out.data_needed = r->in.data_offered;
7688 result = WERR_NO_MORE_ITEMS;
7689 } else {
7691 * the value is:
7692 * - counted in bytes in the request
7693 * - counted in UNICODE chars in the max reply
7694 * - counted in bytes in the real size
7696 * take a pause *before* coding not *during* coding
7699 /* name */
7700 if (r->in.value_offered) {
7701 r->out.value_name = talloc_strdup(r, val->value_name);
7702 if (!r->out.value_name) {
7703 return WERR_NOMEM;
7705 *r->out.value_needed = val->value_name_len;
7706 } else {
7707 r->out.value_name = NULL;
7708 *r->out.value_needed = 0;
7711 /* type */
7713 *r->out.type = val->type;
7715 /* data - counted in bytes */
7718 * See the section "Dynamically Typed Query Parameters"
7719 * in MS-RPRN.
7722 if (r->out.data && val->data && val->data->data &&
7723 val->data_length && r->in.data_offered) {
7724 memcpy(r->out.data, val->data->data,
7725 MIN(val->data_length,r->in.data_offered));
7728 *r->out.data_needed = val->data_length;
7730 result = WERR_OK;
7733 return result;
7736 /****************************************************************
7737 _spoolss_SetPrinterData
7738 ****************************************************************/
7740 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7741 struct spoolss_SetPrinterData *r)
7743 struct spoolss_SetPrinterDataEx r2;
7745 r2.in.handle = r->in.handle;
7746 r2.in.key_name = "PrinterDriverData";
7747 r2.in.value_name = r->in.value_name;
7748 r2.in.type = r->in.type;
7749 r2.in.data = r->in.data;
7750 r2.in.offered = r->in.offered;
7752 return _spoolss_SetPrinterDataEx(p, &r2);
7755 /****************************************************************
7756 _spoolss_ResetPrinter
7757 ****************************************************************/
7759 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7760 struct spoolss_ResetPrinter *r)
7762 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7763 int snum;
7765 DEBUG(5,("_spoolss_ResetPrinter\n"));
7768 * All we do is to check to see if the handle and queue is valid.
7769 * This call really doesn't mean anything to us because we only
7770 * support RAW printing. --jerry
7773 if (!Printer) {
7774 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7775 OUR_HANDLE(r->in.handle)));
7776 return WERR_BADFID;
7779 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7780 return WERR_BADFID;
7783 /* blindly return success */
7784 return WERR_OK;
7787 /****************************************************************
7788 _spoolss_DeletePrinterData
7789 ****************************************************************/
7791 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7792 struct spoolss_DeletePrinterData *r)
7794 struct spoolss_DeletePrinterDataEx r2;
7796 r2.in.handle = r->in.handle;
7797 r2.in.key_name = "PrinterDriverData";
7798 r2.in.value_name = r->in.value_name;
7800 return _spoolss_DeletePrinterDataEx(p, &r2);
7803 /****************************************************************
7804 _spoolss_AddForm
7805 ****************************************************************/
7807 WERROR _spoolss_AddForm(pipes_struct *p,
7808 struct spoolss_AddForm *r)
7810 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7811 int snum = -1;
7812 WERROR status = WERR_OK;
7813 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7815 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7817 DEBUG(5,("_spoolss_AddForm\n"));
7819 if (!Printer) {
7820 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7821 OUR_HANDLE(r->in.handle)));
7822 return WERR_BADFID;
7825 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7826 and not a printer admin, then fail */
7828 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7829 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7830 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7831 p->server_info->info3->base.domain.string,
7832 NULL,
7833 p->server_info->ptok,
7834 lp_printer_admin(snum))) {
7835 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7836 return WERR_ACCESS_DENIED;
7839 switch (form->flags) {
7840 case SPOOLSS_FORM_USER:
7841 case SPOOLSS_FORM_BUILTIN:
7842 case SPOOLSS_FORM_PRINTER:
7843 break;
7844 default:
7845 return WERR_INVALID_PARAM;
7848 status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7849 if (!W_ERROR_IS_OK(status)) {
7850 return status;
7854 * ChangeID must always be set if this is a printer
7856 if (Printer->printer_type == SPLHND_PRINTER) {
7857 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7858 return WERR_BADFID;
7861 status = winreg_printer_update_changeid(p->mem_ctx,
7862 p->server_info,
7863 lp_const_servicename(snum));
7864 if (!W_ERROR_IS_OK(status)) {
7865 return status;
7869 return status;
7872 /****************************************************************
7873 _spoolss_DeleteForm
7874 ****************************************************************/
7876 WERROR _spoolss_DeleteForm(pipes_struct *p,
7877 struct spoolss_DeleteForm *r)
7879 const char *form_name = r->in.form_name;
7880 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7881 int snum = -1;
7882 WERROR status = WERR_OK;
7883 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7885 DEBUG(5,("_spoolss_DeleteForm\n"));
7887 if (!Printer) {
7888 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7889 OUR_HANDLE(r->in.handle)));
7890 return WERR_BADFID;
7893 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7894 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7895 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7896 p->server_info->info3->base.domain.string,
7897 NULL,
7898 p->server_info->ptok,
7899 lp_printer_admin(snum))) {
7900 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7901 return WERR_ACCESS_DENIED;
7904 status = winreg_printer_deleteform1(p->mem_ctx,
7905 p->server_info,
7906 form_name);
7907 if (!W_ERROR_IS_OK(status)) {
7908 return status;
7912 * ChangeID must always be set if this is a printer
7914 if (Printer->printer_type == SPLHND_PRINTER) {
7915 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7916 return WERR_BADFID;
7919 status = winreg_printer_update_changeid(p->mem_ctx,
7920 p->server_info,
7921 lp_const_servicename(snum));
7922 if (!W_ERROR_IS_OK(status)) {
7923 return status;
7927 return status;
7930 /****************************************************************
7931 _spoolss_SetForm
7932 ****************************************************************/
7934 WERROR _spoolss_SetForm(pipes_struct *p,
7935 struct spoolss_SetForm *r)
7937 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7938 const char *form_name = r->in.form_name;
7939 int snum = -1;
7940 WERROR status = WERR_OK;
7941 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7943 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7945 DEBUG(5,("_spoolss_SetForm\n"));
7947 if (!Printer) {
7948 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7949 OUR_HANDLE(r->in.handle)));
7950 return WERR_BADFID;
7953 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7954 and not a printer admin, then fail */
7956 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7957 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7958 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7959 p->server_info->info3->base.domain.string,
7960 NULL,
7961 p->server_info->ptok,
7962 lp_printer_admin(snum))) {
7963 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7964 return WERR_ACCESS_DENIED;
7967 status = winreg_printer_setform1(p->mem_ctx,
7968 p->server_info,
7969 form_name,
7970 form);
7971 if (!W_ERROR_IS_OK(status)) {
7972 return status;
7976 * ChangeID must always be set if this is a printer
7978 if (Printer->printer_type == SPLHND_PRINTER) {
7979 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7980 return WERR_BADFID;
7983 status = winreg_printer_update_changeid(p->mem_ctx,
7984 p->server_info,
7985 lp_const_servicename(snum));
7986 if (!W_ERROR_IS_OK(status)) {
7987 return status;
7991 return status;
7994 /****************************************************************************
7995 fill_print_processor1
7996 ****************************************************************************/
7998 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7999 struct spoolss_PrintProcessorInfo1 *r,
8000 const char *print_processor_name)
8002 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8003 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8005 return WERR_OK;
8008 /****************************************************************************
8009 enumprintprocessors level 1.
8010 ****************************************************************************/
8012 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8013 union spoolss_PrintProcessorInfo **info_p,
8014 uint32_t *count)
8016 union spoolss_PrintProcessorInfo *info;
8017 WERROR result;
8019 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8020 W_ERROR_HAVE_NO_MEMORY(info);
8022 *count = 1;
8024 result = fill_print_processor1(info, &info[0].info1, "winprint");
8025 if (!W_ERROR_IS_OK(result)) {
8026 goto out;
8029 out:
8030 if (!W_ERROR_IS_OK(result)) {
8031 TALLOC_FREE(info);
8032 *count = 0;
8033 return result;
8036 *info_p = info;
8038 return WERR_OK;
8041 /****************************************************************
8042 _spoolss_EnumPrintProcessors
8043 ****************************************************************/
8045 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8046 struct spoolss_EnumPrintProcessors *r)
8048 WERROR result;
8050 /* that's an [in out] buffer */
8052 if (!r->in.buffer && (r->in.offered != 0)) {
8053 return WERR_INVALID_PARAM;
8056 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8059 * Enumerate the print processors ...
8061 * Just reply with "winprint", to keep NT happy
8062 * and I can use my nice printer checker.
8065 *r->out.count = 0;
8066 *r->out.needed = 0;
8067 *r->out.info = NULL;
8069 switch (r->in.level) {
8070 case 1:
8071 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8072 r->out.count);
8073 break;
8074 default:
8075 return WERR_UNKNOWN_LEVEL;
8078 if (!W_ERROR_IS_OK(result)) {
8079 return result;
8082 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8083 spoolss_EnumPrintProcessors,
8084 *r->out.info, r->in.level,
8085 *r->out.count);
8086 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8087 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8089 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8092 /****************************************************************************
8093 fill_printprocdatatype1
8094 ****************************************************************************/
8096 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8097 struct spoolss_PrintProcDataTypesInfo1 *r,
8098 const char *name_array)
8100 r->name_array = talloc_strdup(mem_ctx, name_array);
8101 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8103 return WERR_OK;
8106 /****************************************************************************
8107 enumprintprocdatatypes level 1.
8108 ****************************************************************************/
8110 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8111 union spoolss_PrintProcDataTypesInfo **info_p,
8112 uint32_t *count)
8114 WERROR result;
8115 union spoolss_PrintProcDataTypesInfo *info;
8117 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8118 W_ERROR_HAVE_NO_MEMORY(info);
8120 *count = 1;
8122 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8123 if (!W_ERROR_IS_OK(result)) {
8124 goto out;
8127 out:
8128 if (!W_ERROR_IS_OK(result)) {
8129 TALLOC_FREE(info);
8130 *count = 0;
8131 return result;
8134 *info_p = info;
8136 return WERR_OK;
8139 /****************************************************************
8140 _spoolss_EnumPrintProcDataTypes
8141 ****************************************************************/
8143 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8144 struct spoolss_EnumPrintProcDataTypes *r)
8146 WERROR result;
8148 /* that's an [in out] buffer */
8150 if (!r->in.buffer && (r->in.offered != 0)) {
8151 return WERR_INVALID_PARAM;
8154 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8156 *r->out.count = 0;
8157 *r->out.needed = 0;
8158 *r->out.info = NULL;
8160 switch (r->in.level) {
8161 case 1:
8162 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8163 r->out.count);
8164 break;
8165 default:
8166 return WERR_UNKNOWN_LEVEL;
8169 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8170 spoolss_EnumPrintProcDataTypes,
8171 *r->out.info, r->in.level,
8172 *r->out.count);
8173 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8174 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8176 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8179 /****************************************************************************
8180 fill_monitor_1
8181 ****************************************************************************/
8183 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8184 struct spoolss_MonitorInfo1 *r,
8185 const char *monitor_name)
8187 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8188 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8190 return WERR_OK;
8193 /****************************************************************************
8194 fill_monitor_2
8195 ****************************************************************************/
8197 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8198 struct spoolss_MonitorInfo2 *r,
8199 const char *monitor_name,
8200 const char *environment,
8201 const char *dll_name)
8203 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8204 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8205 r->environment = talloc_strdup(mem_ctx, environment);
8206 W_ERROR_HAVE_NO_MEMORY(r->environment);
8207 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8208 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8210 return WERR_OK;
8213 /****************************************************************************
8214 enumprintmonitors level 1.
8215 ****************************************************************************/
8217 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8218 union spoolss_MonitorInfo **info_p,
8219 uint32_t *count)
8221 union spoolss_MonitorInfo *info;
8222 WERROR result = WERR_OK;
8224 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8225 W_ERROR_HAVE_NO_MEMORY(info);
8227 *count = 2;
8229 result = fill_monitor_1(info, &info[0].info1,
8230 SPL_LOCAL_PORT);
8231 if (!W_ERROR_IS_OK(result)) {
8232 goto out;
8235 result = fill_monitor_1(info, &info[1].info1,
8236 SPL_TCPIP_PORT);
8237 if (!W_ERROR_IS_OK(result)) {
8238 goto out;
8241 out:
8242 if (!W_ERROR_IS_OK(result)) {
8243 TALLOC_FREE(info);
8244 *count = 0;
8245 return result;
8248 *info_p = info;
8250 return WERR_OK;
8253 /****************************************************************************
8254 enumprintmonitors level 2.
8255 ****************************************************************************/
8257 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8258 union spoolss_MonitorInfo **info_p,
8259 uint32_t *count)
8261 union spoolss_MonitorInfo *info;
8262 WERROR result = WERR_OK;
8264 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8265 W_ERROR_HAVE_NO_MEMORY(info);
8267 *count = 2;
8269 result = fill_monitor_2(info, &info[0].info2,
8270 SPL_LOCAL_PORT,
8271 "Windows NT X86", /* FIXME */
8272 "localmon.dll");
8273 if (!W_ERROR_IS_OK(result)) {
8274 goto out;
8277 result = fill_monitor_2(info, &info[1].info2,
8278 SPL_TCPIP_PORT,
8279 "Windows NT X86", /* FIXME */
8280 "tcpmon.dll");
8281 if (!W_ERROR_IS_OK(result)) {
8282 goto out;
8285 out:
8286 if (!W_ERROR_IS_OK(result)) {
8287 TALLOC_FREE(info);
8288 *count = 0;
8289 return result;
8292 *info_p = info;
8294 return WERR_OK;
8297 /****************************************************************
8298 _spoolss_EnumMonitors
8299 ****************************************************************/
8301 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8302 struct spoolss_EnumMonitors *r)
8304 WERROR result;
8306 /* that's an [in out] buffer */
8308 if (!r->in.buffer && (r->in.offered != 0)) {
8309 return WERR_INVALID_PARAM;
8312 DEBUG(5,("_spoolss_EnumMonitors\n"));
8315 * Enumerate the print monitors ...
8317 * Just reply with "Local Port", to keep NT happy
8318 * and I can use my nice printer checker.
8321 *r->out.count = 0;
8322 *r->out.needed = 0;
8323 *r->out.info = NULL;
8325 switch (r->in.level) {
8326 case 1:
8327 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8328 r->out.count);
8329 break;
8330 case 2:
8331 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8332 r->out.count);
8333 break;
8334 default:
8335 return WERR_UNKNOWN_LEVEL;
8338 if (!W_ERROR_IS_OK(result)) {
8339 return result;
8342 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8343 spoolss_EnumMonitors,
8344 *r->out.info, r->in.level,
8345 *r->out.count);
8346 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8347 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8349 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8352 /****************************************************************************
8353 ****************************************************************************/
8355 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8356 const print_queue_struct *queue,
8357 int count, int snum,
8358 struct spoolss_PrinterInfo2 *pinfo2,
8359 uint32_t jobid,
8360 struct spoolss_JobInfo1 *r)
8362 int i = 0;
8363 bool found = false;
8365 for (i=0; i<count; i++) {
8366 if (queue[i].job == (int)jobid) {
8367 found = true;
8368 break;
8372 if (found == false) {
8373 /* NT treats not found as bad param... yet another bad choice */
8374 return WERR_INVALID_PARAM;
8377 return fill_job_info1(mem_ctx,
8379 &queue[i],
8381 snum,
8382 pinfo2);
8385 /****************************************************************************
8386 ****************************************************************************/
8388 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8389 const print_queue_struct *queue,
8390 int count, int snum,
8391 struct spoolss_PrinterInfo2 *pinfo2,
8392 uint32_t jobid,
8393 struct spoolss_JobInfo2 *r)
8395 int i = 0;
8396 bool found = false;
8397 struct spoolss_DeviceMode *devmode;
8398 WERROR result;
8400 for (i=0; i<count; i++) {
8401 if (queue[i].job == (int)jobid) {
8402 found = true;
8403 break;
8407 if (found == false) {
8408 /* NT treats not found as bad param... yet another bad
8409 choice */
8410 return WERR_INVALID_PARAM;
8414 * if the print job does not have a DEVMODE associated with it,
8415 * just use the one for the printer. A NULL devicemode is not
8416 * a failure condition
8419 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8420 if (!devmode) {
8421 result = spoolss_create_default_devmode(mem_ctx,
8422 pinfo2->printername,
8423 &devmode);
8424 if (!W_ERROR_IS_OK(result)) {
8425 DEBUG(3, ("Can't proceed w/o a devmode!"));
8426 return result;
8430 return fill_job_info2(mem_ctx,
8432 &queue[i],
8434 snum,
8435 pinfo2,
8436 devmode);
8439 /****************************************************************
8440 _spoolss_GetJob
8441 ****************************************************************/
8443 WERROR _spoolss_GetJob(pipes_struct *p,
8444 struct spoolss_GetJob *r)
8446 WERROR result = WERR_OK;
8447 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8448 int snum;
8449 int count;
8450 print_queue_struct *queue = NULL;
8451 print_status_struct prt_status;
8453 /* that's an [in out] buffer */
8455 if (!r->in.buffer && (r->in.offered != 0)) {
8456 return WERR_INVALID_PARAM;
8459 DEBUG(5,("_spoolss_GetJob\n"));
8461 *r->out.needed = 0;
8463 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8464 return WERR_BADFID;
8467 result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
8468 lp_servicename(snum), &pinfo2);
8469 if (!W_ERROR_IS_OK(result)) {
8470 return result;
8473 count = print_queue_status(snum, &queue, &prt_status);
8475 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8476 count, prt_status.status, prt_status.message));
8478 switch (r->in.level) {
8479 case 1:
8480 result = getjob_level_1(p->mem_ctx,
8481 queue, count, snum, pinfo2,
8482 r->in.job_id, &r->out.info->info1);
8483 break;
8484 case 2:
8485 result = getjob_level_2(p->mem_ctx,
8486 queue, count, snum, pinfo2,
8487 r->in.job_id, &r->out.info->info2);
8488 break;
8489 default:
8490 result = WERR_UNKNOWN_LEVEL;
8491 break;
8494 SAFE_FREE(queue);
8495 TALLOC_FREE(pinfo2);
8497 if (!W_ERROR_IS_OK(result)) {
8498 TALLOC_FREE(r->out.info);
8499 return result;
8502 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8503 r->in.level);
8504 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8506 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8509 /****************************************************************
8510 _spoolss_GetPrinterDataEx
8511 ****************************************************************/
8513 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8514 struct spoolss_GetPrinterDataEx *r)
8517 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8518 const char *printer;
8519 int snum = 0;
8520 WERROR result = WERR_OK;
8521 DATA_BLOB blob;
8522 enum winreg_Type val_type;
8523 uint8_t *val_data;
8524 uint32_t val_size;
8527 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8529 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8530 r->in.key_name, r->in.value_name));
8532 /* in case of problem, return some default values */
8534 *r->out.needed = 0;
8535 *r->out.type = REG_NONE;
8537 if (!Printer) {
8538 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8539 OUR_HANDLE(r->in.handle)));
8540 result = WERR_BADFID;
8541 goto done;
8544 /* Is the handle to a printer or to the server? */
8546 if (Printer->printer_type == SPLHND_SERVER) {
8548 union spoolss_PrinterData data;
8550 result = getprinterdata_printer_server(p->mem_ctx,
8551 r->in.value_name,
8552 r->out.type,
8553 &data);
8554 if (!W_ERROR_IS_OK(result)) {
8555 return result;
8558 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8559 *r->out.type, &data);
8560 if (!W_ERROR_IS_OK(result)) {
8561 return result;
8564 *r->out.needed = blob.length;
8566 if (r->in.offered >= *r->out.needed) {
8567 memcpy(r->out.data, blob.data, blob.length);
8570 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8573 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8574 return WERR_BADFID;
8576 printer = lp_const_servicename(snum);
8578 /* check to see if the keyname is valid */
8579 if (!strlen(r->in.key_name)) {
8580 return WERR_INVALID_PARAM;
8583 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8584 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8585 strequal(r->in.value_name, "ChangeId")) {
8586 *r->out.type = REG_DWORD;
8587 *r->out.needed = 4;
8588 if (r->in.offered >= *r->out.needed) {
8589 uint32_t changeid = 0;
8591 result = winreg_printer_get_changeid(p->mem_ctx,
8592 p->server_info,
8593 printer,
8594 &changeid);
8595 if (!W_ERROR_IS_OK(result)) {
8596 return result;
8599 SIVAL(r->out.data, 0, changeid);
8600 result = WERR_OK;
8602 goto done;
8605 result = winreg_get_printer_dataex(p->mem_ctx,
8606 p->server_info,
8607 printer,
8608 r->in.key_name,
8609 r->in.value_name,
8610 &val_type,
8611 &val_data,
8612 &val_size);
8613 if (!W_ERROR_IS_OK(result)) {
8614 return result;
8617 *r->out.needed = val_size;
8618 *r->out.type = val_type;
8620 if (r->in.offered >= *r->out.needed) {
8621 memcpy(r->out.data, val_data, val_size);
8624 done:
8625 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8626 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8628 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8631 /****************************************************************
8632 _spoolss_SetPrinterDataEx
8633 ****************************************************************/
8635 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8636 struct spoolss_SetPrinterDataEx *r)
8638 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8639 int snum = 0;
8640 WERROR result = WERR_OK;
8641 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8642 char *oid_string;
8644 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8646 /* From MSDN documentation of SetPrinterDataEx: pass request to
8647 SetPrinterData if key is "PrinterDriverData" */
8649 if (!Printer) {
8650 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8651 OUR_HANDLE(r->in.handle)));
8652 return WERR_BADFID;
8655 if (Printer->printer_type == SPLHND_SERVER) {
8656 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8657 "Not implemented for server handles yet\n"));
8658 return WERR_INVALID_PARAM;
8661 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8662 return WERR_BADFID;
8666 * Access check : NT returns "access denied" if you make a
8667 * SetPrinterData call without the necessary privildge.
8668 * we were originally returning OK if nothing changed
8669 * which made Win2k issue **a lot** of SetPrinterData
8670 * when connecting to a printer --jerry
8673 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8674 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8675 "change denied by handle access permissions\n"));
8676 return WERR_ACCESS_DENIED;
8679 result = winreg_get_printer(Printer, p->server_info,
8680 Printer->servername,
8681 lp_servicename(snum),
8682 &pinfo2);
8683 if (!W_ERROR_IS_OK(result)) {
8684 return result;
8687 /* check for OID in valuename */
8689 oid_string = strchr(r->in.value_name, ',');
8690 if (oid_string) {
8691 *oid_string = '\0';
8692 oid_string++;
8695 /* save the registry data */
8697 result = winreg_set_printer_dataex(p->mem_ctx,
8698 p->server_info,
8699 pinfo2->sharename,
8700 r->in.key_name,
8701 r->in.value_name,
8702 r->in.type,
8703 r->in.data,
8704 r->in.offered);
8706 if (W_ERROR_IS_OK(result)) {
8707 /* save the OID if one was specified */
8708 if (oid_string) {
8709 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8710 r->in.key_name, SPOOL_OID_KEY);
8711 if (!str) {
8712 result = WERR_NOMEM;
8713 goto done;
8717 * I'm not checking the status here on purpose. Don't know
8718 * if this is right, but I'm returning the status from the
8719 * previous set_printer_dataex() call. I have no idea if
8720 * this is right. --jerry
8722 winreg_set_printer_dataex(p->mem_ctx,
8723 p->server_info,
8724 pinfo2->sharename,
8725 str,
8726 r->in.value_name,
8727 REG_SZ,
8728 (uint8_t *) oid_string,
8729 strlen(oid_string) + 1);
8732 result = winreg_printer_update_changeid(p->mem_ctx,
8733 p->server_info,
8734 lp_const_servicename(snum));
8738 done:
8739 talloc_free(pinfo2);
8740 return result;
8743 /****************************************************************
8744 _spoolss_DeletePrinterDataEx
8745 ****************************************************************/
8747 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8748 struct spoolss_DeletePrinterDataEx *r)
8750 const char *printer;
8751 int snum=0;
8752 WERROR status = WERR_OK;
8753 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8755 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8757 if (!Printer) {
8758 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8759 "Invalid handle (%s:%u:%u).\n",
8760 OUR_HANDLE(r->in.handle)));
8761 return WERR_BADFID;
8764 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8765 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8766 "printer properties change denied by handle\n"));
8767 return WERR_ACCESS_DENIED;
8770 if (!r->in.value_name || !r->in.key_name) {
8771 return WERR_NOMEM;
8774 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8775 return WERR_BADFID;
8777 printer = lp_const_servicename(snum);
8779 status = winreg_delete_printer_dataex(p->mem_ctx,
8780 p->server_info,
8781 printer,
8782 r->in.key_name,
8783 r->in.value_name);
8784 if (W_ERROR_IS_OK(status)) {
8785 status = winreg_printer_update_changeid(p->mem_ctx,
8786 p->server_info,
8787 printer);
8790 return status;
8793 /****************************************************************
8794 _spoolss_EnumPrinterKey
8795 ****************************************************************/
8797 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8798 struct spoolss_EnumPrinterKey *r)
8800 uint32_t num_keys;
8801 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8802 int snum = 0;
8803 WERROR result = WERR_BADFILE;
8804 const char **array = NULL;
8805 DATA_BLOB blob;
8807 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8809 if (!Printer) {
8810 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8811 OUR_HANDLE(r->in.handle)));
8812 return WERR_BADFID;
8815 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8816 return WERR_BADFID;
8819 result = winreg_enum_printer_key(p->mem_ctx,
8820 p->server_info,
8821 lp_const_servicename(snum),
8822 r->in.key_name,
8823 &num_keys,
8824 &array);
8825 if (!W_ERROR_IS_OK(result)) {
8826 goto done;
8829 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8830 result = WERR_NOMEM;
8831 goto done;
8834 *r->out._ndr_size = r->in.offered / 2;
8835 *r->out.needed = blob.length;
8837 if (r->in.offered < *r->out.needed) {
8838 result = WERR_MORE_DATA;
8839 } else {
8840 result = WERR_OK;
8841 r->out.key_buffer->string_array = array;
8844 done:
8845 if (!W_ERROR_IS_OK(result)) {
8846 TALLOC_FREE(array);
8847 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8848 *r->out.needed = 0;
8852 return result;
8855 /****************************************************************
8856 _spoolss_DeletePrinterKey
8857 ****************************************************************/
8859 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8860 struct spoolss_DeletePrinterKey *r)
8862 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8863 int snum=0;
8864 WERROR status;
8865 const char *printer;
8867 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8869 if (!Printer) {
8870 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8871 OUR_HANDLE(r->in.handle)));
8872 return WERR_BADFID;
8875 /* if keyname == NULL, return error */
8876 if ( !r->in.key_name )
8877 return WERR_INVALID_PARAM;
8879 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8880 return WERR_BADFID;
8883 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8884 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8885 "printer properties change denied by handle\n"));
8886 return WERR_ACCESS_DENIED;
8889 printer = lp_const_servicename(snum);
8891 /* delete the key and all subkeys */
8892 status = winreg_delete_printer_key(p->mem_ctx,
8893 p->server_info,
8894 printer,
8895 r->in.key_name);
8896 if (W_ERROR_IS_OK(status)) {
8897 status = winreg_printer_update_changeid(p->mem_ctx,
8898 p->server_info,
8899 printer);
8902 return status;
8905 /****************************************************************
8906 _spoolss_EnumPrinterDataEx
8907 ****************************************************************/
8909 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8910 struct spoolss_EnumPrinterDataEx *r)
8912 uint32_t count = 0;
8913 struct spoolss_PrinterEnumValues *info = NULL;
8914 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8915 int snum;
8916 WERROR result;
8918 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8920 *r->out.count = 0;
8921 *r->out.needed = 0;
8922 *r->out.info = NULL;
8924 if (!Printer) {
8925 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8926 OUR_HANDLE(r->in.handle)));
8927 return WERR_BADFID;
8931 * first check for a keyname of NULL or "". Win2k seems to send
8932 * this a lot and we should send back WERR_INVALID_PARAM
8933 * no need to spend time looking up the printer in this case.
8934 * --jerry
8937 if (!strlen(r->in.key_name)) {
8938 result = WERR_INVALID_PARAM;
8939 goto done;
8942 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8943 return WERR_BADFID;
8946 /* now look for a match on the key name */
8947 result = winreg_enum_printer_dataex(p->mem_ctx,
8948 p->server_info,
8949 lp_const_servicename(snum),
8950 r->in.key_name,
8951 &count,
8952 &info);
8953 if (!W_ERROR_IS_OK(result)) {
8954 goto done;
8957 #if 0 /* FIXME - gd */
8958 /* housekeeping information in the reply */
8960 /* Fix from Martin Zielinski <mz@seh.de> - ensure
8961 * the hand marshalled container size is a multiple
8962 * of 4 bytes for RPC alignment.
8965 if (needed % 4) {
8966 needed += 4-(needed % 4);
8968 #endif
8969 *r->out.count = count;
8970 *r->out.info = info;
8972 done:
8973 if (!W_ERROR_IS_OK(result)) {
8974 return result;
8977 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8978 spoolss_EnumPrinterDataEx,
8979 *r->out.info,
8980 *r->out.count);
8981 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8982 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8984 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8987 /****************************************************************************
8988 ****************************************************************************/
8990 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8991 const char *servername,
8992 const char *environment,
8993 struct spoolss_PrintProcessorDirectoryInfo1 *r)
8995 WERROR werr;
8996 char *path = NULL;
8998 werr = compose_spoolss_server_path(mem_ctx,
8999 servername,
9000 environment,
9001 SPOOLSS_PRTPROCS_PATH,
9002 &path);
9003 if (!W_ERROR_IS_OK(werr)) {
9004 return werr;
9007 DEBUG(4,("print processor directory: [%s]\n", path));
9009 r->directory_name = path;
9011 return WERR_OK;
9014 /****************************************************************
9015 _spoolss_GetPrintProcessorDirectory
9016 ****************************************************************/
9018 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9019 struct spoolss_GetPrintProcessorDirectory *r)
9021 WERROR result;
9023 /* that's an [in out] buffer */
9025 if (!r->in.buffer && (r->in.offered != 0)) {
9026 return WERR_INVALID_PARAM;
9029 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9030 r->in.level));
9032 *r->out.needed = 0;
9034 /* r->in.level is ignored */
9036 /* We always should reply with a local print processor directory so that
9037 * users are not forced to have a [prnproc$] share on the Samba spoolss
9038 * server - Guenther */
9040 result = getprintprocessordirectory_level_1(p->mem_ctx,
9041 NULL, /* r->in.server */
9042 r->in.environment,
9043 &r->out.info->info1);
9044 if (!W_ERROR_IS_OK(result)) {
9045 TALLOC_FREE(r->out.info);
9046 return result;
9049 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9050 r->out.info, r->in.level);
9051 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9053 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9056 /*******************************************************************
9057 ********************************************************************/
9059 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9060 const char *dllname)
9062 enum ndr_err_code ndr_err;
9063 struct spoolss_MonitorUi ui;
9065 ui.dll_name = dllname;
9067 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9068 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9069 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9070 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9072 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9075 /*******************************************************************
9076 Streams the monitor UI DLL name in UNICODE
9077 *******************************************************************/
9079 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9080 NT_USER_TOKEN *token, DATA_BLOB *in,
9081 DATA_BLOB *out, uint32_t *needed)
9083 const char *dllname = "tcpmonui.dll";
9085 *needed = (strlen(dllname)+1) * 2;
9087 if (out->length < *needed) {
9088 return WERR_INSUFFICIENT_BUFFER;
9091 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9092 return WERR_NOMEM;
9095 return WERR_OK;
9098 /*******************************************************************
9099 ********************************************************************/
9101 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9102 struct spoolss_PortData1 *port1,
9103 const DATA_BLOB *buf)
9105 enum ndr_err_code ndr_err;
9106 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9107 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9108 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9109 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9111 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9114 /*******************************************************************
9115 ********************************************************************/
9117 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9118 struct spoolss_PortData2 *port2,
9119 const DATA_BLOB *buf)
9121 enum ndr_err_code ndr_err;
9122 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9123 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9124 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9125 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9127 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9130 /*******************************************************************
9131 Create a new TCP/IP port
9132 *******************************************************************/
9134 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9135 NT_USER_TOKEN *token, DATA_BLOB *in,
9136 DATA_BLOB *out, uint32_t *needed)
9138 struct spoolss_PortData1 port1;
9139 struct spoolss_PortData2 port2;
9140 char *device_uri = NULL;
9141 uint32_t version;
9143 const char *portname;
9144 const char *hostaddress;
9145 const char *queue;
9146 uint32_t port_number;
9147 uint32_t protocol;
9149 /* peek for spoolss_PortData version */
9151 if (!in || (in->length < (128 + 4))) {
9152 return WERR_GENERAL_FAILURE;
9155 version = IVAL(in->data, 128);
9157 switch (version) {
9158 case 1:
9159 ZERO_STRUCT(port1);
9161 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9162 return WERR_NOMEM;
9165 portname = port1.portname;
9166 hostaddress = port1.hostaddress;
9167 queue = port1.queue;
9168 protocol = port1.protocol;
9169 port_number = port1.port_number;
9171 break;
9172 case 2:
9173 ZERO_STRUCT(port2);
9175 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9176 return WERR_NOMEM;
9179 portname = port2.portname;
9180 hostaddress = port2.hostaddress;
9181 queue = port2.queue;
9182 protocol = port2.protocol;
9183 port_number = port2.port_number;
9185 break;
9186 default:
9187 DEBUG(1,("xcvtcp_addport: "
9188 "unknown version of port_data: %d\n", version));
9189 return WERR_UNKNOWN_PORT;
9192 /* create the device URI and call the add_port_hook() */
9194 switch (protocol) {
9195 case PROTOCOL_RAWTCP_TYPE:
9196 device_uri = talloc_asprintf(mem_ctx,
9197 "socket://%s:%d/", hostaddress,
9198 port_number);
9199 break;
9201 case PROTOCOL_LPR_TYPE:
9202 device_uri = talloc_asprintf(mem_ctx,
9203 "lpr://%s/%s", hostaddress, queue );
9204 break;
9206 default:
9207 return WERR_UNKNOWN_PORT;
9210 if (!device_uri) {
9211 return WERR_NOMEM;
9214 return add_port_hook(mem_ctx, token, portname, device_uri);
9217 /*******************************************************************
9218 *******************************************************************/
9220 struct xcv_api_table xcvtcp_cmds[] = {
9221 { "MonitorUI", xcvtcp_monitorui },
9222 { "AddPort", xcvtcp_addport},
9223 { NULL, NULL }
9226 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9227 NT_USER_TOKEN *token, const char *command,
9228 DATA_BLOB *inbuf,
9229 DATA_BLOB *outbuf,
9230 uint32_t *needed )
9232 int i;
9234 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9236 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9237 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9238 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9241 return WERR_BADFUNC;
9244 /*******************************************************************
9245 *******************************************************************/
9246 #if 0 /* don't support management using the "Local Port" monitor */
9248 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9249 NT_USER_TOKEN *token, DATA_BLOB *in,
9250 DATA_BLOB *out, uint32_t *needed)
9252 const char *dllname = "localui.dll";
9254 *needed = (strlen(dllname)+1) * 2;
9256 if (out->length < *needed) {
9257 return WERR_INSUFFICIENT_BUFFER;
9260 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9261 return WERR_NOMEM;
9264 return WERR_OK;
9267 /*******************************************************************
9268 *******************************************************************/
9270 struct xcv_api_table xcvlocal_cmds[] = {
9271 { "MonitorUI", xcvlocal_monitorui },
9272 { NULL, NULL }
9274 #else
9275 struct xcv_api_table xcvlocal_cmds[] = {
9276 { NULL, NULL }
9278 #endif
9282 /*******************************************************************
9283 *******************************************************************/
9285 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9286 NT_USER_TOKEN *token, const char *command,
9287 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9288 uint32_t *needed)
9290 int i;
9292 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9294 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9295 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9296 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9298 return WERR_BADFUNC;
9301 /****************************************************************
9302 _spoolss_XcvData
9303 ****************************************************************/
9305 WERROR _spoolss_XcvData(pipes_struct *p,
9306 struct spoolss_XcvData *r)
9308 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9309 DATA_BLOB out_data = data_blob_null;
9310 WERROR werror;
9312 if (!Printer) {
9313 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9314 OUR_HANDLE(r->in.handle)));
9315 return WERR_BADFID;
9318 /* Has to be a handle to the TCP/IP port monitor */
9320 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9321 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9322 return WERR_BADFID;
9325 /* requires administrative access to the server */
9327 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9328 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9329 return WERR_ACCESS_DENIED;
9332 /* Allocate the outgoing buffer */
9334 if (r->in.out_data_size) {
9335 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9336 if (out_data.data == NULL) {
9337 return WERR_NOMEM;
9341 switch ( Printer->printer_type ) {
9342 case SPLHND_PORTMON_TCP:
9343 werror = process_xcvtcp_command(p->mem_ctx,
9344 p->server_info->ptok,
9345 r->in.function_name,
9346 &r->in.in_data, &out_data,
9347 r->out.needed);
9348 break;
9349 case SPLHND_PORTMON_LOCAL:
9350 werror = process_xcvlocal_command(p->mem_ctx,
9351 p->server_info->ptok,
9352 r->in.function_name,
9353 &r->in.in_data, &out_data,
9354 r->out.needed);
9355 break;
9356 default:
9357 werror = WERR_INVALID_PRINT_MONITOR;
9360 if (!W_ERROR_IS_OK(werror)) {
9361 return werror;
9364 *r->out.status_code = 0;
9366 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9367 memcpy(r->out.out_data, out_data.data,
9368 MIN(r->in.out_data_size, out_data.length));
9371 return WERR_OK;
9374 /****************************************************************
9375 _spoolss_AddPrintProcessor
9376 ****************************************************************/
9378 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9379 struct spoolss_AddPrintProcessor *r)
9381 /* for now, just indicate success and ignore the add. We'll
9382 automatically set the winprint processor for printer
9383 entries later. Used to debug the LexMark Optra S 1855 PCL
9384 driver --jerry */
9386 return WERR_OK;
9389 /****************************************************************
9390 _spoolss_AddPort
9391 ****************************************************************/
9393 WERROR _spoolss_AddPort(pipes_struct *p,
9394 struct spoolss_AddPort *r)
9396 /* do what w2k3 does */
9398 return WERR_NOT_SUPPORTED;
9401 /****************************************************************
9402 _spoolss_GetPrinterDriver
9403 ****************************************************************/
9405 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9406 struct spoolss_GetPrinterDriver *r)
9408 p->rng_fault_state = true;
9409 return WERR_NOT_SUPPORTED;
9412 /****************************************************************
9413 _spoolss_ReadPrinter
9414 ****************************************************************/
9416 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9417 struct spoolss_ReadPrinter *r)
9419 p->rng_fault_state = true;
9420 return WERR_NOT_SUPPORTED;
9423 /****************************************************************
9424 _spoolss_WaitForPrinterChange
9425 ****************************************************************/
9427 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9428 struct spoolss_WaitForPrinterChange *r)
9430 p->rng_fault_state = true;
9431 return WERR_NOT_SUPPORTED;
9434 /****************************************************************
9435 _spoolss_ConfigurePort
9436 ****************************************************************/
9438 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9439 struct spoolss_ConfigurePort *r)
9441 p->rng_fault_state = true;
9442 return WERR_NOT_SUPPORTED;
9445 /****************************************************************
9446 _spoolss_DeletePort
9447 ****************************************************************/
9449 WERROR _spoolss_DeletePort(pipes_struct *p,
9450 struct spoolss_DeletePort *r)
9452 p->rng_fault_state = true;
9453 return WERR_NOT_SUPPORTED;
9456 /****************************************************************
9457 _spoolss_CreatePrinterIC
9458 ****************************************************************/
9460 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9461 struct spoolss_CreatePrinterIC *r)
9463 p->rng_fault_state = true;
9464 return WERR_NOT_SUPPORTED;
9467 /****************************************************************
9468 _spoolss_PlayGDIScriptOnPrinterIC
9469 ****************************************************************/
9471 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9472 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9474 p->rng_fault_state = true;
9475 return WERR_NOT_SUPPORTED;
9478 /****************************************************************
9479 _spoolss_DeletePrinterIC
9480 ****************************************************************/
9482 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9483 struct spoolss_DeletePrinterIC *r)
9485 p->rng_fault_state = true;
9486 return WERR_NOT_SUPPORTED;
9489 /****************************************************************
9490 _spoolss_AddPrinterConnection
9491 ****************************************************************/
9493 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9494 struct spoolss_AddPrinterConnection *r)
9496 p->rng_fault_state = true;
9497 return WERR_NOT_SUPPORTED;
9500 /****************************************************************
9501 _spoolss_DeletePrinterConnection
9502 ****************************************************************/
9504 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9505 struct spoolss_DeletePrinterConnection *r)
9507 p->rng_fault_state = true;
9508 return WERR_NOT_SUPPORTED;
9511 /****************************************************************
9512 _spoolss_PrinterMessageBox
9513 ****************************************************************/
9515 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9516 struct spoolss_PrinterMessageBox *r)
9518 p->rng_fault_state = true;
9519 return WERR_NOT_SUPPORTED;
9522 /****************************************************************
9523 _spoolss_AddMonitor
9524 ****************************************************************/
9526 WERROR _spoolss_AddMonitor(pipes_struct *p,
9527 struct spoolss_AddMonitor *r)
9529 p->rng_fault_state = true;
9530 return WERR_NOT_SUPPORTED;
9533 /****************************************************************
9534 _spoolss_DeleteMonitor
9535 ****************************************************************/
9537 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9538 struct spoolss_DeleteMonitor *r)
9540 p->rng_fault_state = true;
9541 return WERR_NOT_SUPPORTED;
9544 /****************************************************************
9545 _spoolss_DeletePrintProcessor
9546 ****************************************************************/
9548 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9549 struct spoolss_DeletePrintProcessor *r)
9551 p->rng_fault_state = true;
9552 return WERR_NOT_SUPPORTED;
9555 /****************************************************************
9556 _spoolss_AddPrintProvidor
9557 ****************************************************************/
9559 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9560 struct spoolss_AddPrintProvidor *r)
9562 p->rng_fault_state = true;
9563 return WERR_NOT_SUPPORTED;
9566 /****************************************************************
9567 _spoolss_DeletePrintProvidor
9568 ****************************************************************/
9570 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9571 struct spoolss_DeletePrintProvidor *r)
9573 p->rng_fault_state = true;
9574 return WERR_NOT_SUPPORTED;
9577 /****************************************************************
9578 _spoolss_FindFirstPrinterChangeNotification
9579 ****************************************************************/
9581 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9582 struct spoolss_FindFirstPrinterChangeNotification *r)
9584 p->rng_fault_state = true;
9585 return WERR_NOT_SUPPORTED;
9588 /****************************************************************
9589 _spoolss_FindNextPrinterChangeNotification
9590 ****************************************************************/
9592 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9593 struct spoolss_FindNextPrinterChangeNotification *r)
9595 p->rng_fault_state = true;
9596 return WERR_NOT_SUPPORTED;
9599 /****************************************************************
9600 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9601 ****************************************************************/
9603 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9604 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9606 p->rng_fault_state = true;
9607 return WERR_NOT_SUPPORTED;
9610 /****************************************************************
9611 _spoolss_ReplyOpenPrinter
9612 ****************************************************************/
9614 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9615 struct spoolss_ReplyOpenPrinter *r)
9617 p->rng_fault_state = true;
9618 return WERR_NOT_SUPPORTED;
9621 /****************************************************************
9622 _spoolss_RouterReplyPrinter
9623 ****************************************************************/
9625 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9626 struct spoolss_RouterReplyPrinter *r)
9628 p->rng_fault_state = true;
9629 return WERR_NOT_SUPPORTED;
9632 /****************************************************************
9633 _spoolss_ReplyClosePrinter
9634 ****************************************************************/
9636 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9637 struct spoolss_ReplyClosePrinter *r)
9639 p->rng_fault_state = true;
9640 return WERR_NOT_SUPPORTED;
9643 /****************************************************************
9644 _spoolss_AddPortEx
9645 ****************************************************************/
9647 WERROR _spoolss_AddPortEx(pipes_struct *p,
9648 struct spoolss_AddPortEx *r)
9650 p->rng_fault_state = true;
9651 return WERR_NOT_SUPPORTED;
9654 /****************************************************************
9655 _spoolss_RouterFindFirstPrinterChangeNotification
9656 ****************************************************************/
9658 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9659 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9661 p->rng_fault_state = true;
9662 return WERR_NOT_SUPPORTED;
9665 /****************************************************************
9666 _spoolss_SpoolerInit
9667 ****************************************************************/
9669 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9670 struct spoolss_SpoolerInit *r)
9672 p->rng_fault_state = true;
9673 return WERR_NOT_SUPPORTED;
9676 /****************************************************************
9677 _spoolss_ResetPrinterEx
9678 ****************************************************************/
9680 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9681 struct spoolss_ResetPrinterEx *r)
9683 p->rng_fault_state = true;
9684 return WERR_NOT_SUPPORTED;
9687 /****************************************************************
9688 _spoolss_RouterReplyPrinterEx
9689 ****************************************************************/
9691 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9692 struct spoolss_RouterReplyPrinterEx *r)
9694 p->rng_fault_state = true;
9695 return WERR_NOT_SUPPORTED;
9698 /****************************************************************
9699 _spoolss_44
9700 ****************************************************************/
9702 WERROR _spoolss_44(pipes_struct *p,
9703 struct spoolss_44 *r)
9705 p->rng_fault_state = true;
9706 return WERR_NOT_SUPPORTED;
9709 /****************************************************************
9710 _spoolss_47
9711 ****************************************************************/
9713 WERROR _spoolss_47(pipes_struct *p,
9714 struct spoolss_47 *r)
9716 p->rng_fault_state = true;
9717 return WERR_NOT_SUPPORTED;
9720 /****************************************************************
9721 _spoolss_4a
9722 ****************************************************************/
9724 WERROR _spoolss_4a(pipes_struct *p,
9725 struct spoolss_4a *r)
9727 p->rng_fault_state = true;
9728 return WERR_NOT_SUPPORTED;
9731 /****************************************************************
9732 _spoolss_4b
9733 ****************************************************************/
9735 WERROR _spoolss_4b(pipes_struct *p,
9736 struct spoolss_4b *r)
9738 p->rng_fault_state = true;
9739 return WERR_NOT_SUPPORTED;
9742 /****************************************************************
9743 _spoolss_4c
9744 ****************************************************************/
9746 WERROR _spoolss_4c(pipes_struct *p,
9747 struct spoolss_4c *r)
9749 p->rng_fault_state = true;
9750 return WERR_NOT_SUPPORTED;
9753 /****************************************************************
9754 _spoolss_53
9755 ****************************************************************/
9757 WERROR _spoolss_53(pipes_struct *p,
9758 struct spoolss_53 *r)
9760 p->rng_fault_state = true;
9761 return WERR_NOT_SUPPORTED;
9764 /****************************************************************
9765 _spoolss_55
9766 ****************************************************************/
9768 WERROR _spoolss_55(pipes_struct *p,
9769 struct spoolss_55 *r)
9771 p->rng_fault_state = true;
9772 return WERR_NOT_SUPPORTED;
9775 /****************************************************************
9776 _spoolss_56
9777 ****************************************************************/
9779 WERROR _spoolss_56(pipes_struct *p,
9780 struct spoolss_56 *r)
9782 p->rng_fault_state = true;
9783 return WERR_NOT_SUPPORTED;
9786 /****************************************************************
9787 _spoolss_57
9788 ****************************************************************/
9790 WERROR _spoolss_57(pipes_struct *p,
9791 struct spoolss_57 *r)
9793 p->rng_fault_state = true;
9794 return WERR_NOT_SUPPORTED;
9797 /****************************************************************
9798 _spoolss_5a
9799 ****************************************************************/
9801 WERROR _spoolss_5a(pipes_struct *p,
9802 struct spoolss_5a *r)
9804 p->rng_fault_state = true;
9805 return WERR_NOT_SUPPORTED;
9808 /****************************************************************
9809 _spoolss_5b
9810 ****************************************************************/
9812 WERROR _spoolss_5b(pipes_struct *p,
9813 struct spoolss_5b *r)
9815 p->rng_fault_state = true;
9816 return WERR_NOT_SUPPORTED;
9819 /****************************************************************
9820 _spoolss_5c
9821 ****************************************************************/
9823 WERROR _spoolss_5c(pipes_struct *p,
9824 struct spoolss_5c *r)
9826 p->rng_fault_state = true;
9827 return WERR_NOT_SUPPORTED;
9830 /****************************************************************
9831 _spoolss_5d
9832 ****************************************************************/
9834 WERROR _spoolss_5d(pipes_struct *p,
9835 struct spoolss_5d *r)
9837 p->rng_fault_state = true;
9838 return WERR_NOT_SUPPORTED;
9841 /****************************************************************
9842 _spoolss_5e
9843 ****************************************************************/
9845 WERROR _spoolss_5e(pipes_struct *p,
9846 struct spoolss_5e *r)
9848 p->rng_fault_state = true;
9849 return WERR_NOT_SUPPORTED;
9852 /****************************************************************
9853 _spoolss_5f
9854 ****************************************************************/
9856 WERROR _spoolss_5f(pipes_struct *p,
9857 struct spoolss_5f *r)
9859 p->rng_fault_state = true;
9860 return WERR_NOT_SUPPORTED;
9863 /****************************************************************
9864 _spoolss_60
9865 ****************************************************************/
9867 WERROR _spoolss_60(pipes_struct *p,
9868 struct spoolss_60 *r)
9870 p->rng_fault_state = true;
9871 return WERR_NOT_SUPPORTED;
9874 /****************************************************************
9875 _spoolss_61
9876 ****************************************************************/
9878 WERROR _spoolss_61(pipes_struct *p,
9879 struct spoolss_61 *r)
9881 p->rng_fault_state = true;
9882 return WERR_NOT_SUPPORTED;
9885 /****************************************************************
9886 _spoolss_62
9887 ****************************************************************/
9889 WERROR _spoolss_62(pipes_struct *p,
9890 struct spoolss_62 *r)
9892 p->rng_fault_state = true;
9893 return WERR_NOT_SUPPORTED;
9896 /****************************************************************
9897 _spoolss_63
9898 ****************************************************************/
9900 WERROR _spoolss_63(pipes_struct *p,
9901 struct spoolss_63 *r)
9903 p->rng_fault_state = true;
9904 return WERR_NOT_SUPPORTED;
9907 /****************************************************************
9908 _spoolss_64
9909 ****************************************************************/
9911 WERROR _spoolss_64(pipes_struct *p,
9912 struct spoolss_64 *r)
9914 p->rng_fault_state = true;
9915 return WERR_NOT_SUPPORTED;
9918 /****************************************************************
9919 _spoolss_65
9920 ****************************************************************/
9922 WERROR _spoolss_65(pipes_struct *p,
9923 struct spoolss_65 *r)
9925 p->rng_fault_state = true;
9926 return WERR_NOT_SUPPORTED;
9929 /****************************************************************
9930 _spoolss_GetCorePrinterDrivers
9931 ****************************************************************/
9933 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9934 struct spoolss_GetCorePrinterDrivers *r)
9936 p->rng_fault_state = true;
9937 return WERR_NOT_SUPPORTED;
9940 /****************************************************************
9941 _spoolss_67
9942 ****************************************************************/
9944 WERROR _spoolss_67(pipes_struct *p,
9945 struct spoolss_67 *r)
9947 p->rng_fault_state = true;
9948 return WERR_NOT_SUPPORTED;
9951 /****************************************************************
9952 _spoolss_GetPrinterDriverPackagePath
9953 ****************************************************************/
9955 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9956 struct spoolss_GetPrinterDriverPackagePath *r)
9958 p->rng_fault_state = true;
9959 return WERR_NOT_SUPPORTED;
9962 /****************************************************************
9963 _spoolss_69
9964 ****************************************************************/
9966 WERROR _spoolss_69(pipes_struct *p,
9967 struct spoolss_69 *r)
9969 p->rng_fault_state = true;
9970 return WERR_NOT_SUPPORTED;
9973 /****************************************************************
9974 _spoolss_6a
9975 ****************************************************************/
9977 WERROR _spoolss_6a(pipes_struct *p,
9978 struct spoolss_6a *r)
9980 p->rng_fault_state = true;
9981 return WERR_NOT_SUPPORTED;
9984 /****************************************************************
9985 _spoolss_6b
9986 ****************************************************************/
9988 WERROR _spoolss_6b(pipes_struct *p,
9989 struct spoolss_6b *r)
9991 p->rng_fault_state = true;
9992 return WERR_NOT_SUPPORTED;
9995 /****************************************************************
9996 _spoolss_6c
9997 ****************************************************************/
9999 WERROR _spoolss_6c(pipes_struct *p,
10000 struct spoolss_6c *r)
10002 p->rng_fault_state = true;
10003 return WERR_NOT_SUPPORTED;
10006 /****************************************************************
10007 _spoolss_6d
10008 ****************************************************************/
10010 WERROR _spoolss_6d(pipes_struct *p,
10011 struct spoolss_6d *r)
10013 p->rng_fault_state = true;
10014 return WERR_NOT_SUPPORTED;