s3-spoolss: Rename Printer_entry to struct printer_handle.
[Samba/vl.git] / source3 / rpc_server / srv_spoolss_nt.c
blob307b1997a55fb0f3612920069d179e5b2b9d66d6
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 "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.h"
37 #include "librpc/gen_ndr/ndr_security.h"
38 #include "registry.h"
39 #include "registry/reg_objects.h"
40 #include "include/printing.h"
41 #include "secrets.h"
42 #include "../librpc/gen_ndr/netlogon.h"
43 #include "rpc_misc.h"
45 /* macros stolen from s4 spoolss server */
46 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
47 ((info)?ndr_size_##fn(info, level, 0):0)
49 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
50 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
52 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
53 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
55 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
57 #undef DBGC_CLASS
58 #define DBGC_CLASS DBGC_RPC_SRV
60 #ifndef MAX_OPEN_PRINTER_EXS
61 #define MAX_OPEN_PRINTER_EXS 50
62 #endif
64 /* structure to store the printer handles */
65 /* and a reference to what it's pointing to */
66 /* and the notify info asked about */
67 /* that's the central struct */
68 struct printer_handle {
69 struct printer_handle *prev, *next;
70 bool document_started;
71 bool page_started;
72 uint32 jobid; /* jobid in printing backend */
73 int printer_type;
74 fstring servername;
75 fstring sharename;
76 uint32 type;
77 uint32 access_granted;
78 struct {
79 uint32 flags;
80 uint32 options;
81 fstring localmachine;
82 uint32 printerlocal;
83 struct spoolss_NotifyOption *option;
84 struct policy_handle client_hnd;
85 bool client_connected;
86 uint32 change;
87 /* are we in a FindNextPrinterChangeNotify() call? */
88 bool fnpcn;
89 struct messaging_context *msg_ctx;
90 } notify;
91 struct {
92 fstring machine;
93 fstring user;
94 } client;
96 /* devmode sent in the OpenPrinter() call */
97 struct spoolss_DeviceMode *devmode;
99 /* TODO cache the printer info2 structure */
100 struct spoolss_PrinterInfo2 *info2;
104 static struct printer_handle *printers_list;
106 struct printer_session_counter {
107 struct printer_session_counter *next;
108 struct printer_session_counter *prev;
110 int snum;
111 uint32_t counter;
114 static struct printer_session_counter *counter_list;
116 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
117 static uint32_t smb_connections = 0;
120 /* Map generic permissions to printer object specific permissions */
122 const struct standard_mapping printer_std_mapping = {
123 PRINTER_READ,
124 PRINTER_WRITE,
125 PRINTER_EXECUTE,
126 PRINTER_ALL_ACCESS
129 /* Map generic permissions to print server object specific permissions */
131 const struct standard_mapping printserver_std_mapping = {
132 SERVER_READ,
133 SERVER_WRITE,
134 SERVER_EXECUTE,
135 SERVER_ALL_ACCESS
138 /* API table for Xcv Monitor functions */
140 struct xcv_api_table {
141 const char *name;
142 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
145 static void prune_printername_cache(void);
147 /********************************************************************
148 * Canonicalize servername.
149 ********************************************************************/
151 static const char *canon_servername(const char *servername)
153 const char *pservername = servername;
154 while (*pservername == '\\') {
155 pservername++;
157 return pservername;
160 /* translate between internal status numbers and NT status numbers */
161 static int nt_printj_status(int v)
163 switch (v) {
164 case LPQ_QUEUED:
165 return 0;
166 case LPQ_PAUSED:
167 return JOB_STATUS_PAUSED;
168 case LPQ_SPOOLING:
169 return JOB_STATUS_SPOOLING;
170 case LPQ_PRINTING:
171 return JOB_STATUS_PRINTING;
172 case LPQ_ERROR:
173 return JOB_STATUS_ERROR;
174 case LPQ_DELETING:
175 return JOB_STATUS_DELETING;
176 case LPQ_OFFLINE:
177 return JOB_STATUS_OFFLINE;
178 case LPQ_PAPEROUT:
179 return JOB_STATUS_PAPEROUT;
180 case LPQ_PRINTED:
181 return JOB_STATUS_PRINTED;
182 case LPQ_DELETED:
183 return JOB_STATUS_DELETED;
184 case LPQ_BLOCKED:
185 return JOB_STATUS_BLOCKED_DEVQ;
186 case LPQ_USER_INTERVENTION:
187 return JOB_STATUS_USER_INTERVENTION;
189 return 0;
192 static int nt_printq_status(int v)
194 switch (v) {
195 case LPQ_PAUSED:
196 return PRINTER_STATUS_PAUSED;
197 case LPQ_QUEUED:
198 case LPQ_SPOOLING:
199 case LPQ_PRINTING:
200 return 0;
202 return 0;
205 /***************************************************************************
206 Disconnect from the client
207 ****************************************************************************/
209 static void srv_spoolss_replycloseprinter(
210 int snum, struct policy_handle *handle,
211 struct messaging_context *msg_ctx)
213 WERROR result;
214 NTSTATUS status;
217 * Tell the specific printing tdb we no longer want messages for this printer
218 * by deregistering our PID.
221 if (!print_notify_deregister_pid(snum))
222 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
224 /* weird if the test succeeds !!! */
225 if (smb_connections==0) {
226 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
227 return;
230 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
231 handle,
232 &result);
233 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
234 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
235 win_errstr(result)));
237 /* if it's the last connection, deconnect the IPC$ share */
238 if (smb_connections==1) {
240 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
242 * The above call shuts down the pipe also.
244 notify_cli_pipe = NULL;
246 if (msg_ctx != NULL) {
247 messaging_deregister(msg_ctx, MSG_PRINTER_NOTIFY2,
248 NULL);
251 * Tell the serverid.tdb we're no longer
252 * interested in printer notify messages.
255 serverid_register_msg_flags(
256 messaging_server_id(msg_ctx),
257 false, FLAG_MSG_PRINT_NOTIFY);
261 smb_connections--;
264 /****************************************************************************
265 Functions to free a printer entry datastruct.
266 ****************************************************************************/
268 static int printer_entry_destructor(struct printer_handle *Printer)
270 if (Printer->notify.client_connected == true) {
271 int snum = -1;
273 if ( Printer->printer_type == SPLHND_SERVER) {
274 snum = -1;
275 srv_spoolss_replycloseprinter(
276 snum, &Printer->notify.client_hnd,
277 Printer->notify.msg_ctx);
278 } else if (Printer->printer_type == SPLHND_PRINTER) {
279 snum = print_queue_snum(Printer->sharename);
280 if (snum != -1)
281 srv_spoolss_replycloseprinter(
282 snum, &Printer->notify.client_hnd,
283 Printer->notify.msg_ctx);
287 Printer->notify.flags=0;
288 Printer->notify.options=0;
289 Printer->notify.localmachine[0]='\0';
290 Printer->notify.printerlocal=0;
291 TALLOC_FREE(Printer->notify.option);
292 Printer->notify.client_connected = false;
294 TALLOC_FREE(Printer->devmode);
296 /* Remove from the internal list. */
297 DLIST_REMOVE(printers_list, Printer);
298 return 0;
301 /****************************************************************************
302 find printer index by handle
303 ****************************************************************************/
305 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
306 struct policy_handle *hnd)
308 struct printer_handle *find_printer = NULL;
310 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
311 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
312 return NULL;
315 return find_printer;
318 /****************************************************************************
319 Close printer index by handle.
320 ****************************************************************************/
322 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
324 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
326 if (!Printer) {
327 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
328 OUR_HANDLE(hnd)));
329 return false;
332 close_policy_hnd(p, hnd);
334 return true;
337 /****************************************************************************
338 Delete a printer given a handle.
339 ****************************************************************************/
341 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
342 const char *sharename,
343 struct messaging_context *msg_ctx)
345 char *cmd = lp_deleteprinter_cmd();
346 char *command = NULL;
347 int ret;
348 SE_PRIV se_printop = SE_PRINT_OPERATOR;
349 bool is_print_op = false;
351 /* can't fail if we don't try */
353 if ( !*cmd )
354 return WERR_OK;
356 command = talloc_asprintf(ctx,
357 "%s \"%s\"",
358 cmd, sharename);
359 if (!command) {
360 return WERR_NOMEM;
362 if ( token )
363 is_print_op = user_has_privileges( token, &se_printop );
365 DEBUG(10,("Running [%s]\n", command));
367 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
369 if ( is_print_op )
370 become_root();
372 if ( (ret = smbrun(command, NULL)) == 0 ) {
373 /* Tell everyone we updated smb.conf. */
374 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
377 if ( is_print_op )
378 unbecome_root();
380 /********** END SePrintOperatorPrivlege BLOCK **********/
382 DEBUGADD(10,("returned [%d]\n", ret));
384 TALLOC_FREE(command);
386 if (ret != 0)
387 return WERR_BADFID; /* What to return here? */
389 /* go ahead and re-read the services immediately */
390 become_root();
391 reload_services(msg_ctx, -1, false);
392 unbecome_root();
394 if ( lp_servicenumber( sharename ) > 0 )
395 return WERR_ACCESS_DENIED;
397 return WERR_OK;
400 /****************************************************************************
401 Delete a printer given a handle.
402 ****************************************************************************/
404 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
406 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
407 WERROR result;
409 if (!Printer) {
410 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
411 OUR_HANDLE(hnd)));
412 return WERR_BADFID;
416 * It turns out that Windows allows delete printer on a handle
417 * opened by an admin user, then used on a pipe handle created
418 * by an anonymous user..... but they're working on security.... riiight !
419 * JRA.
422 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
423 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
424 return WERR_ACCESS_DENIED;
427 /* this does not need a become root since the access check has been
428 done on the handle already */
430 result = winreg_delete_printer_key(p->mem_ctx,
431 get_server_info_system(),
432 p->msg_ctx,
433 Printer->sharename,
434 "");
435 if (!W_ERROR_IS_OK(result)) {
436 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
437 return WERR_BADFID;
440 result = delete_printer_hook(p->mem_ctx, p->server_info->ptok,
441 Printer->sharename, p->msg_ctx);
442 if (!W_ERROR_IS_OK(result)) {
443 return result;
445 prune_printername_cache();
446 return WERR_OK;
449 /****************************************************************************
450 Return the snum of a printer corresponding to an handle.
451 ****************************************************************************/
453 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
454 int *number, struct share_params **params)
456 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
458 if (!Printer) {
459 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
460 OUR_HANDLE(hnd)));
461 return false;
464 switch (Printer->printer_type) {
465 case SPLHND_PRINTER:
466 DEBUG(4,("short name:%s\n", Printer->sharename));
467 *number = print_queue_snum(Printer->sharename);
468 return (*number != -1);
469 case SPLHND_SERVER:
470 return false;
471 default:
472 return false;
476 /****************************************************************************
477 Set printer handle type.
478 Check if it's \\server or \\server\printer
479 ****************************************************************************/
481 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
483 DEBUG(3,("Setting printer type=%s\n", handlename));
485 /* it's a print server */
486 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
487 DEBUGADD(4,("Printer is a print server\n"));
488 Printer->printer_type = SPLHND_SERVER;
490 /* it's a printer (set_printer_hnd_name() will handle port monitors */
491 else {
492 DEBUGADD(4,("Printer is a printer\n"));
493 Printer->printer_type = SPLHND_PRINTER;
496 return true;
499 static void prune_printername_cache_fn(const char *key, const char *value,
500 time_t timeout, void *private_data)
502 gencache_del(key);
505 static void prune_printername_cache(void)
507 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
510 /****************************************************************************
511 Set printer handle name.. Accept names like \\server, \\server\printer,
512 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
513 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
514 XcvDataPort() interface.
515 ****************************************************************************/
517 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
518 const struct auth_serversupplied_info *server_info,
519 struct messaging_context *msg_ctx,
520 struct printer_handle *Printer,
521 const char *handlename)
523 int snum;
524 int n_services=lp_numservices();
525 char *aprinter;
526 const char *printername;
527 const char *servername = NULL;
528 fstring sname;
529 bool found = false;
530 struct spoolss_PrinterInfo2 *info2 = NULL;
531 WERROR result;
534 * Hopefully nobody names his printers like this. Maybe \ or ,
535 * are illegal in printer names even?
537 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
538 char *cache_key;
539 char *tmp;
541 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
542 (unsigned long)strlen(handlename)));
544 aprinter = CONST_DISCARD(char *, handlename);
545 if ( *handlename == '\\' ) {
546 servername = canon_servername(handlename);
547 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
548 *aprinter = '\0';
549 aprinter++;
551 if (!is_myname_or_ipaddr(servername)) {
552 return false;
555 fstrcpy(Printer->servername, servername);
558 if (Printer->printer_type == SPLHND_SERVER) {
559 return true;
562 if (Printer->printer_type != SPLHND_PRINTER) {
563 return false;
566 DEBUGADD(5, ("searching for [%s]\n", aprinter));
568 /* check for the Port Monitor Interface */
569 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
570 Printer->printer_type = SPLHND_PORTMON_TCP;
571 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
572 found = true;
574 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
575 Printer->printer_type = SPLHND_PORTMON_LOCAL;
576 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
577 found = true;
581 * With hundreds of printers, the "for" loop iterating all
582 * shares can be quite expensive, as it is done on every
583 * OpenPrinter. The loop maps "aprinter" to "sname", the
584 * result of which we cache in gencache.
587 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
588 aprinter);
589 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
591 found = (strcmp(tmp, printer_not_found) != 0);
592 if (!found) {
593 DEBUG(4, ("Printer %s not found\n", aprinter));
594 SAFE_FREE(tmp);
595 return false;
597 fstrcpy(sname, tmp);
598 SAFE_FREE(tmp);
601 /* Search all sharenames first as this is easier than pulling
602 the printer_info_2 off of disk. Don't use find_service() since
603 that calls out to map_username() */
605 /* do another loop to look for printernames */
606 for (snum = 0; !found && snum < n_services; snum++) {
607 const char *printer = lp_const_servicename(snum);
609 /* no point going on if this is not a printer */
610 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
611 continue;
614 /* ignore [printers] share */
615 if (strequal(printer, "printers")) {
616 continue;
619 fstrcpy(sname, printer);
620 if (strequal(aprinter, printer)) {
621 found = true;
622 break;
625 /* no point looking up the printer object if
626 we aren't allowing printername != sharename */
627 if (lp_force_printername(snum)) {
628 continue;
631 result = winreg_get_printer(mem_ctx,
632 server_info,
633 msg_ctx,
634 servername,
635 sname,
636 &info2);
637 if ( !W_ERROR_IS_OK(result) ) {
638 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
639 sname, win_errstr(result)));
640 continue;
643 printername = strrchr(info2->printername, '\\');
644 if (printername == NULL) {
645 printername = info2->printername;
646 } else {
647 printername++;
650 if (strequal(printername, aprinter)) {
651 found = true;
652 break;
655 DEBUGADD(10, ("printername: %s\n", printername));
657 TALLOC_FREE(info2);
660 if ( !found ) {
661 if (cache_key != NULL) {
662 gencache_set(cache_key, printer_not_found,
663 time(NULL)+300);
664 TALLOC_FREE(cache_key);
666 DEBUGADD(4,("Printer not found\n"));
667 return false;
670 if (cache_key != NULL) {
671 gencache_set(cache_key, sname, time(NULL)+300);
672 TALLOC_FREE(cache_key);
675 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
677 fstrcpy(Printer->sharename, sname);
679 return true;
682 /****************************************************************************
683 Find first available printer slot. creates a printer handle for you.
684 ****************************************************************************/
686 static bool open_printer_hnd(struct pipes_struct *p, struct policy_handle *hnd,
687 const char *name, uint32_t access_granted)
689 struct printer_handle *new_printer;
691 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
693 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
694 if (new_printer == NULL) {
695 return false;
697 talloc_set_destructor(new_printer, printer_entry_destructor);
699 /* This also steals the printer_handle on the policy_handle */
700 if (!create_policy_hnd(p, hnd, new_printer)) {
701 TALLOC_FREE(new_printer);
702 return false;
705 /* Add to the internal list. */
706 DLIST_ADD(printers_list, new_printer);
708 new_printer->notify.option=NULL;
710 if (!set_printer_hnd_printertype(new_printer, name)) {
711 close_printer_handle(p, hnd);
712 return false;
715 if (!set_printer_hnd_name(p->mem_ctx,
716 get_server_info_system(),
717 p->msg_ctx,
718 new_printer, name)) {
719 close_printer_handle(p, hnd);
720 return false;
723 new_printer->access_granted = access_granted;
725 DEBUG(5, ("%d printer handles active\n",
726 (int)num_pipe_handles(p)));
728 return true;
731 /***************************************************************************
732 check to see if the client motify handle is monitoring the notification
733 given by (notify_type, notify_field).
734 **************************************************************************/
736 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
737 uint16_t notify_field)
739 return true;
742 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
743 uint16_t notify_field)
745 struct spoolss_NotifyOption *option = p->notify.option;
746 uint32_t i, j;
749 * Flags should always be zero when the change notify
750 * is registered by the client's spooler. A user Win32 app
751 * might use the flags though instead of the NOTIFY_OPTION_INFO
752 * --jerry
755 if (!option) {
756 return false;
759 if (p->notify.flags)
760 return is_monitoring_event_flags(
761 p->notify.flags, notify_type, notify_field);
763 for (i = 0; i < option->count; i++) {
765 /* Check match for notify_type */
767 if (option->types[i].type != notify_type)
768 continue;
770 /* Check match for field */
772 for (j = 0; j < option->types[i].count; j++) {
773 if (option->types[i].fields[j].field == notify_field) {
774 return true;
779 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
780 p->servername, p->sharename, notify_type, notify_field));
782 return false;
785 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
786 _data->data.integer[0] = _integer; \
787 _data->data.integer[1] = 0;
790 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
791 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
792 if (!_data->data.string.string) {\
793 _data->data.string.size = 0; \
795 _data->data.string.size = strlen_m_term(_p) * 2;
797 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
798 _data->data.devmode.devmode = _devmode;
800 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
801 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
802 if (!_data->data.sd.sd) { \
803 _data->data.sd.sd_size = 0; \
805 _data->data.sd.sd_size = \
806 ndr_size_security_descriptor(_data->data.sd.sd, 0);
808 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
809 struct tm *t,
810 const char **pp,
811 uint32_t *plen)
813 struct spoolss_Time st;
814 uint32_t len = 16;
815 char *p;
817 if (!init_systemtime(&st, t)) {
818 return;
821 p = talloc_array(mem_ctx, char, len);
822 if (!p) {
823 return;
827 * Systemtime must be linearized as a set of UINT16's.
828 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
831 SSVAL(p, 0, st.year);
832 SSVAL(p, 2, st.month);
833 SSVAL(p, 4, st.day_of_week);
834 SSVAL(p, 6, st.day);
835 SSVAL(p, 8, st.hour);
836 SSVAL(p, 10, st.minute);
837 SSVAL(p, 12, st.second);
838 SSVAL(p, 14, st.millisecond);
840 *pp = p;
841 *plen = len;
844 /* Convert a notification message to a struct spoolss_Notify */
846 static void notify_one_value(struct spoolss_notify_msg *msg,
847 struct spoolss_Notify *data,
848 TALLOC_CTX *mem_ctx)
850 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
853 static void notify_string(struct spoolss_notify_msg *msg,
854 struct spoolss_Notify *data,
855 TALLOC_CTX *mem_ctx)
857 /* The length of the message includes the trailing \0 */
859 data->data.string.size = msg->len * 2;
860 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
861 if (!data->data.string.string) {
862 data->data.string.size = 0;
863 return;
867 static void notify_system_time(struct spoolss_notify_msg *msg,
868 struct spoolss_Notify *data,
869 TALLOC_CTX *mem_ctx)
871 data->data.string.string = NULL;
872 data->data.string.size = 0;
874 if (msg->len != sizeof(time_t)) {
875 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
876 msg->len));
877 return;
880 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
881 &data->data.string.string,
882 &data->data.string.size);
885 struct notify2_message_table {
886 const char *name;
887 void (*fn)(struct spoolss_notify_msg *msg,
888 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
891 static struct notify2_message_table printer_notify_table[] = {
892 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
893 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
894 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
895 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
896 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
897 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
898 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
899 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
900 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
901 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
902 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
903 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
904 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
905 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
906 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
907 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
908 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
909 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
910 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
913 static struct notify2_message_table job_notify_table[] = {
914 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
915 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
916 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
917 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
918 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
919 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
920 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
921 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
922 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
923 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
924 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
925 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
926 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
927 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
928 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
929 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
930 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
931 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
932 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
933 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
934 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
935 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
936 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
937 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
941 /***********************************************************************
942 Allocate talloc context for container object
943 **********************************************************************/
945 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
947 if ( !ctr )
948 return;
950 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
952 return;
955 /***********************************************************************
956 release all allocated memory and zero out structure
957 **********************************************************************/
959 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
961 if ( !ctr )
962 return;
964 if ( ctr->ctx )
965 talloc_destroy(ctr->ctx);
967 ZERO_STRUCTP(ctr);
969 return;
972 /***********************************************************************
973 **********************************************************************/
975 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
977 if ( !ctr )
978 return NULL;
980 return ctr->ctx;
983 /***********************************************************************
984 **********************************************************************/
986 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
988 if ( !ctr || !ctr->msg_groups )
989 return NULL;
991 if ( idx >= ctr->num_groups )
992 return NULL;
994 return &ctr->msg_groups[idx];
998 /***********************************************************************
999 How many groups of change messages do we have ?
1000 **********************************************************************/
1002 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1004 if ( !ctr )
1005 return 0;
1007 return ctr->num_groups;
1010 /***********************************************************************
1011 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1012 **********************************************************************/
1014 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1016 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1017 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1018 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1019 int i, new_slot;
1021 if ( !ctr || !msg )
1022 return 0;
1024 /* loop over all groups looking for a matching printer name */
1026 for ( i=0; i<ctr->num_groups; i++ ) {
1027 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1028 break;
1031 /* add a new group? */
1033 if ( i == ctr->num_groups ) {
1034 ctr->num_groups++;
1036 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1037 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1038 return 0;
1040 ctr->msg_groups = groups;
1042 /* clear the new entry and set the printer name */
1044 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1045 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1048 /* add the change messages; 'i' is the correct index now regardless */
1050 msg_grp = &ctr->msg_groups[i];
1052 msg_grp->num_msgs++;
1054 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1055 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1056 return 0;
1058 msg_grp->msgs = msg_list;
1060 new_slot = msg_grp->num_msgs-1;
1061 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1063 /* need to allocate own copy of data */
1065 if ( msg->len != 0 )
1066 msg_grp->msgs[new_slot].notify.data = (char *)
1067 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1069 return ctr->num_groups;
1072 static void construct_info_data(struct spoolss_Notify *info_data,
1073 enum spoolss_NotifyType type,
1074 uint16_t field, int id);
1076 /***********************************************************************
1077 Send a change notication message on all handles which have a call
1078 back registered
1079 **********************************************************************/
1081 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1083 struct printer_handle *p;
1084 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1085 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1086 SPOOLSS_NOTIFY_MSG *messages;
1087 int sending_msg_count;
1089 if ( !msg_group ) {
1090 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1091 return;
1094 messages = msg_group->msgs;
1096 if ( !messages ) {
1097 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
1098 return;
1101 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1103 /* loop over all printers */
1105 for (p = printers_list; p; p = p->next) {
1106 struct spoolss_Notify *notifies;
1107 uint32_t count = 0;
1108 uint32_t id;
1109 int i;
1111 /* Is there notification on this handle? */
1113 if ( !p->notify.client_connected )
1114 continue;
1116 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1118 /* For this printer? Print servers always receive
1119 notifications. */
1121 if ( ( p->printer_type == SPLHND_PRINTER ) &&
1122 ( !strequal(msg_group->printername, p->sharename) ) )
1123 continue;
1125 DEBUG(10,("Our printer\n"));
1127 /* allocate the max entries possible */
1129 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1130 if (!notifies) {
1131 return;
1134 /* build the array of change notifications */
1136 sending_msg_count = 0;
1138 for ( i=0; i<msg_group->num_msgs; i++ ) {
1139 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1141 /* Are we monitoring this event? */
1143 if (!is_monitoring_event(p, msg->type, msg->field))
1144 continue;
1146 sending_msg_count++;
1149 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1150 msg->type, msg->field, p->sharename));
1153 * if the is a printer notification handle and not a job notification
1154 * type, then set the id to 0. Other wise just use what was specified
1155 * in the message.
1157 * When registering change notification on a print server handle
1158 * we always need to send back the id (snum) matching the printer
1159 * for which the change took place. For change notify registered
1160 * on a printer handle, this does not matter and the id should be 0.
1162 * --jerry
1165 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1166 id = 0;
1167 else
1168 id = msg->id;
1171 /* Convert unix jobid to smb jobid */
1173 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1174 id = sysjob_to_jobid(msg->id);
1176 if (id == -1) {
1177 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1178 goto done;
1182 construct_info_data(&notifies[count],
1183 (enum spoolss_NotifyType) msg->type,
1184 msg->field,
1185 id);
1187 switch(msg->type) {
1188 case PRINTER_NOTIFY_TYPE:
1189 if ( printer_notify_table[msg->field].fn )
1190 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1191 break;
1193 case JOB_NOTIFY_TYPE:
1194 if ( job_notify_table[msg->field].fn )
1195 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1196 break;
1198 default:
1199 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1200 goto done;
1203 count++;
1206 if ( sending_msg_count ) {
1207 NTSTATUS status;
1208 WERROR werr;
1209 union spoolss_ReplyPrinterInfo info;
1210 struct spoolss_NotifyInfo info0;
1211 uint32_t reply_result;
1213 info0.version = 0x2;
1214 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1215 info0.count = count;
1216 info0.notifies = notifies;
1218 info.info0 = &info0;
1220 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1221 &p->notify.client_hnd,
1222 p->notify.change, /* color */
1223 p->notify.flags,
1224 &reply_result,
1225 0, /* reply_type, must be 0 */
1226 info,
1227 &werr);
1228 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1229 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1230 notify_cli_pipe->srv_name_slash,
1231 win_errstr(werr)));
1233 switch (reply_result) {
1234 case 0:
1235 break;
1236 case PRINTER_NOTIFY_INFO_DISCARDED:
1237 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1238 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1239 break;
1240 default:
1241 break;
1246 done:
1247 DEBUG(8,("send_notify2_changes: Exit...\n"));
1248 return;
1251 /***********************************************************************
1252 **********************************************************************/
1254 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1257 uint32_t tv_sec, tv_usec;
1258 size_t offset = 0;
1260 /* Unpack message */
1262 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1263 msg->printer);
1265 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1266 &tv_sec, &tv_usec,
1267 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1269 if (msg->len == 0)
1270 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1271 &msg->notify.value[0], &msg->notify.value[1]);
1272 else
1273 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1274 &msg->len, &msg->notify.data);
1276 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1277 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1279 tv->tv_sec = tv_sec;
1280 tv->tv_usec = tv_usec;
1282 if (msg->len == 0)
1283 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1284 msg->notify.value[1]));
1285 else
1286 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1288 return true;
1291 /********************************************************************
1292 Receive a notify2 message list
1293 ********************************************************************/
1295 static void receive_notify2_message_list(struct messaging_context *msg,
1296 void *private_data,
1297 uint32_t msg_type,
1298 struct server_id server_id,
1299 DATA_BLOB *data)
1301 size_t msg_count, i;
1302 char *buf = (char *)data->data;
1303 char *msg_ptr;
1304 size_t msg_len;
1305 SPOOLSS_NOTIFY_MSG notify;
1306 SPOOLSS_NOTIFY_MSG_CTR messages;
1307 int num_groups;
1309 if (data->length < 4) {
1310 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1311 return;
1314 msg_count = IVAL(buf, 0);
1315 msg_ptr = buf + 4;
1317 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1319 if (msg_count == 0) {
1320 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1321 return;
1324 /* initialize the container */
1326 ZERO_STRUCT( messages );
1327 notify_msg_ctr_init( &messages );
1330 * build message groups for each printer identified
1331 * in a change_notify msg. Remember that a PCN message
1332 * includes the handle returned for the srv_spoolss_replyopenprinter()
1333 * call. Therefore messages are grouped according to printer handle.
1336 for ( i=0; i<msg_count; i++ ) {
1337 struct timeval msg_tv;
1339 if (msg_ptr + 4 - buf > data->length) {
1340 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1341 return;
1344 msg_len = IVAL(msg_ptr,0);
1345 msg_ptr += 4;
1347 if (msg_ptr + msg_len - buf > data->length) {
1348 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1349 return;
1352 /* unpack messages */
1354 ZERO_STRUCT( notify );
1355 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1356 msg_ptr += msg_len;
1358 /* add to correct list in container */
1360 notify_msg_ctr_addmsg( &messages, &notify );
1362 /* free memory that might have been allocated by notify2_unpack_msg() */
1364 if ( notify.len != 0 )
1365 SAFE_FREE( notify.notify.data );
1368 /* process each group of messages */
1370 num_groups = notify_msg_ctr_numgroups( &messages );
1371 for ( i=0; i<num_groups; i++ )
1372 send_notify2_changes( &messages, i );
1375 /* cleanup */
1377 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1378 (uint32_t)msg_count ));
1380 notify_msg_ctr_destroy( &messages );
1382 return;
1385 /********************************************************************
1386 Send a message to ourself about new driver being installed
1387 so we can upgrade the information for each printer bound to this
1388 driver
1389 ********************************************************************/
1391 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1392 struct messaging_context *msg_ctx)
1394 int len = strlen(drivername);
1396 if (!len)
1397 return false;
1399 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1400 drivername));
1402 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1403 MSG_PRINTER_DRVUPGRADE,
1404 (uint8_t *)drivername, len+1);
1406 return true;
1409 /**********************************************************************
1410 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1411 over all printers, upgrading ones as necessary
1412 **********************************************************************/
1414 void do_drv_upgrade_printer(struct messaging_context *msg,
1415 void *private_data,
1416 uint32_t msg_type,
1417 struct server_id server_id,
1418 DATA_BLOB *data)
1420 TALLOC_CTX *tmp_ctx;
1421 struct auth_serversupplied_info *server_info = NULL;
1422 struct spoolss_PrinterInfo2 *pinfo2;
1423 NTSTATUS status;
1424 WERROR result;
1425 const char *drivername;
1426 int snum;
1427 int n_services = lp_numservices();
1428 size_t len;
1430 tmp_ctx = talloc_new(NULL);
1431 if (!tmp_ctx) return;
1433 status = make_server_info_system(tmp_ctx, &server_info);
1434 if (!NT_STATUS_IS_OK(status)) {
1435 DEBUG(0, ("do_drv_upgrade_printer: "
1436 "Could not create system server_info\n"));
1437 goto done;
1440 len = MIN(data->length,sizeof(drivername)-1);
1441 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1442 if (!drivername) {
1443 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1444 goto done;
1447 DEBUG(10, ("do_drv_upgrade_printer: "
1448 "Got message for new driver [%s]\n", drivername));
1450 /* Iterate the printer list */
1452 for (snum = 0; snum < n_services; snum++) {
1453 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1454 continue;
1457 result = winreg_get_printer(tmp_ctx, server_info, msg,
1458 NULL,
1459 lp_const_servicename(snum),
1460 &pinfo2);
1462 if (!W_ERROR_IS_OK(result)) {
1463 continue;
1466 if (!pinfo2->drivername) {
1467 continue;
1470 if (strcmp(drivername, pinfo2->drivername) != 0) {
1471 continue;
1474 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1476 /* all we care about currently is the change_id */
1477 result = winreg_printer_update_changeid(tmp_ctx,
1478 server_info,
1479 msg,
1480 pinfo2->printername);
1482 if (!W_ERROR_IS_OK(result)) {
1483 DEBUG(3, ("do_drv_upgrade_printer: "
1484 "Failed to update changeid [%s]\n",
1485 win_errstr(result)));
1489 /* all done */
1490 done:
1491 talloc_free(tmp_ctx);
1494 /********************************************************************
1495 Update the cache for all printq's with a registered client
1496 connection
1497 ********************************************************************/
1499 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1501 struct printer_handle *printer = printers_list;
1502 int snum;
1504 /* loop through all printers and update the cache where
1505 client_connected == true */
1506 while ( printer )
1508 if ( (printer->printer_type == SPLHND_PRINTER)
1509 && printer->notify.client_connected )
1511 snum = print_queue_snum(printer->sharename);
1512 print_queue_status(msg_ctx, snum, NULL, NULL );
1515 printer = printer->next;
1518 return;
1521 /****************************************************************
1522 _spoolss_OpenPrinter
1523 ****************************************************************/
1525 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1526 struct spoolss_OpenPrinter *r)
1528 struct spoolss_OpenPrinterEx e;
1529 WERROR werr;
1531 ZERO_STRUCT(e.in.userlevel);
1533 e.in.printername = r->in.printername;
1534 e.in.datatype = r->in.datatype;
1535 e.in.devmode_ctr = r->in.devmode_ctr;
1536 e.in.access_mask = r->in.access_mask;
1537 e.in.level = 0;
1539 e.out.handle = r->out.handle;
1541 werr = _spoolss_OpenPrinterEx(p, &e);
1543 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1544 /* OpenPrinterEx returns this for a bad
1545 * printer name. We must return WERR_INVALID_PRINTER_NAME
1546 * instead.
1548 werr = WERR_INVALID_PRINTER_NAME;
1551 return werr;
1554 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1555 struct spoolss_DeviceMode *orig,
1556 struct spoolss_DeviceMode **dest)
1558 struct spoolss_DeviceMode *dm;
1560 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1561 if (!dm) {
1562 return WERR_NOMEM;
1565 /* copy all values, then duplicate strings and structs */
1566 *dm = *orig;
1568 dm->devicename = talloc_strdup(dm, orig->devicename);
1569 if (!dm->devicename) {
1570 return WERR_NOMEM;
1572 dm->formname = talloc_strdup(dm, orig->formname);
1573 if (!dm->formname) {
1574 return WERR_NOMEM;
1576 if (orig->driverextra_data.data) {
1577 dm->driverextra_data.data =
1578 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1579 orig->driverextra_data.length);
1580 if (!dm->driverextra_data.data) {
1581 return WERR_NOMEM;
1585 *dest = dm;
1586 return WERR_OK;
1589 /****************************************************************
1590 _spoolss_OpenPrinterEx
1591 ****************************************************************/
1593 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1594 struct spoolss_OpenPrinterEx *r)
1596 int snum;
1597 struct printer_handle *Printer=NULL;
1599 if (!r->in.printername) {
1600 return WERR_INVALID_PARAM;
1603 /* some sanity check because you can open a printer or a print server */
1604 /* aka: \\server\printer or \\server */
1606 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1608 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1609 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1610 "for printer %s\n", r->in.printername));
1611 ZERO_STRUCTP(r->out.handle);
1612 return WERR_INVALID_PARAM;
1615 Printer = find_printer_index_by_hnd(p, r->out.handle);
1616 if ( !Printer ) {
1617 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1618 "handle we created for printer %s\n", r->in.printername));
1619 close_printer_handle(p, r->out.handle);
1620 ZERO_STRUCTP(r->out.handle);
1621 return WERR_INVALID_PARAM;
1625 * First case: the user is opening the print server:
1627 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1628 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1630 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1631 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1632 * or if the user is listed in the smb.conf printer admin parameter.
1634 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1635 * client view printer folder, but does not show the MSAPW.
1637 * Note: this test needs code to check access rights here too. Jeremy
1638 * could you look at this?
1640 * Second case: the user is opening a printer:
1641 * NT doesn't let us connect to a printer if the connecting user
1642 * doesn't have print permission.
1644 * Third case: user is opening a Port Monitor
1645 * access checks same as opening a handle to the print server.
1648 switch (Printer->printer_type )
1650 case SPLHND_SERVER:
1651 case SPLHND_PORTMON_TCP:
1652 case SPLHND_PORTMON_LOCAL:
1653 /* Printserver handles use global struct... */
1655 snum = -1;
1657 /* Map standard access rights to object specific access rights */
1659 se_map_standard(&r->in.access_mask,
1660 &printserver_std_mapping);
1662 /* Deny any object specific bits that don't apply to print
1663 servers (i.e printer and job specific bits) */
1665 r->in.access_mask &= SEC_MASK_SPECIFIC;
1667 if (r->in.access_mask &
1668 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1669 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1670 close_printer_handle(p, r->out.handle);
1671 ZERO_STRUCTP(r->out.handle);
1672 return WERR_ACCESS_DENIED;
1675 /* Allow admin access */
1677 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1679 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1681 if (!lp_ms_add_printer_wizard()) {
1682 close_printer_handle(p, r->out.handle);
1683 ZERO_STRUCTP(r->out.handle);
1684 return WERR_ACCESS_DENIED;
1687 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1688 and not a printer admin, then fail */
1690 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1691 !user_has_privileges(p->server_info->ptok,
1692 &se_printop ) &&
1693 !token_contains_name_in_list(
1694 uidtoname(p->server_info->utok.uid),
1695 p->server_info->info3->base.domain.string,
1696 NULL,
1697 p->server_info->ptok,
1698 lp_printer_admin(snum))) {
1699 close_printer_handle(p, r->out.handle);
1700 ZERO_STRUCTP(r->out.handle);
1701 return WERR_ACCESS_DENIED;
1704 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1706 else
1708 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1711 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1712 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1714 /* We fall through to return WERR_OK */
1715 break;
1717 case SPLHND_PRINTER:
1718 /* NT doesn't let us connect to a printer if the connecting user
1719 doesn't have print permission. */
1721 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1722 close_printer_handle(p, r->out.handle);
1723 ZERO_STRUCTP(r->out.handle);
1724 return WERR_BADFID;
1727 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1728 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1731 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1733 /* map an empty access mask to the minimum access mask */
1734 if (r->in.access_mask == 0x0)
1735 r->in.access_mask = PRINTER_ACCESS_USE;
1738 * If we are not serving the printer driver for this printer,
1739 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1740 * will keep NT clients happy --jerry
1743 if (lp_use_client_driver(snum)
1744 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1746 r->in.access_mask = PRINTER_ACCESS_USE;
1749 /* check smb.conf parameters and the the sec_desc */
1751 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1752 p->client_id->name, p->client_id->addr)) {
1753 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1754 ZERO_STRUCTP(r->out.handle);
1755 return WERR_ACCESS_DENIED;
1758 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1759 p->server_info->ptok, snum) ||
1760 !print_access_check(get_server_info_system(),
1761 p->msg_ctx,
1762 snum,
1763 r->in.access_mask)) {
1764 DEBUG(3, ("access DENIED for printer open\n"));
1765 close_printer_handle(p, r->out.handle);
1766 ZERO_STRUCTP(r->out.handle);
1767 return WERR_ACCESS_DENIED;
1770 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1771 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1772 close_printer_handle(p, r->out.handle);
1773 ZERO_STRUCTP(r->out.handle);
1774 return WERR_ACCESS_DENIED;
1777 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1778 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1779 else
1780 r->in.access_mask = PRINTER_ACCESS_USE;
1782 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1783 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1785 winreg_create_printer(p->mem_ctx,
1786 get_server_info_system(),
1787 p->msg_ctx,
1788 Printer->servername,
1789 lp_const_servicename(snum));
1791 break;
1793 default:
1794 /* sanity check to prevent programmer error */
1795 ZERO_STRUCTP(r->out.handle);
1796 return WERR_BADFID;
1799 Printer->access_granted = r->in.access_mask;
1802 * If the client sent a devmode in the OpenPrinter() call, then
1803 * save it here in case we get a job submission on this handle
1806 if ((Printer->printer_type != SPLHND_SERVER) &&
1807 r->in.devmode_ctr.devmode) {
1808 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1809 &Printer->devmode);
1812 #if 0 /* JERRY -- I'm doubtful this is really effective */
1813 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1814 optimization in Windows 2000 clients --jerry */
1816 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1817 && (RA_WIN2K == get_remote_arch()) )
1819 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1820 sys_usleep( 500000 );
1822 #endif
1824 return WERR_OK;
1827 /****************************************************************
1828 _spoolss_ClosePrinter
1829 ****************************************************************/
1831 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1832 struct spoolss_ClosePrinter *r)
1834 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1836 if (Printer && Printer->document_started) {
1837 struct spoolss_EndDocPrinter e;
1839 e.in.handle = r->in.handle;
1841 _spoolss_EndDocPrinter(p, &e);
1844 if (!close_printer_handle(p, r->in.handle))
1845 return WERR_BADFID;
1847 /* clear the returned printer handle. Observed behavior
1848 from Win2k server. Don't think this really matters.
1849 Previous code just copied the value of the closed
1850 handle. --jerry */
1852 ZERO_STRUCTP(r->out.handle);
1854 return WERR_OK;
1857 /****************************************************************
1858 _spoolss_DeletePrinter
1859 ****************************************************************/
1861 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1862 struct spoolss_DeletePrinter *r)
1864 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1865 WERROR result;
1866 int snum;
1868 if (Printer && Printer->document_started) {
1869 struct spoolss_EndDocPrinter e;
1871 e.in.handle = r->in.handle;
1873 _spoolss_EndDocPrinter(p, &e);
1876 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1877 winreg_delete_printer_key(p->mem_ctx,
1878 get_server_info_system(),
1879 p->msg_ctx,
1880 lp_const_servicename(snum),
1881 "");
1884 result = delete_printer_handle(p, r->in.handle);
1886 return result;
1889 /*******************************************************************
1890 * static function to lookup the version id corresponding to an
1891 * long architecture string
1892 ******************************************************************/
1894 static const struct print_architecture_table_node archi_table[]= {
1896 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1897 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1898 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1899 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1900 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1901 {"Windows IA64", SPL_ARCH_IA64, 3 },
1902 {"Windows x64", SPL_ARCH_X64, 3 },
1903 {NULL, "", -1 }
1906 static int get_version_id(const char *arch)
1908 int i;
1910 for (i=0; archi_table[i].long_archi != NULL; i++)
1912 if (strcmp(arch, archi_table[i].long_archi) == 0)
1913 return (archi_table[i].version);
1916 return -1;
1919 /****************************************************************
1920 _spoolss_DeletePrinterDriver
1921 ****************************************************************/
1923 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
1924 struct spoolss_DeletePrinterDriver *r)
1927 struct spoolss_DriverInfo8 *info = NULL;
1928 struct spoolss_DriverInfo8 *info_win2k = NULL;
1929 int version;
1930 WERROR status;
1931 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1933 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1934 and not a printer admin, then fail */
1936 if ( (p->server_info->utok.uid != sec_initial_uid())
1937 && !user_has_privileges(p->server_info->ptok, &se_printop )
1938 && !token_contains_name_in_list(
1939 uidtoname(p->server_info->utok.uid),
1940 p->server_info->info3->base.domain.string,
1941 NULL,
1942 p->server_info->ptok,
1943 lp_printer_admin(-1)) )
1945 return WERR_ACCESS_DENIED;
1948 /* check that we have a valid driver name first */
1950 if ((version = get_version_id(r->in.architecture)) == -1)
1951 return WERR_INVALID_ENVIRONMENT;
1953 status = winreg_get_driver(p->mem_ctx,
1954 get_server_info_system(),
1955 p->msg_ctx,
1956 r->in.architecture, r->in.driver,
1957 version, &info);
1958 if (!W_ERROR_IS_OK(status)) {
1959 /* try for Win2k driver if "Windows NT x86" */
1961 if ( version == 2 ) {
1962 version = 3;
1964 status = winreg_get_driver(p->mem_ctx,
1965 get_server_info_system(),
1966 p->msg_ctx,
1967 r->in.architecture,
1968 r->in.driver,
1969 version, &info);
1970 if (!W_ERROR_IS_OK(status)) {
1971 status = WERR_UNKNOWN_PRINTER_DRIVER;
1972 goto done;
1975 /* otherwise it was a failure */
1976 else {
1977 status = WERR_UNKNOWN_PRINTER_DRIVER;
1978 goto done;
1983 if (printer_driver_in_use(p->mem_ctx,
1984 get_server_info_system(),
1985 p->msg_ctx,
1986 info)) {
1987 status = WERR_PRINTER_DRIVER_IN_USE;
1988 goto done;
1991 if (version == 2) {
1992 status = winreg_get_driver(p->mem_ctx,
1993 get_server_info_system(),
1994 p->msg_ctx,
1995 r->in.architecture,
1996 r->in.driver, 3, &info_win2k);
1997 if (W_ERROR_IS_OK(status)) {
1998 /* if we get to here, we now have 2 driver info structures to remove */
1999 /* remove the Win2k driver first*/
2001 status = winreg_del_driver(p->mem_ctx,
2002 get_server_info_system(),
2003 p->msg_ctx,
2004 info_win2k, 3);
2005 talloc_free(info_win2k);
2007 /* this should not have failed---if it did, report to client */
2008 if (!W_ERROR_IS_OK(status)) {
2009 goto done;
2014 status = winreg_del_driver(p->mem_ctx,
2015 get_server_info_system(),
2016 p->msg_ctx,
2017 info, version);
2019 done:
2020 talloc_free(info);
2022 return status;
2025 /****************************************************************
2026 _spoolss_DeletePrinterDriverEx
2027 ****************************************************************/
2029 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2030 struct spoolss_DeletePrinterDriverEx *r)
2032 struct spoolss_DriverInfo8 *info = NULL;
2033 struct spoolss_DriverInfo8 *info_win2k = NULL;
2034 int version;
2035 bool delete_files;
2036 WERROR status;
2037 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2039 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2040 and not a printer admin, then fail */
2042 if ( (p->server_info->utok.uid != sec_initial_uid())
2043 && !user_has_privileges(p->server_info->ptok, &se_printop )
2044 && !token_contains_name_in_list(
2045 uidtoname(p->server_info->utok.uid),
2046 p->server_info->info3->base.domain.string,
2047 NULL,
2048 p->server_info->ptok, lp_printer_admin(-1)) )
2050 return WERR_ACCESS_DENIED;
2053 /* check that we have a valid driver name first */
2054 if ((version = get_version_id(r->in.architecture)) == -1) {
2055 /* this is what NT returns */
2056 return WERR_INVALID_ENVIRONMENT;
2059 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2060 version = r->in.version;
2062 status = winreg_get_driver(p->mem_ctx,
2063 get_server_info_system(),
2064 p->msg_ctx,
2065 r->in.architecture,
2066 r->in.driver,
2067 version,
2068 &info);
2069 if (!W_ERROR_IS_OK(status)) {
2070 status = WERR_UNKNOWN_PRINTER_DRIVER;
2073 * if the client asked for a specific version,
2074 * or this is something other than Windows NT x86,
2075 * then we've failed
2078 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2079 goto done;
2081 /* try for Win2k driver if "Windows NT x86" */
2083 version = 3;
2084 status = winreg_get_driver(info,
2085 get_server_info_system(),
2086 p->msg_ctx,
2087 r->in.architecture,
2088 r->in.driver,
2089 version, &info);
2090 if (!W_ERROR_IS_OK(status)) {
2091 status = WERR_UNKNOWN_PRINTER_DRIVER;
2092 goto done;
2096 if (printer_driver_in_use(info,
2097 get_server_info_system(),
2098 p->msg_ctx,
2099 info)) {
2100 status = WERR_PRINTER_DRIVER_IN_USE;
2101 goto done;
2105 * we have a couple of cases to consider.
2106 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2107 * then the delete should fail if **any** files overlap with
2108 * other drivers
2109 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2110 * non-overlapping files
2111 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2112 * is set, the do not delete any files
2113 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2116 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2118 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2120 if (delete_files &&
2121 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2122 printer_driver_files_in_use(info,
2123 get_server_info_system(),
2124 p->msg_ctx,
2125 info)) {
2126 /* no idea of the correct error here */
2127 status = WERR_ACCESS_DENIED;
2128 goto done;
2132 /* also check for W32X86/3 if necessary; maybe we already have? */
2134 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2135 status = winreg_get_driver(info,
2136 get_server_info_system(),
2137 p->msg_ctx,
2138 r->in.architecture,
2139 r->in.driver, 3, &info_win2k);
2140 if (W_ERROR_IS_OK(status)) {
2142 if (delete_files &&
2143 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2144 printer_driver_files_in_use(info,
2145 get_server_info_system(),
2146 p->msg_ctx,
2147 info_win2k)) {
2148 /* no idea of the correct error here */
2149 talloc_free(info_win2k);
2150 status = WERR_ACCESS_DENIED;
2151 goto done;
2154 /* if we get to here, we now have 2 driver info structures to remove */
2155 /* remove the Win2k driver first*/
2157 status = winreg_del_driver(info,
2158 get_server_info_system(),
2159 p->msg_ctx,
2160 info_win2k,
2163 /* this should not have failed---if it did, report to client */
2165 if (!W_ERROR_IS_OK(status)) {
2166 goto done;
2170 * now delete any associated files if delete_files is
2171 * true. Even if this part failes, we return succes
2172 * because the driver doesn not exist any more
2174 if (delete_files) {
2175 delete_driver_files(get_server_info_system(),
2176 info_win2k);
2181 status = winreg_del_driver(info,
2182 get_server_info_system(),
2183 p->msg_ctx,
2184 info,
2185 version);
2186 if (!W_ERROR_IS_OK(status)) {
2187 goto done;
2191 * now delete any associated files if delete_files is
2192 * true. Even if this part failes, we return succes
2193 * because the driver doesn not exist any more
2195 if (delete_files) {
2196 delete_driver_files(get_server_info_system(), info);
2199 done:
2200 talloc_free(info);
2201 return status;
2205 /********************************************************************
2206 GetPrinterData on a printer server Handle.
2207 ********************************************************************/
2209 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2210 const char *value,
2211 enum winreg_Type *type,
2212 union spoolss_PrinterData *data)
2214 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2216 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2217 *type = REG_DWORD;
2218 data->value = 0x00;
2219 return WERR_OK;
2222 if (!StrCaseCmp(value, "BeepEnabled")) {
2223 *type = REG_DWORD;
2224 data->value = 0x00;
2225 return WERR_OK;
2228 if (!StrCaseCmp(value, "EventLog")) {
2229 *type = REG_DWORD;
2230 /* formally was 0x1b */
2231 data->value = 0x00;
2232 return WERR_OK;
2235 if (!StrCaseCmp(value, "NetPopup")) {
2236 *type = REG_DWORD;
2237 data->value = 0x00;
2238 return WERR_OK;
2241 if (!StrCaseCmp(value, "MajorVersion")) {
2242 *type = REG_DWORD;
2244 /* Windows NT 4.0 seems to not allow uploading of drivers
2245 to a server that reports 0x3 as the MajorVersion.
2246 need to investigate more how Win2k gets around this .
2247 -- jerry */
2249 if (RA_WINNT == get_remote_arch()) {
2250 data->value = 0x02;
2251 } else {
2252 data->value = 0x03;
2255 return WERR_OK;
2258 if (!StrCaseCmp(value, "MinorVersion")) {
2259 *type = REG_DWORD;
2260 data->value = 0x00;
2261 return WERR_OK;
2264 /* REG_BINARY
2265 * uint32_t size = 0x114
2266 * uint32_t major = 5
2267 * uint32_t minor = [0|1]
2268 * uint32_t build = [2195|2600]
2269 * extra unicode string = e.g. "Service Pack 3"
2271 if (!StrCaseCmp(value, "OSVersion")) {
2272 DATA_BLOB blob;
2273 enum ndr_err_code ndr_err;
2274 struct spoolss_OSVersion os;
2276 os.major = 5; /* Windows 2000 == 5.0 */
2277 os.minor = 0;
2278 os.build = 2195; /* build */
2279 os.extra_string = ""; /* leave extra string empty */
2281 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2282 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2283 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2284 return WERR_GENERAL_FAILURE;
2287 *type = REG_BINARY;
2288 data->binary = blob;
2290 return WERR_OK;
2294 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2295 *type = REG_SZ;
2297 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2298 W_ERROR_HAVE_NO_MEMORY(data->string);
2300 return WERR_OK;
2303 if (!StrCaseCmp(value, "Architecture")) {
2304 *type = REG_SZ;
2305 data->string = talloc_strdup(mem_ctx,
2306 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2307 W_ERROR_HAVE_NO_MEMORY(data->string);
2309 return WERR_OK;
2312 if (!StrCaseCmp(value, "DsPresent")) {
2313 *type = REG_DWORD;
2315 /* only show the publish check box if we are a
2316 member of a AD domain */
2318 if (lp_security() == SEC_ADS) {
2319 data->value = 0x01;
2320 } else {
2321 data->value = 0x00;
2323 return WERR_OK;
2326 if (!StrCaseCmp(value, "DNSMachineName")) {
2327 const char *hostname = get_mydnsfullname();
2329 if (!hostname) {
2330 return WERR_BADFILE;
2333 *type = REG_SZ;
2334 data->string = talloc_strdup(mem_ctx, hostname);
2335 W_ERROR_HAVE_NO_MEMORY(data->string);
2337 return WERR_OK;
2340 *type = REG_NONE;
2342 return WERR_INVALID_PARAM;
2345 /****************************************************************
2346 _spoolss_GetPrinterData
2347 ****************************************************************/
2349 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2350 struct spoolss_GetPrinterData *r)
2352 struct spoolss_GetPrinterDataEx r2;
2354 r2.in.handle = r->in.handle;
2355 r2.in.key_name = "PrinterDriverData";
2356 r2.in.value_name = r->in.value_name;
2357 r2.in.offered = r->in.offered;
2358 r2.out.type = r->out.type;
2359 r2.out.data = r->out.data;
2360 r2.out.needed = r->out.needed;
2362 return _spoolss_GetPrinterDataEx(p, &r2);
2365 /*********************************************************
2366 Connect to the client machine.
2367 **********************************************************/
2369 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2370 struct sockaddr_storage *client_ss, const char *remote_machine)
2372 NTSTATUS ret;
2373 struct cli_state *the_cli;
2374 struct sockaddr_storage rm_addr;
2375 char addr[INET6_ADDRSTRLEN];
2377 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2378 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2379 remote_machine));
2380 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2381 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2382 return false;
2384 print_sockaddr(addr, sizeof(addr), &rm_addr);
2385 } else {
2386 rm_addr = *client_ss;
2387 print_sockaddr(addr, sizeof(addr), &rm_addr);
2388 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2389 addr));
2392 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2393 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2394 addr));
2395 return false;
2398 /* setup the connection */
2399 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2400 &rm_addr, 0, "IPC$", "IPC",
2401 "", /* username */
2402 "", /* domain */
2403 "", /* password */
2404 0, lp_client_signing(), NULL );
2406 if ( !NT_STATUS_IS_OK( ret ) ) {
2407 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2408 remote_machine ));
2409 return false;
2412 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2413 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2414 cli_shutdown(the_cli);
2415 return false;
2419 * Ok - we have an anonymous connection to the IPC$ share.
2420 * Now start the NT Domain stuff :-).
2423 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2424 if (!NT_STATUS_IS_OK(ret)) {
2425 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2426 remote_machine, nt_errstr(ret)));
2427 cli_shutdown(the_cli);
2428 return false;
2431 return true;
2434 /***************************************************************************
2435 Connect to the client.
2436 ****************************************************************************/
2438 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2439 uint32_t localprinter,
2440 enum winreg_Type type,
2441 struct policy_handle *handle,
2442 struct sockaddr_storage *client_ss,
2443 struct messaging_context *msg_ctx)
2445 WERROR result;
2446 NTSTATUS status;
2449 * If it's the first connection, contact the client
2450 * and connect to the IPC$ share anonymously
2452 if (smb_connections==0) {
2453 fstring unix_printer;
2455 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2457 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2458 return false;
2460 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2461 receive_notify2_message_list);
2462 /* Tell the connections db we're now interested in printer
2463 * notify messages. */
2464 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2465 true, FLAG_MSG_PRINT_NOTIFY);
2469 * Tell the specific printing tdb we want messages for this printer
2470 * by registering our PID.
2473 if (!print_notify_register_pid(snum))
2474 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2476 smb_connections++;
2478 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2479 printer,
2480 localprinter,
2481 type,
2483 NULL,
2484 handle,
2485 &result);
2486 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2487 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2488 win_errstr(result)));
2490 return (W_ERROR_IS_OK(result));
2493 /****************************************************************
2494 ****************************************************************/
2496 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2497 const struct spoolss_NotifyOption *r)
2499 struct spoolss_NotifyOption *option;
2500 uint32_t i,k;
2502 if (!r) {
2503 return NULL;
2506 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2507 if (!option) {
2508 return NULL;
2511 *option = *r;
2513 if (!option->count) {
2514 return option;
2517 option->types = talloc_zero_array(option,
2518 struct spoolss_NotifyOptionType, option->count);
2519 if (!option->types) {
2520 talloc_free(option);
2521 return NULL;
2524 for (i=0; i < option->count; i++) {
2525 option->types[i] = r->types[i];
2527 if (option->types[i].count) {
2528 option->types[i].fields = talloc_zero_array(option,
2529 union spoolss_Field, option->types[i].count);
2530 if (!option->types[i].fields) {
2531 talloc_free(option);
2532 return NULL;
2534 for (k=0; k<option->types[i].count; k++) {
2535 option->types[i].fields[k] =
2536 r->types[i].fields[k];
2541 return option;
2544 /****************************************************************
2545 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2547 * before replying OK: status=0 a rpc call is made to the workstation
2548 * asking ReplyOpenPrinter
2550 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2551 * called from api_spoolss_rffpcnex
2552 ****************************************************************/
2554 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2555 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2557 int snum = -1;
2558 struct spoolss_NotifyOption *option = r->in.notify_options;
2559 struct sockaddr_storage client_ss;
2561 /* store the notify value in the printer struct */
2563 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2565 if (!Printer) {
2566 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2567 "Invalid handle (%s:%u:%u).\n",
2568 OUR_HANDLE(r->in.handle)));
2569 return WERR_BADFID;
2572 Printer->notify.flags = r->in.flags;
2573 Printer->notify.options = r->in.options;
2574 Printer->notify.printerlocal = r->in.printer_local;
2575 Printer->notify.msg_ctx = p->msg_ctx;
2577 TALLOC_FREE(Printer->notify.option);
2578 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2580 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2582 /* Connect to the client machine and send a ReplyOpenPrinter */
2584 if ( Printer->printer_type == SPLHND_SERVER)
2585 snum = -1;
2586 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2587 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2588 return WERR_BADFID;
2590 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2591 "client_address is %s\n", p->client_id->addr));
2593 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2594 AI_NUMERICHOST)) {
2595 return WERR_SERVER_UNAVAILABLE;
2598 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2599 Printer->notify.printerlocal, REG_SZ,
2600 &Printer->notify.client_hnd,
2601 &client_ss, p->msg_ctx))
2602 return WERR_SERVER_UNAVAILABLE;
2604 Printer->notify.client_connected = true;
2606 return WERR_OK;
2609 /*******************************************************************
2610 * fill a notify_info_data with the servername
2611 ********************************************************************/
2613 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2614 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->servername);
2623 /*******************************************************************
2624 * fill a notify_info_data with the printername (not including the servername).
2625 ********************************************************************/
2627 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2628 int snum,
2629 struct spoolss_Notify *data,
2630 print_queue_struct *queue,
2631 struct spoolss_PrinterInfo2 *pinfo2,
2632 TALLOC_CTX *mem_ctx)
2634 /* the notify name should not contain the \\server\ part */
2635 const char *p = strrchr(pinfo2->printername, '\\');
2637 if (!p) {
2638 p = pinfo2->printername;
2639 } else {
2640 p++;
2643 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2646 /*******************************************************************
2647 * fill a notify_info_data with the servicename
2648 ********************************************************************/
2650 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2651 int snum,
2652 struct spoolss_Notify *data,
2653 print_queue_struct *queue,
2654 struct spoolss_PrinterInfo2 *pinfo2,
2655 TALLOC_CTX *mem_ctx)
2657 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2660 /*******************************************************************
2661 * fill a notify_info_data with the port name
2662 ********************************************************************/
2664 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2665 int snum,
2666 struct spoolss_Notify *data,
2667 print_queue_struct *queue,
2668 struct spoolss_PrinterInfo2 *pinfo2,
2669 TALLOC_CTX *mem_ctx)
2671 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2674 /*******************************************************************
2675 * fill a notify_info_data with the printername
2676 * but it doesn't exist, have to see what to do
2677 ********************************************************************/
2679 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2680 int snum,
2681 struct spoolss_Notify *data,
2682 print_queue_struct *queue,
2683 struct spoolss_PrinterInfo2 *pinfo2,
2684 TALLOC_CTX *mem_ctx)
2686 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2689 /*******************************************************************
2690 * fill a notify_info_data with the comment
2691 ********************************************************************/
2693 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2694 int snum,
2695 struct spoolss_Notify *data,
2696 print_queue_struct *queue,
2697 struct spoolss_PrinterInfo2 *pinfo2,
2698 TALLOC_CTX *mem_ctx)
2700 const char *p;
2702 if (*pinfo2->comment == '\0') {
2703 p = lp_comment(snum);
2704 } else {
2705 p = pinfo2->comment;
2708 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2711 /*******************************************************************
2712 * fill a notify_info_data with the comment
2713 * location = "Room 1, floor 2, building 3"
2714 ********************************************************************/
2716 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2717 int snum,
2718 struct spoolss_Notify *data,
2719 print_queue_struct *queue,
2720 struct spoolss_PrinterInfo2 *pinfo2,
2721 TALLOC_CTX *mem_ctx)
2723 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2726 /*******************************************************************
2727 * fill a notify_info_data with the device mode
2728 * jfm:xxxx don't to it for know but that's a real problem !!!
2729 ********************************************************************/
2731 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2732 int snum,
2733 struct spoolss_Notify *data,
2734 print_queue_struct *queue,
2735 struct spoolss_PrinterInfo2 *pinfo2,
2736 TALLOC_CTX *mem_ctx)
2738 /* for a dummy implementation we have to zero the fields */
2739 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2742 /*******************************************************************
2743 * fill a notify_info_data with the separator file name
2744 ********************************************************************/
2746 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2747 int snum,
2748 struct spoolss_Notify *data,
2749 print_queue_struct *queue,
2750 struct spoolss_PrinterInfo2 *pinfo2,
2751 TALLOC_CTX *mem_ctx)
2753 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2756 /*******************************************************************
2757 * fill a notify_info_data with the print processor
2758 * jfm:xxxx return always winprint to indicate we don't do anything to it
2759 ********************************************************************/
2761 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2762 int snum,
2763 struct spoolss_Notify *data,
2764 print_queue_struct *queue,
2765 struct spoolss_PrinterInfo2 *pinfo2,
2766 TALLOC_CTX *mem_ctx)
2768 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2771 /*******************************************************************
2772 * fill a notify_info_data with the print processor options
2773 * jfm:xxxx send an empty string
2774 ********************************************************************/
2776 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2777 int snum,
2778 struct spoolss_Notify *data,
2779 print_queue_struct *queue,
2780 struct spoolss_PrinterInfo2 *pinfo2,
2781 TALLOC_CTX *mem_ctx)
2783 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2786 /*******************************************************************
2787 * fill a notify_info_data with the data type
2788 * jfm:xxxx always send RAW as data type
2789 ********************************************************************/
2791 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2792 int snum,
2793 struct spoolss_Notify *data,
2794 print_queue_struct *queue,
2795 struct spoolss_PrinterInfo2 *pinfo2,
2796 TALLOC_CTX *mem_ctx)
2798 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2801 /*******************************************************************
2802 * fill a notify_info_data with the security descriptor
2803 * jfm:xxxx send an null pointer to say no security desc
2804 * have to implement security before !
2805 ********************************************************************/
2807 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2808 int snum,
2809 struct spoolss_Notify *data,
2810 print_queue_struct *queue,
2811 struct spoolss_PrinterInfo2 *pinfo2,
2812 TALLOC_CTX *mem_ctx)
2814 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2817 /*******************************************************************
2818 * fill a notify_info_data with the attributes
2819 * jfm:xxxx a samba printer is always shared
2820 ********************************************************************/
2822 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2823 int snum,
2824 struct spoolss_Notify *data,
2825 print_queue_struct *queue,
2826 struct spoolss_PrinterInfo2 *pinfo2,
2827 TALLOC_CTX *mem_ctx)
2829 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2832 /*******************************************************************
2833 * fill a notify_info_data with the priority
2834 ********************************************************************/
2836 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2837 int snum,
2838 struct spoolss_Notify *data,
2839 print_queue_struct *queue,
2840 struct spoolss_PrinterInfo2 *pinfo2,
2841 TALLOC_CTX *mem_ctx)
2843 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2846 /*******************************************************************
2847 * fill a notify_info_data with the default priority
2848 ********************************************************************/
2850 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2851 int snum,
2852 struct spoolss_Notify *data,
2853 print_queue_struct *queue,
2854 struct spoolss_PrinterInfo2 *pinfo2,
2855 TALLOC_CTX *mem_ctx)
2857 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2860 /*******************************************************************
2861 * fill a notify_info_data with the start time
2862 ********************************************************************/
2864 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2865 int snum,
2866 struct spoolss_Notify *data,
2867 print_queue_struct *queue,
2868 struct spoolss_PrinterInfo2 *pinfo2,
2869 TALLOC_CTX *mem_ctx)
2871 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2874 /*******************************************************************
2875 * fill a notify_info_data with the until time
2876 ********************************************************************/
2878 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2879 int snum,
2880 struct spoolss_Notify *data,
2881 print_queue_struct *queue,
2882 struct spoolss_PrinterInfo2 *pinfo2,
2883 TALLOC_CTX *mem_ctx)
2885 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2888 /*******************************************************************
2889 * fill a notify_info_data with the status
2890 ********************************************************************/
2892 static void spoolss_notify_status(struct messaging_context *msg_ctx,
2893 int snum,
2894 struct spoolss_Notify *data,
2895 print_queue_struct *queue,
2896 struct spoolss_PrinterInfo2 *pinfo2,
2897 TALLOC_CTX *mem_ctx)
2899 print_status_struct status;
2901 print_queue_length(msg_ctx, snum, &status);
2902 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2905 /*******************************************************************
2906 * fill a notify_info_data with the number of jobs queued
2907 ********************************************************************/
2909 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
2910 int snum,
2911 struct spoolss_Notify *data,
2912 print_queue_struct *queue,
2913 struct spoolss_PrinterInfo2 *pinfo2,
2914 TALLOC_CTX *mem_ctx)
2916 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
2917 data, print_queue_length(msg_ctx, snum, NULL));
2920 /*******************************************************************
2921 * fill a notify_info_data with the average ppm
2922 ********************************************************************/
2924 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
2925 int snum,
2926 struct spoolss_Notify *data,
2927 print_queue_struct *queue,
2928 struct spoolss_PrinterInfo2 *pinfo2,
2929 TALLOC_CTX *mem_ctx)
2931 /* always respond 8 pages per minutes */
2932 /* a little hard ! */
2933 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
2936 /*******************************************************************
2937 * fill a notify_info_data with username
2938 ********************************************************************/
2940 static void spoolss_notify_username(struct messaging_context *msg_ctx,
2941 int snum,
2942 struct spoolss_Notify *data,
2943 print_queue_struct *queue,
2944 struct spoolss_PrinterInfo2 *pinfo2,
2945 TALLOC_CTX *mem_ctx)
2947 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2950 /*******************************************************************
2951 * fill a notify_info_data with job status
2952 ********************************************************************/
2954 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
2955 int snum,
2956 struct spoolss_Notify *data,
2957 print_queue_struct *queue,
2958 struct spoolss_PrinterInfo2 *pinfo2,
2959 TALLOC_CTX *mem_ctx)
2961 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2964 /*******************************************************************
2965 * fill a notify_info_data with job name
2966 ********************************************************************/
2968 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
2969 int snum,
2970 struct spoolss_Notify *data,
2971 print_queue_struct *queue,
2972 struct spoolss_PrinterInfo2 *pinfo2,
2973 TALLOC_CTX *mem_ctx)
2975 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2978 /*******************************************************************
2979 * fill a notify_info_data with job status
2980 ********************************************************************/
2982 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
2983 int snum,
2984 struct spoolss_Notify *data,
2985 print_queue_struct *queue,
2986 struct spoolss_PrinterInfo2 *pinfo2,
2987 TALLOC_CTX *mem_ctx)
2990 * Now we're returning job status codes we just return a "" here. JRA.
2993 const char *p = "";
2995 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2996 p = "unknown";
2998 switch (queue->status) {
2999 case LPQ_QUEUED:
3000 p = "Queued";
3001 break;
3002 case LPQ_PAUSED:
3003 p = ""; /* NT provides the paused string */
3004 break;
3005 case LPQ_SPOOLING:
3006 p = "Spooling";
3007 break;
3008 case LPQ_PRINTING:
3009 p = "Printing";
3010 break;
3012 #endif /* NO LONGER NEEDED. */
3014 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3017 /*******************************************************************
3018 * fill a notify_info_data with job time
3019 ********************************************************************/
3021 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3022 int snum,
3023 struct spoolss_Notify *data,
3024 print_queue_struct *queue,
3025 struct spoolss_PrinterInfo2 *pinfo2,
3026 TALLOC_CTX *mem_ctx)
3028 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3031 /*******************************************************************
3032 * fill a notify_info_data with job size
3033 ********************************************************************/
3035 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3036 int snum,
3037 struct spoolss_Notify *data,
3038 print_queue_struct *queue,
3039 struct spoolss_PrinterInfo2 *pinfo2,
3040 TALLOC_CTX *mem_ctx)
3042 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3045 /*******************************************************************
3046 * fill a notify_info_data with page info
3047 ********************************************************************/
3048 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3049 int snum,
3050 struct spoolss_Notify *data,
3051 print_queue_struct *queue,
3052 struct spoolss_PrinterInfo2 *pinfo2,
3053 TALLOC_CTX *mem_ctx)
3055 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3058 /*******************************************************************
3059 * fill a notify_info_data with pages printed info.
3060 ********************************************************************/
3061 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3062 int snum,
3063 struct spoolss_Notify *data,
3064 print_queue_struct *queue,
3065 struct spoolss_PrinterInfo2 *pinfo2,
3066 TALLOC_CTX *mem_ctx)
3068 /* Add code when back-end tracks this */
3069 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3072 /*******************************************************************
3073 Fill a notify_info_data with job position.
3074 ********************************************************************/
3076 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3077 int snum,
3078 struct spoolss_Notify *data,
3079 print_queue_struct *queue,
3080 struct spoolss_PrinterInfo2 *pinfo2,
3081 TALLOC_CTX *mem_ctx)
3083 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3086 /*******************************************************************
3087 Fill a notify_info_data with submitted time.
3088 ********************************************************************/
3090 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3091 int snum,
3092 struct spoolss_Notify *data,
3093 print_queue_struct *queue,
3094 struct spoolss_PrinterInfo2 *pinfo2,
3095 TALLOC_CTX *mem_ctx)
3097 data->data.string.string = NULL;
3098 data->data.string.size = 0;
3100 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3101 &data->data.string.string,
3102 &data->data.string.size);
3106 struct s_notify_info_data_table
3108 enum spoolss_NotifyType type;
3109 uint16_t field;
3110 const char *name;
3111 enum spoolss_NotifyTable variable_type;
3112 void (*fn) (struct messaging_context *msg_ctx,
3113 int snum, struct spoolss_Notify *data,
3114 print_queue_struct *queue,
3115 struct spoolss_PrinterInfo2 *pinfo2,
3116 TALLOC_CTX *mem_ctx);
3119 /* A table describing the various print notification constants and
3120 whether the notification data is a pointer to a variable sized
3121 buffer, a one value uint32_t or a two value uint32_t. */
3123 static const struct s_notify_info_data_table notify_info_data_table[] =
3125 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3126 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3127 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3128 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3129 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3130 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3131 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3132 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3133 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3134 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3135 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3136 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3137 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3138 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3139 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3140 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3141 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3142 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3143 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3144 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3145 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3146 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3147 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3148 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3149 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3150 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3151 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3152 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3153 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3154 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3155 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3156 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3157 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3158 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3159 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3160 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3161 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3162 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3163 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3164 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3165 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3166 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3167 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3168 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3169 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3170 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3171 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3172 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3173 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3176 /*******************************************************************
3177 Return the variable_type of info_data structure.
3178 ********************************************************************/
3180 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3181 uint16_t field)
3183 int i=0;
3185 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3186 if ( (notify_info_data_table[i].type == type) &&
3187 (notify_info_data_table[i].field == field) ) {
3188 return notify_info_data_table[i].variable_type;
3192 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3194 return (enum spoolss_NotifyTable) 0;
3197 /****************************************************************************
3198 ****************************************************************************/
3200 static bool search_notify(enum spoolss_NotifyType type,
3201 uint16_t field,
3202 int *value)
3204 int i;
3206 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3207 if (notify_info_data_table[i].type == type &&
3208 notify_info_data_table[i].field == field &&
3209 notify_info_data_table[i].fn != NULL) {
3210 *value = i;
3211 return true;
3215 return false;
3218 /****************************************************************************
3219 ****************************************************************************/
3221 static void construct_info_data(struct spoolss_Notify *info_data,
3222 enum spoolss_NotifyType type,
3223 uint16_t field, int id)
3225 info_data->type = type;
3226 info_data->field.field = field;
3227 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3228 info_data->job_id = id;
3231 /*******************************************************************
3233 * fill a notify_info struct with info asked
3235 ********************************************************************/
3237 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3238 struct printer_handle *print_hnd,
3239 struct spoolss_NotifyInfo *info,
3240 struct spoolss_PrinterInfo2 *pinfo2,
3241 int snum,
3242 const struct spoolss_NotifyOptionType *option_type,
3243 uint32_t id,
3244 TALLOC_CTX *mem_ctx)
3246 int field_num,j;
3247 enum spoolss_NotifyType type;
3248 uint16_t field;
3250 struct spoolss_Notify *current_data;
3251 print_queue_struct *queue=NULL;
3253 type = option_type->type;
3255 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3256 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3257 option_type->count, lp_servicename(snum)));
3259 for(field_num=0; field_num < option_type->count; field_num++) {
3260 field = option_type->fields[field_num].field;
3262 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3264 if (!search_notify(type, field, &j) )
3265 continue;
3267 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3268 struct spoolss_Notify,
3269 info->count + 1);
3270 if (info->notifies == NULL) {
3271 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3272 return false;
3275 current_data = &info->notifies[info->count];
3277 construct_info_data(current_data, type, field, id);
3279 DEBUG(10, ("construct_notify_printer_info: "
3280 "calling [%s] snum=%d printername=[%s])\n",
3281 notify_info_data_table[j].name, snum,
3282 pinfo2->printername));
3284 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3285 queue, pinfo2, mem_ctx);
3287 info->count++;
3290 return true;
3293 /*******************************************************************
3295 * fill a notify_info struct with info asked
3297 ********************************************************************/
3299 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3300 print_queue_struct *queue,
3301 struct spoolss_NotifyInfo *info,
3302 struct spoolss_PrinterInfo2 *pinfo2,
3303 int snum,
3304 const struct spoolss_NotifyOptionType *option_type,
3305 uint32_t id,
3306 TALLOC_CTX *mem_ctx)
3308 int field_num,j;
3309 enum spoolss_NotifyType type;
3310 uint16_t field;
3311 struct spoolss_Notify *current_data;
3313 DEBUG(4,("construct_notify_jobs_info\n"));
3315 type = option_type->type;
3317 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3318 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3319 option_type->count));
3321 for(field_num=0; field_num<option_type->count; field_num++) {
3322 field = option_type->fields[field_num].field;
3324 if (!search_notify(type, field, &j) )
3325 continue;
3327 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3328 struct spoolss_Notify,
3329 info->count + 1);
3330 if (info->notifies == NULL) {
3331 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3332 return false;
3335 current_data=&(info->notifies[info->count]);
3337 construct_info_data(current_data, type, field, id);
3338 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3339 queue, pinfo2, mem_ctx);
3340 info->count++;
3343 return true;
3347 * JFM: The enumeration is not that simple, it's even non obvious.
3349 * let's take an example: I want to monitor the PRINTER SERVER for
3350 * the printer's name and the number of jobs currently queued.
3351 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3352 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3354 * I have 3 printers on the back of my server.
3356 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3357 * structures.
3358 * Number Data Id
3359 * 1 printer 1 name 1
3360 * 2 printer 1 cjob 1
3361 * 3 printer 2 name 2
3362 * 4 printer 2 cjob 2
3363 * 5 printer 3 name 3
3364 * 6 printer 3 name 3
3366 * that's the print server case, the printer case is even worse.
3369 /*******************************************************************
3371 * enumerate all printers on the printserver
3372 * fill a notify_info struct with info asked
3374 ********************************************************************/
3376 static WERROR printserver_notify_info(struct pipes_struct *p,
3377 struct policy_handle *hnd,
3378 struct spoolss_NotifyInfo *info,
3379 TALLOC_CTX *mem_ctx)
3381 int snum;
3382 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3383 int n_services=lp_numservices();
3384 int i;
3385 struct spoolss_NotifyOption *option;
3386 struct spoolss_NotifyOptionType option_type;
3387 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3388 WERROR result;
3390 DEBUG(4,("printserver_notify_info\n"));
3392 if (!Printer)
3393 return WERR_BADFID;
3395 option = Printer->notify.option;
3397 info->version = 2;
3398 info->notifies = NULL;
3399 info->count = 0;
3401 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3402 sending a ffpcn() request first */
3404 if ( !option )
3405 return WERR_BADFID;
3407 for (i=0; i<option->count; i++) {
3408 option_type = option->types[i];
3410 if (option_type.type != PRINTER_NOTIFY_TYPE)
3411 continue;
3413 for (snum = 0; snum < n_services; snum++) {
3414 if (!lp_browseable(snum) ||
3415 !lp_snum_ok(snum) ||
3416 !lp_print_ok(snum)) {
3417 continue; /* skip */
3420 /* Maybe we should use the SYSTEM server_info here... */
3421 result = winreg_get_printer(mem_ctx,
3422 get_server_info_system(),
3423 p->msg_ctx,
3424 Printer->servername,
3425 lp_servicename(snum),
3426 &pinfo2);
3427 if (!W_ERROR_IS_OK(result)) {
3428 DEBUG(4, ("printserver_notify_info: "
3429 "Failed to get printer [%s]\n",
3430 lp_servicename(snum)));
3431 continue;
3435 construct_notify_printer_info(p->msg_ctx,
3436 Printer, info,
3437 pinfo2, snum,
3438 &option_type, snum,
3439 mem_ctx);
3441 TALLOC_FREE(pinfo2);
3445 #if 0
3447 * Debugging information, don't delete.
3450 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3451 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3452 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3454 for (i=0; i<info->count; i++) {
3455 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3456 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3457 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3459 #endif
3461 return WERR_OK;
3464 /*******************************************************************
3466 * fill a notify_info struct with info asked
3468 ********************************************************************/
3470 static WERROR printer_notify_info(struct pipes_struct *p,
3471 struct policy_handle *hnd,
3472 struct spoolss_NotifyInfo *info,
3473 TALLOC_CTX *mem_ctx)
3475 int snum;
3476 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3477 int i;
3478 uint32_t id;
3479 struct spoolss_NotifyOption *option;
3480 struct spoolss_NotifyOptionType option_type;
3481 int count,j;
3482 print_queue_struct *queue=NULL;
3483 print_status_struct status;
3484 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3485 WERROR result;
3487 DEBUG(4,("printer_notify_info\n"));
3489 if (!Printer)
3490 return WERR_BADFID;
3492 option = Printer->notify.option;
3493 id = 0x0;
3495 info->version = 2;
3496 info->notifies = NULL;
3497 info->count = 0;
3499 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3500 sending a ffpcn() request first */
3502 if ( !option )
3503 return WERR_BADFID;
3505 get_printer_snum(p, hnd, &snum, NULL);
3507 /* Maybe we should use the SYSTEM server_info here... */
3508 result = winreg_get_printer(mem_ctx,
3509 get_server_info_system(),
3510 p->msg_ctx,
3511 Printer->servername,
3512 lp_servicename(snum), &pinfo2);
3513 if (!W_ERROR_IS_OK(result)) {
3514 return WERR_BADFID;
3517 for (i=0; i<option->count; i++) {
3518 option_type = option->types[i];
3520 switch (option_type.type) {
3521 case PRINTER_NOTIFY_TYPE:
3522 if (construct_notify_printer_info(p->msg_ctx,
3523 Printer, info,
3524 pinfo2, snum,
3525 &option_type, id,
3526 mem_ctx)) {
3527 id--;
3529 break;
3531 case JOB_NOTIFY_TYPE:
3533 count = print_queue_status(p->msg_ctx, snum, &queue,
3534 &status);
3536 for (j=0; j<count; j++) {
3537 construct_notify_jobs_info(p->msg_ctx,
3538 &queue[j], info,
3539 pinfo2, snum,
3540 &option_type,
3541 queue[j].job,
3542 mem_ctx);
3545 SAFE_FREE(queue);
3546 break;
3551 * Debugging information, don't delete.
3554 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3555 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3556 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3558 for (i=0; i<info->count; i++) {
3559 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3560 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3561 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3565 talloc_free(pinfo2);
3566 return WERR_OK;
3569 /****************************************************************
3570 _spoolss_RouterRefreshPrinterChangeNotify
3571 ****************************************************************/
3573 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3574 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3576 struct spoolss_NotifyInfo *info;
3578 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3579 WERROR result = WERR_BADFID;
3581 /* we always have a spoolss_NotifyInfo struct */
3582 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3583 if (!info) {
3584 result = WERR_NOMEM;
3585 goto done;
3588 *r->out.info = info;
3590 if (!Printer) {
3591 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3592 "Invalid handle (%s:%u:%u).\n",
3593 OUR_HANDLE(r->in.handle)));
3594 goto done;
3597 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3600 * We are now using the change value, and
3601 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3602 * I don't have a global notification system, I'm sending back all the
3603 * informations even when _NOTHING_ has changed.
3606 /* We need to keep track of the change value to send back in
3607 RRPCN replies otherwise our updates are ignored. */
3609 Printer->notify.fnpcn = true;
3611 if (Printer->notify.client_connected) {
3612 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3613 "Saving change value in request [%x]\n",
3614 r->in.change_low));
3615 Printer->notify.change = r->in.change_low;
3618 /* just ignore the spoolss_NotifyOption */
3620 switch (Printer->printer_type) {
3621 case SPLHND_SERVER:
3622 result = printserver_notify_info(p, r->in.handle,
3623 info, p->mem_ctx);
3624 break;
3626 case SPLHND_PRINTER:
3627 result = printer_notify_info(p, r->in.handle,
3628 info, p->mem_ctx);
3629 break;
3632 Printer->notify.fnpcn = false;
3634 done:
3635 return result;
3638 /********************************************************************
3639 * construct_printer_info_0
3640 * fill a printer_info_0 struct
3641 ********************************************************************/
3643 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3644 const struct auth_serversupplied_info *server_info,
3645 struct messaging_context *msg_ctx,
3646 struct spoolss_PrinterInfo2 *info2,
3647 struct spoolss_PrinterInfo0 *r,
3648 int snum)
3650 int count;
3651 struct printer_session_counter *session_counter;
3652 struct timeval setuptime;
3653 print_status_struct status;
3655 r->printername = talloc_strdup(mem_ctx, info2->printername);
3656 W_ERROR_HAVE_NO_MEMORY(r->printername);
3658 r->servername = talloc_strdup(mem_ctx, info2->servername);
3659 W_ERROR_HAVE_NO_MEMORY(r->servername);
3661 count = print_queue_length(msg_ctx, snum, &status);
3663 /* check if we already have a counter for this printer */
3664 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3665 if (session_counter->snum == snum)
3666 break;
3669 /* it's the first time, add it to the list */
3670 if (session_counter == NULL) {
3671 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3672 W_ERROR_HAVE_NO_MEMORY(session_counter);
3673 session_counter->snum = snum;
3674 session_counter->counter = 0;
3675 DLIST_ADD(counter_list, session_counter);
3678 /* increment it */
3679 session_counter->counter++;
3681 r->cjobs = count;
3682 r->total_jobs = 0;
3683 r->total_bytes = 0;
3685 get_startup_time(&setuptime);
3686 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3688 /* JFM:
3689 * the global_counter should be stored in a TDB as it's common to all the clients
3690 * and should be zeroed on samba startup
3692 r->global_counter = session_counter->counter;
3693 r->total_pages = 0;
3694 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3695 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3696 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3697 r->free_build = SPOOLSS_RELEASE_BUILD;
3698 r->spooling = 0;
3699 r->max_spooling = 0;
3700 r->session_counter = session_counter->counter;
3701 r->num_error_out_of_paper = 0x0;
3702 r->num_error_not_ready = 0x0; /* number of print failure */
3703 r->job_error = 0x0;
3704 r->number_of_processors = 0x1;
3705 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3706 r->high_part_total_bytes = 0x0;
3708 /* ChangeID in milliseconds*/
3709 winreg_printer_get_changeid(mem_ctx, server_info, msg_ctx,
3710 info2->sharename, &r->change_id);
3712 r->last_error = WERR_OK;
3713 r->status = nt_printq_status(status.status);
3714 r->enumerate_network_printers = 0x0;
3715 r->c_setprinter = 0x0;
3716 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3717 r->processor_level = 0x6; /* 6 ???*/
3718 r->ref_ic = 0;
3719 r->reserved2 = 0;
3720 r->reserved3 = 0;
3722 return WERR_OK;
3726 /********************************************************************
3727 * construct_printer_info1
3728 * fill a spoolss_PrinterInfo1 struct
3729 ********************************************************************/
3731 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3732 const struct spoolss_PrinterInfo2 *info2,
3733 uint32_t flags,
3734 struct spoolss_PrinterInfo1 *r,
3735 int snum)
3737 r->flags = flags;
3739 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3740 info2->printername,
3741 info2->drivername,
3742 info2->location);
3743 W_ERROR_HAVE_NO_MEMORY(r->description);
3745 if (info2->comment == NULL || info2->comment[0] == '\0') {
3746 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3747 } else {
3748 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3750 W_ERROR_HAVE_NO_MEMORY(r->comment);
3752 r->name = talloc_strdup(mem_ctx, info2->printername);
3753 W_ERROR_HAVE_NO_MEMORY(r->name);
3755 return WERR_OK;
3758 /********************************************************************
3759 * construct_printer_info2
3760 * fill a spoolss_PrinterInfo2 struct
3761 ********************************************************************/
3763 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3764 struct messaging_context *msg_ctx,
3765 const struct spoolss_PrinterInfo2 *info2,
3766 struct spoolss_PrinterInfo2 *r,
3767 int snum)
3769 int count;
3770 print_status_struct status;
3772 count = print_queue_length(msg_ctx, snum, &status);
3774 r->servername = talloc_strdup(mem_ctx, info2->servername);
3775 W_ERROR_HAVE_NO_MEMORY(r->servername);
3776 r->printername = talloc_strdup(mem_ctx, info2->printername);
3777 W_ERROR_HAVE_NO_MEMORY(r->printername);
3778 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3779 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3780 r->portname = talloc_strdup(mem_ctx, info2->portname);
3781 W_ERROR_HAVE_NO_MEMORY(r->portname);
3782 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3783 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3785 if (info2->comment[0] == '\0') {
3786 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3787 } else {
3788 r->comment = talloc_strdup(mem_ctx, info2->comment);
3790 W_ERROR_HAVE_NO_MEMORY(r->comment);
3792 r->location = talloc_strdup(mem_ctx, info2->location);
3793 W_ERROR_HAVE_NO_MEMORY(r->location);
3794 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
3795 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3796 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
3797 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3798 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
3799 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3800 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
3801 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3803 r->attributes = info2->attributes;
3805 r->priority = info2->priority;
3806 r->defaultpriority = info2->defaultpriority;
3807 r->starttime = info2->starttime;
3808 r->untiltime = info2->untiltime;
3809 r->status = nt_printq_status(status.status);
3810 r->cjobs = count;
3811 r->averageppm = info2->averageppm;
3813 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3814 if (!r->devmode) {
3815 DEBUG(8,("Returning NULL Devicemode!\n"));
3818 r->secdesc = NULL;
3820 if (info2->secdesc != NULL) {
3821 /* don't use talloc_steal() here unless you do a deep steal of all
3822 the SEC_DESC members */
3824 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3827 return WERR_OK;
3830 /********************************************************************
3831 * construct_printer_info3
3832 * fill a spoolss_PrinterInfo3 struct
3833 ********************************************************************/
3835 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3836 const struct spoolss_PrinterInfo2 *info2,
3837 struct spoolss_PrinterInfo3 *r,
3838 int snum)
3840 /* These are the components of the SD we are returning. */
3842 if (info2->secdesc != NULL) {
3843 /* don't use talloc_steal() here unless you do a deep steal of all
3844 the SEC_DESC members */
3846 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3847 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3850 return WERR_OK;
3853 /********************************************************************
3854 * construct_printer_info4
3855 * fill a spoolss_PrinterInfo4 struct
3856 ********************************************************************/
3858 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3859 const struct spoolss_PrinterInfo2 *info2,
3860 struct spoolss_PrinterInfo4 *r,
3861 int snum)
3863 r->printername = talloc_strdup(mem_ctx, info2->printername);
3864 W_ERROR_HAVE_NO_MEMORY(r->printername);
3865 r->servername = talloc_strdup(mem_ctx, info2->servername);
3866 W_ERROR_HAVE_NO_MEMORY(r->servername);
3868 r->attributes = info2->attributes;
3870 return WERR_OK;
3873 /********************************************************************
3874 * construct_printer_info5
3875 * fill a spoolss_PrinterInfo5 struct
3876 ********************************************************************/
3878 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3879 const struct spoolss_PrinterInfo2 *info2,
3880 struct spoolss_PrinterInfo5 *r,
3881 int snum)
3883 r->printername = talloc_strdup(mem_ctx, info2->printername);
3884 W_ERROR_HAVE_NO_MEMORY(r->printername);
3885 r->portname = talloc_strdup(mem_ctx, info2->portname);
3886 W_ERROR_HAVE_NO_MEMORY(r->portname);
3888 r->attributes = info2->attributes;
3890 /* these two are not used by NT+ according to MSDN */
3891 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3892 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3894 return WERR_OK;
3897 /********************************************************************
3898 * construct_printer_info_6
3899 * fill a spoolss_PrinterInfo6 struct
3900 ********************************************************************/
3902 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3903 struct messaging_context *msg_ctx,
3904 const struct spoolss_PrinterInfo2 *info2,
3905 struct spoolss_PrinterInfo6 *r,
3906 int snum)
3908 int count;
3909 print_status_struct status;
3911 count = print_queue_length(msg_ctx, snum, &status);
3913 r->status = nt_printq_status(status.status);
3915 return WERR_OK;
3918 /********************************************************************
3919 * construct_printer_info7
3920 * fill a spoolss_PrinterInfo7 struct
3921 ********************************************************************/
3923 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3924 struct messaging_context *msg_ctx,
3925 struct printer_handle *print_hnd,
3926 struct spoolss_PrinterInfo7 *r,
3927 int snum)
3929 struct auth_serversupplied_info *server_info;
3930 struct GUID guid;
3931 NTSTATUS status;
3933 status = make_server_info_system(mem_ctx, &server_info);
3934 if (!NT_STATUS_IS_OK(status)) {
3935 DEBUG(0, ("construct_printer_info7: "
3936 "Could not create system server_info\n"));
3937 return WERR_NOMEM;
3940 if (is_printer_published(mem_ctx, server_info, msg_ctx,
3941 print_hnd->servername,
3942 lp_servicename(snum), &guid, NULL)) {
3943 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3944 r->action = DSPRINT_PUBLISH;
3945 } else {
3946 r->guid = talloc_strdup(mem_ctx, "");
3947 r->action = DSPRINT_UNPUBLISH;
3949 W_ERROR_HAVE_NO_MEMORY(r->guid);
3951 TALLOC_FREE(server_info);
3952 return WERR_OK;
3955 /********************************************************************
3956 * construct_printer_info8
3957 * fill a spoolss_PrinterInfo8 struct
3958 ********************************************************************/
3960 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3961 const struct spoolss_PrinterInfo2 *info2,
3962 struct spoolss_DeviceModeInfo *r,
3963 int snum)
3965 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3966 if (!r->devmode) {
3967 DEBUG(8,("Returning NULL Devicemode!\n"));
3970 return WERR_OK;
3974 /********************************************************************
3975 ********************************************************************/
3977 static bool snum_is_shared_printer(int snum)
3979 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3982 /********************************************************************
3983 Spoolss_enumprinters.
3984 ********************************************************************/
3986 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3987 const struct auth_serversupplied_info *server_info,
3988 struct messaging_context *msg_ctx,
3989 uint32_t level,
3990 uint32_t flags,
3991 union spoolss_PrinterInfo **info_p,
3992 uint32_t *count_p)
3994 int snum;
3995 int n_services = lp_numservices();
3996 union spoolss_PrinterInfo *info = NULL;
3997 uint32_t count = 0;
3998 WERROR result = WERR_OK;
4000 *count_p = 0;
4001 *info_p = NULL;
4003 for (snum = 0; snum < n_services; snum++) {
4005 const char *printer;
4006 struct spoolss_PrinterInfo2 *info2;
4008 if (!snum_is_shared_printer(snum)) {
4009 continue;
4012 printer = lp_const_servicename(snum);
4014 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4015 printer, snum));
4017 result = winreg_create_printer(mem_ctx,
4018 server_info,
4019 msg_ctx,
4020 NULL,
4021 printer);
4022 if (!W_ERROR_IS_OK(result)) {
4023 goto out;
4026 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4027 union spoolss_PrinterInfo,
4028 count + 1);
4029 if (!info) {
4030 result = WERR_NOMEM;
4031 goto out;
4034 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
4035 NULL, printer, &info2);
4036 if (!W_ERROR_IS_OK(result)) {
4037 goto out;
4040 switch (level) {
4041 case 0:
4042 result = construct_printer_info0(info, server_info,
4043 msg_ctx, info2,
4044 &info[count].info0, snum);
4045 break;
4046 case 1:
4047 result = construct_printer_info1(info, info2, flags,
4048 &info[count].info1, snum);
4049 break;
4050 case 2:
4051 result = construct_printer_info2(info, msg_ctx, info2,
4052 &info[count].info2, snum);
4053 break;
4054 case 4:
4055 result = construct_printer_info4(info, info2,
4056 &info[count].info4, snum);
4057 break;
4058 case 5:
4059 result = construct_printer_info5(info, info2,
4060 &info[count].info5, snum);
4061 break;
4063 default:
4064 result = WERR_UNKNOWN_LEVEL;
4065 goto out;
4068 if (!W_ERROR_IS_OK(result)) {
4069 goto out;
4072 count++;
4075 *count_p = count;
4076 *info_p = info;
4078 out:
4079 if (!W_ERROR_IS_OK(result)) {
4080 TALLOC_FREE(info);
4081 return result;
4084 *info_p = info;
4086 return WERR_OK;
4089 /********************************************************************
4090 * handle enumeration of printers at level 0
4091 ********************************************************************/
4093 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4094 const struct auth_serversupplied_info *server_info,
4095 struct messaging_context *msg_ctx,
4096 uint32_t flags,
4097 const char *servername,
4098 union spoolss_PrinterInfo **info,
4099 uint32_t *count)
4101 DEBUG(4,("enum_all_printers_info_0\n"));
4103 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4104 0, flags, info, count);
4108 /********************************************************************
4109 ********************************************************************/
4111 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4112 const struct auth_serversupplied_info *server_info,
4113 struct messaging_context *msg_ctx,
4114 uint32_t flags,
4115 union spoolss_PrinterInfo **info,
4116 uint32_t *count)
4118 DEBUG(4,("enum_all_printers_info_1\n"));
4120 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4121 1, flags, info, count);
4124 /********************************************************************
4125 enum_all_printers_info_1_local.
4126 *********************************************************************/
4128 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4129 const struct auth_serversupplied_info *server_info,
4130 struct messaging_context *msg_ctx,
4131 union spoolss_PrinterInfo **info,
4132 uint32_t *count)
4134 DEBUG(4,("enum_all_printers_info_1_local\n"));
4136 return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4137 PRINTER_ENUM_ICON8, info, count);
4140 /********************************************************************
4141 enum_all_printers_info_1_name.
4142 *********************************************************************/
4144 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4145 const struct auth_serversupplied_info *server_info,
4146 struct messaging_context *msg_ctx,
4147 const char *name,
4148 union spoolss_PrinterInfo **info,
4149 uint32_t *count)
4151 const char *s = name;
4153 DEBUG(4,("enum_all_printers_info_1_name\n"));
4155 if ((name[0] == '\\') && (name[1] == '\\')) {
4156 s = name + 2;
4159 if (!is_myname_or_ipaddr(s)) {
4160 return WERR_INVALID_NAME;
4163 return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4164 PRINTER_ENUM_ICON8, info, count);
4167 /********************************************************************
4168 enum_all_printers_info_1_network.
4169 *********************************************************************/
4171 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4172 const struct auth_serversupplied_info *server_info,
4173 struct messaging_context *msg_ctx,
4174 const char *name,
4175 union spoolss_PrinterInfo **info,
4176 uint32_t *count)
4178 const char *s = name;
4180 DEBUG(4,("enum_all_printers_info_1_network\n"));
4182 /* If we respond to a enum_printers level 1 on our name with flags
4183 set to PRINTER_ENUM_REMOTE with a list of printers then these
4184 printers incorrectly appear in the APW browse list.
4185 Specifically the printers for the server appear at the workgroup
4186 level where all the other servers in the domain are
4187 listed. Windows responds to this call with a
4188 WERR_CAN_NOT_COMPLETE so we should do the same. */
4190 if (name[0] == '\\' && name[1] == '\\') {
4191 s = name + 2;
4194 if (is_myname_or_ipaddr(s)) {
4195 return WERR_CAN_NOT_COMPLETE;
4198 return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4199 PRINTER_ENUM_NAME, info, count);
4202 /********************************************************************
4203 * api_spoolss_enumprinters
4205 * called from api_spoolss_enumprinters (see this to understand)
4206 ********************************************************************/
4208 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4209 const struct auth_serversupplied_info *server_info,
4210 struct messaging_context *msg_ctx,
4211 union spoolss_PrinterInfo **info,
4212 uint32_t *count)
4214 DEBUG(4,("enum_all_printers_info_2\n"));
4216 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4217 2, 0, info, count);
4220 /********************************************************************
4221 * handle enumeration of printers at level 1
4222 ********************************************************************/
4224 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4225 const struct auth_serversupplied_info *server_info,
4226 struct messaging_context *msg_ctx,
4227 uint32_t flags,
4228 const char *name,
4229 union spoolss_PrinterInfo **info,
4230 uint32_t *count)
4232 /* Not all the flags are equals */
4234 if (flags & PRINTER_ENUM_LOCAL) {
4235 return enum_all_printers_info_1_local(mem_ctx, server_info,
4236 msg_ctx, info, count);
4239 if (flags & PRINTER_ENUM_NAME) {
4240 return enum_all_printers_info_1_name(mem_ctx, server_info,
4241 msg_ctx, name, info,
4242 count);
4245 if (flags & PRINTER_ENUM_NETWORK) {
4246 return enum_all_printers_info_1_network(mem_ctx, server_info,
4247 msg_ctx, name, info,
4248 count);
4251 return WERR_OK; /* NT4sp5 does that */
4254 /********************************************************************
4255 * handle enumeration of printers at level 2
4256 ********************************************************************/
4258 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4259 const struct auth_serversupplied_info *server_info,
4260 struct messaging_context *msg_ctx,
4261 uint32_t flags,
4262 const char *servername,
4263 union spoolss_PrinterInfo **info,
4264 uint32_t *count)
4266 if (flags & PRINTER_ENUM_LOCAL) {
4267 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4268 info, count);
4271 if (flags & PRINTER_ENUM_NAME) {
4272 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4273 return WERR_INVALID_NAME;
4276 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4277 info, count);
4280 if (flags & PRINTER_ENUM_REMOTE) {
4281 return WERR_UNKNOWN_LEVEL;
4284 return WERR_OK;
4287 /********************************************************************
4288 * handle enumeration of printers at level 4
4289 ********************************************************************/
4291 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4292 const struct auth_serversupplied_info *server_info,
4293 struct messaging_context *msg_ctx,
4294 uint32_t flags,
4295 const char *servername,
4296 union spoolss_PrinterInfo **info,
4297 uint32_t *count)
4299 DEBUG(4,("enum_all_printers_info_4\n"));
4301 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4302 4, flags, info, count);
4306 /********************************************************************
4307 * handle enumeration of printers at level 5
4308 ********************************************************************/
4310 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4311 const struct auth_serversupplied_info *server_info,
4312 struct messaging_context *msg_ctx,
4313 uint32_t flags,
4314 const char *servername,
4315 union spoolss_PrinterInfo **info,
4316 uint32_t *count)
4318 DEBUG(4,("enum_all_printers_info_5\n"));
4320 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4321 5, flags, info, count);
4324 /****************************************************************
4325 _spoolss_EnumPrinters
4326 ****************************************************************/
4328 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4329 struct spoolss_EnumPrinters *r)
4331 const struct auth_serversupplied_info *server_info = get_server_info_system();
4332 const char *name = NULL;
4333 WERROR result;
4335 /* that's an [in out] buffer */
4337 if (!r->in.buffer && (r->in.offered != 0)) {
4338 return WERR_INVALID_PARAM;
4341 DEBUG(4,("_spoolss_EnumPrinters\n"));
4343 *r->out.needed = 0;
4344 *r->out.count = 0;
4345 *r->out.info = NULL;
4348 * Level 1:
4349 * flags==PRINTER_ENUM_NAME
4350 * if name=="" then enumerates all printers
4351 * if name!="" then enumerate the printer
4352 * flags==PRINTER_ENUM_REMOTE
4353 * name is NULL, enumerate printers
4354 * Level 2: name!="" enumerates printers, name can't be NULL
4355 * Level 3: doesn't exist
4356 * Level 4: does a local registry lookup
4357 * Level 5: same as Level 2
4360 if (r->in.server) {
4361 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4362 W_ERROR_HAVE_NO_MEMORY(name);
4365 switch (r->in.level) {
4366 case 0:
4367 result = enumprinters_level0(p->mem_ctx, server_info,
4368 p->msg_ctx, r->in.flags, name,
4369 r->out.info, r->out.count);
4370 break;
4371 case 1:
4372 result = enumprinters_level1(p->mem_ctx, server_info,
4373 p->msg_ctx, r->in.flags, name,
4374 r->out.info, r->out.count);
4375 break;
4376 case 2:
4377 result = enumprinters_level2(p->mem_ctx, server_info,
4378 p->msg_ctx, r->in.flags, name,
4379 r->out.info, r->out.count);
4380 break;
4381 case 4:
4382 result = enumprinters_level4(p->mem_ctx, server_info,
4383 p->msg_ctx, r->in.flags, name,
4384 r->out.info, r->out.count);
4385 break;
4386 case 5:
4387 result = enumprinters_level5(p->mem_ctx, server_info,
4388 p->msg_ctx, r->in.flags, name,
4389 r->out.info, r->out.count);
4390 break;
4391 default:
4392 return WERR_UNKNOWN_LEVEL;
4395 if (!W_ERROR_IS_OK(result)) {
4396 return result;
4399 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4400 spoolss_EnumPrinters,
4401 *r->out.info, r->in.level,
4402 *r->out.count);
4403 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4404 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4406 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4409 /****************************************************************
4410 _spoolss_GetPrinter
4411 ****************************************************************/
4413 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4414 struct spoolss_GetPrinter *r)
4416 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4417 struct spoolss_PrinterInfo2 *info2 = NULL;
4418 WERROR result = WERR_OK;
4419 const char *servername = NULL;
4420 int snum;
4422 /* that's an [in out] buffer */
4424 if (!r->in.buffer && (r->in.offered != 0)) {
4425 return WERR_INVALID_PARAM;
4428 *r->out.needed = 0;
4430 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4431 return WERR_BADFID;
4434 if (Printer != NULL || Printer->servername != NULL) {
4435 servername = Printer->servername;
4438 result = winreg_get_printer(p->mem_ctx,
4439 get_server_info_system(),
4440 p->msg_ctx,
4441 servername,
4442 lp_const_servicename(snum),
4443 &info2);
4444 if (!W_ERROR_IS_OK(result)) {
4445 return result;
4448 switch (r->in.level) {
4449 case 0:
4450 result = construct_printer_info0(p->mem_ctx,
4451 get_server_info_system(),
4452 p->msg_ctx,
4453 info2,
4454 &r->out.info->info0,
4455 snum);
4456 break;
4457 case 1:
4458 result = construct_printer_info1(p->mem_ctx, info2,
4459 PRINTER_ENUM_ICON8,
4460 &r->out.info->info1, snum);
4461 break;
4462 case 2:
4463 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4464 &r->out.info->info2, snum);
4465 break;
4466 case 3:
4467 result = construct_printer_info3(p->mem_ctx, info2,
4468 &r->out.info->info3, snum);
4469 break;
4470 case 4:
4471 result = construct_printer_info4(p->mem_ctx, info2,
4472 &r->out.info->info4, snum);
4473 break;
4474 case 5:
4475 result = construct_printer_info5(p->mem_ctx, info2,
4476 &r->out.info->info5, snum);
4477 break;
4478 case 6:
4479 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4480 &r->out.info->info6, snum);
4481 break;
4482 case 7:
4483 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4484 Printer,
4485 &r->out.info->info7, snum);
4486 break;
4487 case 8:
4488 result = construct_printer_info8(p->mem_ctx, info2,
4489 &r->out.info->info8, snum);
4490 break;
4491 default:
4492 result = WERR_UNKNOWN_LEVEL;
4493 break;
4496 if (!W_ERROR_IS_OK(result)) {
4497 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4498 r->in.level, win_errstr(result)));
4499 TALLOC_FREE(r->out.info);
4500 return result;
4503 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4504 r->out.info, r->in.level);
4505 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4507 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4510 /********************************************************************
4511 ********************************************************************/
4513 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4514 do { \
4515 if (in && strlen(in)) { \
4516 out = talloc_strdup(mem_ctx, in); \
4517 } else { \
4518 out = talloc_strdup(mem_ctx, ""); \
4520 W_ERROR_HAVE_NO_MEMORY(out); \
4521 } while (0);
4523 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4524 do { \
4525 if (in && strlen(in)) { \
4526 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4527 } else { \
4528 out = talloc_strdup(mem_ctx, ""); \
4530 W_ERROR_HAVE_NO_MEMORY(out); \
4531 } while (0);
4533 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4534 const char **string_array,
4535 const char ***presult,
4536 const char *cservername,
4537 const char *arch,
4538 int version)
4540 int i, num_strings = 0;
4541 const char **array = NULL;
4543 if (string_array == NULL) {
4544 return WERR_INVALID_PARAMETER;;
4547 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4548 const char *str = NULL;
4550 if (cservername == NULL || arch == NULL) {
4551 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4552 } else {
4553 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4556 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4557 TALLOC_FREE(array);
4558 return WERR_NOMEM;
4562 if (i > 0) {
4563 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4564 &array, &num_strings);
4567 if (presult) {
4568 *presult = array;
4571 return WERR_OK;
4574 /********************************************************************
4575 * fill a spoolss_DriverInfo1 struct
4576 ********************************************************************/
4578 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4579 struct spoolss_DriverInfo1 *r,
4580 const struct spoolss_DriverInfo8 *driver,
4581 const char *servername)
4583 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4584 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4586 return WERR_OK;
4589 /********************************************************************
4590 * fill a spoolss_DriverInfo2 struct
4591 ********************************************************************/
4593 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4594 struct spoolss_DriverInfo2 *r,
4595 const struct spoolss_DriverInfo8 *driver,
4596 const char *servername)
4599 const char *cservername = canon_servername(servername);
4601 r->version = driver->version;
4603 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4604 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4605 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4606 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4608 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4609 driver->architecture,
4610 driver->version,
4611 driver->driver_path,
4612 r->driver_path);
4614 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4615 driver->architecture,
4616 driver->version,
4617 driver->data_file,
4618 r->data_file);
4620 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4621 driver->architecture,
4622 driver->version,
4623 driver->config_file,
4624 r->config_file);
4626 return WERR_OK;
4629 /********************************************************************
4630 * fill a spoolss_DriverInfo3 struct
4631 ********************************************************************/
4633 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4634 struct spoolss_DriverInfo3 *r,
4635 const struct spoolss_DriverInfo8 *driver,
4636 const char *servername)
4638 const char *cservername = canon_servername(servername);
4640 r->version = driver->version;
4642 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4643 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4644 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4645 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4647 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4648 driver->architecture,
4649 driver->version,
4650 driver->driver_path,
4651 r->driver_path);
4653 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4654 driver->architecture,
4655 driver->version,
4656 driver->data_file,
4657 r->data_file);
4659 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4660 driver->architecture,
4661 driver->version,
4662 driver->config_file,
4663 r->config_file);
4665 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4666 driver->architecture,
4667 driver->version,
4668 driver->help_file,
4669 r->help_file);
4671 FILL_DRIVER_STRING(mem_ctx,
4672 driver->monitor_name,
4673 r->monitor_name);
4675 FILL_DRIVER_STRING(mem_ctx,
4676 driver->default_datatype,
4677 r->default_datatype);
4679 return string_array_from_driver_info(mem_ctx,
4680 driver->dependent_files,
4681 &r->dependent_files,
4682 cservername,
4683 driver->architecture,
4684 driver->version);
4687 /********************************************************************
4688 * fill a spoolss_DriverInfo4 struct
4689 ********************************************************************/
4691 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4692 struct spoolss_DriverInfo4 *r,
4693 const struct spoolss_DriverInfo8 *driver,
4694 const char *servername)
4696 const char *cservername = canon_servername(servername);
4697 WERROR result;
4699 r->version = driver->version;
4701 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4702 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4703 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4704 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4706 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4707 driver->architecture,
4708 driver->version,
4709 driver->driver_path,
4710 r->driver_path);
4712 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4713 driver->architecture,
4714 driver->version,
4715 driver->data_file,
4716 r->data_file);
4718 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4719 driver->architecture,
4720 driver->version,
4721 driver->config_file,
4722 r->config_file);
4724 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4725 driver->architecture,
4726 driver->version,
4727 driver->help_file,
4728 r->help_file);
4730 result = string_array_from_driver_info(mem_ctx,
4731 driver->dependent_files,
4732 &r->dependent_files,
4733 cservername,
4734 driver->architecture,
4735 driver->version);
4736 if (!W_ERROR_IS_OK(result)) {
4737 return result;
4740 FILL_DRIVER_STRING(mem_ctx,
4741 driver->monitor_name,
4742 r->monitor_name);
4744 FILL_DRIVER_STRING(mem_ctx,
4745 driver->default_datatype,
4746 r->default_datatype);
4749 result = string_array_from_driver_info(mem_ctx,
4750 driver->previous_names,
4751 &r->previous_names,
4752 NULL, NULL, 0);
4754 return result;
4757 /********************************************************************
4758 * fill a spoolss_DriverInfo5 struct
4759 ********************************************************************/
4761 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4762 struct spoolss_DriverInfo5 *r,
4763 const struct spoolss_DriverInfo8 *driver,
4764 const char *servername)
4766 const char *cservername = canon_servername(servername);
4768 r->version = driver->version;
4770 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4771 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4772 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4773 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4775 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4776 driver->architecture,
4777 driver->version,
4778 driver->driver_path,
4779 r->driver_path);
4781 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4782 driver->architecture,
4783 driver->version,
4784 driver->data_file,
4785 r->data_file);
4787 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4788 driver->architecture,
4789 driver->version,
4790 driver->config_file,
4791 r->config_file);
4793 r->driver_attributes = 0;
4794 r->config_version = 0;
4795 r->driver_version = 0;
4797 return WERR_OK;
4799 /********************************************************************
4800 * fill a spoolss_DriverInfo6 struct
4801 ********************************************************************/
4803 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4804 struct spoolss_DriverInfo6 *r,
4805 const struct spoolss_DriverInfo8 *driver,
4806 const char *servername)
4808 const char *cservername = canon_servername(servername);
4809 WERROR result;
4811 r->version = driver->version;
4813 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4814 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4815 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4816 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4818 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4819 driver->architecture,
4820 driver->version,
4821 driver->driver_path,
4822 r->driver_path);
4824 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4825 driver->architecture,
4826 driver->version,
4827 driver->data_file,
4828 r->data_file);
4830 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4831 driver->architecture,
4832 driver->version,
4833 driver->config_file,
4834 r->config_file);
4836 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4837 driver->architecture,
4838 driver->version,
4839 driver->help_file,
4840 r->help_file);
4842 FILL_DRIVER_STRING(mem_ctx,
4843 driver->monitor_name,
4844 r->monitor_name);
4846 FILL_DRIVER_STRING(mem_ctx,
4847 driver->default_datatype,
4848 r->default_datatype);
4850 result = string_array_from_driver_info(mem_ctx,
4851 driver->dependent_files,
4852 &r->dependent_files,
4853 cservername,
4854 driver->architecture,
4855 driver->version);
4856 if (!W_ERROR_IS_OK(result)) {
4857 return result;
4860 result = string_array_from_driver_info(mem_ctx,
4861 driver->previous_names,
4862 &r->previous_names,
4863 NULL, NULL, 0);
4864 if (!W_ERROR_IS_OK(result)) {
4865 return result;
4868 r->driver_date = driver->driver_date;
4869 r->driver_version = driver->driver_version;
4871 FILL_DRIVER_STRING(mem_ctx,
4872 driver->manufacturer_name,
4873 r->manufacturer_name);
4874 FILL_DRIVER_STRING(mem_ctx,
4875 driver->manufacturer_url,
4876 r->manufacturer_url);
4877 FILL_DRIVER_STRING(mem_ctx,
4878 driver->hardware_id,
4879 r->hardware_id);
4880 FILL_DRIVER_STRING(mem_ctx,
4881 driver->provider,
4882 r->provider);
4884 return WERR_OK;
4887 /********************************************************************
4888 * fill a spoolss_DriverInfo8 struct
4889 ********************************************************************/
4891 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4892 struct spoolss_DriverInfo8 *r,
4893 const struct spoolss_DriverInfo8 *driver,
4894 const char *servername)
4896 const char *cservername = canon_servername(servername);
4897 WERROR result;
4899 r->version = driver->version;
4901 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4902 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4903 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4904 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4906 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4907 driver->architecture,
4908 driver->version,
4909 driver->driver_path,
4910 r->driver_path);
4912 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4913 driver->architecture,
4914 driver->version,
4915 driver->data_file,
4916 r->data_file);
4918 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4919 driver->architecture,
4920 driver->version,
4921 driver->config_file,
4922 r->config_file);
4924 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4925 driver->architecture,
4926 driver->version,
4927 driver->help_file,
4928 r->help_file);
4930 FILL_DRIVER_STRING(mem_ctx,
4931 driver->monitor_name,
4932 r->monitor_name);
4934 FILL_DRIVER_STRING(mem_ctx,
4935 driver->default_datatype,
4936 r->default_datatype);
4938 result = string_array_from_driver_info(mem_ctx,
4939 driver->dependent_files,
4940 &r->dependent_files,
4941 cservername,
4942 driver->architecture,
4943 driver->version);
4944 if (!W_ERROR_IS_OK(result)) {
4945 return result;
4948 result = string_array_from_driver_info(mem_ctx,
4949 driver->previous_names,
4950 &r->previous_names,
4951 NULL, NULL, 0);
4952 if (!W_ERROR_IS_OK(result)) {
4953 return result;
4956 r->driver_date = driver->driver_date;
4957 r->driver_version = driver->driver_version;
4959 FILL_DRIVER_STRING(mem_ctx,
4960 driver->manufacturer_name,
4961 r->manufacturer_name);
4962 FILL_DRIVER_STRING(mem_ctx,
4963 driver->manufacturer_url,
4964 r->manufacturer_url);
4965 FILL_DRIVER_STRING(mem_ctx,
4966 driver->hardware_id,
4967 r->hardware_id);
4968 FILL_DRIVER_STRING(mem_ctx,
4969 driver->provider,
4970 r->provider);
4972 FILL_DRIVER_STRING(mem_ctx,
4973 driver->print_processor,
4974 r->print_processor);
4975 FILL_DRIVER_STRING(mem_ctx,
4976 driver->vendor_setup,
4977 r->vendor_setup);
4979 result = string_array_from_driver_info(mem_ctx,
4980 driver->color_profiles,
4981 &r->color_profiles,
4982 NULL, NULL, 0);
4983 if (!W_ERROR_IS_OK(result)) {
4984 return result;
4987 FILL_DRIVER_STRING(mem_ctx,
4988 driver->inf_path,
4989 r->inf_path);
4991 r->printer_driver_attributes = driver->printer_driver_attributes;
4993 result = string_array_from_driver_info(mem_ctx,
4994 driver->core_driver_dependencies,
4995 &r->core_driver_dependencies,
4996 NULL, NULL, 0);
4997 if (!W_ERROR_IS_OK(result)) {
4998 return result;
5001 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5002 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5004 return WERR_OK;
5007 #if 0 /* disabled until marshalling issues are resolved - gd */
5008 /********************************************************************
5009 ********************************************************************/
5011 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5012 struct spoolss_DriverFileInfo *r,
5013 const char *cservername,
5014 const char *file_name,
5015 enum spoolss_DriverFileType file_type,
5016 uint32_t file_version)
5018 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5019 cservername, file_name);
5020 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5021 r->file_type = file_type;
5022 r->file_version = file_version;
5024 return WERR_OK;
5027 /********************************************************************
5028 ********************************************************************/
5030 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5031 const struct spoolss_DriverInfo8 *driver,
5032 const char *cservername,
5033 struct spoolss_DriverFileInfo **info_p,
5034 uint32_t *count_p)
5036 struct spoolss_DriverFileInfo *info = NULL;
5037 uint32_t count = 0;
5038 WERROR result;
5039 uint32_t i;
5041 *info_p = NULL;
5042 *count_p = 0;
5044 if (strlen(driver->driver_path)) {
5045 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5046 struct spoolss_DriverFileInfo,
5047 count + 1);
5048 W_ERROR_HAVE_NO_MEMORY(info);
5049 result = fill_spoolss_DriverFileInfo(info,
5050 &info[count],
5051 cservername,
5052 driver->driver_path,
5053 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5055 W_ERROR_NOT_OK_RETURN(result);
5056 count++;
5059 if (strlen(driver->config_file)) {
5060 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5061 struct spoolss_DriverFileInfo,
5062 count + 1);
5063 W_ERROR_HAVE_NO_MEMORY(info);
5064 result = fill_spoolss_DriverFileInfo(info,
5065 &info[count],
5066 cservername,
5067 driver->config_file,
5068 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5070 W_ERROR_NOT_OK_RETURN(result);
5071 count++;
5074 if (strlen(driver->data_file)) {
5075 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5076 struct spoolss_DriverFileInfo,
5077 count + 1);
5078 W_ERROR_HAVE_NO_MEMORY(info);
5079 result = fill_spoolss_DriverFileInfo(info,
5080 &info[count],
5081 cservername,
5082 driver->data_file,
5083 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5085 W_ERROR_NOT_OK_RETURN(result);
5086 count++;
5089 if (strlen(driver->help_file)) {
5090 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5091 struct spoolss_DriverFileInfo,
5092 count + 1);
5093 W_ERROR_HAVE_NO_MEMORY(info);
5094 result = fill_spoolss_DriverFileInfo(info,
5095 &info[count],
5096 cservername,
5097 driver->help_file,
5098 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5100 W_ERROR_NOT_OK_RETURN(result);
5101 count++;
5104 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5105 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5106 struct spoolss_DriverFileInfo,
5107 count + 1);
5108 W_ERROR_HAVE_NO_MEMORY(info);
5109 result = fill_spoolss_DriverFileInfo(info,
5110 &info[count],
5111 cservername,
5112 driver->dependent_files[i],
5113 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5115 W_ERROR_NOT_OK_RETURN(result);
5116 count++;
5119 *info_p = info;
5120 *count_p = count;
5122 return WERR_OK;
5125 /********************************************************************
5126 * fill a spoolss_DriverInfo101 struct
5127 ********************************************************************/
5129 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5130 struct spoolss_DriverInfo101 *r,
5131 const struct spoolss_DriverInfo8 *driver,
5132 const char *servername)
5134 const char *cservername = canon_servername(servername);
5135 WERROR result;
5137 r->version = driver->version;
5139 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5140 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5141 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5142 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5144 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5145 cservername,
5146 &r->file_info,
5147 &r->file_count);
5148 if (!W_ERROR_IS_OK(result)) {
5149 return result;
5152 FILL_DRIVER_STRING(mem_ctx,
5153 driver->monitor_name,
5154 r->monitor_name);
5156 FILL_DRIVER_STRING(mem_ctx,
5157 driver->default_datatype,
5158 r->default_datatype);
5160 result = string_array_from_driver_info(mem_ctx,
5161 driver->previous_names,
5162 &r->previous_names,
5163 NULL, NULL, 0);
5164 if (!W_ERROR_IS_OK(result)) {
5165 return result;
5168 r->driver_date = driver->driver_date;
5169 r->driver_version = driver->driver_version;
5171 FILL_DRIVER_STRING(mem_ctx,
5172 driver->manufacturer_name,
5173 r->manufacturer_name);
5174 FILL_DRIVER_STRING(mem_ctx,
5175 driver->manufacturer_url,
5176 r->manufacturer_url);
5177 FILL_DRIVER_STRING(mem_ctx,
5178 driver->hardware_id,
5179 r->hardware_id);
5180 FILL_DRIVER_STRING(mem_ctx,
5181 driver->provider,
5182 r->provider);
5184 return WERR_OK;
5186 #endif
5187 /********************************************************************
5188 ********************************************************************/
5190 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5191 const struct auth_serversupplied_info *server_info,
5192 struct messaging_context *msg_ctx,
5193 uint32_t level,
5194 union spoolss_DriverInfo *r,
5195 int snum,
5196 const char *servername,
5197 const char *architecture,
5198 uint32_t version)
5200 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5201 struct spoolss_DriverInfo8 *driver;
5202 WERROR result;
5204 result = winreg_get_printer(mem_ctx,
5205 server_info,
5206 msg_ctx,
5207 servername,
5208 lp_const_servicename(snum),
5209 &pinfo2);
5211 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5212 win_errstr(result)));
5214 if (!W_ERROR_IS_OK(result)) {
5215 return WERR_INVALID_PRINTER_NAME;
5218 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5219 architecture,
5220 pinfo2->drivername, version, &driver);
5222 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5223 win_errstr(result)));
5225 if (!W_ERROR_IS_OK(result)) {
5227 * Is this a W2k client ?
5230 if (version < 3) {
5231 talloc_free(pinfo2);
5232 return WERR_UNKNOWN_PRINTER_DRIVER;
5235 /* Yes - try again with a WinNT driver. */
5236 version = 2;
5237 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5238 architecture,
5239 pinfo2->drivername,
5240 version, &driver);
5241 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5242 win_errstr(result)));
5243 if (!W_ERROR_IS_OK(result)) {
5244 talloc_free(pinfo2);
5245 return WERR_UNKNOWN_PRINTER_DRIVER;
5249 switch (level) {
5250 case 1:
5251 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5252 break;
5253 case 2:
5254 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5255 break;
5256 case 3:
5257 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5258 break;
5259 case 4:
5260 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5261 break;
5262 case 5:
5263 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5264 break;
5265 case 6:
5266 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5267 break;
5268 case 8:
5269 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5270 break;
5271 #if 0 /* disabled until marshalling issues are resolved - gd */
5272 case 101:
5273 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5274 break;
5275 #endif
5276 default:
5277 result = WERR_UNKNOWN_LEVEL;
5278 break;
5281 talloc_free(pinfo2);
5282 talloc_free(driver);
5284 return result;
5287 /****************************************************************
5288 _spoolss_GetPrinterDriver2
5289 ****************************************************************/
5291 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5292 struct spoolss_GetPrinterDriver2 *r)
5294 struct printer_handle *printer;
5295 WERROR result;
5297 int snum;
5299 /* that's an [in out] buffer */
5301 if (!r->in.buffer && (r->in.offered != 0)) {
5302 return WERR_INVALID_PARAM;
5305 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5307 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5308 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5309 return WERR_INVALID_PRINTER_NAME;
5312 *r->out.needed = 0;
5313 *r->out.server_major_version = 0;
5314 *r->out.server_minor_version = 0;
5316 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5317 return WERR_BADFID;
5320 result = construct_printer_driver_info_level(p->mem_ctx,
5321 get_server_info_system(),
5322 p->msg_ctx,
5323 r->in.level, r->out.info,
5324 snum, printer->servername,
5325 r->in.architecture,
5326 r->in.client_major_version);
5327 if (!W_ERROR_IS_OK(result)) {
5328 TALLOC_FREE(r->out.info);
5329 return result;
5332 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5333 r->out.info, r->in.level);
5334 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5336 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5340 /****************************************************************
5341 _spoolss_StartPagePrinter
5342 ****************************************************************/
5344 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5345 struct spoolss_StartPagePrinter *r)
5347 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5349 if (!Printer) {
5350 DEBUG(3,("_spoolss_StartPagePrinter: "
5351 "Error in startpageprinter printer handle\n"));
5352 return WERR_BADFID;
5355 Printer->page_started = true;
5356 return WERR_OK;
5359 /****************************************************************
5360 _spoolss_EndPagePrinter
5361 ****************************************************************/
5363 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5364 struct spoolss_EndPagePrinter *r)
5366 int snum;
5368 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5370 if (!Printer) {
5371 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5372 OUR_HANDLE(r->in.handle)));
5373 return WERR_BADFID;
5376 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5377 return WERR_BADFID;
5379 Printer->page_started = false;
5380 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5382 return WERR_OK;
5385 /****************************************************************
5386 _spoolss_StartDocPrinter
5387 ****************************************************************/
5389 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5390 struct spoolss_StartDocPrinter *r)
5392 struct spoolss_DocumentInfo1 *info_1;
5393 int snum;
5394 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5395 WERROR werr;
5397 if (!Printer) {
5398 DEBUG(2,("_spoolss_StartDocPrinter: "
5399 "Invalid handle (%s:%u:%u)\n",
5400 OUR_HANDLE(r->in.handle)));
5401 return WERR_BADFID;
5404 if (Printer->jobid) {
5405 DEBUG(2, ("_spoolss_StartDocPrinter: "
5406 "StartDocPrinter called twice! "
5407 "(existing jobid = %d)\n", Printer->jobid));
5408 return WERR_INVALID_HANDLE;
5411 if (r->in.level != 1) {
5412 return WERR_UNKNOWN_LEVEL;
5415 info_1 = r->in.info.info1;
5418 * a nice thing with NT is it doesn't listen to what you tell it.
5419 * when asked to send _only_ RAW datas, it tries to send datas
5420 * in EMF format.
5422 * So I add checks like in NT Server ...
5425 if (info_1->datatype) {
5426 if (strcmp(info_1->datatype, "RAW") != 0) {
5427 *r->out.job_id = 0;
5428 return WERR_INVALID_DATATYPE;
5432 /* get the share number of the printer */
5433 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5434 return WERR_BADFID;
5437 werr = print_job_start(get_server_info_system(),
5438 p->msg_ctx,
5439 p->client_id->name,
5440 snum,
5441 info_1->document_name,
5442 info_1->output_file,
5443 Printer->devmode,
5444 &Printer->jobid);
5446 /* An error occured in print_job_start() so return an appropriate
5447 NT error code. */
5449 if (!W_ERROR_IS_OK(werr)) {
5450 return werr;
5453 Printer->document_started = true;
5454 *r->out.job_id = Printer->jobid;
5456 return WERR_OK;
5459 /****************************************************************
5460 _spoolss_EndDocPrinter
5461 ****************************************************************/
5463 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5464 struct spoolss_EndDocPrinter *r)
5466 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5467 NTSTATUS status;
5468 int snum;
5470 if (!Printer) {
5471 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5472 OUR_HANDLE(r->in.handle)));
5473 return WERR_BADFID;
5476 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5477 return WERR_BADFID;
5480 Printer->document_started = false;
5481 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5482 if (!NT_STATUS_IS_OK(status)) {
5483 DEBUG(2, ("_spoolss_EndDocPrinter: "
5484 "print_job_end failed [%s]\n",
5485 nt_errstr(status)));
5488 Printer->jobid = 0;
5489 return ntstatus_to_werror(status);
5492 /****************************************************************
5493 _spoolss_WritePrinter
5494 ****************************************************************/
5496 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5497 struct spoolss_WritePrinter *r)
5499 ssize_t buffer_written;
5500 int snum;
5501 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5503 if (!Printer) {
5504 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5505 OUR_HANDLE(r->in.handle)));
5506 *r->out.num_written = r->in._data_size;
5507 return WERR_BADFID;
5510 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5511 return WERR_BADFID;
5513 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5514 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5515 snum, Printer->jobid,
5516 (const char *)r->in.data.data,
5517 (size_t)r->in._data_size);
5518 if (buffer_written == (ssize_t)-1) {
5519 *r->out.num_written = 0;
5520 if (errno == ENOSPC)
5521 return WERR_NO_SPOOL_SPACE;
5522 else
5523 return WERR_ACCESS_DENIED;
5526 *r->out.num_written = r->in._data_size;
5528 return WERR_OK;
5531 /********************************************************************
5532 * api_spoolss_getprinter
5533 * called from the spoolss dispatcher
5535 ********************************************************************/
5537 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5538 struct pipes_struct *p)
5540 const struct auth_serversupplied_info *server_info = get_server_info_system();
5541 int snum;
5542 WERROR errcode = WERR_BADFUNC;
5543 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5545 if (!Printer) {
5546 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5547 OUR_HANDLE(handle)));
5548 return WERR_BADFID;
5551 if (!get_printer_snum(p, handle, &snum, NULL))
5552 return WERR_BADFID;
5554 switch (command) {
5555 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5556 errcode = print_queue_pause(server_info, p->msg_ctx, snum);
5557 break;
5558 case SPOOLSS_PRINTER_CONTROL_RESUME:
5559 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5560 errcode = print_queue_resume(server_info, p->msg_ctx, snum);
5561 break;
5562 case SPOOLSS_PRINTER_CONTROL_PURGE:
5563 errcode = print_queue_purge(server_info, p->msg_ctx, snum);
5564 break;
5565 default:
5566 return WERR_UNKNOWN_LEVEL;
5569 return errcode;
5573 /****************************************************************
5574 _spoolss_AbortPrinter
5575 * From MSDN: "Deletes printer's spool file if printer is configured
5576 * for spooling"
5577 ****************************************************************/
5579 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5580 struct spoolss_AbortPrinter *r)
5582 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5583 int snum;
5584 WERROR errcode = WERR_OK;
5586 if (!Printer) {
5587 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5588 OUR_HANDLE(r->in.handle)));
5589 return WERR_BADFID;
5592 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5593 return WERR_BADFID;
5595 if (!Printer->document_started) {
5596 return WERR_SPL_NO_STARTDOC;
5599 errcode = print_job_delete(get_server_info_system(),
5600 p->msg_ctx,
5601 snum,
5602 Printer->jobid);
5604 return errcode;
5607 /********************************************************************
5608 * called by spoolss_api_setprinter
5609 * when updating a printer description
5610 ********************************************************************/
5612 static WERROR update_printer_sec(struct policy_handle *handle,
5613 struct pipes_struct *p,
5614 struct sec_desc_buf *secdesc_ctr)
5616 struct spoolss_security_descriptor *new_secdesc = NULL;
5617 struct spoolss_security_descriptor *old_secdesc = NULL;
5618 const char *printer;
5619 WERROR result;
5620 int snum;
5622 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5624 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5625 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5626 OUR_HANDLE(handle)));
5628 result = WERR_BADFID;
5629 goto done;
5632 if (secdesc_ctr == NULL) {
5633 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5634 result = WERR_INVALID_PARAM;
5635 goto done;
5637 printer = lp_const_servicename(snum);
5639 /* Check the user has permissions to change the security
5640 descriptor. By experimentation with two NT machines, the user
5641 requires Full Access to the printer to change security
5642 information. */
5644 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5645 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5646 result = WERR_ACCESS_DENIED;
5647 goto done;
5650 /* NT seems to like setting the security descriptor even though
5651 nothing may have actually changed. */
5652 result = winreg_get_printer_secdesc(p->mem_ctx,
5653 get_server_info_system(),
5654 p->msg_ctx,
5655 printer,
5656 &old_secdesc);
5657 if (!W_ERROR_IS_OK(result)) {
5658 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5659 result = WERR_BADFID;
5660 goto done;
5663 if (DEBUGLEVEL >= 10) {
5664 struct security_acl *the_acl;
5665 int i;
5667 the_acl = old_secdesc->dacl;
5668 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5669 printer, the_acl->num_aces));
5671 for (i = 0; i < the_acl->num_aces; i++) {
5672 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5673 &the_acl->aces[i].trustee),
5674 the_acl->aces[i].access_mask));
5677 the_acl = secdesc_ctr->sd->dacl;
5679 if (the_acl) {
5680 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5681 printer, the_acl->num_aces));
5683 for (i = 0; i < the_acl->num_aces; i++) {
5684 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5685 &the_acl->aces[i].trustee),
5686 the_acl->aces[i].access_mask));
5688 } else {
5689 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5693 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5694 if (new_secdesc == NULL) {
5695 result = WERR_NOMEM;
5696 goto done;
5699 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5700 result = WERR_OK;
5701 goto done;
5704 result = winreg_set_printer_secdesc(p->mem_ctx,
5705 get_server_info_system(),
5706 p->msg_ctx,
5707 printer,
5708 new_secdesc);
5710 done:
5711 return result;
5714 /********************************************************************
5715 Canonicalize printer info from a client
5716 ********************************************************************/
5718 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5719 struct spoolss_SetPrinterInfo2 *info2,
5720 int snum)
5722 fstring printername;
5723 const char *p;
5725 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5726 "portname=%s drivername=%s comment=%s location=%s\n",
5727 info2->servername, info2->printername, info2->sharename,
5728 info2->portname, info2->drivername, info2->comment,
5729 info2->location));
5731 /* we force some elements to "correct" values */
5732 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5733 if (info2->servername == NULL) {
5734 return false;
5736 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5737 if (info2->sharename == NULL) {
5738 return false;
5741 /* check to see if we allow printername != sharename */
5742 if (lp_force_printername(snum)) {
5743 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5744 global_myname(), info2->sharename);
5745 } else {
5746 /* make sure printername is in \\server\printername format */
5747 fstrcpy(printername, info2->printername);
5748 p = printername;
5749 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5750 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5751 p++;
5754 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5755 global_myname(), p);
5757 if (info2->printername == NULL) {
5758 return false;
5761 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5762 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5764 return true;
5767 /****************************************************************************
5768 ****************************************************************************/
5770 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5772 char *cmd = lp_addport_cmd();
5773 char *command = NULL;
5774 int ret;
5775 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5776 bool is_print_op = false;
5778 if ( !*cmd ) {
5779 return WERR_ACCESS_DENIED;
5782 command = talloc_asprintf(ctx,
5783 "%s \"%s\" \"%s\"", cmd, portname, uri );
5784 if (!command) {
5785 return WERR_NOMEM;
5788 if ( token )
5789 is_print_op = user_has_privileges( token, &se_printop );
5791 DEBUG(10,("Running [%s]\n", command));
5793 /********* BEGIN SePrintOperatorPrivilege **********/
5795 if ( is_print_op )
5796 become_root();
5798 ret = smbrun(command, NULL);
5800 if ( is_print_op )
5801 unbecome_root();
5803 /********* END SePrintOperatorPrivilege **********/
5805 DEBUGADD(10,("returned [%d]\n", ret));
5807 TALLOC_FREE(command);
5809 if ( ret != 0 ) {
5810 return WERR_ACCESS_DENIED;
5813 return WERR_OK;
5816 /****************************************************************************
5817 ****************************************************************************/
5819 static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5820 struct spoolss_SetPrinterInfo2 *info2,
5821 const char *remote_machine,
5822 struct messaging_context *msg_ctx)
5824 char *cmd = lp_addprinter_cmd();
5825 char **qlines;
5826 char *command = NULL;
5827 int numlines;
5828 int ret;
5829 int fd;
5830 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5831 bool is_print_op = false;
5833 if (!remote_machine) {
5834 return false;
5837 command = talloc_asprintf(ctx,
5838 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5839 cmd, info2->printername, info2->sharename,
5840 info2->portname, info2->drivername,
5841 info2->location, info2->comment, remote_machine);
5842 if (!command) {
5843 return false;
5846 if ( token )
5847 is_print_op = user_has_privileges( token, &se_printop );
5849 DEBUG(10,("Running [%s]\n", command));
5851 /********* BEGIN SePrintOperatorPrivilege **********/
5853 if ( is_print_op )
5854 become_root();
5856 if ( (ret = smbrun(command, &fd)) == 0 ) {
5857 /* Tell everyone we updated smb.conf. */
5858 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5861 if ( is_print_op )
5862 unbecome_root();
5864 /********* END SePrintOperatorPrivilege **********/
5866 DEBUGADD(10,("returned [%d]\n", ret));
5868 TALLOC_FREE(command);
5870 if ( ret != 0 ) {
5871 if (fd != -1)
5872 close(fd);
5873 return false;
5876 /* reload our services immediately */
5877 become_root();
5878 reload_services(msg_ctx, -1, false);
5879 unbecome_root();
5881 numlines = 0;
5882 /* Get lines and convert them back to dos-codepage */
5883 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5884 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5885 close(fd);
5887 /* Set the portname to what the script says the portname should be. */
5888 /* but don't require anything to be return from the script exit a good error code */
5890 if (numlines) {
5891 /* Set the portname to what the script says the portname should be. */
5892 info2->portname = talloc_strdup(ctx, qlines[0]);
5893 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5896 TALLOC_FREE(qlines);
5897 return true;
5900 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5901 const struct auth_serversupplied_info *server_info,
5902 struct messaging_context *msg_ctx,
5903 int snum,
5904 struct spoolss_SetPrinterInfo2 *printer,
5905 struct spoolss_PrinterInfo2 *old_printer)
5907 bool force_update = (old_printer == NULL);
5908 const char *dnsdomname;
5909 const char *longname;
5910 const char *uncname;
5911 const char *spooling;
5912 DATA_BLOB buffer;
5913 WERROR result = WERR_OK;
5915 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
5916 push_reg_sz(mem_ctx, &buffer, printer->drivername);
5917 winreg_set_printer_dataex(mem_ctx,
5918 server_info,
5919 msg_ctx,
5920 printer->sharename,
5921 SPOOL_DSSPOOLER_KEY,
5922 SPOOL_REG_DRIVERNAME,
5923 REG_SZ,
5924 buffer.data,
5925 buffer.length);
5927 if (!force_update) {
5928 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5929 printer->drivername));
5931 notify_printer_driver(server_event_context(), msg_ctx,
5932 snum, printer->drivername);
5936 if (force_update || !strequal(printer->comment, old_printer->comment)) {
5937 push_reg_sz(mem_ctx, &buffer, printer->comment);
5938 winreg_set_printer_dataex(mem_ctx,
5939 server_info,
5940 msg_ctx,
5941 printer->sharename,
5942 SPOOL_DSSPOOLER_KEY,
5943 SPOOL_REG_DESCRIPTION,
5944 REG_SZ,
5945 buffer.data,
5946 buffer.length);
5948 if (!force_update) {
5949 notify_printer_comment(server_event_context(), msg_ctx,
5950 snum, printer->comment);
5954 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
5955 push_reg_sz(mem_ctx, &buffer, printer->sharename);
5956 winreg_set_printer_dataex(mem_ctx,
5957 server_info,
5958 msg_ctx,
5959 printer->sharename,
5960 SPOOL_DSSPOOLER_KEY,
5961 SPOOL_REG_PRINTSHARENAME,
5962 REG_SZ,
5963 buffer.data,
5964 buffer.length);
5966 if (!force_update) {
5967 notify_printer_sharename(server_event_context(),
5968 msg_ctx,
5969 snum, printer->sharename);
5973 if (force_update || !strequal(printer->printername, old_printer->printername)) {
5974 const char *p;
5976 p = strrchr(printer->printername, '\\' );
5977 if (p != NULL) {
5978 p++;
5979 } else {
5980 p = printer->printername;
5983 push_reg_sz(mem_ctx, &buffer, p);
5984 winreg_set_printer_dataex(mem_ctx,
5985 server_info,
5986 msg_ctx,
5987 printer->sharename,
5988 SPOOL_DSSPOOLER_KEY,
5989 SPOOL_REG_PRINTERNAME,
5990 REG_SZ,
5991 buffer.data,
5992 buffer.length);
5994 if (!force_update) {
5995 notify_printer_printername(server_event_context(),
5996 msg_ctx, snum, p);
6000 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6001 push_reg_sz(mem_ctx, &buffer, printer->portname);
6002 winreg_set_printer_dataex(mem_ctx,
6003 server_info,
6004 msg_ctx,
6005 printer->sharename,
6006 SPOOL_DSSPOOLER_KEY,
6007 SPOOL_REG_PORTNAME,
6008 REG_SZ,
6009 buffer.data,
6010 buffer.length);
6012 if (!force_update) {
6013 notify_printer_port(server_event_context(),
6014 msg_ctx, snum, printer->portname);
6018 if (force_update || !strequal(printer->location, old_printer->location)) {
6019 push_reg_sz(mem_ctx, &buffer, printer->location);
6020 winreg_set_printer_dataex(mem_ctx,
6021 server_info,
6022 msg_ctx,
6023 printer->sharename,
6024 SPOOL_DSSPOOLER_KEY,
6025 SPOOL_REG_LOCATION,
6026 REG_SZ,
6027 buffer.data,
6028 buffer.length);
6030 if (!force_update) {
6031 notify_printer_location(server_event_context(),
6032 msg_ctx, snum,
6033 printer->location);
6037 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6038 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6039 winreg_set_printer_dataex(mem_ctx,
6040 server_info,
6041 msg_ctx,
6042 printer->sharename,
6043 SPOOL_DSSPOOLER_KEY,
6044 SPOOL_REG_PRINTSEPARATORFILE,
6045 REG_SZ,
6046 buffer.data,
6047 buffer.length);
6049 if (!force_update) {
6050 notify_printer_location(server_event_context(),
6051 msg_ctx, snum,
6052 printer->location);
6056 if (force_update || printer->starttime != old_printer->starttime) {
6057 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6058 SIVAL(buffer.data, 0, printer->starttime);
6059 winreg_set_printer_dataex(mem_ctx,
6060 server_info,
6061 msg_ctx,
6062 printer->sharename,
6063 SPOOL_DSSPOOLER_KEY,
6064 SPOOL_REG_PRINTSTARTTIME,
6065 REG_DWORD,
6066 buffer.data,
6067 buffer.length);
6070 if (force_update || printer->untiltime != old_printer->untiltime) {
6071 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6072 SIVAL(buffer.data, 0, printer->untiltime);
6073 winreg_set_printer_dataex(mem_ctx,
6074 server_info,
6075 msg_ctx,
6076 printer->sharename,
6077 SPOOL_DSSPOOLER_KEY,
6078 SPOOL_REG_PRINTENDTIME,
6079 REG_DWORD,
6080 buffer.data,
6081 buffer.length);
6084 if (force_update || printer->priority != old_printer->priority) {
6085 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6086 SIVAL(buffer.data, 0, printer->priority);
6087 winreg_set_printer_dataex(mem_ctx,
6088 server_info,
6089 msg_ctx,
6090 printer->sharename,
6091 SPOOL_DSSPOOLER_KEY,
6092 SPOOL_REG_PRIORITY,
6093 REG_DWORD,
6094 buffer.data,
6095 buffer.length);
6098 if (force_update || printer->attributes != old_printer->attributes) {
6099 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6100 SIVAL(buffer.data, 0, (printer->attributes &
6101 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6102 winreg_set_printer_dataex(mem_ctx,
6103 server_info,
6104 msg_ctx,
6105 printer->sharename,
6106 SPOOL_DSSPOOLER_KEY,
6107 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6108 REG_DWORD,
6109 buffer.data,
6110 buffer.length);
6112 switch (printer->attributes & 0x3) {
6113 case 0:
6114 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6115 break;
6116 case 1:
6117 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6118 break;
6119 case 2:
6120 spooling = SPOOL_REGVAL_PRINTDIRECT;
6121 break;
6122 default:
6123 spooling = "unknown";
6125 push_reg_sz(mem_ctx, &buffer, spooling);
6126 winreg_set_printer_dataex(mem_ctx,
6127 server_info,
6128 msg_ctx,
6129 printer->sharename,
6130 SPOOL_DSSPOOLER_KEY,
6131 SPOOL_REG_PRINTSPOOLING,
6132 REG_SZ,
6133 buffer.data,
6134 buffer.length);
6137 push_reg_sz(mem_ctx, &buffer, global_myname());
6138 winreg_set_printer_dataex(mem_ctx,
6139 server_info,
6140 msg_ctx,
6141 printer->sharename,
6142 SPOOL_DSSPOOLER_KEY,
6143 SPOOL_REG_SHORTSERVERNAME,
6144 REG_SZ,
6145 buffer.data,
6146 buffer.length);
6148 dnsdomname = get_mydnsfullname();
6149 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6150 longname = talloc_strdup(mem_ctx, dnsdomname);
6151 } else {
6152 longname = talloc_strdup(mem_ctx, global_myname());
6154 if (longname == NULL) {
6155 result = WERR_NOMEM;
6156 goto done;
6159 push_reg_sz(mem_ctx, &buffer, longname);
6160 winreg_set_printer_dataex(mem_ctx,
6161 server_info,
6162 msg_ctx,
6163 printer->sharename,
6164 SPOOL_DSSPOOLER_KEY,
6165 SPOOL_REG_SERVERNAME,
6166 REG_SZ,
6167 buffer.data,
6168 buffer.length);
6170 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6171 global_myname(), printer->sharename);
6172 push_reg_sz(mem_ctx, &buffer, uncname);
6173 winreg_set_printer_dataex(mem_ctx,
6174 server_info,
6175 msg_ctx,
6176 printer->sharename,
6177 SPOOL_DSSPOOLER_KEY,
6178 SPOOL_REG_UNCNAME,
6179 REG_SZ,
6180 buffer.data,
6181 buffer.length);
6183 done:
6184 return result;
6187 /********************************************************************
6188 * Called by spoolss_api_setprinter
6189 * when updating a printer description.
6190 ********************************************************************/
6192 static WERROR update_printer(struct pipes_struct *p,
6193 struct policy_handle *handle,
6194 struct spoolss_SetPrinterInfoCtr *info_ctr,
6195 struct spoolss_DeviceMode *devmode)
6197 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6198 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6199 struct spoolss_PrinterInfo2 *old_printer;
6200 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6201 const char *servername = NULL;
6202 int snum;
6203 WERROR result = WERR_OK;
6204 TALLOC_CTX *tmp_ctx;
6206 DEBUG(8,("update_printer\n"));
6208 tmp_ctx = talloc_new(p->mem_ctx);
6209 if (tmp_ctx == NULL) {
6210 return WERR_NOMEM;
6213 if (!Printer) {
6214 result = WERR_BADFID;
6215 goto done;
6218 if (!get_printer_snum(p, handle, &snum, NULL)) {
6219 result = WERR_BADFID;
6220 goto done;
6223 if (Printer != NULL || Printer->servername != NULL) {
6224 servername = Printer->servername;
6227 result = winreg_get_printer(tmp_ctx,
6228 get_server_info_system(),
6229 p->msg_ctx,
6230 servername,
6231 lp_const_servicename(snum),
6232 &old_printer);
6233 if (!W_ERROR_IS_OK(result)) {
6234 result = WERR_BADFID;
6235 goto done;
6238 /* Do sanity check on the requested changes for Samba */
6239 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6240 result = WERR_INVALID_PARAM;
6241 goto done;
6244 /* FIXME!!! If the driver has changed we really should verify that
6245 it is installed before doing much else --jerry */
6247 /* Check calling user has permission to update printer description */
6248 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6249 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6250 result = WERR_ACCESS_DENIED;
6251 goto done;
6254 /* Call addprinter hook */
6255 /* Check changes to see if this is really needed */
6257 if (*lp_addprinter_cmd() &&
6258 (!strequal(printer->drivername, old_printer->drivername) ||
6259 !strequal(printer->comment, old_printer->comment) ||
6260 !strequal(printer->portname, old_printer->portname) ||
6261 !strequal(printer->location, old_printer->location)) )
6263 /* add_printer_hook() will call reload_services() */
6264 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
6265 printer, p->client_id->addr,
6266 p->msg_ctx)) {
6267 result = WERR_ACCESS_DENIED;
6268 goto done;
6272 update_dsspooler(tmp_ctx,
6273 get_server_info_system(),
6274 p->msg_ctx,
6275 snum,
6276 printer,
6277 old_printer);
6279 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6281 if (devmode == NULL) {
6282 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6284 result = winreg_update_printer(tmp_ctx,
6285 get_server_info_system(),
6286 p->msg_ctx,
6287 printer->sharename,
6288 printer_mask,
6289 printer,
6290 devmode,
6291 NULL);
6293 done:
6294 talloc_free(tmp_ctx);
6296 return result;
6299 /****************************************************************************
6300 ****************************************************************************/
6301 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6302 struct policy_handle *handle,
6303 struct spoolss_SetPrinterInfo7 *info7)
6305 #ifdef HAVE_ADS
6306 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6307 WERROR result;
6308 int snum;
6309 struct printer_handle *Printer;
6311 if ( lp_security() != SEC_ADS ) {
6312 return WERR_UNKNOWN_LEVEL;
6315 Printer = find_printer_index_by_hnd(p, handle);
6317 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6319 if (!Printer)
6320 return WERR_BADFID;
6322 if (!get_printer_snum(p, handle, &snum, NULL))
6323 return WERR_BADFID;
6325 result = winreg_get_printer(p->mem_ctx,
6326 get_server_info_system(),
6327 p->msg_ctx,
6328 Printer->servername,
6329 lp_servicename(snum),
6330 &pinfo2);
6331 if (!W_ERROR_IS_OK(result)) {
6332 return WERR_BADFID;
6335 nt_printer_publish(pinfo2,
6336 get_server_info_system(),
6337 p->msg_ctx,
6338 pinfo2,
6339 info7->action);
6341 TALLOC_FREE(pinfo2);
6342 return WERR_OK;
6343 #else
6344 return WERR_UNKNOWN_LEVEL;
6345 #endif
6348 /********************************************************************
6349 ********************************************************************/
6351 static WERROR update_printer_devmode(struct pipes_struct *p,
6352 struct policy_handle *handle,
6353 struct spoolss_DeviceMode *devmode)
6355 int snum;
6356 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6357 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6359 DEBUG(8,("update_printer_devmode\n"));
6361 if (!Printer) {
6362 return WERR_BADFID;
6365 if (!get_printer_snum(p, handle, &snum, NULL)) {
6366 return WERR_BADFID;
6369 /* Check calling user has permission to update printer description */
6370 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6371 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6372 return WERR_ACCESS_DENIED;
6375 return winreg_update_printer(p->mem_ctx,
6376 get_server_info_system(),
6377 p->msg_ctx,
6378 lp_const_servicename(snum),
6379 info2_mask,
6380 NULL,
6381 devmode,
6382 NULL);
6386 /****************************************************************
6387 _spoolss_SetPrinter
6388 ****************************************************************/
6390 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6391 struct spoolss_SetPrinter *r)
6393 WERROR result;
6395 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6397 if (!Printer) {
6398 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6399 OUR_HANDLE(r->in.handle)));
6400 return WERR_BADFID;
6403 /* check the level */
6404 switch (r->in.info_ctr->level) {
6405 case 0:
6406 return control_printer(r->in.handle, r->in.command, p);
6407 case 2:
6408 result = update_printer(p, r->in.handle,
6409 r->in.info_ctr,
6410 r->in.devmode_ctr->devmode);
6411 if (!W_ERROR_IS_OK(result))
6412 return result;
6413 if (r->in.secdesc_ctr->sd)
6414 result = update_printer_sec(r->in.handle, p,
6415 r->in.secdesc_ctr);
6416 return result;
6417 case 3:
6418 return update_printer_sec(r->in.handle, p,
6419 r->in.secdesc_ctr);
6420 case 7:
6421 return publish_or_unpublish_printer(p, r->in.handle,
6422 r->in.info_ctr->info.info7);
6423 case 8:
6424 return update_printer_devmode(p, r->in.handle,
6425 r->in.devmode_ctr->devmode);
6426 default:
6427 return WERR_UNKNOWN_LEVEL;
6431 /****************************************************************
6432 _spoolss_FindClosePrinterNotify
6433 ****************************************************************/
6435 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6436 struct spoolss_FindClosePrinterNotify *r)
6438 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6440 if (!Printer) {
6441 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6442 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6443 return WERR_BADFID;
6446 if (Printer->notify.client_connected == true) {
6447 int snum = -1;
6449 if ( Printer->printer_type == SPLHND_SERVER)
6450 snum = -1;
6451 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6452 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6453 return WERR_BADFID;
6455 srv_spoolss_replycloseprinter(
6456 snum, &Printer->notify.client_hnd, p->msg_ctx);
6459 Printer->notify.flags=0;
6460 Printer->notify.options=0;
6461 Printer->notify.localmachine[0]='\0';
6462 Printer->notify.printerlocal=0;
6463 TALLOC_FREE(Printer->notify.option);
6464 Printer->notify.client_connected = false;
6466 return WERR_OK;
6469 /****************************************************************
6470 _spoolss_AddJob
6471 ****************************************************************/
6473 WERROR _spoolss_AddJob(struct pipes_struct *p,
6474 struct spoolss_AddJob *r)
6476 if (!r->in.buffer && (r->in.offered != 0)) {
6477 return WERR_INVALID_PARAM;
6480 /* this is what a NT server returns for AddJob. AddJob must fail on
6481 * non-local printers */
6483 if (r->in.level != 1) {
6484 return WERR_UNKNOWN_LEVEL;
6487 return WERR_INVALID_PARAM;
6490 /****************************************************************************
6491 fill_job_info1
6492 ****************************************************************************/
6494 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6495 struct spoolss_JobInfo1 *r,
6496 const print_queue_struct *queue,
6497 int position, int snum,
6498 struct spoolss_PrinterInfo2 *pinfo2)
6500 struct tm *t;
6502 t = gmtime(&queue->time);
6504 r->job_id = queue->job;
6506 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6507 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6508 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6509 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6510 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6511 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6512 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6513 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6514 r->data_type = talloc_strdup(mem_ctx, "RAW");
6515 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6516 r->text_status = talloc_strdup(mem_ctx, "");
6517 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6519 r->status = nt_printj_status(queue->status);
6520 r->priority = queue->priority;
6521 r->position = position;
6522 r->total_pages = queue->page_count;
6523 r->pages_printed = 0; /* ??? */
6525 init_systemtime(&r->submitted, t);
6527 return WERR_OK;
6530 /****************************************************************************
6531 fill_job_info2
6532 ****************************************************************************/
6534 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6535 struct spoolss_JobInfo2 *r,
6536 const print_queue_struct *queue,
6537 int position, int snum,
6538 struct spoolss_PrinterInfo2 *pinfo2,
6539 struct spoolss_DeviceMode *devmode)
6541 struct tm *t;
6543 t = gmtime(&queue->time);
6545 r->job_id = queue->job;
6547 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6548 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6549 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6550 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6551 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6552 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6553 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6554 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6555 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6556 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6557 r->data_type = talloc_strdup(mem_ctx, "RAW");
6558 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6559 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6560 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6561 r->parameters = talloc_strdup(mem_ctx, "");
6562 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6563 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6564 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6566 r->devmode = devmode;
6568 r->text_status = talloc_strdup(mem_ctx, "");
6569 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6571 r->secdesc = NULL;
6573 r->status = nt_printj_status(queue->status);
6574 r->priority = queue->priority;
6575 r->position = position;
6576 r->start_time = 0;
6577 r->until_time = 0;
6578 r->total_pages = queue->page_count;
6579 r->size = queue->size;
6580 init_systemtime(&r->submitted, t);
6581 r->time = 0;
6582 r->pages_printed = 0; /* ??? */
6584 return WERR_OK;
6587 /****************************************************************************
6588 fill_job_info3
6589 ****************************************************************************/
6591 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6592 struct spoolss_JobInfo3 *r,
6593 const print_queue_struct *queue,
6594 const print_queue_struct *next_queue,
6595 int position, int snum,
6596 struct spoolss_PrinterInfo2 *pinfo2)
6598 r->job_id = queue->job;
6599 r->next_job_id = 0;
6600 if (next_queue) {
6601 r->next_job_id = next_queue->job;
6603 r->reserved = 0;
6605 return WERR_OK;
6608 /****************************************************************************
6609 Enumjobs at level 1.
6610 ****************************************************************************/
6612 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6613 const print_queue_struct *queue,
6614 uint32_t num_queues, int snum,
6615 struct spoolss_PrinterInfo2 *pinfo2,
6616 union spoolss_JobInfo **info_p,
6617 uint32_t *count)
6619 union spoolss_JobInfo *info;
6620 int i;
6621 WERROR result = WERR_OK;
6623 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6624 W_ERROR_HAVE_NO_MEMORY(info);
6626 *count = num_queues;
6628 for (i=0; i<*count; i++) {
6629 result = fill_job_info1(info,
6630 &info[i].info1,
6631 &queue[i],
6633 snum,
6634 pinfo2);
6635 if (!W_ERROR_IS_OK(result)) {
6636 goto out;
6640 out:
6641 if (!W_ERROR_IS_OK(result)) {
6642 TALLOC_FREE(info);
6643 *count = 0;
6644 return result;
6647 *info_p = info;
6649 return WERR_OK;
6652 /****************************************************************************
6653 Enumjobs at level 2.
6654 ****************************************************************************/
6656 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6657 const print_queue_struct *queue,
6658 uint32_t num_queues, int snum,
6659 struct spoolss_PrinterInfo2 *pinfo2,
6660 union spoolss_JobInfo **info_p,
6661 uint32_t *count)
6663 union spoolss_JobInfo *info;
6664 int i;
6665 WERROR result = WERR_OK;
6667 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6668 W_ERROR_HAVE_NO_MEMORY(info);
6670 *count = num_queues;
6672 for (i=0; i<*count; i++) {
6673 struct spoolss_DeviceMode *devmode;
6675 result = spoolss_create_default_devmode(info,
6676 pinfo2->printername,
6677 &devmode);
6678 if (!W_ERROR_IS_OK(result)) {
6679 DEBUG(3, ("Can't proceed w/o a devmode!"));
6680 goto out;
6683 result = fill_job_info2(info,
6684 &info[i].info2,
6685 &queue[i],
6687 snum,
6688 pinfo2,
6689 devmode);
6690 if (!W_ERROR_IS_OK(result)) {
6691 goto out;
6695 out:
6696 if (!W_ERROR_IS_OK(result)) {
6697 TALLOC_FREE(info);
6698 *count = 0;
6699 return result;
6702 *info_p = info;
6704 return WERR_OK;
6707 /****************************************************************************
6708 Enumjobs at level 3.
6709 ****************************************************************************/
6711 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6712 const print_queue_struct *queue,
6713 uint32_t num_queues, int snum,
6714 struct spoolss_PrinterInfo2 *pinfo2,
6715 union spoolss_JobInfo **info_p,
6716 uint32_t *count)
6718 union spoolss_JobInfo *info;
6719 int i;
6720 WERROR result = WERR_OK;
6722 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6723 W_ERROR_HAVE_NO_MEMORY(info);
6725 *count = num_queues;
6727 for (i=0; i<*count; i++) {
6728 const print_queue_struct *next_queue = NULL;
6730 if (i+1 < *count) {
6731 next_queue = &queue[i+1];
6734 result = fill_job_info3(info,
6735 &info[i].info3,
6736 &queue[i],
6737 next_queue,
6739 snum,
6740 pinfo2);
6741 if (!W_ERROR_IS_OK(result)) {
6742 goto out;
6746 out:
6747 if (!W_ERROR_IS_OK(result)) {
6748 TALLOC_FREE(info);
6749 *count = 0;
6750 return result;
6753 *info_p = info;
6755 return WERR_OK;
6758 /****************************************************************
6759 _spoolss_EnumJobs
6760 ****************************************************************/
6762 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
6763 struct spoolss_EnumJobs *r)
6765 WERROR result;
6766 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6767 int snum;
6768 print_status_struct prt_status;
6769 print_queue_struct *queue = NULL;
6770 uint32_t count;
6772 /* that's an [in out] buffer */
6774 if (!r->in.buffer && (r->in.offered != 0)) {
6775 return WERR_INVALID_PARAM;
6778 DEBUG(4,("_spoolss_EnumJobs\n"));
6780 *r->out.needed = 0;
6781 *r->out.count = 0;
6782 *r->out.info = NULL;
6784 /* lookup the printer snum and tdb entry */
6786 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6787 return WERR_BADFID;
6790 result = winreg_get_printer(p->mem_ctx,
6791 get_server_info_system(),
6792 p->msg_ctx,
6793 NULL,
6794 lp_const_servicename(snum),
6795 &pinfo2);
6796 if (!W_ERROR_IS_OK(result)) {
6797 return result;
6800 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
6801 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6802 count, prt_status.status, prt_status.message));
6804 if (count == 0) {
6805 SAFE_FREE(queue);
6806 TALLOC_FREE(pinfo2);
6807 return WERR_OK;
6810 switch (r->in.level) {
6811 case 1:
6812 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6813 pinfo2, r->out.info, r->out.count);
6814 break;
6815 case 2:
6816 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6817 pinfo2, r->out.info, r->out.count);
6818 break;
6819 case 3:
6820 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6821 pinfo2, r->out.info, r->out.count);
6822 break;
6823 default:
6824 result = WERR_UNKNOWN_LEVEL;
6825 break;
6828 SAFE_FREE(queue);
6829 TALLOC_FREE(pinfo2);
6831 if (!W_ERROR_IS_OK(result)) {
6832 return result;
6835 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6836 spoolss_EnumJobs,
6837 *r->out.info, r->in.level,
6838 *r->out.count);
6839 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6840 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6842 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6845 /****************************************************************
6846 _spoolss_ScheduleJob
6847 ****************************************************************/
6849 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
6850 struct spoolss_ScheduleJob *r)
6852 return WERR_OK;
6855 /****************************************************************
6856 ****************************************************************/
6858 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6859 struct messaging_context *msg_ctx,
6860 const char *printer_name,
6861 uint32_t job_id,
6862 struct spoolss_SetJobInfo1 *r)
6864 char *old_doc_name;
6866 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6867 return WERR_BADFID;
6870 if (strequal(old_doc_name, r->document_name)) {
6871 return WERR_OK;
6874 if (!print_job_set_name(server_event_context(), msg_ctx,
6875 printer_name, job_id, r->document_name)) {
6876 return WERR_BADFID;
6879 return WERR_OK;
6882 /****************************************************************
6883 _spoolss_SetJob
6884 ****************************************************************/
6886 WERROR _spoolss_SetJob(struct pipes_struct *p,
6887 struct spoolss_SetJob *r)
6889 const struct auth_serversupplied_info *server_info = get_server_info_system();
6890 int snum;
6891 WERROR errcode = WERR_BADFUNC;
6893 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6894 return WERR_BADFID;
6897 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6898 return WERR_INVALID_PRINTER_NAME;
6901 switch (r->in.command) {
6902 case SPOOLSS_JOB_CONTROL_CANCEL:
6903 case SPOOLSS_JOB_CONTROL_DELETE:
6904 errcode = print_job_delete(server_info, p->msg_ctx,
6905 snum, r->in.job_id);
6906 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
6907 errcode = WERR_OK;
6909 break;
6910 case SPOOLSS_JOB_CONTROL_PAUSE:
6911 if (print_job_pause(server_info, p->msg_ctx,
6912 snum, r->in.job_id, &errcode)) {
6913 errcode = WERR_OK;
6915 break;
6916 case SPOOLSS_JOB_CONTROL_RESTART:
6917 case SPOOLSS_JOB_CONTROL_RESUME:
6918 if (print_job_resume(server_info, p->msg_ctx,
6919 snum, r->in.job_id, &errcode)) {
6920 errcode = WERR_OK;
6922 break;
6923 case 0:
6924 errcode = WERR_OK;
6925 break;
6926 default:
6927 return WERR_UNKNOWN_LEVEL;
6930 if (!W_ERROR_IS_OK(errcode)) {
6931 return errcode;
6934 if (r->in.ctr == NULL) {
6935 return errcode;
6938 switch (r->in.ctr->level) {
6939 case 1:
6940 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
6941 lp_const_servicename(snum),
6942 r->in.job_id,
6943 r->in.ctr->info.info1);
6944 break;
6945 case 2:
6946 case 3:
6947 case 4:
6948 default:
6949 return WERR_UNKNOWN_LEVEL;
6952 return errcode;
6955 /****************************************************************************
6956 Enumerates all printer drivers by level and architecture.
6957 ****************************************************************************/
6959 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6960 const struct auth_serversupplied_info *server_info,
6961 struct messaging_context *msg_ctx,
6962 const char *servername,
6963 const char *architecture,
6964 uint32_t level,
6965 union spoolss_DriverInfo **info_p,
6966 uint32_t *count_p)
6968 int i;
6969 uint32_t version;
6970 struct spoolss_DriverInfo8 *driver;
6971 union spoolss_DriverInfo *info = NULL;
6972 uint32_t count = 0;
6973 WERROR result = WERR_OK;
6974 uint32_t num_drivers;
6975 const char **drivers;
6977 *count_p = 0;
6978 *info_p = NULL;
6980 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6981 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
6982 architecture, version,
6983 &num_drivers, &drivers);
6984 if (!W_ERROR_IS_OK(result)) {
6985 goto out;
6987 DEBUG(4, ("we have:[%d] drivers in environment"
6988 " [%s] and version [%d]\n",
6989 num_drivers, architecture, version));
6991 if (num_drivers != 0) {
6992 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6993 union spoolss_DriverInfo,
6994 count + num_drivers);
6995 if (!info) {
6996 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6997 "failed to enlarge driver info buffer!\n"));
6998 result = WERR_NOMEM;
6999 goto out;
7003 for (i = 0; i < num_drivers; i++) {
7004 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7006 result = winreg_get_driver(mem_ctx, server_info,
7007 msg_ctx,
7008 architecture, drivers[i],
7009 version, &driver);
7010 if (!W_ERROR_IS_OK(result)) {
7011 goto out;
7014 switch (level) {
7015 case 1:
7016 result = fill_printer_driver_info1(info, &info[count+i].info1,
7017 driver, servername);
7018 break;
7019 case 2:
7020 result = fill_printer_driver_info2(info, &info[count+i].info2,
7021 driver, servername);
7022 break;
7023 case 3:
7024 result = fill_printer_driver_info3(info, &info[count+i].info3,
7025 driver, servername);
7026 break;
7027 case 4:
7028 result = fill_printer_driver_info4(info, &info[count+i].info4,
7029 driver, servername);
7030 break;
7031 case 5:
7032 result = fill_printer_driver_info5(info, &info[count+i].info5,
7033 driver, servername);
7034 break;
7035 case 6:
7036 result = fill_printer_driver_info6(info, &info[count+i].info6,
7037 driver, servername);
7038 break;
7039 case 8:
7040 result = fill_printer_driver_info8(info, &info[count+i].info8,
7041 driver, servername);
7042 break;
7043 default:
7044 result = WERR_UNKNOWN_LEVEL;
7045 break;
7048 TALLOC_FREE(driver);
7050 if (!W_ERROR_IS_OK(result)) {
7051 goto out;
7055 count += num_drivers;
7056 TALLOC_FREE(drivers);
7059 out:
7060 TALLOC_FREE(drivers);
7062 if (!W_ERROR_IS_OK(result)) {
7063 TALLOC_FREE(info);
7064 return result;
7067 *info_p = info;
7068 *count_p = count;
7070 return WERR_OK;
7073 /****************************************************************************
7074 Enumerates all printer drivers by level.
7075 ****************************************************************************/
7077 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7078 const struct auth_serversupplied_info *server_info,
7079 struct messaging_context *msg_ctx,
7080 const char *servername,
7081 const char *architecture,
7082 uint32_t level,
7083 union spoolss_DriverInfo **info_p,
7084 uint32_t *count_p)
7086 uint32_t a,i;
7087 WERROR result = WERR_OK;
7089 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7091 for (a=0; archi_table[a].long_archi != NULL; a++) {
7093 union spoolss_DriverInfo *info = NULL;
7094 uint32_t count = 0;
7096 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7097 server_info,
7098 msg_ctx,
7099 servername,
7100 archi_table[a].long_archi,
7101 level,
7102 &info,
7103 &count);
7104 if (!W_ERROR_IS_OK(result)) {
7105 continue;
7108 for (i=0; i < count; i++) {
7109 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7110 info[i], info_p, count_p);
7114 return result;
7117 return enumprinterdrivers_level_by_architecture(mem_ctx,
7118 server_info,
7119 msg_ctx,
7120 servername,
7121 architecture,
7122 level,
7123 info_p,
7124 count_p);
7127 /****************************************************************
7128 _spoolss_EnumPrinterDrivers
7129 ****************************************************************/
7131 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7132 struct spoolss_EnumPrinterDrivers *r)
7134 const char *cservername;
7135 WERROR result;
7137 /* that's an [in out] buffer */
7139 if (!r->in.buffer && (r->in.offered != 0)) {
7140 return WERR_INVALID_PARAM;
7143 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7145 *r->out.needed = 0;
7146 *r->out.count = 0;
7147 *r->out.info = NULL;
7149 cservername = canon_servername(r->in.server);
7151 if (!is_myname_or_ipaddr(cservername)) {
7152 return WERR_UNKNOWN_PRINTER_DRIVER;
7155 result = enumprinterdrivers_level(p->mem_ctx,
7156 get_server_info_system(),
7157 p->msg_ctx,
7158 cservername,
7159 r->in.environment,
7160 r->in.level,
7161 r->out.info,
7162 r->out.count);
7163 if (!W_ERROR_IS_OK(result)) {
7164 return result;
7167 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7168 spoolss_EnumPrinterDrivers,
7169 *r->out.info, r->in.level,
7170 *r->out.count);
7171 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7172 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7174 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7177 /****************************************************************
7178 _spoolss_EnumForms
7179 ****************************************************************/
7181 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7182 struct spoolss_EnumForms *r)
7184 WERROR result;
7186 *r->out.count = 0;
7187 *r->out.needed = 0;
7188 *r->out.info = NULL;
7190 /* that's an [in out] buffer */
7192 if (!r->in.buffer && (r->in.offered != 0) ) {
7193 return WERR_INVALID_PARAM;
7196 DEBUG(4,("_spoolss_EnumForms\n"));
7197 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7198 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7200 switch (r->in.level) {
7201 case 1:
7202 result = winreg_printer_enumforms1(p->mem_ctx,
7203 get_server_info_system(),
7204 p->msg_ctx,
7205 r->out.count,
7206 r->out.info);
7207 break;
7208 default:
7209 result = WERR_UNKNOWN_LEVEL;
7210 break;
7213 if (!W_ERROR_IS_OK(result)) {
7214 return result;
7217 if (*r->out.count == 0) {
7218 return WERR_NO_MORE_ITEMS;
7221 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7222 spoolss_EnumForms,
7223 *r->out.info, r->in.level,
7224 *r->out.count);
7225 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7226 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7228 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7231 /****************************************************************
7232 _spoolss_GetForm
7233 ****************************************************************/
7235 WERROR _spoolss_GetForm(struct pipes_struct *p,
7236 struct spoolss_GetForm *r)
7238 WERROR result;
7240 /* that's an [in out] buffer */
7242 if (!r->in.buffer && (r->in.offered != 0)) {
7243 return WERR_INVALID_PARAM;
7246 DEBUG(4,("_spoolss_GetForm\n"));
7247 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7248 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7250 switch (r->in.level) {
7251 case 1:
7252 result = winreg_printer_getform1(p->mem_ctx,
7253 get_server_info_system(),
7254 p->msg_ctx,
7255 r->in.form_name,
7256 &r->out.info->info1);
7257 break;
7258 default:
7259 result = WERR_UNKNOWN_LEVEL;
7260 break;
7263 if (!W_ERROR_IS_OK(result)) {
7264 TALLOC_FREE(r->out.info);
7265 return result;
7268 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7269 r->out.info, r->in.level);
7270 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7272 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7275 /****************************************************************************
7276 ****************************************************************************/
7278 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7279 struct spoolss_PortInfo1 *r,
7280 const char *name)
7282 r->port_name = talloc_strdup(mem_ctx, name);
7283 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7285 return WERR_OK;
7288 /****************************************************************************
7289 TODO: This probably needs distinguish between TCP/IP and Local ports
7290 somehow.
7291 ****************************************************************************/
7293 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7294 struct spoolss_PortInfo2 *r,
7295 const char *name)
7297 r->port_name = talloc_strdup(mem_ctx, name);
7298 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7300 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7301 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7303 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7304 W_ERROR_HAVE_NO_MEMORY(r->description);
7306 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7307 r->reserved = 0;
7309 return WERR_OK;
7313 /****************************************************************************
7314 wrapper around the enumer ports command
7315 ****************************************************************************/
7317 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7319 char *cmd = lp_enumports_cmd();
7320 char **qlines = NULL;
7321 char *command = NULL;
7322 int numlines;
7323 int ret;
7324 int fd;
7326 *count = 0;
7327 *lines = NULL;
7329 /* if no hook then just fill in the default port */
7331 if ( !*cmd ) {
7332 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7333 return WERR_NOMEM;
7335 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7336 TALLOC_FREE(qlines);
7337 return WERR_NOMEM;
7339 qlines[1] = NULL;
7340 numlines = 1;
7342 else {
7343 /* we have a valid enumport command */
7345 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7346 if (!command) {
7347 return WERR_NOMEM;
7350 DEBUG(10,("Running [%s]\n", command));
7351 ret = smbrun(command, &fd);
7352 DEBUG(10,("Returned [%d]\n", ret));
7353 TALLOC_FREE(command);
7354 if (ret != 0) {
7355 if (fd != -1) {
7356 close(fd);
7358 return WERR_ACCESS_DENIED;
7361 numlines = 0;
7362 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7363 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7364 close(fd);
7367 *count = numlines;
7368 *lines = qlines;
7370 return WERR_OK;
7373 /****************************************************************************
7374 enumports level 1.
7375 ****************************************************************************/
7377 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7378 union spoolss_PortInfo **info_p,
7379 uint32_t *count)
7381 union spoolss_PortInfo *info = NULL;
7382 int i=0;
7383 WERROR result = WERR_OK;
7384 char **qlines = NULL;
7385 int numlines = 0;
7387 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7388 if (!W_ERROR_IS_OK(result)) {
7389 goto out;
7392 if (numlines) {
7393 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7394 if (!info) {
7395 DEBUG(10,("Returning WERR_NOMEM\n"));
7396 result = WERR_NOMEM;
7397 goto out;
7400 for (i=0; i<numlines; i++) {
7401 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7402 result = fill_port_1(info, &info[i].info1, qlines[i]);
7403 if (!W_ERROR_IS_OK(result)) {
7404 goto out;
7408 TALLOC_FREE(qlines);
7410 out:
7411 if (!W_ERROR_IS_OK(result)) {
7412 TALLOC_FREE(info);
7413 TALLOC_FREE(qlines);
7414 *count = 0;
7415 *info_p = NULL;
7416 return result;
7419 *info_p = info;
7420 *count = numlines;
7422 return WERR_OK;
7425 /****************************************************************************
7426 enumports level 2.
7427 ****************************************************************************/
7429 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7430 union spoolss_PortInfo **info_p,
7431 uint32_t *count)
7433 union spoolss_PortInfo *info = NULL;
7434 int i=0;
7435 WERROR result = WERR_OK;
7436 char **qlines = NULL;
7437 int numlines = 0;
7439 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7440 if (!W_ERROR_IS_OK(result)) {
7441 goto out;
7444 if (numlines) {
7445 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7446 if (!info) {
7447 DEBUG(10,("Returning WERR_NOMEM\n"));
7448 result = WERR_NOMEM;
7449 goto out;
7452 for (i=0; i<numlines; i++) {
7453 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7454 result = fill_port_2(info, &info[i].info2, qlines[i]);
7455 if (!W_ERROR_IS_OK(result)) {
7456 goto out;
7460 TALLOC_FREE(qlines);
7462 out:
7463 if (!W_ERROR_IS_OK(result)) {
7464 TALLOC_FREE(info);
7465 TALLOC_FREE(qlines);
7466 *count = 0;
7467 *info_p = NULL;
7468 return result;
7471 *info_p = info;
7472 *count = numlines;
7474 return WERR_OK;
7477 /****************************************************************
7478 _spoolss_EnumPorts
7479 ****************************************************************/
7481 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7482 struct spoolss_EnumPorts *r)
7484 WERROR result;
7486 /* that's an [in out] buffer */
7488 if (!r->in.buffer && (r->in.offered != 0)) {
7489 return WERR_INVALID_PARAM;
7492 DEBUG(4,("_spoolss_EnumPorts\n"));
7494 *r->out.count = 0;
7495 *r->out.needed = 0;
7496 *r->out.info = NULL;
7498 switch (r->in.level) {
7499 case 1:
7500 result = enumports_level_1(p->mem_ctx, r->out.info,
7501 r->out.count);
7502 break;
7503 case 2:
7504 result = enumports_level_2(p->mem_ctx, r->out.info,
7505 r->out.count);
7506 break;
7507 default:
7508 return WERR_UNKNOWN_LEVEL;
7511 if (!W_ERROR_IS_OK(result)) {
7512 return result;
7515 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7516 spoolss_EnumPorts,
7517 *r->out.info, r->in.level,
7518 *r->out.count);
7519 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7520 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7522 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7525 /****************************************************************************
7526 ****************************************************************************/
7528 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7529 const char *server,
7530 struct spoolss_SetPrinterInfoCtr *info_ctr,
7531 struct spoolss_DeviceMode *devmode,
7532 struct security_descriptor *secdesc,
7533 struct spoolss_UserLevelCtr *user_ctr,
7534 struct policy_handle *handle)
7536 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7537 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7538 int snum;
7539 WERROR err = WERR_OK;
7541 /* samba does not have a concept of local, non-shared printers yet, so
7542 * make sure we always setup sharename - gd */
7543 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7544 (info2->printername != NULL && info2->printername[0] != '\0')) {
7545 DEBUG(5, ("spoolss_addprinterex_level_2: "
7546 "no sharename has been set, setting printername %s as sharename\n",
7547 info2->printername));
7548 info2->sharename = info2->printername;
7551 /* check to see if the printer already exists */
7552 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7553 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7554 info2->sharename));
7555 return WERR_PRINTER_ALREADY_EXISTS;
7558 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7559 if ((snum = print_queue_snum(info2->printername)) != -1) {
7560 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7561 info2->printername));
7562 return WERR_PRINTER_ALREADY_EXISTS;
7566 /* validate printer info struct */
7567 if (!info2->printername || strlen(info2->printername) == 0) {
7568 return WERR_INVALID_PRINTER_NAME;
7570 if (!info2->portname || strlen(info2->portname) == 0) {
7571 return WERR_UNKNOWN_PORT;
7573 if (!info2->drivername || strlen(info2->drivername) == 0) {
7574 return WERR_UNKNOWN_PRINTER_DRIVER;
7576 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7577 return WERR_UNKNOWN_PRINTPROCESSOR;
7580 /* FIXME!!! smbd should check to see if the driver is installed before
7581 trying to add a printer like this --jerry */
7583 if (*lp_addprinter_cmd() ) {
7584 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7585 info2, p->client_id->addr,
7586 p->msg_ctx) ) {
7587 return WERR_ACCESS_DENIED;
7589 } else {
7590 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7591 "smb.conf parameter \"addprinter command\" is defined. This"
7592 "parameter must exist for this call to succeed\n",
7593 info2->sharename ));
7596 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7597 return WERR_ACCESS_DENIED;
7600 /* you must be a printer admin to add a new printer */
7601 if (!print_access_check(get_server_info_system(),
7602 p->msg_ctx,
7603 snum,
7604 PRINTER_ACCESS_ADMINISTER)) {
7605 return WERR_ACCESS_DENIED;
7609 * Do sanity check on the requested changes for Samba.
7612 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7613 return WERR_INVALID_PARAM;
7616 if (devmode == NULL) {
7617 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7620 update_dsspooler(p->mem_ctx,
7621 get_server_info_system(),
7622 p->msg_ctx,
7624 info2,
7625 NULL);
7627 err = winreg_update_printer(p->mem_ctx,
7628 get_server_info_system(),
7629 p->msg_ctx,
7630 info2->sharename,
7631 info2_mask,
7632 info2,
7633 devmode,
7634 secdesc);
7635 if (!W_ERROR_IS_OK(err)) {
7636 return err;
7639 if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7640 /* Handle open failed - remove addition. */
7641 ZERO_STRUCTP(handle);
7642 return WERR_ACCESS_DENIED;
7645 return WERR_OK;
7648 /****************************************************************
7649 _spoolss_AddPrinterEx
7650 ****************************************************************/
7652 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7653 struct spoolss_AddPrinterEx *r)
7655 switch (r->in.info_ctr->level) {
7656 case 1:
7657 /* we don't handle yet */
7658 /* but I know what to do ... */
7659 return WERR_UNKNOWN_LEVEL;
7660 case 2:
7661 return spoolss_addprinterex_level_2(p, r->in.server,
7662 r->in.info_ctr,
7663 r->in.devmode_ctr->devmode,
7664 r->in.secdesc_ctr->sd,
7665 r->in.userlevel_ctr,
7666 r->out.handle);
7667 default:
7668 return WERR_UNKNOWN_LEVEL;
7672 /****************************************************************
7673 _spoolss_AddPrinter
7674 ****************************************************************/
7676 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7677 struct spoolss_AddPrinter *r)
7679 struct spoolss_AddPrinterEx a;
7680 struct spoolss_UserLevelCtr userlevel_ctr;
7682 ZERO_STRUCT(userlevel_ctr);
7684 userlevel_ctr.level = 1;
7686 a.in.server = r->in.server;
7687 a.in.info_ctr = r->in.info_ctr;
7688 a.in.devmode_ctr = r->in.devmode_ctr;
7689 a.in.secdesc_ctr = r->in.secdesc_ctr;
7690 a.in.userlevel_ctr = &userlevel_ctr;
7691 a.out.handle = r->out.handle;
7693 return _spoolss_AddPrinterEx(p, &a);
7696 /****************************************************************
7697 _spoolss_AddPrinterDriverEx
7698 ****************************************************************/
7700 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7701 struct spoolss_AddPrinterDriverEx *r)
7703 WERROR err = WERR_OK;
7704 const char *driver_name = NULL;
7705 uint32_t version;
7706 const char *fn;
7708 switch (p->opnum) {
7709 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7710 fn = "_spoolss_AddPrinterDriver";
7711 break;
7712 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7713 fn = "_spoolss_AddPrinterDriverEx";
7714 break;
7715 default:
7716 return WERR_INVALID_PARAM;
7720 * we only support the semantics of AddPrinterDriver()
7721 * i.e. only copy files that are newer than existing ones
7724 if (r->in.flags == 0) {
7725 return WERR_INVALID_PARAM;
7728 if (r->in.flags != APD_COPY_NEW_FILES) {
7729 return WERR_ACCESS_DENIED;
7732 /* FIXME */
7733 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7734 /* Clever hack from Martin Zielinski <mz@seh.de>
7735 * to allow downgrade from level 8 (Vista).
7737 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7738 r->in.info_ctr->level));
7739 return WERR_UNKNOWN_LEVEL;
7742 DEBUG(5,("Cleaning driver's information\n"));
7743 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7744 if (!W_ERROR_IS_OK(err))
7745 goto done;
7747 DEBUG(5,("Moving driver to final destination\n"));
7748 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7749 &err)) ) {
7750 goto done;
7753 err = winreg_add_driver(p->mem_ctx,
7754 get_server_info_system(),
7755 p->msg_ctx,
7756 r->in.info_ctr,
7757 &driver_name,
7758 &version);
7759 if (!W_ERROR_IS_OK(err)) {
7760 goto done;
7764 * I think this is where he DrvUpgradePrinter() hook would be
7765 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7766 * server. Right now, we just need to send ourselves a message
7767 * to update each printer bound to this driver. --jerry
7770 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
7771 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7772 fn, driver_name));
7775 done:
7776 return err;
7779 /****************************************************************
7780 _spoolss_AddPrinterDriver
7781 ****************************************************************/
7783 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
7784 struct spoolss_AddPrinterDriver *r)
7786 struct spoolss_AddPrinterDriverEx a;
7788 switch (r->in.info_ctr->level) {
7789 case 2:
7790 case 3:
7791 case 4:
7792 case 5:
7793 break;
7794 default:
7795 return WERR_UNKNOWN_LEVEL;
7798 a.in.servername = r->in.servername;
7799 a.in.info_ctr = r->in.info_ctr;
7800 a.in.flags = APD_COPY_NEW_FILES;
7802 return _spoolss_AddPrinterDriverEx(p, &a);
7805 /****************************************************************************
7806 ****************************************************************************/
7808 struct _spoolss_paths {
7809 int type;
7810 const char *share;
7811 const char *dir;
7814 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7816 static const struct _spoolss_paths spoolss_paths[]= {
7817 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7818 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7821 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7822 const char *servername,
7823 const char *environment,
7824 int component,
7825 char **path)
7827 const char *pservername = NULL;
7828 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7829 const char *short_archi;
7831 *path = NULL;
7833 /* environment may be empty */
7834 if (environment && strlen(environment)) {
7835 long_archi = environment;
7838 /* servername may be empty */
7839 if (servername && strlen(servername)) {
7840 pservername = canon_servername(servername);
7842 if (!is_myname_or_ipaddr(pservername)) {
7843 return WERR_INVALID_PARAM;
7847 if (!(short_archi = get_short_archi(long_archi))) {
7848 return WERR_INVALID_ENVIRONMENT;
7851 switch (component) {
7852 case SPOOLSS_PRTPROCS_PATH:
7853 case SPOOLSS_DRIVER_PATH:
7854 if (pservername) {
7855 *path = talloc_asprintf(mem_ctx,
7856 "\\\\%s\\%s\\%s",
7857 pservername,
7858 spoolss_paths[component].share,
7859 short_archi);
7860 } else {
7861 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7862 SPOOLSS_DEFAULT_SERVER_PATH,
7863 spoolss_paths[component].dir,
7864 short_archi);
7866 break;
7867 default:
7868 return WERR_INVALID_PARAM;
7871 if (!*path) {
7872 return WERR_NOMEM;
7875 return WERR_OK;
7878 /****************************************************************************
7879 ****************************************************************************/
7881 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7882 const char *servername,
7883 const char *environment,
7884 struct spoolss_DriverDirectoryInfo1 *r)
7886 WERROR werr;
7887 char *path = NULL;
7889 werr = compose_spoolss_server_path(mem_ctx,
7890 servername,
7891 environment,
7892 SPOOLSS_DRIVER_PATH,
7893 &path);
7894 if (!W_ERROR_IS_OK(werr)) {
7895 return werr;
7898 DEBUG(4,("printer driver directory: [%s]\n", path));
7900 r->directory_name = path;
7902 return WERR_OK;
7905 /****************************************************************
7906 _spoolss_GetPrinterDriverDirectory
7907 ****************************************************************/
7909 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
7910 struct spoolss_GetPrinterDriverDirectory *r)
7912 WERROR werror;
7914 /* that's an [in out] buffer */
7916 if (!r->in.buffer && (r->in.offered != 0)) {
7917 return WERR_INVALID_PARAM;
7920 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7921 r->in.level));
7923 *r->out.needed = 0;
7925 /* r->in.level is ignored */
7927 werror = getprinterdriverdir_level_1(p->mem_ctx,
7928 r->in.server,
7929 r->in.environment,
7930 &r->out.info->info1);
7931 if (!W_ERROR_IS_OK(werror)) {
7932 TALLOC_FREE(r->out.info);
7933 return werror;
7936 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7937 r->out.info, r->in.level);
7938 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7940 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7943 /****************************************************************
7944 _spoolss_EnumPrinterData
7945 ****************************************************************/
7947 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
7948 struct spoolss_EnumPrinterData *r)
7950 WERROR result;
7951 struct spoolss_EnumPrinterDataEx r2;
7952 uint32_t count;
7953 struct spoolss_PrinterEnumValues *info, *val = NULL;
7954 uint32_t needed;
7956 r2.in.handle = r->in.handle;
7957 r2.in.key_name = "PrinterDriverData";
7958 r2.in.offered = 0;
7959 r2.out.count = &count;
7960 r2.out.info = &info;
7961 r2.out.needed = &needed;
7963 result = _spoolss_EnumPrinterDataEx(p, &r2);
7964 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7965 r2.in.offered = needed;
7966 result = _spoolss_EnumPrinterDataEx(p, &r2);
7968 if (!W_ERROR_IS_OK(result)) {
7969 return result;
7973 * The NT machine wants to know the biggest size of value and data
7975 * cf: MSDN EnumPrinterData remark section
7978 if (!r->in.value_offered && !r->in.data_offered) {
7979 uint32_t biggest_valuesize = 0;
7980 uint32_t biggest_datasize = 0;
7981 int i, name_length;
7983 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7985 for (i=0; i<count; i++) {
7987 name_length = strlen(info[i].value_name);
7988 if (strlen(info[i].value_name) > biggest_valuesize) {
7989 biggest_valuesize = name_length;
7992 if (info[i].data_length > biggest_datasize) {
7993 biggest_datasize = info[i].data_length;
7996 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7997 biggest_datasize));
8000 /* the value is an UNICODE string but real_value_size is the length
8001 in bytes including the trailing 0 */
8003 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8004 *r->out.data_needed = biggest_datasize;
8006 DEBUG(6,("final values: [%d], [%d]\n",
8007 *r->out.value_needed, *r->out.data_needed));
8009 return WERR_OK;
8012 if (r->in.enum_index < count) {
8013 val = &info[r->in.enum_index];
8016 if (val == NULL) {
8017 /* out_value should default to "" or else NT4 has
8018 problems unmarshalling the response */
8020 if (r->in.value_offered) {
8021 *r->out.value_needed = 1;
8022 r->out.value_name = talloc_strdup(r, "");
8023 if (!r->out.value_name) {
8024 return WERR_NOMEM;
8026 } else {
8027 r->out.value_name = NULL;
8028 *r->out.value_needed = 0;
8031 /* the data is counted in bytes */
8033 *r->out.data_needed = r->in.data_offered;
8035 result = WERR_NO_MORE_ITEMS;
8036 } else {
8038 * the value is:
8039 * - counted in bytes in the request
8040 * - counted in UNICODE chars in the max reply
8041 * - counted in bytes in the real size
8043 * take a pause *before* coding not *during* coding
8046 /* name */
8047 if (r->in.value_offered) {
8048 r->out.value_name = talloc_strdup(r, val->value_name);
8049 if (!r->out.value_name) {
8050 return WERR_NOMEM;
8052 *r->out.value_needed = val->value_name_len;
8053 } else {
8054 r->out.value_name = NULL;
8055 *r->out.value_needed = 0;
8058 /* type */
8060 *r->out.type = val->type;
8062 /* data - counted in bytes */
8065 * See the section "Dynamically Typed Query Parameters"
8066 * in MS-RPRN.
8069 if (r->out.data && val->data && val->data->data &&
8070 val->data_length && r->in.data_offered) {
8071 memcpy(r->out.data, val->data->data,
8072 MIN(val->data_length,r->in.data_offered));
8075 *r->out.data_needed = val->data_length;
8077 result = WERR_OK;
8080 return result;
8083 /****************************************************************
8084 _spoolss_SetPrinterData
8085 ****************************************************************/
8087 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8088 struct spoolss_SetPrinterData *r)
8090 struct spoolss_SetPrinterDataEx r2;
8092 r2.in.handle = r->in.handle;
8093 r2.in.key_name = "PrinterDriverData";
8094 r2.in.value_name = r->in.value_name;
8095 r2.in.type = r->in.type;
8096 r2.in.data = r->in.data;
8097 r2.in.offered = r->in.offered;
8099 return _spoolss_SetPrinterDataEx(p, &r2);
8102 /****************************************************************
8103 _spoolss_ResetPrinter
8104 ****************************************************************/
8106 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8107 struct spoolss_ResetPrinter *r)
8109 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8110 int snum;
8112 DEBUG(5,("_spoolss_ResetPrinter\n"));
8115 * All we do is to check to see if the handle and queue is valid.
8116 * This call really doesn't mean anything to us because we only
8117 * support RAW printing. --jerry
8120 if (!Printer) {
8121 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8122 OUR_HANDLE(r->in.handle)));
8123 return WERR_BADFID;
8126 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8127 return WERR_BADFID;
8130 /* blindly return success */
8131 return WERR_OK;
8134 /****************************************************************
8135 _spoolss_DeletePrinterData
8136 ****************************************************************/
8138 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8139 struct spoolss_DeletePrinterData *r)
8141 struct spoolss_DeletePrinterDataEx r2;
8143 r2.in.handle = r->in.handle;
8144 r2.in.key_name = "PrinterDriverData";
8145 r2.in.value_name = r->in.value_name;
8147 return _spoolss_DeletePrinterDataEx(p, &r2);
8150 /****************************************************************
8151 _spoolss_AddForm
8152 ****************************************************************/
8154 WERROR _spoolss_AddForm(struct pipes_struct *p,
8155 struct spoolss_AddForm *r)
8157 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8158 int snum = -1;
8159 WERROR status = WERR_OK;
8160 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8162 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8164 DEBUG(5,("_spoolss_AddForm\n"));
8166 if (!Printer) {
8167 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8168 OUR_HANDLE(r->in.handle)));
8169 return WERR_BADFID;
8172 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8173 and not a printer admin, then fail */
8175 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8176 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8177 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8178 p->server_info->info3->base.domain.string,
8179 NULL,
8180 p->server_info->ptok,
8181 lp_printer_admin(snum))) {
8182 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8183 return WERR_ACCESS_DENIED;
8186 switch (form->flags) {
8187 case SPOOLSS_FORM_USER:
8188 case SPOOLSS_FORM_BUILTIN:
8189 case SPOOLSS_FORM_PRINTER:
8190 break;
8191 default:
8192 return WERR_INVALID_PARAM;
8195 status = winreg_printer_addform1(p->mem_ctx,
8196 get_server_info_system(),
8197 p->msg_ctx,
8198 form);
8199 if (!W_ERROR_IS_OK(status)) {
8200 return status;
8204 * ChangeID must always be set if this is a printer
8206 if (Printer->printer_type == SPLHND_PRINTER) {
8207 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8208 return WERR_BADFID;
8211 status = winreg_printer_update_changeid(p->mem_ctx,
8212 get_server_info_system(),
8213 p->msg_ctx,
8214 lp_const_servicename(snum));
8215 if (!W_ERROR_IS_OK(status)) {
8216 return status;
8220 return status;
8223 /****************************************************************
8224 _spoolss_DeleteForm
8225 ****************************************************************/
8227 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8228 struct spoolss_DeleteForm *r)
8230 const char *form_name = r->in.form_name;
8231 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8232 int snum = -1;
8233 WERROR status = WERR_OK;
8234 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8236 DEBUG(5,("_spoolss_DeleteForm\n"));
8238 if (!Printer) {
8239 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8240 OUR_HANDLE(r->in.handle)));
8241 return WERR_BADFID;
8244 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8245 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8246 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8247 p->server_info->info3->base.domain.string,
8248 NULL,
8249 p->server_info->ptok,
8250 lp_printer_admin(snum))) {
8251 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8252 return WERR_ACCESS_DENIED;
8255 status = winreg_printer_deleteform1(p->mem_ctx,
8256 get_server_info_system(),
8257 p->msg_ctx,
8258 form_name);
8259 if (!W_ERROR_IS_OK(status)) {
8260 return status;
8264 * ChangeID must always be set if this is a printer
8266 if (Printer->printer_type == SPLHND_PRINTER) {
8267 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8268 return WERR_BADFID;
8271 status = winreg_printer_update_changeid(p->mem_ctx,
8272 get_server_info_system(),
8273 p->msg_ctx,
8274 lp_const_servicename(snum));
8275 if (!W_ERROR_IS_OK(status)) {
8276 return status;
8280 return status;
8283 /****************************************************************
8284 _spoolss_SetForm
8285 ****************************************************************/
8287 WERROR _spoolss_SetForm(struct pipes_struct *p,
8288 struct spoolss_SetForm *r)
8290 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8291 const char *form_name = r->in.form_name;
8292 int snum = -1;
8293 WERROR status = WERR_OK;
8294 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8296 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8298 DEBUG(5,("_spoolss_SetForm\n"));
8300 if (!Printer) {
8301 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8302 OUR_HANDLE(r->in.handle)));
8303 return WERR_BADFID;
8306 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8307 and not a printer admin, then fail */
8309 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8310 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8311 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8312 p->server_info->info3->base.domain.string,
8313 NULL,
8314 p->server_info->ptok,
8315 lp_printer_admin(snum))) {
8316 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8317 return WERR_ACCESS_DENIED;
8320 status = winreg_printer_setform1(p->mem_ctx,
8321 get_server_info_system(),
8322 p->msg_ctx,
8323 form_name,
8324 form);
8325 if (!W_ERROR_IS_OK(status)) {
8326 return status;
8330 * ChangeID must always be set if this is a printer
8332 if (Printer->printer_type == SPLHND_PRINTER) {
8333 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8334 return WERR_BADFID;
8337 status = winreg_printer_update_changeid(p->mem_ctx,
8338 get_server_info_system(),
8339 p->msg_ctx,
8340 lp_const_servicename(snum));
8341 if (!W_ERROR_IS_OK(status)) {
8342 return status;
8346 return status;
8349 /****************************************************************************
8350 fill_print_processor1
8351 ****************************************************************************/
8353 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8354 struct spoolss_PrintProcessorInfo1 *r,
8355 const char *print_processor_name)
8357 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8358 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8360 return WERR_OK;
8363 /****************************************************************************
8364 enumprintprocessors level 1.
8365 ****************************************************************************/
8367 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8368 union spoolss_PrintProcessorInfo **info_p,
8369 uint32_t *count)
8371 union spoolss_PrintProcessorInfo *info;
8372 WERROR result;
8374 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8375 W_ERROR_HAVE_NO_MEMORY(info);
8377 *count = 1;
8379 result = fill_print_processor1(info, &info[0].info1, "winprint");
8380 if (!W_ERROR_IS_OK(result)) {
8381 goto out;
8384 out:
8385 if (!W_ERROR_IS_OK(result)) {
8386 TALLOC_FREE(info);
8387 *count = 0;
8388 return result;
8391 *info_p = info;
8393 return WERR_OK;
8396 /****************************************************************
8397 _spoolss_EnumPrintProcessors
8398 ****************************************************************/
8400 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8401 struct spoolss_EnumPrintProcessors *r)
8403 WERROR result;
8405 /* that's an [in out] buffer */
8407 if (!r->in.buffer && (r->in.offered != 0)) {
8408 return WERR_INVALID_PARAM;
8411 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8414 * Enumerate the print processors ...
8416 * Just reply with "winprint", to keep NT happy
8417 * and I can use my nice printer checker.
8420 *r->out.count = 0;
8421 *r->out.needed = 0;
8422 *r->out.info = NULL;
8424 switch (r->in.level) {
8425 case 1:
8426 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8427 r->out.count);
8428 break;
8429 default:
8430 return WERR_UNKNOWN_LEVEL;
8433 if (!W_ERROR_IS_OK(result)) {
8434 return result;
8437 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8438 spoolss_EnumPrintProcessors,
8439 *r->out.info, r->in.level,
8440 *r->out.count);
8441 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8442 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8444 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8447 /****************************************************************************
8448 fill_printprocdatatype1
8449 ****************************************************************************/
8451 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8452 struct spoolss_PrintProcDataTypesInfo1 *r,
8453 const char *name_array)
8455 r->name_array = talloc_strdup(mem_ctx, name_array);
8456 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8458 return WERR_OK;
8461 /****************************************************************************
8462 enumprintprocdatatypes level 1.
8463 ****************************************************************************/
8465 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8466 union spoolss_PrintProcDataTypesInfo **info_p,
8467 uint32_t *count)
8469 WERROR result;
8470 union spoolss_PrintProcDataTypesInfo *info;
8472 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8473 W_ERROR_HAVE_NO_MEMORY(info);
8475 *count = 1;
8477 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8478 if (!W_ERROR_IS_OK(result)) {
8479 goto out;
8482 out:
8483 if (!W_ERROR_IS_OK(result)) {
8484 TALLOC_FREE(info);
8485 *count = 0;
8486 return result;
8489 *info_p = info;
8491 return WERR_OK;
8494 /****************************************************************
8495 _spoolss_EnumPrintProcDataTypes
8496 ****************************************************************/
8498 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8499 struct spoolss_EnumPrintProcDataTypes *r)
8501 WERROR result;
8503 /* that's an [in out] buffer */
8505 if (!r->in.buffer && (r->in.offered != 0)) {
8506 return WERR_INVALID_PARAM;
8509 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8511 *r->out.count = 0;
8512 *r->out.needed = 0;
8513 *r->out.info = NULL;
8515 switch (r->in.level) {
8516 case 1:
8517 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8518 r->out.count);
8519 break;
8520 default:
8521 return WERR_UNKNOWN_LEVEL;
8524 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8525 spoolss_EnumPrintProcDataTypes,
8526 *r->out.info, r->in.level,
8527 *r->out.count);
8528 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8529 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8531 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8534 /****************************************************************************
8535 fill_monitor_1
8536 ****************************************************************************/
8538 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8539 struct spoolss_MonitorInfo1 *r,
8540 const char *monitor_name)
8542 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8543 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8545 return WERR_OK;
8548 /****************************************************************************
8549 fill_monitor_2
8550 ****************************************************************************/
8552 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8553 struct spoolss_MonitorInfo2 *r,
8554 const char *monitor_name,
8555 const char *environment,
8556 const char *dll_name)
8558 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8559 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8560 r->environment = talloc_strdup(mem_ctx, environment);
8561 W_ERROR_HAVE_NO_MEMORY(r->environment);
8562 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8563 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8565 return WERR_OK;
8568 /****************************************************************************
8569 enumprintmonitors level 1.
8570 ****************************************************************************/
8572 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8573 union spoolss_MonitorInfo **info_p,
8574 uint32_t *count)
8576 union spoolss_MonitorInfo *info;
8577 WERROR result = WERR_OK;
8579 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8580 W_ERROR_HAVE_NO_MEMORY(info);
8582 *count = 2;
8584 result = fill_monitor_1(info, &info[0].info1,
8585 SPL_LOCAL_PORT);
8586 if (!W_ERROR_IS_OK(result)) {
8587 goto out;
8590 result = fill_monitor_1(info, &info[1].info1,
8591 SPL_TCPIP_PORT);
8592 if (!W_ERROR_IS_OK(result)) {
8593 goto out;
8596 out:
8597 if (!W_ERROR_IS_OK(result)) {
8598 TALLOC_FREE(info);
8599 *count = 0;
8600 return result;
8603 *info_p = info;
8605 return WERR_OK;
8608 /****************************************************************************
8609 enumprintmonitors level 2.
8610 ****************************************************************************/
8612 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8613 union spoolss_MonitorInfo **info_p,
8614 uint32_t *count)
8616 union spoolss_MonitorInfo *info;
8617 WERROR result = WERR_OK;
8619 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8620 W_ERROR_HAVE_NO_MEMORY(info);
8622 *count = 2;
8624 result = fill_monitor_2(info, &info[0].info2,
8625 SPL_LOCAL_PORT,
8626 "Windows NT X86", /* FIXME */
8627 "localmon.dll");
8628 if (!W_ERROR_IS_OK(result)) {
8629 goto out;
8632 result = fill_monitor_2(info, &info[1].info2,
8633 SPL_TCPIP_PORT,
8634 "Windows NT X86", /* FIXME */
8635 "tcpmon.dll");
8636 if (!W_ERROR_IS_OK(result)) {
8637 goto out;
8640 out:
8641 if (!W_ERROR_IS_OK(result)) {
8642 TALLOC_FREE(info);
8643 *count = 0;
8644 return result;
8647 *info_p = info;
8649 return WERR_OK;
8652 /****************************************************************
8653 _spoolss_EnumMonitors
8654 ****************************************************************/
8656 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8657 struct spoolss_EnumMonitors *r)
8659 WERROR result;
8661 /* that's an [in out] buffer */
8663 if (!r->in.buffer && (r->in.offered != 0)) {
8664 return WERR_INVALID_PARAM;
8667 DEBUG(5,("_spoolss_EnumMonitors\n"));
8670 * Enumerate the print monitors ...
8672 * Just reply with "Local Port", to keep NT happy
8673 * and I can use my nice printer checker.
8676 *r->out.count = 0;
8677 *r->out.needed = 0;
8678 *r->out.info = NULL;
8680 switch (r->in.level) {
8681 case 1:
8682 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8683 r->out.count);
8684 break;
8685 case 2:
8686 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8687 r->out.count);
8688 break;
8689 default:
8690 return WERR_UNKNOWN_LEVEL;
8693 if (!W_ERROR_IS_OK(result)) {
8694 return result;
8697 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8698 spoolss_EnumMonitors,
8699 *r->out.info, r->in.level,
8700 *r->out.count);
8701 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8702 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8704 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8707 /****************************************************************************
8708 ****************************************************************************/
8710 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8711 const print_queue_struct *queue,
8712 int count, int snum,
8713 struct spoolss_PrinterInfo2 *pinfo2,
8714 uint32_t jobid,
8715 struct spoolss_JobInfo1 *r)
8717 int i = 0;
8718 bool found = false;
8720 for (i=0; i<count; i++) {
8721 if (queue[i].job == (int)jobid) {
8722 found = true;
8723 break;
8727 if (found == false) {
8728 /* NT treats not found as bad param... yet another bad choice */
8729 return WERR_INVALID_PARAM;
8732 return fill_job_info1(mem_ctx,
8734 &queue[i],
8736 snum,
8737 pinfo2);
8740 /****************************************************************************
8741 ****************************************************************************/
8743 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8744 const print_queue_struct *queue,
8745 int count, int snum,
8746 struct spoolss_PrinterInfo2 *pinfo2,
8747 uint32_t jobid,
8748 struct spoolss_JobInfo2 *r)
8750 int i = 0;
8751 bool found = false;
8752 struct spoolss_DeviceMode *devmode;
8753 WERROR result;
8755 for (i=0; i<count; i++) {
8756 if (queue[i].job == (int)jobid) {
8757 found = true;
8758 break;
8762 if (found == false) {
8763 /* NT treats not found as bad param... yet another bad
8764 choice */
8765 return WERR_INVALID_PARAM;
8769 * if the print job does not have a DEVMODE associated with it,
8770 * just use the one for the printer. A NULL devicemode is not
8771 * a failure condition
8774 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8775 if (!devmode) {
8776 result = spoolss_create_default_devmode(mem_ctx,
8777 pinfo2->printername,
8778 &devmode);
8779 if (!W_ERROR_IS_OK(result)) {
8780 DEBUG(3, ("Can't proceed w/o a devmode!"));
8781 return result;
8785 return fill_job_info2(mem_ctx,
8787 &queue[i],
8789 snum,
8790 pinfo2,
8791 devmode);
8794 /****************************************************************
8795 _spoolss_GetJob
8796 ****************************************************************/
8798 WERROR _spoolss_GetJob(struct pipes_struct *p,
8799 struct spoolss_GetJob *r)
8801 WERROR result = WERR_OK;
8802 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8803 int snum;
8804 int count;
8805 print_queue_struct *queue = NULL;
8806 print_status_struct prt_status;
8808 /* that's an [in out] buffer */
8810 if (!r->in.buffer && (r->in.offered != 0)) {
8811 return WERR_INVALID_PARAM;
8814 DEBUG(5,("_spoolss_GetJob\n"));
8816 *r->out.needed = 0;
8818 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8819 return WERR_BADFID;
8822 result = winreg_get_printer(p->mem_ctx,
8823 get_server_info_system(),
8824 p->msg_ctx,
8825 NULL,
8826 lp_const_servicename(snum),
8827 &pinfo2);
8828 if (!W_ERROR_IS_OK(result)) {
8829 return result;
8832 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
8834 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8835 count, prt_status.status, prt_status.message));
8837 switch (r->in.level) {
8838 case 1:
8839 result = getjob_level_1(p->mem_ctx,
8840 queue, count, snum, pinfo2,
8841 r->in.job_id, &r->out.info->info1);
8842 break;
8843 case 2:
8844 result = getjob_level_2(p->mem_ctx,
8845 queue, count, snum, pinfo2,
8846 r->in.job_id, &r->out.info->info2);
8847 break;
8848 default:
8849 result = WERR_UNKNOWN_LEVEL;
8850 break;
8853 SAFE_FREE(queue);
8854 TALLOC_FREE(pinfo2);
8856 if (!W_ERROR_IS_OK(result)) {
8857 TALLOC_FREE(r->out.info);
8858 return result;
8861 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8862 r->in.level);
8863 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8865 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8868 /****************************************************************
8869 _spoolss_GetPrinterDataEx
8870 ****************************************************************/
8872 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
8873 struct spoolss_GetPrinterDataEx *r)
8876 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8877 const char *printer;
8878 int snum = 0;
8879 WERROR result = WERR_OK;
8880 DATA_BLOB blob;
8881 enum winreg_Type val_type;
8882 uint8_t *val_data;
8883 uint32_t val_size;
8886 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8888 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8889 r->in.key_name, r->in.value_name));
8891 /* in case of problem, return some default values */
8893 *r->out.needed = 0;
8894 *r->out.type = REG_NONE;
8896 if (!Printer) {
8897 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8898 OUR_HANDLE(r->in.handle)));
8899 result = WERR_BADFID;
8900 goto done;
8903 /* Is the handle to a printer or to the server? */
8905 if (Printer->printer_type == SPLHND_SERVER) {
8907 union spoolss_PrinterData data;
8909 result = getprinterdata_printer_server(p->mem_ctx,
8910 r->in.value_name,
8911 r->out.type,
8912 &data);
8913 if (!W_ERROR_IS_OK(result)) {
8914 return result;
8917 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8918 *r->out.type, &data);
8919 if (!W_ERROR_IS_OK(result)) {
8920 return result;
8923 *r->out.needed = blob.length;
8925 if (r->in.offered >= *r->out.needed) {
8926 memcpy(r->out.data, blob.data, blob.length);
8929 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8932 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8933 return WERR_BADFID;
8935 printer = lp_const_servicename(snum);
8937 /* check to see if the keyname is valid */
8938 if (!strlen(r->in.key_name)) {
8939 return WERR_INVALID_PARAM;
8942 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8943 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8944 strequal(r->in.value_name, "ChangeId")) {
8945 *r->out.type = REG_DWORD;
8946 *r->out.needed = 4;
8947 if (r->in.offered >= *r->out.needed) {
8948 uint32_t changeid = 0;
8950 result = winreg_printer_get_changeid(p->mem_ctx,
8951 get_server_info_system(),
8952 p->msg_ctx,
8953 printer,
8954 &changeid);
8955 if (!W_ERROR_IS_OK(result)) {
8956 return result;
8959 SIVAL(r->out.data, 0, changeid);
8960 result = WERR_OK;
8962 goto done;
8965 result = winreg_get_printer_dataex(p->mem_ctx,
8966 get_server_info_system(),
8967 p->msg_ctx,
8968 printer,
8969 r->in.key_name,
8970 r->in.value_name,
8971 &val_type,
8972 &val_data,
8973 &val_size);
8974 if (!W_ERROR_IS_OK(result)) {
8975 return result;
8978 *r->out.needed = val_size;
8979 *r->out.type = val_type;
8981 if (r->in.offered >= *r->out.needed) {
8982 memcpy(r->out.data, val_data, val_size);
8985 done:
8986 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8987 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8989 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8992 /****************************************************************
8993 _spoolss_SetPrinterDataEx
8994 ****************************************************************/
8996 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
8997 struct spoolss_SetPrinterDataEx *r)
8999 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9000 int snum = 0;
9001 WERROR result = WERR_OK;
9002 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9003 char *oid_string;
9005 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9007 /* From MSDN documentation of SetPrinterDataEx: pass request to
9008 SetPrinterData if key is "PrinterDriverData" */
9010 if (!Printer) {
9011 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9012 OUR_HANDLE(r->in.handle)));
9013 return WERR_BADFID;
9016 if (Printer->printer_type == SPLHND_SERVER) {
9017 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9018 "Not implemented for server handles yet\n"));
9019 return WERR_INVALID_PARAM;
9022 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9023 return WERR_BADFID;
9027 * Access check : NT returns "access denied" if you make a
9028 * SetPrinterData call without the necessary privildge.
9029 * we were originally returning OK if nothing changed
9030 * which made Win2k issue **a lot** of SetPrinterData
9031 * when connecting to a printer --jerry
9034 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9035 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9036 "change denied by handle access permissions\n"));
9037 return WERR_ACCESS_DENIED;
9040 result = winreg_get_printer(Printer,
9041 get_server_info_system(),
9042 p->msg_ctx,
9043 Printer->servername,
9044 lp_servicename(snum),
9045 &pinfo2);
9046 if (!W_ERROR_IS_OK(result)) {
9047 return result;
9050 /* check for OID in valuename */
9052 oid_string = strchr(r->in.value_name, ',');
9053 if (oid_string) {
9054 *oid_string = '\0';
9055 oid_string++;
9058 /* save the registry data */
9060 result = winreg_set_printer_dataex(p->mem_ctx,
9061 get_server_info_system(),
9062 p->msg_ctx,
9063 pinfo2->sharename,
9064 r->in.key_name,
9065 r->in.value_name,
9066 r->in.type,
9067 r->in.data,
9068 r->in.offered);
9070 if (W_ERROR_IS_OK(result)) {
9071 /* save the OID if one was specified */
9072 if (oid_string) {
9073 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9074 r->in.key_name, SPOOL_OID_KEY);
9075 if (!str) {
9076 result = WERR_NOMEM;
9077 goto done;
9081 * I'm not checking the status here on purpose. Don't know
9082 * if this is right, but I'm returning the status from the
9083 * previous set_printer_dataex() call. I have no idea if
9084 * this is right. --jerry
9086 winreg_set_printer_dataex(p->mem_ctx,
9087 get_server_info_system(),
9088 p->msg_ctx,
9089 pinfo2->sharename,
9090 str,
9091 r->in.value_name,
9092 REG_SZ,
9093 (uint8_t *) oid_string,
9094 strlen(oid_string) + 1);
9097 result = winreg_printer_update_changeid(p->mem_ctx,
9098 get_server_info_system(),
9099 p->msg_ctx,
9100 lp_const_servicename(snum));
9104 done:
9105 talloc_free(pinfo2);
9106 return result;
9109 /****************************************************************
9110 _spoolss_DeletePrinterDataEx
9111 ****************************************************************/
9113 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9114 struct spoolss_DeletePrinterDataEx *r)
9116 const char *printer;
9117 int snum=0;
9118 WERROR status = WERR_OK;
9119 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9121 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9123 if (!Printer) {
9124 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9125 "Invalid handle (%s:%u:%u).\n",
9126 OUR_HANDLE(r->in.handle)));
9127 return WERR_BADFID;
9130 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9131 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9132 "printer properties change denied by handle\n"));
9133 return WERR_ACCESS_DENIED;
9136 if (!r->in.value_name || !r->in.key_name) {
9137 return WERR_NOMEM;
9140 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9141 return WERR_BADFID;
9143 printer = lp_const_servicename(snum);
9145 status = winreg_delete_printer_dataex(p->mem_ctx,
9146 get_server_info_system(),
9147 p->msg_ctx,
9148 printer,
9149 r->in.key_name,
9150 r->in.value_name);
9151 if (W_ERROR_IS_OK(status)) {
9152 status = winreg_printer_update_changeid(p->mem_ctx,
9153 get_server_info_system(),
9154 p->msg_ctx,
9155 printer);
9158 return status;
9161 /****************************************************************
9162 _spoolss_EnumPrinterKey
9163 ****************************************************************/
9165 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9166 struct spoolss_EnumPrinterKey *r)
9168 uint32_t num_keys;
9169 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9170 int snum = 0;
9171 WERROR result = WERR_BADFILE;
9172 const char **array = NULL;
9173 DATA_BLOB blob;
9175 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9177 if (!Printer) {
9178 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9179 OUR_HANDLE(r->in.handle)));
9180 return WERR_BADFID;
9183 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9184 return WERR_BADFID;
9187 result = winreg_enum_printer_key(p->mem_ctx,
9188 get_server_info_system(),
9189 p->msg_ctx,
9190 lp_const_servicename(snum),
9191 r->in.key_name,
9192 &num_keys,
9193 &array);
9194 if (!W_ERROR_IS_OK(result)) {
9195 goto done;
9198 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9199 result = WERR_NOMEM;
9200 goto done;
9203 *r->out._ndr_size = r->in.offered / 2;
9204 *r->out.needed = blob.length;
9206 if (r->in.offered < *r->out.needed) {
9207 result = WERR_MORE_DATA;
9208 } else {
9209 result = WERR_OK;
9210 r->out.key_buffer->string_array = array;
9213 done:
9214 if (!W_ERROR_IS_OK(result)) {
9215 TALLOC_FREE(array);
9216 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9217 *r->out.needed = 0;
9221 return result;
9224 /****************************************************************
9225 _spoolss_DeletePrinterKey
9226 ****************************************************************/
9228 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9229 struct spoolss_DeletePrinterKey *r)
9231 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9232 int snum=0;
9233 WERROR status;
9234 const char *printer;
9236 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9238 if (!Printer) {
9239 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9240 OUR_HANDLE(r->in.handle)));
9241 return WERR_BADFID;
9244 /* if keyname == NULL, return error */
9245 if ( !r->in.key_name )
9246 return WERR_INVALID_PARAM;
9248 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9249 return WERR_BADFID;
9252 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9253 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9254 "printer properties change denied by handle\n"));
9255 return WERR_ACCESS_DENIED;
9258 printer = lp_const_servicename(snum);
9260 /* delete the key and all subkeys */
9261 status = winreg_delete_printer_key(p->mem_ctx,
9262 get_server_info_system(),
9263 p->msg_ctx,
9264 printer,
9265 r->in.key_name);
9266 if (W_ERROR_IS_OK(status)) {
9267 status = winreg_printer_update_changeid(p->mem_ctx,
9268 get_server_info_system(),
9269 p->msg_ctx,
9270 printer);
9273 return status;
9276 /****************************************************************
9277 _spoolss_EnumPrinterDataEx
9278 ****************************************************************/
9280 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9281 struct spoolss_EnumPrinterDataEx *r)
9283 uint32_t count = 0;
9284 struct spoolss_PrinterEnumValues *info = NULL;
9285 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9286 int snum;
9287 WERROR result;
9289 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9291 *r->out.count = 0;
9292 *r->out.needed = 0;
9293 *r->out.info = NULL;
9295 if (!Printer) {
9296 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9297 OUR_HANDLE(r->in.handle)));
9298 return WERR_BADFID;
9302 * first check for a keyname of NULL or "". Win2k seems to send
9303 * this a lot and we should send back WERR_INVALID_PARAM
9304 * no need to spend time looking up the printer in this case.
9305 * --jerry
9308 if (!strlen(r->in.key_name)) {
9309 result = WERR_INVALID_PARAM;
9310 goto done;
9313 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9314 return WERR_BADFID;
9317 /* now look for a match on the key name */
9318 result = winreg_enum_printer_dataex(p->mem_ctx,
9319 get_server_info_system(),
9320 p->msg_ctx,
9321 lp_const_servicename(snum),
9322 r->in.key_name,
9323 &count,
9324 &info);
9325 if (!W_ERROR_IS_OK(result)) {
9326 goto done;
9329 #if 0 /* FIXME - gd */
9330 /* housekeeping information in the reply */
9332 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9333 * the hand marshalled container size is a multiple
9334 * of 4 bytes for RPC alignment.
9337 if (needed % 4) {
9338 needed += 4-(needed % 4);
9340 #endif
9341 *r->out.count = count;
9342 *r->out.info = info;
9344 done:
9345 if (!W_ERROR_IS_OK(result)) {
9346 return result;
9349 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9350 spoolss_EnumPrinterDataEx,
9351 *r->out.info,
9352 *r->out.count);
9353 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9354 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9356 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9359 /****************************************************************************
9360 ****************************************************************************/
9362 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9363 const char *servername,
9364 const char *environment,
9365 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9367 WERROR werr;
9368 char *path = NULL;
9370 werr = compose_spoolss_server_path(mem_ctx,
9371 servername,
9372 environment,
9373 SPOOLSS_PRTPROCS_PATH,
9374 &path);
9375 if (!W_ERROR_IS_OK(werr)) {
9376 return werr;
9379 DEBUG(4,("print processor directory: [%s]\n", path));
9381 r->directory_name = path;
9383 return WERR_OK;
9386 /****************************************************************
9387 _spoolss_GetPrintProcessorDirectory
9388 ****************************************************************/
9390 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9391 struct spoolss_GetPrintProcessorDirectory *r)
9393 WERROR result;
9395 /* that's an [in out] buffer */
9397 if (!r->in.buffer && (r->in.offered != 0)) {
9398 return WERR_INVALID_PARAM;
9401 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9402 r->in.level));
9404 *r->out.needed = 0;
9406 /* r->in.level is ignored */
9408 /* We always should reply with a local print processor directory so that
9409 * users are not forced to have a [prnproc$] share on the Samba spoolss
9410 * server - Guenther */
9412 result = getprintprocessordirectory_level_1(p->mem_ctx,
9413 NULL, /* r->in.server */
9414 r->in.environment,
9415 &r->out.info->info1);
9416 if (!W_ERROR_IS_OK(result)) {
9417 TALLOC_FREE(r->out.info);
9418 return result;
9421 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9422 r->out.info, r->in.level);
9423 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9425 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9428 /*******************************************************************
9429 ********************************************************************/
9431 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9432 const char *dllname)
9434 enum ndr_err_code ndr_err;
9435 struct spoolss_MonitorUi ui;
9437 ui.dll_name = dllname;
9439 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9440 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9441 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9442 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9444 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9447 /*******************************************************************
9448 Streams the monitor UI DLL name in UNICODE
9449 *******************************************************************/
9451 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9452 NT_USER_TOKEN *token, DATA_BLOB *in,
9453 DATA_BLOB *out, uint32_t *needed)
9455 const char *dllname = "tcpmonui.dll";
9457 *needed = (strlen(dllname)+1) * 2;
9459 if (out->length < *needed) {
9460 return WERR_INSUFFICIENT_BUFFER;
9463 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9464 return WERR_NOMEM;
9467 return WERR_OK;
9470 /*******************************************************************
9471 ********************************************************************/
9473 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9474 struct spoolss_PortData1 *port1,
9475 const DATA_BLOB *buf)
9477 enum ndr_err_code ndr_err;
9478 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9479 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9480 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9481 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9483 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9486 /*******************************************************************
9487 ********************************************************************/
9489 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9490 struct spoolss_PortData2 *port2,
9491 const DATA_BLOB *buf)
9493 enum ndr_err_code ndr_err;
9494 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9495 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9496 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9497 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9499 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9502 /*******************************************************************
9503 Create a new TCP/IP port
9504 *******************************************************************/
9506 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9507 NT_USER_TOKEN *token, DATA_BLOB *in,
9508 DATA_BLOB *out, uint32_t *needed)
9510 struct spoolss_PortData1 port1;
9511 struct spoolss_PortData2 port2;
9512 char *device_uri = NULL;
9513 uint32_t version;
9515 const char *portname;
9516 const char *hostaddress;
9517 const char *queue;
9518 uint32_t port_number;
9519 uint32_t protocol;
9521 /* peek for spoolss_PortData version */
9523 if (!in || (in->length < (128 + 4))) {
9524 return WERR_GENERAL_FAILURE;
9527 version = IVAL(in->data, 128);
9529 switch (version) {
9530 case 1:
9531 ZERO_STRUCT(port1);
9533 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9534 return WERR_NOMEM;
9537 portname = port1.portname;
9538 hostaddress = port1.hostaddress;
9539 queue = port1.queue;
9540 protocol = port1.protocol;
9541 port_number = port1.port_number;
9543 break;
9544 case 2:
9545 ZERO_STRUCT(port2);
9547 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9548 return WERR_NOMEM;
9551 portname = port2.portname;
9552 hostaddress = port2.hostaddress;
9553 queue = port2.queue;
9554 protocol = port2.protocol;
9555 port_number = port2.port_number;
9557 break;
9558 default:
9559 DEBUG(1,("xcvtcp_addport: "
9560 "unknown version of port_data: %d\n", version));
9561 return WERR_UNKNOWN_PORT;
9564 /* create the device URI and call the add_port_hook() */
9566 switch (protocol) {
9567 case PROTOCOL_RAWTCP_TYPE:
9568 device_uri = talloc_asprintf(mem_ctx,
9569 "socket://%s:%d/", hostaddress,
9570 port_number);
9571 break;
9573 case PROTOCOL_LPR_TYPE:
9574 device_uri = talloc_asprintf(mem_ctx,
9575 "lpr://%s/%s", hostaddress, queue );
9576 break;
9578 default:
9579 return WERR_UNKNOWN_PORT;
9582 if (!device_uri) {
9583 return WERR_NOMEM;
9586 return add_port_hook(mem_ctx, token, portname, device_uri);
9589 /*******************************************************************
9590 *******************************************************************/
9592 struct xcv_api_table xcvtcp_cmds[] = {
9593 { "MonitorUI", xcvtcp_monitorui },
9594 { "AddPort", xcvtcp_addport},
9595 { NULL, NULL }
9598 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9599 NT_USER_TOKEN *token, const char *command,
9600 DATA_BLOB *inbuf,
9601 DATA_BLOB *outbuf,
9602 uint32_t *needed )
9604 int i;
9606 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9608 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9609 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9610 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9613 return WERR_BADFUNC;
9616 /*******************************************************************
9617 *******************************************************************/
9618 #if 0 /* don't support management using the "Local Port" monitor */
9620 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9621 NT_USER_TOKEN *token, DATA_BLOB *in,
9622 DATA_BLOB *out, uint32_t *needed)
9624 const char *dllname = "localui.dll";
9626 *needed = (strlen(dllname)+1) * 2;
9628 if (out->length < *needed) {
9629 return WERR_INSUFFICIENT_BUFFER;
9632 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9633 return WERR_NOMEM;
9636 return WERR_OK;
9639 /*******************************************************************
9640 *******************************************************************/
9642 struct xcv_api_table xcvlocal_cmds[] = {
9643 { "MonitorUI", xcvlocal_monitorui },
9644 { NULL, NULL }
9646 #else
9647 struct xcv_api_table xcvlocal_cmds[] = {
9648 { NULL, NULL }
9650 #endif
9654 /*******************************************************************
9655 *******************************************************************/
9657 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9658 NT_USER_TOKEN *token, const char *command,
9659 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9660 uint32_t *needed)
9662 int i;
9664 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9666 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9667 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9668 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9670 return WERR_BADFUNC;
9673 /****************************************************************
9674 _spoolss_XcvData
9675 ****************************************************************/
9677 WERROR _spoolss_XcvData(struct pipes_struct *p,
9678 struct spoolss_XcvData *r)
9680 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9681 DATA_BLOB out_data = data_blob_null;
9682 WERROR werror;
9684 if (!Printer) {
9685 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9686 OUR_HANDLE(r->in.handle)));
9687 return WERR_BADFID;
9690 /* Has to be a handle to the TCP/IP port monitor */
9692 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9693 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9694 return WERR_BADFID;
9697 /* requires administrative access to the server */
9699 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9700 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9701 return WERR_ACCESS_DENIED;
9704 /* Allocate the outgoing buffer */
9706 if (r->in.out_data_size) {
9707 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9708 if (out_data.data == NULL) {
9709 return WERR_NOMEM;
9713 switch ( Printer->printer_type ) {
9714 case SPLHND_PORTMON_TCP:
9715 werror = process_xcvtcp_command(p->mem_ctx,
9716 p->server_info->ptok,
9717 r->in.function_name,
9718 &r->in.in_data, &out_data,
9719 r->out.needed);
9720 break;
9721 case SPLHND_PORTMON_LOCAL:
9722 werror = process_xcvlocal_command(p->mem_ctx,
9723 p->server_info->ptok,
9724 r->in.function_name,
9725 &r->in.in_data, &out_data,
9726 r->out.needed);
9727 break;
9728 default:
9729 werror = WERR_INVALID_PRINT_MONITOR;
9732 if (!W_ERROR_IS_OK(werror)) {
9733 return werror;
9736 *r->out.status_code = 0;
9738 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9739 memcpy(r->out.out_data, out_data.data,
9740 MIN(r->in.out_data_size, out_data.length));
9743 return WERR_OK;
9746 /****************************************************************
9747 _spoolss_AddPrintProcessor
9748 ****************************************************************/
9750 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
9751 struct spoolss_AddPrintProcessor *r)
9753 /* for now, just indicate success and ignore the add. We'll
9754 automatically set the winprint processor for printer
9755 entries later. Used to debug the LexMark Optra S 1855 PCL
9756 driver --jerry */
9758 return WERR_OK;
9761 /****************************************************************
9762 _spoolss_AddPort
9763 ****************************************************************/
9765 WERROR _spoolss_AddPort(struct pipes_struct *p,
9766 struct spoolss_AddPort *r)
9768 /* do what w2k3 does */
9770 return WERR_NOT_SUPPORTED;
9773 /****************************************************************
9774 _spoolss_GetPrinterDriver
9775 ****************************************************************/
9777 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
9778 struct spoolss_GetPrinterDriver *r)
9780 p->rng_fault_state = true;
9781 return WERR_NOT_SUPPORTED;
9784 /****************************************************************
9785 _spoolss_ReadPrinter
9786 ****************************************************************/
9788 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
9789 struct spoolss_ReadPrinter *r)
9791 p->rng_fault_state = true;
9792 return WERR_NOT_SUPPORTED;
9795 /****************************************************************
9796 _spoolss_WaitForPrinterChange
9797 ****************************************************************/
9799 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
9800 struct spoolss_WaitForPrinterChange *r)
9802 p->rng_fault_state = true;
9803 return WERR_NOT_SUPPORTED;
9806 /****************************************************************
9807 _spoolss_ConfigurePort
9808 ****************************************************************/
9810 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
9811 struct spoolss_ConfigurePort *r)
9813 p->rng_fault_state = true;
9814 return WERR_NOT_SUPPORTED;
9817 /****************************************************************
9818 _spoolss_DeletePort
9819 ****************************************************************/
9821 WERROR _spoolss_DeletePort(struct pipes_struct *p,
9822 struct spoolss_DeletePort *r)
9824 p->rng_fault_state = true;
9825 return WERR_NOT_SUPPORTED;
9828 /****************************************************************
9829 _spoolss_CreatePrinterIC
9830 ****************************************************************/
9832 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
9833 struct spoolss_CreatePrinterIC *r)
9835 p->rng_fault_state = true;
9836 return WERR_NOT_SUPPORTED;
9839 /****************************************************************
9840 _spoolss_PlayGDIScriptOnPrinterIC
9841 ****************************************************************/
9843 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
9844 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9846 p->rng_fault_state = true;
9847 return WERR_NOT_SUPPORTED;
9850 /****************************************************************
9851 _spoolss_DeletePrinterIC
9852 ****************************************************************/
9854 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
9855 struct spoolss_DeletePrinterIC *r)
9857 p->rng_fault_state = true;
9858 return WERR_NOT_SUPPORTED;
9861 /****************************************************************
9862 _spoolss_AddPrinterConnection
9863 ****************************************************************/
9865 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
9866 struct spoolss_AddPrinterConnection *r)
9868 p->rng_fault_state = true;
9869 return WERR_NOT_SUPPORTED;
9872 /****************************************************************
9873 _spoolss_DeletePrinterConnection
9874 ****************************************************************/
9876 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
9877 struct spoolss_DeletePrinterConnection *r)
9879 p->rng_fault_state = true;
9880 return WERR_NOT_SUPPORTED;
9883 /****************************************************************
9884 _spoolss_PrinterMessageBox
9885 ****************************************************************/
9887 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
9888 struct spoolss_PrinterMessageBox *r)
9890 p->rng_fault_state = true;
9891 return WERR_NOT_SUPPORTED;
9894 /****************************************************************
9895 _spoolss_AddMonitor
9896 ****************************************************************/
9898 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
9899 struct spoolss_AddMonitor *r)
9901 p->rng_fault_state = true;
9902 return WERR_NOT_SUPPORTED;
9905 /****************************************************************
9906 _spoolss_DeleteMonitor
9907 ****************************************************************/
9909 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
9910 struct spoolss_DeleteMonitor *r)
9912 p->rng_fault_state = true;
9913 return WERR_NOT_SUPPORTED;
9916 /****************************************************************
9917 _spoolss_DeletePrintProcessor
9918 ****************************************************************/
9920 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
9921 struct spoolss_DeletePrintProcessor *r)
9923 p->rng_fault_state = true;
9924 return WERR_NOT_SUPPORTED;
9927 /****************************************************************
9928 _spoolss_AddPrintProvidor
9929 ****************************************************************/
9931 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
9932 struct spoolss_AddPrintProvidor *r)
9934 p->rng_fault_state = true;
9935 return WERR_NOT_SUPPORTED;
9938 /****************************************************************
9939 _spoolss_DeletePrintProvidor
9940 ****************************************************************/
9942 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
9943 struct spoolss_DeletePrintProvidor *r)
9945 p->rng_fault_state = true;
9946 return WERR_NOT_SUPPORTED;
9949 /****************************************************************
9950 _spoolss_FindFirstPrinterChangeNotification
9951 ****************************************************************/
9953 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
9954 struct spoolss_FindFirstPrinterChangeNotification *r)
9956 p->rng_fault_state = true;
9957 return WERR_NOT_SUPPORTED;
9960 /****************************************************************
9961 _spoolss_FindNextPrinterChangeNotification
9962 ****************************************************************/
9964 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
9965 struct spoolss_FindNextPrinterChangeNotification *r)
9967 p->rng_fault_state = true;
9968 return WERR_NOT_SUPPORTED;
9971 /****************************************************************
9972 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9973 ****************************************************************/
9975 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
9976 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9978 p->rng_fault_state = true;
9979 return WERR_NOT_SUPPORTED;
9982 /****************************************************************
9983 _spoolss_ReplyOpenPrinter
9984 ****************************************************************/
9986 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
9987 struct spoolss_ReplyOpenPrinter *r)
9989 p->rng_fault_state = true;
9990 return WERR_NOT_SUPPORTED;
9993 /****************************************************************
9994 _spoolss_RouterReplyPrinter
9995 ****************************************************************/
9997 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
9998 struct spoolss_RouterReplyPrinter *r)
10000 p->rng_fault_state = true;
10001 return WERR_NOT_SUPPORTED;
10004 /****************************************************************
10005 _spoolss_ReplyClosePrinter
10006 ****************************************************************/
10008 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10009 struct spoolss_ReplyClosePrinter *r)
10011 p->rng_fault_state = true;
10012 return WERR_NOT_SUPPORTED;
10015 /****************************************************************
10016 _spoolss_AddPortEx
10017 ****************************************************************/
10019 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10020 struct spoolss_AddPortEx *r)
10022 p->rng_fault_state = true;
10023 return WERR_NOT_SUPPORTED;
10026 /****************************************************************
10027 _spoolss_RouterFindFirstPrinterChangeNotification
10028 ****************************************************************/
10030 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10031 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10033 p->rng_fault_state = true;
10034 return WERR_NOT_SUPPORTED;
10037 /****************************************************************
10038 _spoolss_SpoolerInit
10039 ****************************************************************/
10041 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10042 struct spoolss_SpoolerInit *r)
10044 p->rng_fault_state = true;
10045 return WERR_NOT_SUPPORTED;
10048 /****************************************************************
10049 _spoolss_ResetPrinterEx
10050 ****************************************************************/
10052 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10053 struct spoolss_ResetPrinterEx *r)
10055 p->rng_fault_state = true;
10056 return WERR_NOT_SUPPORTED;
10059 /****************************************************************
10060 _spoolss_RouterReplyPrinterEx
10061 ****************************************************************/
10063 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10064 struct spoolss_RouterReplyPrinterEx *r)
10066 p->rng_fault_state = true;
10067 return WERR_NOT_SUPPORTED;
10070 /****************************************************************
10071 _spoolss_44
10072 ****************************************************************/
10074 WERROR _spoolss_44(struct pipes_struct *p,
10075 struct spoolss_44 *r)
10077 p->rng_fault_state = true;
10078 return WERR_NOT_SUPPORTED;
10081 /****************************************************************
10082 _spoolss_47
10083 ****************************************************************/
10085 WERROR _spoolss_47(struct pipes_struct *p,
10086 struct spoolss_47 *r)
10088 p->rng_fault_state = true;
10089 return WERR_NOT_SUPPORTED;
10092 /****************************************************************
10093 _spoolss_4a
10094 ****************************************************************/
10096 WERROR _spoolss_4a(struct pipes_struct *p,
10097 struct spoolss_4a *r)
10099 p->rng_fault_state = true;
10100 return WERR_NOT_SUPPORTED;
10103 /****************************************************************
10104 _spoolss_4b
10105 ****************************************************************/
10107 WERROR _spoolss_4b(struct pipes_struct *p,
10108 struct spoolss_4b *r)
10110 p->rng_fault_state = true;
10111 return WERR_NOT_SUPPORTED;
10114 /****************************************************************
10115 _spoolss_4c
10116 ****************************************************************/
10118 WERROR _spoolss_4c(struct pipes_struct *p,
10119 struct spoolss_4c *r)
10121 p->rng_fault_state = true;
10122 return WERR_NOT_SUPPORTED;
10125 /****************************************************************
10126 _spoolss_53
10127 ****************************************************************/
10129 WERROR _spoolss_53(struct pipes_struct *p,
10130 struct spoolss_53 *r)
10132 p->rng_fault_state = true;
10133 return WERR_NOT_SUPPORTED;
10136 /****************************************************************
10137 _spoolss_55
10138 ****************************************************************/
10140 WERROR _spoolss_55(struct pipes_struct *p,
10141 struct spoolss_55 *r)
10143 p->rng_fault_state = true;
10144 return WERR_NOT_SUPPORTED;
10147 /****************************************************************
10148 _spoolss_56
10149 ****************************************************************/
10151 WERROR _spoolss_56(struct pipes_struct *p,
10152 struct spoolss_56 *r)
10154 p->rng_fault_state = true;
10155 return WERR_NOT_SUPPORTED;
10158 /****************************************************************
10159 _spoolss_57
10160 ****************************************************************/
10162 WERROR _spoolss_57(struct pipes_struct *p,
10163 struct spoolss_57 *r)
10165 p->rng_fault_state = true;
10166 return WERR_NOT_SUPPORTED;
10169 /****************************************************************
10170 _spoolss_5a
10171 ****************************************************************/
10173 WERROR _spoolss_5a(struct pipes_struct *p,
10174 struct spoolss_5a *r)
10176 p->rng_fault_state = true;
10177 return WERR_NOT_SUPPORTED;
10180 /****************************************************************
10181 _spoolss_5b
10182 ****************************************************************/
10184 WERROR _spoolss_5b(struct pipes_struct *p,
10185 struct spoolss_5b *r)
10187 p->rng_fault_state = true;
10188 return WERR_NOT_SUPPORTED;
10191 /****************************************************************
10192 _spoolss_5c
10193 ****************************************************************/
10195 WERROR _spoolss_5c(struct pipes_struct *p,
10196 struct spoolss_5c *r)
10198 p->rng_fault_state = true;
10199 return WERR_NOT_SUPPORTED;
10202 /****************************************************************
10203 _spoolss_5d
10204 ****************************************************************/
10206 WERROR _spoolss_5d(struct pipes_struct *p,
10207 struct spoolss_5d *r)
10209 p->rng_fault_state = true;
10210 return WERR_NOT_SUPPORTED;
10213 /****************************************************************
10214 _spoolss_5e
10215 ****************************************************************/
10217 WERROR _spoolss_5e(struct pipes_struct *p,
10218 struct spoolss_5e *r)
10220 p->rng_fault_state = true;
10221 return WERR_NOT_SUPPORTED;
10224 /****************************************************************
10225 _spoolss_5f
10226 ****************************************************************/
10228 WERROR _spoolss_5f(struct pipes_struct *p,
10229 struct spoolss_5f *r)
10231 p->rng_fault_state = true;
10232 return WERR_NOT_SUPPORTED;
10235 /****************************************************************
10236 _spoolss_60
10237 ****************************************************************/
10239 WERROR _spoolss_60(struct pipes_struct *p,
10240 struct spoolss_60 *r)
10242 p->rng_fault_state = true;
10243 return WERR_NOT_SUPPORTED;
10246 /****************************************************************
10247 _spoolss_61
10248 ****************************************************************/
10250 WERROR _spoolss_61(struct pipes_struct *p,
10251 struct spoolss_61 *r)
10253 p->rng_fault_state = true;
10254 return WERR_NOT_SUPPORTED;
10257 /****************************************************************
10258 _spoolss_62
10259 ****************************************************************/
10261 WERROR _spoolss_62(struct pipes_struct *p,
10262 struct spoolss_62 *r)
10264 p->rng_fault_state = true;
10265 return WERR_NOT_SUPPORTED;
10268 /****************************************************************
10269 _spoolss_63
10270 ****************************************************************/
10272 WERROR _spoolss_63(struct pipes_struct *p,
10273 struct spoolss_63 *r)
10275 p->rng_fault_state = true;
10276 return WERR_NOT_SUPPORTED;
10279 /****************************************************************
10280 _spoolss_64
10281 ****************************************************************/
10283 WERROR _spoolss_64(struct pipes_struct *p,
10284 struct spoolss_64 *r)
10286 p->rng_fault_state = true;
10287 return WERR_NOT_SUPPORTED;
10290 /****************************************************************
10291 _spoolss_65
10292 ****************************************************************/
10294 WERROR _spoolss_65(struct pipes_struct *p,
10295 struct spoolss_65 *r)
10297 p->rng_fault_state = true;
10298 return WERR_NOT_SUPPORTED;
10301 /****************************************************************
10302 _spoolss_GetCorePrinterDrivers
10303 ****************************************************************/
10305 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10306 struct spoolss_GetCorePrinterDrivers *r)
10308 p->rng_fault_state = true;
10309 return WERR_NOT_SUPPORTED;
10312 /****************************************************************
10313 _spoolss_67
10314 ****************************************************************/
10316 WERROR _spoolss_67(struct pipes_struct *p,
10317 struct spoolss_67 *r)
10319 p->rng_fault_state = true;
10320 return WERR_NOT_SUPPORTED;
10323 /****************************************************************
10324 _spoolss_GetPrinterDriverPackagePath
10325 ****************************************************************/
10327 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10328 struct spoolss_GetPrinterDriverPackagePath *r)
10330 p->rng_fault_state = true;
10331 return WERR_NOT_SUPPORTED;
10334 /****************************************************************
10335 _spoolss_69
10336 ****************************************************************/
10338 WERROR _spoolss_69(struct pipes_struct *p,
10339 struct spoolss_69 *r)
10341 p->rng_fault_state = true;
10342 return WERR_NOT_SUPPORTED;
10345 /****************************************************************
10346 _spoolss_6a
10347 ****************************************************************/
10349 WERROR _spoolss_6a(struct pipes_struct *p,
10350 struct spoolss_6a *r)
10352 p->rng_fault_state = true;
10353 return WERR_NOT_SUPPORTED;
10356 /****************************************************************
10357 _spoolss_6b
10358 ****************************************************************/
10360 WERROR _spoolss_6b(struct pipes_struct *p,
10361 struct spoolss_6b *r)
10363 p->rng_fault_state = true;
10364 return WERR_NOT_SUPPORTED;
10367 /****************************************************************
10368 _spoolss_6c
10369 ****************************************************************/
10371 WERROR _spoolss_6c(struct pipes_struct *p,
10372 struct spoolss_6c *r)
10374 p->rng_fault_state = true;
10375 return WERR_NOT_SUPPORTED;
10378 /****************************************************************
10379 _spoolss_6d
10380 ****************************************************************/
10382 WERROR _spoolss_6d(struct pipes_struct *p,
10383 struct spoolss_6d *r)
10385 p->rng_fault_state = true;
10386 return WERR_NOT_SUPPORTED;